Add performance improvements documentation and game-logic enhancements
- Add IMPROVEMENTS.md with detailed analysis of performance issues and bugs - Update CLAUDE.md with negative Y overflow explanation - Update README.md with socket events documentation - Enhance game-logic.js with improved comments and validation - Improve server/index.js with better documentation and edge case handling
This commit is contained in:
+37
-2
@@ -49,6 +49,9 @@ function getPieceFromType(pieceType) {
|
||||
* @param {number[][]} board - The game board
|
||||
* @param {number[][]} shape - Optional custom shape (for rotation)
|
||||
* @returns {boolean} True if position is valid
|
||||
*
|
||||
* Note: Negative Y is allowed (overflow/spawn area above visible board).
|
||||
* This allows pieces to be pushed up by garbage without immediate elimination.
|
||||
*/
|
||||
function isValidPosition(piece, x, y, board, shape = null) {
|
||||
const pieceShape = shape || piece.shape;
|
||||
@@ -59,11 +62,14 @@ function isValidPosition(piece, x, y, board, shape = null) {
|
||||
const newY = y + row;
|
||||
|
||||
// Check bounds
|
||||
// Note: Only checks if piece goes BELOW board (newY >= 20)
|
||||
// Negative Y is allowed - pieces can exist above visible board
|
||||
if (newX < 0 || newX >= BOARD_WIDTH || newY >= BOARD_HEIGHT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check collision with locked pieces (only if on board)
|
||||
// Note: Only checks collision if piece is in visible area (newY >= 0)
|
||||
if (newY >= 0 && board[newY][newX]) {
|
||||
return false;
|
||||
}
|
||||
@@ -93,6 +99,14 @@ function getGhostY(piece, board) {
|
||||
* Check if board has overflowed (blocks in top 2 rows)
|
||||
* @param {number[][]} board - The game board
|
||||
* @returns {boolean} True if board has overflowed
|
||||
*
|
||||
* Checks rows 0 AND 1 because:
|
||||
* - I piece at y=0 only places blocks in row 1 (unique shape)
|
||||
* - T piece at y=0 also only fills row 1
|
||||
* - If we only checked row 0, these pieces would NOT trigger elimination
|
||||
*
|
||||
* This is called when a piece LOCKS, not when garbage is received.
|
||||
* Player is eliminated only when they lock a piece that overflows.
|
||||
*/
|
||||
function checkBoardOverflow(board) {
|
||||
for (let row = 0; row < 2; row++) {
|
||||
@@ -110,18 +124,30 @@ function checkBoardOverflow(board) {
|
||||
* @param {number[][]} board - The game board
|
||||
* @param {object} currentPiece - Current falling piece (may be null)
|
||||
* @returns {object} Object with new board, updated piece, and gap position
|
||||
*
|
||||
* When garbage is added:
|
||||
* - All board rows shift up by 1 (top row removed)
|
||||
* - New garbage row added at bottom with one random gap
|
||||
* - Current piece y position decreases by 1 (pushed up)
|
||||
*
|
||||
* Note: Piece y can become negative (above visible board). This is intentional
|
||||
* - Player is NOT eliminated when piece goes negative
|
||||
* - Piece will drop naturally back into visible area
|
||||
* - Elimination only occurs when piece LOCKS with blocks in rows 0-1
|
||||
*/
|
||||
function addGarbageRow(board, currentPiece) {
|
||||
// Remove top row
|
||||
// Remove top row (all rows shift up)
|
||||
const newBoard = board.slice(1);
|
||||
|
||||
// Add garbage row with random gap
|
||||
// Add garbage row with random gap at bottom
|
||||
const garbageRow = Array(BOARD_WIDTH).fill(GARBAGE_COLOR);
|
||||
const gap = Math.floor(Math.random() * BOARD_WIDTH);
|
||||
garbageRow[gap] = 0;
|
||||
newBoard.push(garbageRow);
|
||||
|
||||
// Push current piece up by 1 row
|
||||
// Note: y can become negative (above visible board) - this is intentional
|
||||
// Player survives and piece will drop naturally back into view
|
||||
let updatedPiece = currentPiece;
|
||||
if (currentPiece) {
|
||||
updatedPiece = {
|
||||
@@ -138,6 +164,13 @@ function addGarbageRow(board, currentPiece) {
|
||||
* @param {object} piece - The piece to lock
|
||||
* @param {number[][]} board - The game board
|
||||
* @returns {number[][]} New board with piece locked
|
||||
*
|
||||
* Only locks blocks that are within visible board bounds [0, 20).
|
||||
* Blocks at negative Y (above board) are clipped and not locked.
|
||||
*
|
||||
* Example: I piece at y=-2 has blocks at rows -2,-1,0,1
|
||||
* - Only blocks at rows 0 and 1 get locked to board
|
||||
* - Blocks at rows -2 and -1 are clipped (discarded)
|
||||
*/
|
||||
function lockPieceToBoard(piece, board) {
|
||||
const newBoard = board.map(row => [...row]);
|
||||
@@ -148,6 +181,8 @@ function lockPieceToBoard(piece, board) {
|
||||
const boardY = piece.y + row;
|
||||
const boardX = piece.x + col;
|
||||
|
||||
// Only lock blocks within visible board bounds
|
||||
// Blocks above board (negative Y) are clipped
|
||||
if (boardY >= 0 && boardY < BOARD_HEIGHT && boardX >= 0 && boardX < BOARD_WIDTH) {
|
||||
newBoard[boardY][boardX] = piece.color;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user