rework clear rows function to be more efficient, and shorter.

This commit is contained in:
2025-09-08 12:51:24 +02:00
parent 7583da2ad3
commit c339accedc

View File

@@ -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 (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;
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];
}
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++) {
if (count) {
for (int i = 0; i < count; 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);