From 5e382ce25df64e6e7486896b415495d70bc7a62c Mon Sep 17 00:00:00 2001 From: enzotar Date: Fri, 27 Feb 2026 13:02:06 -0800 Subject: [PATCH] feat: full grid collision, freeze, and T-piece support (20 rows) Extended collision detection from py 12-17 to py 0-17 (full grid). Extended freeze writes from rows 13-19 to all 20 rows (0-19). Extended T-piece bottom cell freeze from 6 rows to all 19 rows. Pieces now correctly collide at ANY height in the grid. Previously pieces fell through tall stacks because collision only checked rows 12-17. --- examples/game-tetris.ds | 123 +++++++++++++++++++++++++++------------- 1 file changed, 83 insertions(+), 40 deletions(-) diff --git a/examples/game-tetris.ds b/examples/game-tetris.ds index 2c861bc..48fbc71 100644 --- a/examples/game-tetris.ds +++ b/examples/game-tetris.ds @@ -87,11 +87,11 @@ on keydown(ev) -> paused = if ev.key == "p" then (if paused then 0 else 1) else -- Collision detection: can the piece move down? -- All pieces: check grid[py+1] at px, px+1, px+2 (top row destination). -- T-piece (6) only: also check grid[py+2] at px+1 (protruding bottom cell). --- Bottom wall: py >= 18. +-- Bottom wall: py >= 18. Full grid coverage (py 0-17). let blocked = 0 --- Piece-aware collision: top row for all, bottom cell only for T-piece -every 33 -> blocked = if py > 17 then 1 else (if py == 17 then (if g18[px] > 0 then 1 else (if g18[px + 1] > 0 then 1 else (if g18[px + 2] > 0 then 1 else (if piece == 6 then (if g19[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 16 then (if g17[px] > 0 then 1 else (if g17[px + 1] > 0 then 1 else (if g17[px + 2] > 0 then 1 else (if piece == 6 then (if g18[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 15 then (if g16[px] > 0 then 1 else (if g16[px + 1] > 0 then 1 else (if g16[px + 2] > 0 then 1 else (if piece == 6 then (if g17[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 14 then (if g15[px] > 0 then 1 else (if g15[px + 1] > 0 then 1 else (if g15[px + 2] > 0 then 1 else (if piece == 6 then (if g16[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 13 then (if g14[px] > 0 then 1 else (if g14[px + 1] > 0 then 1 else (if g14[px + 2] > 0 then 1 else (if piece == 6 then (if g15[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 12 then (if g13[px] > 0 then 1 else (if g13[px + 1] > 0 then 1 else (if g13[px + 2] > 0 then 1 else (if piece == 6 then (if g14[px + 1] > 0 then 1 else 0) else 0)))) else 0)))))) +-- Piece-aware collision: full grid, top row + T-piece bottom cell +every 33 -> blocked = if py > 17 then 1 else (if py == 17 then (if g18[px] > 0 then 1 else (if g18[px + 1] > 0 then 1 else (if g18[px + 2] > 0 then 1 else (if piece == 6 then (if g19[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 16 then (if g17[px] > 0 then 1 else (if g17[px + 1] > 0 then 1 else (if g17[px + 2] > 0 then 1 else (if piece == 6 then (if g18[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 15 then (if g16[px] > 0 then 1 else (if g16[px + 1] > 0 then 1 else (if g16[px + 2] > 0 then 1 else (if piece == 6 then (if g17[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 14 then (if g15[px] > 0 then 1 else (if g15[px + 1] > 0 then 1 else (if g15[px + 2] > 0 then 1 else (if piece == 6 then (if g16[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 13 then (if g14[px] > 0 then 1 else (if g14[px + 1] > 0 then 1 else (if g14[px + 2] > 0 then 1 else (if piece == 6 then (if g15[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 12 then (if g13[px] > 0 then 1 else (if g13[px + 1] > 0 then 1 else (if g13[px + 2] > 0 then 1 else (if piece == 6 then (if g14[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 11 then (if g12[px] > 0 then 1 else (if g12[px + 1] > 0 then 1 else (if g12[px + 2] > 0 then 1 else (if piece == 6 then (if g13[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 10 then (if g11[px] > 0 then 1 else (if g11[px + 1] > 0 then 1 else (if g11[px + 2] > 0 then 1 else (if piece == 6 then (if g12[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 9 then (if g10[px] > 0 then 1 else (if g10[px + 1] > 0 then 1 else (if g10[px + 2] > 0 then 1 else (if piece == 6 then (if g11[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 8 then (if g9[px] > 0 then 1 else (if g9[px + 1] > 0 then 1 else (if g9[px + 2] > 0 then 1 else (if piece == 6 then (if g10[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 7 then (if g8[px] > 0 then 1 else (if g8[px + 1] > 0 then 1 else (if g8[px + 2] > 0 then 1 else (if piece == 6 then (if g9[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 6 then (if g7[px] > 0 then 1 else (if g7[px + 1] > 0 then 1 else (if g7[px + 2] > 0 then 1 else (if piece == 6 then (if g8[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 5 then (if g6[px] > 0 then 1 else (if g6[px + 1] > 0 then 1 else (if g6[px + 2] > 0 then 1 else (if piece == 6 then (if g7[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 4 then (if g5[px] > 0 then 1 else (if g5[px + 1] > 0 then 1 else (if g5[px + 2] > 0 then 1 else (if piece == 6 then (if g6[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 3 then (if g4[px] > 0 then 1 else (if g4[px + 1] > 0 then 1 else (if g4[px + 2] > 0 then 1 else (if piece == 6 then (if g5[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 2 then (if g3[px] > 0 then 1 else (if g3[px + 1] > 0 then 1 else (if g3[px + 2] > 0 then 1 else (if piece == 6 then (if g4[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 1 then (if g2[px] > 0 then 1 else (if g2[px + 1] > 0 then 1 else (if g2[px + 2] > 0 then 1 else (if piece == 6 then (if g3[px + 1] > 0 then 1 else 0) else 0)))) else (if py == 0 then (if g1[px] > 0 then 1 else (if g1[px + 1] > 0 then 1 else (if g1[px + 2] > 0 then 1 else (if piece == 6 then (if g2[px + 1] > 0 then 1 else 0) else 0)))) else 0)))))))))))))))))) -- Gravity tick every 33 -> gravityTick = if paused then gravityTick else (if gameOver then gravityTick else gravityTick + 1) @@ -104,48 +104,91 @@ every 33 -> gravityTick = if gravityTick > dropInterval then 0 else gravityTick every 33 -> lockTick = if blocked then lockTick + 1 else 0 -- ── Freeze piece into grid at py position on lock ── --- The piece top-row cells go into row py, bottom-row cell into py+1 --- For T-piece: (px,py), (px+1,py), (px+2,py) and (px+1,py+1) --- We write the top 3 cells into grid[py] and bottom cell into grid[py+1] +-- Top 3 cells go into grid[py], T-piece bottom cell into grid[py+1] +-- Full grid coverage: rows 0-19 --- Freeze top cells into grid row py (for each possible py value) --- Row 19 -every 33 -> g19[px] = if lockTick == 3 then (if py == 19 then piece else g19[px]) else g19[px] -every 33 -> g19[px + 1] = if lockTick == 3 then (if py == 19 then piece else g19[px + 1]) else g19[px + 1] -every 33 -> g19[px + 2] = if lockTick == 3 then (if py == 19 then piece else g19[px + 2]) else g19[px + 2] --- Row 18 -every 33 -> g18[px] = if lockTick == 3 then (if py == 18 then piece else g18[px]) else g18[px] -every 33 -> g18[px + 1] = if lockTick == 3 then (if py == 18 then piece else g18[px + 1]) else g18[px + 1] -every 33 -> g18[px + 2] = if lockTick == 3 then (if py == 18 then piece else g18[px + 2]) else g18[px + 2] --- Row 17 -every 33 -> g17[px] = if lockTick == 3 then (if py == 17 then piece else g17[px]) else g17[px] -every 33 -> g17[px + 1] = if lockTick == 3 then (if py == 17 then piece else g17[px + 1]) else g17[px + 1] -every 33 -> g17[px + 2] = if lockTick == 3 then (if py == 17 then piece else g17[px + 2]) else g17[px + 2] --- Row 16 -every 33 -> g16[px] = if lockTick == 3 then (if py == 16 then piece else g16[px]) else g16[px] -every 33 -> g16[px + 1] = if lockTick == 3 then (if py == 16 then piece else g16[px + 1]) else g16[px + 1] -every 33 -> g16[px + 2] = if lockTick == 3 then (if py == 16 then piece else g16[px + 2]) else g16[px + 2] --- Row 15 -every 33 -> g15[px] = if lockTick == 3 then (if py == 15 then piece else g15[px]) else g15[px] -every 33 -> g15[px + 1] = if lockTick == 3 then (if py == 15 then piece else g15[px + 1]) else g15[px + 1] -every 33 -> g15[px + 2] = if lockTick == 3 then (if py == 15 then piece else g15[px + 2]) else g15[px + 2] --- Row 14 -every 33 -> g14[px] = if lockTick == 3 then (if py == 14 then piece else g14[px]) else g14[px] -every 33 -> g14[px + 1] = if lockTick == 3 then (if py == 14 then piece else g14[px + 1]) else g14[px + 1] -every 33 -> g14[px + 2] = if lockTick == 3 then (if py == 14 then piece else g14[px + 2]) else g14[px + 2] --- Row 13 -every 33 -> g13[px] = if lockTick == 3 then (if py == 13 then piece else g13[px]) else g13[px] +-- Freeze top cells (3 per row, all 20 rows) +every 33 -> g0[px] = if lockTick == 3 then (if py == 0 then piece else g0[px]) else g0[px] +every 33 -> g0[px + 1] = if lockTick == 3 then (if py == 0 then piece else g0[px + 1]) else g0[px + 1] +every 33 -> g0[px + 2] = if lockTick == 3 then (if py == 0 then piece else g0[px + 2]) else g0[px + 2] +every 33 -> g1[px] = if lockTick == 3 then (if py == 1 then piece else g1[px]) else g1[px] +every 33 -> g1[px + 1] = if lockTick == 3 then (if py == 1 then piece else g1[px + 1]) else g1[px + 1] +every 33 -> g1[px + 2] = if lockTick == 3 then (if py == 1 then piece else g1[px + 2]) else g1[px + 2] +every 33 -> g2[px] = if lockTick == 3 then (if py == 2 then piece else g2[px]) else g2[px] +every 33 -> g2[px + 1] = if lockTick == 3 then (if py == 2 then piece else g2[px + 1]) else g2[px + 1] +every 33 -> g2[px + 2] = if lockTick == 3 then (if py == 2 then piece else g2[px + 2]) else g2[px + 2] +every 33 -> g3[px] = if lockTick == 3 then (if py == 3 then piece else g3[px]) else g3[px] +every 33 -> g3[px + 1] = if lockTick == 3 then (if py == 3 then piece else g3[px + 1]) else g3[px + 1] +every 33 -> g3[px + 2] = if lockTick == 3 then (if py == 3 then piece else g3[px + 2]) else g3[px + 2] +every 33 -> g4[px] = if lockTick == 3 then (if py == 4 then piece else g4[px]) else g4[px] +every 33 -> g4[px + 1] = if lockTick == 3 then (if py == 4 then piece else g4[px + 1]) else g4[px + 1] +every 33 -> g4[px + 2] = if lockTick == 3 then (if py == 4 then piece else g4[px + 2]) else g4[px + 2] +every 33 -> g5[px] = if lockTick == 3 then (if py == 5 then piece else g5[px]) else g5[px] +every 33 -> g5[px + 1] = if lockTick == 3 then (if py == 5 then piece else g5[px + 1]) else g5[px + 1] +every 33 -> g5[px + 2] = if lockTick == 3 then (if py == 5 then piece else g5[px + 2]) else g5[px + 2] +every 33 -> g6[px] = if lockTick == 3 then (if py == 6 then piece else g6[px]) else g6[px] +every 33 -> g6[px + 1] = if lockTick == 3 then (if py == 6 then piece else g6[px + 1]) else g6[px + 1] +every 33 -> g6[px + 2] = if lockTick == 3 then (if py == 6 then piece else g6[px + 2]) else g6[px + 2] +every 33 -> g7[px] = if lockTick == 3 then (if py == 7 then piece else g7[px]) else g7[px] +every 33 -> g7[px + 1] = if lockTick == 3 then (if py == 7 then piece else g7[px + 1]) else g7[px + 1] +every 33 -> g7[px + 2] = if lockTick == 3 then (if py == 7 then piece else g7[px + 2]) else g7[px + 2] +every 33 -> g8[px] = if lockTick == 3 then (if py == 8 then piece else g8[px]) else g8[px] +every 33 -> g8[px + 1] = if lockTick == 3 then (if py == 8 then piece else g8[px + 1]) else g8[px + 1] +every 33 -> g8[px + 2] = if lockTick == 3 then (if py == 8 then piece else g8[px + 2]) else g8[px + 2] +every 33 -> g9[px] = if lockTick == 3 then (if py == 9 then piece else g9[px]) else g9[px] +every 33 -> g9[px + 1] = if lockTick == 3 then (if py == 9 then piece else g9[px + 1]) else g9[px + 1] +every 33 -> g9[px + 2] = if lockTick == 3 then (if py == 9 then piece else g9[px + 2]) else g9[px + 2] +every 33 -> g10[px] = if lockTick == 3 then (if py == 10 then piece else g10[px]) else g10[px] +every 33 -> g10[px + 1] = if lockTick == 3 then (if py == 10 then piece else g10[px + 1]) else g10[px + 1] +every 33 -> g10[px + 2] = if lockTick == 3 then (if py == 10 then piece else g10[px + 2]) else g10[px + 2] +every 33 -> g11[px] = if lockTick == 3 then (if py == 11 then piece else g11[px]) else g11[px] +every 33 -> g11[px + 1] = if lockTick == 3 then (if py == 11 then piece else g11[px + 1]) else g11[px + 1] +every 33 -> g11[px + 2] = if lockTick == 3 then (if py == 11 then piece else g11[px + 2]) else g11[px + 2] +every 33 -> g12[px] = if lockTick == 3 then (if py == 12 then piece else g12[px]) else g12[px] +every 33 -> g12[px + 1] = if lockTick == 3 then (if py == 12 then piece else g12[px + 1]) else g12[px + 1] +every 33 -> g12[px + 2] = if lockTick == 3 then (if py == 12 then piece else g12[px + 2]) else g12[px + 2] +every 33 -> g13[px] = if lockTick == 3 then (if py == 13 then piece else g13[px]) else g13[px] every 33 -> g13[px + 1] = if lockTick == 3 then (if py == 13 then piece else g13[px + 1]) else g13[px + 1] every 33 -> g13[px + 2] = if lockTick == 3 then (if py == 13 then piece else g13[px + 2]) else g13[px + 2] +every 33 -> g14[px] = if lockTick == 3 then (if py == 14 then piece else g14[px]) else g14[px] +every 33 -> g14[px + 1] = if lockTick == 3 then (if py == 14 then piece else g14[px + 1]) else g14[px + 1] +every 33 -> g14[px + 2] = if lockTick == 3 then (if py == 14 then piece else g14[px + 2]) else g14[px + 2] +every 33 -> g15[px] = if lockTick == 3 then (if py == 15 then piece else g15[px]) else g15[px] +every 33 -> g15[px + 1] = if lockTick == 3 then (if py == 15 then piece else g15[px + 1]) else g15[px + 1] +every 33 -> g15[px + 2] = if lockTick == 3 then (if py == 15 then piece else g15[px + 2]) else g15[px + 2] +every 33 -> g16[px] = if lockTick == 3 then (if py == 16 then piece else g16[px]) else g16[px] +every 33 -> g16[px + 1] = if lockTick == 3 then (if py == 16 then piece else g16[px + 1]) else g16[px + 1] +every 33 -> g16[px + 2] = if lockTick == 3 then (if py == 16 then piece else g16[px + 2]) else g16[px + 2] +every 33 -> g17[px] = if lockTick == 3 then (if py == 17 then piece else g17[px]) else g17[px] +every 33 -> g17[px + 1] = if lockTick == 3 then (if py == 17 then piece else g17[px + 1]) else g17[px + 1] +every 33 -> g17[px + 2] = if lockTick == 3 then (if py == 17 then piece else g17[px + 2]) else g17[px + 2] +every 33 -> g18[px] = if lockTick == 3 then (if py == 18 then piece else g18[px]) else g18[px] +every 33 -> g18[px + 1] = if lockTick == 3 then (if py == 18 then piece else g18[px + 1]) else g18[px + 1] +every 33 -> g18[px + 2] = if lockTick == 3 then (if py == 18 then piece else g18[px + 2]) else g18[px + 2] +every 33 -> g19[px] = if lockTick == 3 then (if py == 19 then piece else g19[px]) else g19[px] +every 33 -> g19[px + 1] = if lockTick == 3 then (if py == 19 then piece else g19[px + 1]) else g19[px + 1] +every 33 -> g19[px + 2] = if lockTick == 3 then (if py == 19 then piece else g19[px + 2]) else g19[px + 2] --- Freeze T-piece bottom center cell into grid[py+1] --- (T has a cell at px+1, py+1; also applicable to O, S, Z shapes) -every 33 -> g19[px + 1] = if lockTick == 3 then (if py == 18 then (if piece == 6 then 6 else g19[px + 1]) else g19[px + 1]) else g19[px + 1] -every 33 -> g18[px + 1] = if lockTick == 3 then (if py == 17 then (if piece == 6 then 6 else g18[px + 1]) else g18[px + 1]) else g18[px + 1] -every 33 -> g17[px + 1] = if lockTick == 3 then (if py == 16 then (if piece == 6 then 6 else g17[px + 1]) else g17[px + 1]) else g17[px + 1] -every 33 -> g16[px + 1] = if lockTick == 3 then (if py == 15 then (if piece == 6 then 6 else g16[px + 1]) else g16[px + 1]) else g16[px + 1] -every 33 -> g15[px + 1] = if lockTick == 3 then (if py == 14 then (if piece == 6 then 6 else g15[px + 1]) else g15[px + 1]) else g15[px + 1] +-- Freeze T-piece bottom center cell into grid[py+1] (all rows) +every 33 -> g1[px + 1] = if lockTick == 3 then (if py == 0 then (if piece == 6 then 6 else g1[px + 1]) else g1[px + 1]) else g1[px + 1] +every 33 -> g2[px + 1] = if lockTick == 3 then (if py == 1 then (if piece == 6 then 6 else g2[px + 1]) else g2[px + 1]) else g2[px + 1] +every 33 -> g3[px + 1] = if lockTick == 3 then (if py == 2 then (if piece == 6 then 6 else g3[px + 1]) else g3[px + 1]) else g3[px + 1] +every 33 -> g4[px + 1] = if lockTick == 3 then (if py == 3 then (if piece == 6 then 6 else g4[px + 1]) else g4[px + 1]) else g4[px + 1] +every 33 -> g5[px + 1] = if lockTick == 3 then (if py == 4 then (if piece == 6 then 6 else g5[px + 1]) else g5[px + 1]) else g5[px + 1] +every 33 -> g6[px + 1] = if lockTick == 3 then (if py == 5 then (if piece == 6 then 6 else g6[px + 1]) else g6[px + 1]) else g6[px + 1] +every 33 -> g7[px + 1] = if lockTick == 3 then (if py == 6 then (if piece == 6 then 6 else g7[px + 1]) else g7[px + 1]) else g7[px + 1] +every 33 -> g8[px + 1] = if lockTick == 3 then (if py == 7 then (if piece == 6 then 6 else g8[px + 1]) else g8[px + 1]) else g8[px + 1] +every 33 -> g9[px + 1] = if lockTick == 3 then (if py == 8 then (if piece == 6 then 6 else g9[px + 1]) else g9[px + 1]) else g9[px + 1] +every 33 -> g10[px + 1] = if lockTick == 3 then (if py == 9 then (if piece == 6 then 6 else g10[px + 1]) else g10[px + 1]) else g10[px + 1] +every 33 -> g11[px + 1] = if lockTick == 3 then (if py == 10 then (if piece == 6 then 6 else g11[px + 1]) else g11[px + 1]) else g11[px + 1] +every 33 -> g12[px + 1] = if lockTick == 3 then (if py == 11 then (if piece == 6 then 6 else g12[px + 1]) else g12[px + 1]) else g12[px + 1] +every 33 -> g13[px + 1] = if lockTick == 3 then (if py == 12 then (if piece == 6 then 6 else g13[px + 1]) else g13[px + 1]) else g13[px + 1] every 33 -> g14[px + 1] = if lockTick == 3 then (if py == 13 then (if piece == 6 then 6 else g14[px + 1]) else g14[px + 1]) else g14[px + 1] +every 33 -> g15[px + 1] = if lockTick == 3 then (if py == 14 then (if piece == 6 then 6 else g15[px + 1]) else g15[px + 1]) else g15[px + 1] +every 33 -> g16[px + 1] = if lockTick == 3 then (if py == 15 then (if piece == 6 then 6 else g16[px + 1]) else g16[px + 1]) else g16[px + 1] +every 33 -> g17[px + 1] = if lockTick == 3 then (if py == 16 then (if piece == 6 then 6 else g17[px + 1]) else g17[px + 1]) else g17[px + 1] +every 33 -> g18[px + 1] = if lockTick == 3 then (if py == 17 then (if piece == 6 then 6 else g18[px + 1]) else g18[px + 1]) else g18[px + 1] +every 33 -> g19[px + 1] = if lockTick == 3 then (if py == 18 then (if piece == 6 then 6 else g19[px + 1]) else g19[px + 1]) else g19[px + 1] -- Spawn new piece after lock every 33 -> piece = if lockTick == 3 then nextPiece else piece