From c339accedcfe2348d30d6efb8a83d0f06d191bbf Mon Sep 17 00:00:00 2001 From: Quinn Date: Mon, 8 Sep 2025 12:51:24 +0200 Subject: [PATCH] rework clear rows function to be more efficient, and shorter. --- src/game/tetromino/placing.c | 53 ++++++++++-------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/src/game/tetromino/placing.c b/src/game/tetromino/placing.c index c1d1c89..a9d7dd0 100644 --- a/src/game/tetromino/placing.c +++ b/src/game/tetromino/placing.c @@ -12,47 +12,24 @@ #include "shapes.h" -/* count the empty columns in the row */ -__attribute_const__ static int count_empty(u8 const* restrict row) { - int cnt = 0; -#if defined(__clang__) -#pragma unroll COLUMNS -#elif defined(__GNUC__) -#pragma GCC unroll COLUMNS -#endif - for (int i = 0; i < COLUMNS; i++) - cnt += !row[i]; - return cnt; -} +static int clear_rows(u8* restrict* restrict rows) { + int count = 0; + u8* cache[4]; /* the maximum amount of rows the user can clear at once is four */ -/* checks for filled rows, clearing a max of 4 consecutive rows, if present. - * all row pointers will be moved down to fill the gap, the filled rows will be inserted at the top, and zeroed-out */ -static void clear_rows(u8* restrict* restrict rows, u16* const score) { - u8* cache[4] = {0}; // the I piece is 4 long, meaning only 4 rows can be cleared at a time - uint fillc = 0; - uint checkc = 0; + for (int y = ROWS - 1; y >= 0; y--) { + int x = 0; + while (x < COLUMNS && rows[y][x] && count < 4) x++; + if (x >= COLUMNS) cache[count++] = rows[y]; + else rows[y + count] = rows[y]; + } - for (uint y = 0; y < (ROWS - fillc) && checkc <= 4; y++) { - int i = (ROWS - 1) - y; // invert the index direction, so we start at the highest index - rows[i] = rows[i - fillc]; // either assigns the current row to itself, or to the "next" row - - if (count_empty(rows[i])) { - checkc += (fillc > 0 && checkc < 4); - continue; + if (count) { + for (int i = 0; i < count; i++) { + memset(cache[i], 0, COLUMNS); + rows[i] = cache[i]; } - - - cache[fillc] = rows[i]; // cache the current row address, since it's going to be overridden - fillc++; - checkc++; - y--; - } - - *score += (8 << fillc) * !!fillc; - for (uint i = 0; i < fillc; i++) { - memset(cache[i], 0, COLUMNS); - rows[i] = cache[i]; } + return count; } /* writes a shape to the screen */ @@ -99,7 +76,7 @@ int place_update(struct gamedata* gdat, int movdat) { if (tmp) { gdat->pdat.sel[VY]--; plcmnt_place(gdat->rows, id, gdat->pdat.sel); - clear_rows(gdat->rows, &gdat->pnts); // clear the rows that have been completed + gdat->pnts += clear_rows(gdat->rows) << 4; // clear the rows that have been completed next_shape(); audio_play(AUDIO_ID_PLACE);