Files
tetris_clone/src/tetris.c

82 lines
2.1 KiB
C

#include "tetris.h"
#include <string.h>
#include "util/intdef.h"
/* Board co-ordinates:
* 0 1 2 3
* 4 5 6 7
* 8 9 A B
* C D E F */
const u16 tetromino_shapes[7][4] = {
/* NONE CW_90 CW_180 CW_270 */
[TET_I] = {0x159D, 0x89AB, 0x26AE, 0x4567},
[TET_O] = {0x569A, 0x569A, 0x569A, 0x569A},
[TET_T] = {0x1456, 0x1569, 0x4569, 0x1459},
[TET_J] = {0x0456, 0x1259, 0x456A, 0x1589},
[TET_L] = {0x4536, 0x159A, 0x4568, 0x0159},
[TET_S] = {0x1245, 0x156A, 0x5689, 0x0459},
[TET_Z] = {0x0156, 0x2569, 0x459A, 0x1458},
};
void tetris_get_blocks(u8 tetromino, uint *restrict positions) {
uint shape = tetromino_shapes[tetromino & 7][tetromino >> 3];
uint *end = positions + 8;
while (positions < end) {
*positions += shape & 3;
shape >>= 2;
positions++;
}
}
void tetris_init_rows(const u8 *restrict data, const u8 *restrict *restrict out) {
const u8 *restrict *end = out + TET_HEIGHT;
while (out < end) {
*out = data;
data += TET_WIDTH;
out++;
}
}
int tetris_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 */
for (int y = 0; y < TET_HEIGHT; y++) {
int x = 0;
while (x < TET_WIDTH && rows[y][x] && count < 4) x++;
if (x >= TET_WIDTH) cache[count++] = rows[y];
else rows[y - count] = rows[y];
}
if (count) {
for (int i = 0; i < count; i++) {
memset(cache[i], 0, TET_WIDTH);
rows[TET_HEIGHT - 1 - i] = cache[i];
}
}
return count;
}
int tetris_intersect(const u8 *restrict const *restrict rows, u8 tetromino, uint x, uint y) {
uint *pos = (uint[8]){x, y, x, y, x, y, x, y};
uint *end = pos + 8;
tetris_get_blocks(tetromino, pos);
for (; pos < end; pos += 2) {
if (*(pos + 0) >= TET_WIDTH) return 2;
if (*(pos + 1) >= TET_HEIGHT) return 2;
if (rows[*(pos + 1)][*pos]) break;
}
return pos < end;
}
void tetris_place(u8 *restrict *restrict rows, u8 tetromino, uint x, uint y) {
uint *pos = (uint[8]){x, y, x, y, x, y, x, y};
uint *end = pos + 8;
tetris_get_blocks(tetromino, pos);
tetromino &= 7; /* strip rotation data */
tetromino |= TET_NON_EMPTY;
for (; pos < end; pos += 2)
rows[*(pos + 1)][*pos] = tetromino;
}