summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/\277
-rw-r--r--core/include/cetris.h12
-rw-r--r--core/include/matrix.h7
-rw-r--r--core/include/types.h11
-rw-r--r--core/src/cetris.c118
-rw-r--r--core/src/input.c12
-rw-r--r--core/src/matrix.c100
-rw-r--r--core/src/test.c4
8 files changed, 423 insertions, 118 deletions
diff --git a/core/\ b/core/\
new file mode 100644
index 0000000..80e819a
--- /dev/null
+++ b/core/\
@@ -0,0 +1,277 @@
+#include <string.h>
+
+#include "matrix.h"
+#include "types.h"
+#include "cetris.h"
+
+/* SRS WALL KICK VALUES */
+
+// https://tetris.wiki/SRS
+static const vec2 srs_wall_kicks[8][5] = {
+ { {0, 0}, {-1, 0}, {-1,1}, {0,-2}, {-1,-2} }, // 0->R
+ { {0, 0}, {1, 0}, {1,-1}, {0,2}, {1,2} }, // R->0
+ { {0, 0}, {1, 0}, {1,-1}, {0,2}, {1,2} }, // R->2
+ { {0, 0}, {-1, 0}, {-1,1}, {0,-2}, {-1,-2} }, // 2->R
+ { {0, 0}, {1, 0}, {1,1}, {0,-2}, {1,-2} }, // 2->L
+ { {0, 0}, {-1, 0}, {-1,-1}, {0,2}, {-1,2} }, // L->2
+ { {0, 0}, {-1, 0}, {-1,-1}, {0,2}, {-1,2} }, // L->0
+ { {0, 0}, {1, 0}, {1,1}, {0,-2}, {1,-2} } // 0->L
+};
+
+static const vec2 srs_wall_kicks_i[8][5] = {
+ { {0, 0}, {-2, 0}, {1, 0}, {-2,-1}, {1,2} }, // 0->R
+ { {0, 0}, {2, 0}, {-1, 0}, {2,1}, {-1,-2} }, // R->0
+ { {0, 0}, {-1, 0}, {2, 0}, {-1,2}, {2,-1} }, // R->2
+ { {0, 0}, {1, 0}, {-2, 0}, {1,-2}, {-2,1} }, // 2->R
+ { {0, 0}, {2, 0}, {-1, 0}, {2,1}, {-1,-2} }, // 2->L
+ { {0, 0}, {-2, 0}, {1, 0}, {-2,-1}, {1,2} }, // L->2
+ { {0, 0}, {1, 0}, {-2, 0}, {1,-2}, {-2,1} }, // L->0
+ { {0, 0}, {-1, 0}, {2, 0}, {-1,2}, {2,-1} } // 0->L
+};
+
+/* DEFAULT MATRIX FOR EACH POSSIBLE TETRIMINO */
+
+const piece_matrix default_matrices[7] = {
+ {
+ { 0, 0, 0, 0 },
+ { 0, 1, 1, 0 },
+ { 0, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 1, 1, 1, 1 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 0, 1, 1, 0 },
+ { 1, 1, 0, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 1, 1, 0, 0 },
+ { 0, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 0, 0, 1, 0 },
+ { 1, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 1, 0, 0, 0 },
+ { 1, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 0, 1, 0, 0 },
+ { 1, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ }
+};
+
+/* MATRIX MODIFICATION */
+
+const vec2 basic_movements[4] = {
+ {0, 0}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, RIGHT, LEFT
+};
+
+void move_current(struct cetris_game* g, vec2 offset) {
+ if (g->game_over) return;
+g->current.pos.y += offset.y; g->current.pos.x += offset.x;
+
+ i8 check = check_new_matrix(g, g->current.m);
+ if (check <= 0) {
+ g->current.pos.y -= offset.y;
+ g->current.pos.x -= offset.x;
+
+ if (check == -1 && g->current.lock_tick == 0) {
+ g->current.lock_tick = g->tick + 30;
+ }
+ }
+
+ update_board(g);
+}
+
+i8 overlay_matrix(struct cetris_game* g, piece_matrix m, bool set_board) {
+ for (i8 y = 0; y < 4; y++) {
+ for (i8 x = 0; x < 4; x++) {
+ vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
+ if (r.x > CETRIS_BOARD_X || r.x < 0 || r.y > CETRIS_BOARD_Y)
+ return 0;
+ if (m[y][x] && r.y >= 0) {
+ if (g->board[r.x][r.y].occupied) return -1;
+ if (set_board) {
+ g->board[r.x][r.y].occupied = 1;
+ g->board[r.x][r.y].c = g->current.c;
+ }
+ }
+ }
+ }
+ return 1;
+}
+
+void hard_drop(struct cetris_game* g) {
+ if (g->game_over) return;
+
+ bool drop = false;
+ u8 drop_count = 0;
+ while (!drop) {
+ g->current.pos.y++;
+ drop_count++;
+ i8 check = check_new_matrix(g, g->current.m);
+ if (check <= 0) {
+ g->current.pos.y--;
+ drop_count--;
+ drop = true;
+ }
+ }
+
+ g->score += 2 * drop_count; // 2 score for each hard-drop'd cell
+
+ update_board(g);
+ next_piece(g);
+}
+
+void rotate_matrix(struct cetris_game* g, bool clockwise) {
+ if (g->game_over) return;
+ if (g->current.t == O) return;
+
+ rstate next = 0;
+ u8 wall_kick = 0;
+ switch (g->current.r) {
+ case INIT:
+ if (clockwise) {
+ next = ONCE_RIGHT;
+ wall_kick = 0;
+ } else {
+ next = ONCE_LEFT;
+ wall_kick = 7;
+ } break;
+ case ONCE_RIGHT:
+ if (clockwise) {
+ next = TWICE;
+ wall_kick = 2;
+ } else {
+ next = INIT;
+ wall_kick = 1;
+ } break;
+ case ONCE_LEFT:
+ if (clockwise) {
+ next = INIT;
+ wall_kick = 6;
+ } else {
+ next = TWICE;
+ wall_kick = 5;
+ } break;
+ case TWICE:
+ if (clockwise) {
+ next = ONCE_LEFT;
+ wall_kick = 4;
+ } else {
+ next = ONCE_RIGHT;
+ wall_kick = 3;
+ } break;
+ }
+
+ piece_matrix m;
+ memset(m, 0, sizeof(piece_matrix));
+
+ for (u8 x = 0; x < 4; x++) {
+ for (u8 y = 0; y < 4; y++) {
+ if (g->current.m[y][x]) {
+ u8 new_x = (clockwise) ? 1 - (y - 2) : 1 + (y - 2);
+ u8 new_y = (clockwise) ? 2 + (x - 1) : 2 - (x - 1);
+
+ if (g->current.t == I) {
+ if (clockwise) new_y--;
+ else new_x++;
+ }
+
+ m[new_y][new_x] = 1;
+ }
+ }
+ }
+
+ vec2 kick;
+ bool set_current = false;
+ bool did_kick = false;
+ for (u8 i = 0; i < 5; i++) {
+ if (g->current.t == I) {
+ kick = srs_wall_kicks_i[wall_kick][i];
+ } else {
+ kick = srs_wall_kicks[wall_kick][i];
+ }
+ g->current.pos.x += kick.x;
+ g->current.pos.y += kick.y;
+ if (check_new_matrix(g, m) > 0) {
+ set_current = true;
+ if (i > 0) did_kick = true;
+ break;
+ } else {
+ g->current.pos.x -= kick.x;
+ g->current.pos.y -= kick.y;
+ }
+ }
+
+ if (set_current) {
+ memcpy(g->current.m, m, sizeof(piece_matrix));
+
+ /* check for tspin */
+ if (g->current.t == T) {
+ u8 did_tspin = 1;
+ for (int i = 0; i < 4; i++) {
+ g->current.pos.x += basic_movements[i].x;
+ g->current.pos.y += basic_movements[i].y;
+
+ if (overlay_current_matrix(g, false) == 1)
+ did_tspin = 0;
+
+ g->current.pos.x -= basic_movements[i].x;
+ g->current.pos.y -= basic_movements[i].y;
+ }
+
+ if (did_tspin) {
+ if (did_kick) g->mini_tspin = 1;
+ else g->tspin = 1;
+ }
+ }
+
+ g->current.r = next;
+ update_board(g);
+ }
+}
+
+
+/*
+i8 check_new_matrix(struct cetris_game* g, piece_matrix m) {
+ for (u8 x = 0; x < 4; x++) {
+ for (u8 y = 0; y < 4; y++) {
+ vec2 r = (vec2){g->current.pos.x + x, g->current.pos.y + y};
+ if (m[y][x]) {
+ if (r.x > CETRIS_BOARD_X - 1 || r.x < 0)
+ return 0;
+
+ if (r.y > CETRIS_BOARD_Y - 1)
+ return -1;
+
+ if (g->board[r.x][r.y].occupied && g->board[r.x][r.y].constant)
+ return -1;
+ }
+ }
+ }
+ return 1;
+}
+*/
diff --git a/core/include/cetris.h b/core/include/cetris.h
index e41abdf..9e3cf83 100644
--- a/core/include/cetris.h
+++ b/core/include/cetris.h
@@ -6,14 +6,18 @@
#include "types.h"
#define CETRIS_BOARD_X 10
-#define CETRIS_BOARD_Y 43
-#define CETRIS_BOARD_VISABLE 23
+#define CETRIS_BOARD_Y 20
+#define CETRIS_INITIAL_X 3
+#define CETRIS_INITIAL_Y 0
+#define CETRIS_INITIAL_Y_OFFSET 2
+//#define CETRIS_BOARD_VISABLE 21
#define CETRIS_HZ 60
#define CETRIS_DAS_DELAY 11
#define CETRIS_DAS_PERIOD 3
#define CETRIS_DROP_PERIOD 2
#define CETRIS_LINE_CLEAR_DELAY 40
+#define CETRIS_LOCK_DELAY 40
#define CETRIS_WAIT_ON_CLEAR 0
typedef enum {
@@ -43,12 +47,14 @@ struct tetrimino {
rstate r;
color c;
piece_matrix m;
+ u8 ghost_y;
vec2 pos;
u32 lock_tick;
};
typedef struct {
bool occupied;
+ bool ghost;
bool constant;
u32 remove_tick;
color c;
@@ -90,7 +96,7 @@ struct cetris_game {
};
void next_piece(struct cetris_game* g);
-void wipe_board(struct cetris_game* g);
+void update_board(struct cetris_game* g);
/* API PROTOTYPES FUNCTIONS */
diff --git a/core/include/matrix.h b/core/include/matrix.h
index 658906c..050a32e 100644
--- a/core/include/matrix.h
+++ b/core/include/matrix.h
@@ -6,10 +6,9 @@
#include "cetris.h"
extern const piece_matrix default_matrices[7];
-extern const vec2 basic_movements[4];
-void move_current(struct cetris_game* g, vec2 offset);
-void overlay_current_matrix(struct cetris_game* g);
+void move_current(struct cetris_game* g, input_t move);
void hard_drop(struct cetris_game* g);
void rotate_matrix(struct cetris_game* g, bool clockwise);
-i8 check_new_matrix(struct cetris_game* g, piece_matrix m);
+void set_matrix(struct cetris_game* g, piece_matrix *m);
+i8 check_matrix(struct cetris_game* g, piece_matrix *m);
diff --git a/core/include/types.h b/core/include/types.h
index 0431de1..3471f3c 100644
--- a/core/include/types.h
+++ b/core/include/types.h
@@ -20,9 +20,10 @@ typedef u8 piece_matrix[4][4];
typedef enum {
DOWN = 1,
- RIGHT = 2,
- LEFT = 3,
- ROTATE_CCW = 4,
- ROTATE_CW = 5,
- HARD_DROP = 6
+ USER_DOWN = 2,
+ RIGHT = 3,
+ LEFT = 4,
+ ROTATE_CCW = 5,
+ ROTATE_CW = 6,
+ HARD_DROP = 7
} input_t;
diff --git a/core/src/cetris.c b/core/src/cetris.c
index 5466327..a3f2ded 100644
--- a/core/src/cetris.c
+++ b/core/src/cetris.c
@@ -1,4 +1,3 @@
-#include <stdio.h>
#include <locale.h>
#include <time.h>
#include <string.h>
@@ -20,6 +19,7 @@
static void init_piece_queue(struct cetris_game* g);
static void shuffle_queue(struct cetris_game* g);
static void set_constants(struct cetris_game* g);
+static void add_score(struct cetris_game* g, u8 lines);
/* LEVEL DROP SPEED VALUES */
@@ -71,7 +71,8 @@ void init_piece_queue(struct cetris_game* g) {
memcpy(g->piece_queue[i].m, default_matrices[i], sizeof(piece_matrix));
g->piece_queue[i].r = INIT;
g->piece_queue[i].lock_tick = 0;
- g->piece_queue[i].pos = (vec2){3, 20}; // y = 22 - 1 for matrix
+ g->piece_queue[i].pos = (vec2){CETRIS_INITIAL_X, CETRIS_INITIAL_Y - CETRIS_INITIAL_Y_OFFSET};
+ g->piece_queue[i].ghost_y = 0;
}
}
@@ -88,16 +89,20 @@ void update_game_tick(struct cetris_game* g) {
if (g->game_over) return;
bool did_move = false;
- if (g->tick == g->next_drop_tick) {
- move_current(g, basic_movements[DOWN]);
+ if (g->tick >= g->next_drop_tick || !g->next_drop_tick) {
+ if (g->next_drop_tick) move_current(g, DOWN);
did_move = true;
- g->next_drop_tick = g->tick + level_drop_delay[g->level - 1];
+ if (g->level <= 20) {
+ g->next_drop_tick = g->tick + level_drop_delay[g->level - 1];
+ } else {
+ g->next_drop_tick = g->tick + level_drop_delay[19];
+ }
}
/* lock piece if it was hovering for CETRIS_LOCK_DELAY */
if (g->current.lock_tick && g->current.lock_tick <= g->tick) {
g->current.pos.y++;
- if (check_new_matrix(g, g->current.m) <= 0) {
+ if (check_matrix(g, &g->current.m) <= 0) {
next_piece(g);
}
g->current.pos.y--;
@@ -108,16 +113,18 @@ void update_game_tick(struct cetris_game* g) {
did_move = true;
}
- if (did_move) wipe_board(g);
+ if (did_move) update_board(g);
g->tick++;
}
void next_piece(struct cetris_game* g) {
set_constants(g);
+
+ g->next_drop_tick = 0;
g->current = g->piece_queue[g->current_index];
- if (check_new_matrix(g, g->current.m) <= 0) {
+ if (check_matrix(g, &g->current.m) <= 0) {
g->game_over = true;
}
g->current_index++;
@@ -136,34 +143,20 @@ void set_constants(struct cetris_game* g) {
}
}
-void add_score(struct cetris_game* g, u8 lines) {
- if (!g->tspin && !g->mini_tspin) {
- switch (lines) {
- case 1: g->score += 100 * g->level; break;
- case 2: g->score += 300 * g->level; break;
- case 3: g->score += 500 * g->level; break;
- case 4: g->score += 800 * g->level; break;
- }
- } else if (g->tspin) {
- switch (lines) {
- case 0: g->score += 400 * g->level; break;
- case 1: g->score += 800 * g->level; break;
- case 2: g->score += 1200 * g->level; break;
- case 3: g->score += 1600 * g->level; break;
- }
- g->tspin = false;
- } else if (g->mini_tspin) {
- switch (lines) {
- case 0: g->score += 100 * g->level; break;
- case 1: g->score += 200 * g->level; break;
- case 2: g->score += 400 * g->level; break;
+void make_ghosts(struct cetris_game* g) {
+ u8 orig_y = g->current.pos.y;
+ while (true) {
+ g->current.pos.y++;
+ if (check_matrix(g, &g->current.m) <= 0) {
+ g->current.ghost_y = g->current.pos.y - 1;
+ g->current.pos.y = orig_y;
+ break;
}
- g->mini_tspin = false;
}
}
-void wipe_board(struct cetris_game* g) {
- uint32_t lines_cleared = 0;
+void update_board(struct cetris_game* g) {
+ u8 lines_cleared = 0;
for (u8 y = 0; y < CETRIS_BOARD_Y; y++) {
bool clear_line = true;
for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
@@ -171,34 +164,60 @@ void wipe_board(struct cetris_game* g) {
memset(&g->board[x][y], 0, sizeof(slot));
}
- if (g->board[x][y].remove_tick && g->board[x][y].remove_tick <= g->tick) {
- memset(&g->board[x][y], 0, sizeof(slot));
- for (i8 s = y - 1; s >= 0; s--) {
- g->board[x][s + 1] = g->board[x][s];
- }
- }
-
- if (!g->board[x][y].occupied || g->board[x][y].remove_tick > 0) {
+ if (!g->board[x][y].occupied || g->board[0][y].remove_tick > 0) {
clear_line = false;
}
}
- if (clear_line) {
- lines_cleared++;
- for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
- g->board[x][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY;
+ // remove tick only tracked on first block of line
+ if (g->board[0][y].remove_tick && g->board[0][y].remove_tick <= g->tick) {
+ for (i8 s = y - 1; s >= 0; s--) {
+ for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
+ g->board[x][s + 1] = g->board[x][s];
+ }
}
+ lines_cleared++;
}
+ if (clear_line) g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY;
}
- overlay_current_matrix(g);
+ make_ghosts(g);
+ set_matrix(g, &g->current.m);
assert(lines_cleared <= 4);
- if (lines_cleared > 0) {
+ if (lines_cleared > 0 || g->tspin || g->mini_tspin) {
add_score(g, lines_cleared);
if (lines_cleared > 0) {
g->lines += lines_cleared;
- if (g->lines >= (g->level * 10) && g->level <= 20) g->level++;
+ if (g->lines >= (g->level * 10)) g->level++;
+ }
+ }
+}
+
+/* SCORE FUNCTIONS */
+
+void add_score(struct cetris_game* g, u8 lines) {
+ if (!g->tspin && !g->mini_tspin) {
+ switch (lines) {
+ case 1: g->score += 100 * g->level; break;
+ case 2: g->score += 300 * g->level; break;
+ case 3: g->score += 500 * g->level; break;
+ case 4: g->score += 800 * g->level; break;
}
+ } else if (g->tspin) {
+ switch (lines) {
+ case 0: g->score += 400 * g->level; break;
+ case 1: g->score += 800 * g->level; break;
+ case 2: g->score += 1200 * g->level; break;
+ case 3: g->score += 1600 * g->level; break;
+ }
+ g->tspin = false;
+ } else if (g->mini_tspin) {
+ switch (lines) {
+ case 0: g->score += 100 * g->level; break;
+ case 1: g->score += 200 * g->level; break;
+ case 2: g->score += 400 * g->level; break;
+ }
+ g->mini_tspin = false;
}
}
@@ -210,7 +229,8 @@ void move_piece(struct cetris_game* g, input_t move) {
case LEFT:
case RIGHT:
case DOWN:
- move_current(g, basic_movements[move]);
+ case USER_DOWN:
+ move_current(g, move);
break;
case HARD_DROP:
hard_drop(g);
@@ -231,5 +251,5 @@ void stop_holding(struct cetris_game* g, input_t move) {
if (move == RIGHT || move == LEFT) {
g->das_move_tick = 0;
g->das_repeat = 0;
- } else if (move == DOWN) g->down_move_tick = 0;
+ } else if (move == USER_DOWN) g->down_move_tick = 0;
}
diff --git a/core/src/input.c b/core/src/input.c
index edcd450..2904158 100644
--- a/core/src/input.c
+++ b/core/src/input.c
@@ -15,7 +15,7 @@ bool handle_inputs(struct cetris_game* g) {
}
}
- if (g->held_moves[DOWN] && !g->down_move_tick) {
+ if (g->held_moves[USER_DOWN] && !g->down_move_tick) {
g->down_move_tick = g->tick + CETRIS_DROP_PERIOD;
}
@@ -24,14 +24,14 @@ bool handle_inputs(struct cetris_game* g) {
if (g->held_moves[RIGHT]) {
if (g->prev_das_move == RIGHT || g->das_repeat == 0) g->das_repeat++;
else g->das_repeat = 0;
- move_current(g, basic_movements[RIGHT]);
+ move_current(g, RIGHT);
g->prev_das_move = RIGHT;
}
if (g->held_moves[LEFT]) {
if (g->prev_das_move == LEFT || g->das_repeat == 0) g->das_repeat++;
else g->das_repeat = 0;
- move_current(g, basic_movements[LEFT]);
+ move_current(g, LEFT);
g->prev_das_move = LEFT;
}
@@ -40,12 +40,12 @@ bool handle_inputs(struct cetris_game* g) {
}
if (g->down_move_tick && g->tick >= g->down_move_tick) {
- if (g->held_moves[DOWN]) {
- move_current(g, basic_movements[DOWN]);
+ if (g->held_moves[USER_DOWN]) {
+ move_current(g, USER_DOWN);
+ did_move = true;
}
g->down_move_tick = 0;
- did_move = true;
}
return did_move;
}
diff --git a/core/src/matrix.c b/core/src/matrix.c
index 265fe05..86e9ad2 100644
--- a/core/src/matrix.c
+++ b/core/src/matrix.c
@@ -84,36 +84,58 @@ const piece_matrix default_matrices[7] = {
/* MATRIX MODIFICATION */
-const vec2 basic_movements[4] = {
- {0, 0}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, RIGHT, LEFT
+const vec2 basic_movements[5] = {
+ {0, 0}, {0, 1}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, USER_DOWN, RIGHT, LEFT
};
-void move_current(struct cetris_game* g, vec2 offset) {
+void move_current(struct cetris_game* g, input_t move) {
if (g->game_over) return;
- g->current.pos.y += offset.y;
- g->current.pos.x += offset.x;
+ g->current.pos.y += basic_movements[move].y;
+ g->current.pos.x += basic_movements[move].x;
- int32_t check = check_new_matrix(g, g->current.m);
+ i8 check = check_matrix(g, &g->current.m);
if (check <= 0) {
- g->current.pos.y -= offset.y;
- g->current.pos.x -= offset.x;
+ g->current.pos.y -= basic_movements[move].y;
+ g->current.pos.x -= basic_movements[move].x;
- if (check == -1 && g->current.lock_tick == 0) {
- g->current.lock_tick = g->tick + 30;
+ if (move == USER_DOWN) g->score++;
+ if (move == DOWN && check == -1 && !g->current.lock_tick) {
+ g->current.lock_tick = g->tick + CETRIS_LOCK_DELAY;
}
}
- wipe_board(g);
+ update_board(g);
}
-void overlay_current_matrix(struct cetris_game* g) {
- for (uint32_t y = 0; y < 4; y++) {
- for (uint32_t x = 0; x < 4; x++) {
+i8 check_matrix(struct cetris_game* g, piece_matrix *m) {
+ for (i8 y = 0; y < 4; y++) {
+ for (i8 x = 0; x < 4; x++) {
vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
- if (g->current.m[y][x]) {
- g->board[r.x][r.y].occupied = 1;
- g->board[r.x][r.y].c = g->current.c;
+ if (r.y < 0) continue;
+ if ((*m)[y][x]) {
+ if (r.x >= CETRIS_BOARD_X || r.x < 0) return 0;
+ if (r.y >= CETRIS_BOARD_Y) return -1;
+ if (g->board[r.x][r.y].occupied &&
+ g->board[r.x][r.y].constant) return -1;
+ }
+ }
+ }
+ return 1;
+}
+
+void set_matrix(struct cetris_game *g, piece_matrix *m) {
+ for (i8 y = 0; y < 4; y++) {
+ for (i8 x = 0; x < 4; x++) {
+ vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
+ if ((*m)[y][x]) {
+ if (r.y >= 0) {
+ g->board[r.x][r.y].occupied = true;
+ g->board[r.x][r.y].c = g->current.c;
+ }
+ if (g->current.ghost_y + y >= 0) {
+ g->board[r.x][g->current.ghost_y + y].ghost = true;
+ }
}
}
}
@@ -127,17 +149,16 @@ void hard_drop(struct cetris_game* g) {
while (!drop) {
g->current.pos.y++;
drop_count++;
- i8 check = check_new_matrix(g, g->current.m);
- if (check <= 0) {
+ if (check_matrix(g, &g->current.m) <= 0) {
g->current.pos.y--;
drop_count--;
drop = true;
}
}
- g->score += 2 * drop_count; // 2 score for each harddrop cell
+ g->score += 2 * drop_count; // 2 score for each hard-drop'd cell
- wipe_board(g);
+ update_board(g);
next_piece(g);
}
@@ -145,7 +166,7 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) {
if (g->game_over) return;
if (g->current.t == O) return;
- rstate next;
+ rstate next = 0;
u8 wall_kick = 0;
switch (g->current.r) {
case INIT:
@@ -212,7 +233,7 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) {
}
g->current.pos.x += kick.x;
g->current.pos.y += kick.y;
- if (check_new_matrix(g, m) > 0) {
+ if (check_matrix(g, &m) > 0) {
set_current = true;
if (i > 0) did_kick = true;
break;
@@ -223,47 +244,28 @@ void rotate_matrix(struct cetris_game* g, bool clockwise) {
}
if (set_current) {
+
/* check for tspin */
if (g->current.t == T) {
- u8 did_tspin = 1;
- for (u8 i = 0; i < 4; i++) {
+ bool did_tspin = true;
+ for (int i = 1; i < 5; i++) {
g->current.pos.x += basic_movements[i].x;
g->current.pos.y += basic_movements[i].y;
- if (check_new_matrix(g, m) == 1)
- did_tspin = 0;
+ if (check_matrix(g, &m) == 1) did_tspin = false;
g->current.pos.x -= basic_movements[i].x;
g->current.pos.y -= basic_movements[i].y;
}
if (did_tspin) {
- if (did_kick) g->mini_tspin = 1;
- else g->tspin = 1;
+ if (did_kick) g->mini_tspin = true;
+ else g->tspin = true;
}
}
g->current.r = next;
memcpy(g->current.m, m, sizeof(piece_matrix));
- wipe_board(g);
+ update_board(g);
}
}
-
-i8 check_new_matrix(struct cetris_game* g, piece_matrix m) {
- for (u8 x = 0; x < 4; x++) {
- for (u8 y = 0; y < 4; y++) {
- vec2 r = (vec2){g->current.pos.x + x, g->current.pos.y + y};
- if (m[y][x]) {
- if (r.x > CETRIS_BOARD_X - 1 || r.x < 0)
- return 0;
-
- if (r.y > CETRIS_BOARD_Y - 1 || r.y < 0)
- return -1;
-
- if (g->board[r.x][r.y].occupied && g->board[r.x][r.y].constant)
- return -1;
- }
- }
- }
- return 1;
-}
diff --git a/core/src/test.c b/core/src/test.c
index e9ce23e..7db2fe5 100644
--- a/core/src/test.c
+++ b/core/src/test.c
@@ -59,9 +59,9 @@ void apply_test_board(struct cetris_game* g, enum tests t) {
default:
return;
}
- for (u8 y = CETRIS_BOARD_VISABLE; y < CETRIS_BOARD_Y; y++) {
+ for (u8 y = 0; y < CETRIS_BOARD_Y; y++) {
for (u8 x = 0; x < 10; x++) {
- if ((*board)[y - CETRIS_BOARD_VISABLE][x]) {
+ if ((*board)[y][x]) {
g->board[x][y].occupied = 1;
g->board[x][y].constant = 1;
g->board[x][y].c = COLOR_I;