-
Notifications
You must be signed in to change notification settings - Fork 0
/
ttrs_action.c
97 lines (84 loc) · 2.43 KB
/
ttrs_action.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <limits.h>
#include <ncurses.h>
#include <stdbool.h>
#include <string.h>
#include "tetris.h"
#include "ttrs_action.h"
#include "ttrs_display.h"
#include "ttrs_matrix.h"
#include "ttrs_mino.h"
static t_keyhook_func g_keyhooks[UCHAR_MAX + 1] = {0};
// clang-format off
#define MINO_DOWN(pos) (t_position){pos.row + 1, pos.col}
#define MINO_LEFT(pos) (t_position){pos.row, pos.col - 1}
#define MINO_RIGHT(pos) (t_position){pos.row, pos.col + 1}
// clang-format on
void init_keyhook_func_ptr_array(void)
{
g_keyhooks[DROP_KEY] = try_drop;
g_keyhooks[LEFT_KEY] = try_left;
g_keyhooks[RIGHT_KEY] = try_right;
g_keyhooks[SPIN_KEY] = try_spin;
// g_keyhooks[HARD_DROP_KEY] = hard_drop;
}
t_status try_drop(t_tetris *tetris, t_current_mino *current)
{
t_position moved_pos = MINO_DOWN(current->pos);
if (can_place_on_matrix(tetris->matrix, ¤t->mino, moved_pos)) {
current->pos = moved_pos;
return TETRIS_PLAY;
}
return TETRIS_LOCK_DOWN;
}
t_status try_left(t_tetris *tetris, t_current_mino *current)
{
t_position moved_pos = MINO_LEFT(current->pos);
if (can_place_on_matrix(tetris->matrix, ¤t->mino, moved_pos))
current->pos = moved_pos;
return TETRIS_PLAY;
}
t_status try_right(t_tetris *tetris, t_current_mino *current)
{
t_position moved_pos = MINO_RIGHT(current->pos);
if (can_place_on_matrix(tetris->matrix, ¤t->mino, moved_pos))
current->pos = moved_pos;
return TETRIS_PLAY;
}
t_status try_spin(t_tetris *tetris, t_current_mino *current)
{
t_current_mino spun_mino = *current;
spin_right(&spun_mino.mino);
if (can_place_on_matrix(tetris->matrix, &spun_mino.mino, spun_mino.pos)) {
*current = spun_mino;
}
return TETRIS_PLAY;
}
t_status hard_drop(t_tetris *tetris, t_current_mino *current)
{
while (can_place_on_matrix(tetris->matrix, ¤t->mino, MINO_DOWN(current->pos))) {
current->pos.row += 1;
}
return TETRIS_LOCK_DOWN;
}
static bool is_valid_key(int key)
{
if (key < 0 || key > UCHAR_MAX)
return false;
return g_keyhooks[key] != NULL;
}
t_status handle_key_input(t_tetris *tetris, t_current_mino *current)
{
int key = getch();
if (key != ERR && is_valid_key(key)) {
return g_keyhooks[key](tetris, current);
}
return TETRIS_PLAY;
}
t_status handle_auto_drop(t_tetris *tetris, t_current_mino *current)
{
if (is_time_to_drop(tetris->time.next_drop_time)) {
tetris->time.next_drop_time = generate_next_drop_time(tetris->time.interval);
return try_drop(tetris, current);
}
return TETRIS_PLAY;
}