forked from maximecb/uvm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgameoflife.c
132 lines (108 loc) · 3.05 KB
/
gameoflife.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <uvm/syscalls.h>
#include <uvm/utils.h>
#include <stdlib.h>
#include <stdint.h>
#define FRAME_WIDTH 600
#define FRAME_HEIGHT 600
#define CELL_SIZE 4
#define NUM_ROWS 150
#define NUM_COLS 150
// RGBA pixels: 600 * 600
uint32_t frame_buffer[360_000];
// Current and next board
bool board[2][NUM_ROWS][NUM_COLS];
// Current generation counter
uint32_t gen_no = 0;
void draw_rect(int xmin, int ymin, int width, int height, u32 color)
{
for (int j = 0; j < height; ++j)
{
for (int i = 0; i < width; ++i)
{
u32* pix_ptr = frame_buffer + (FRAME_WIDTH) * (ymin + j) + (xmin + i);
*pix_ptr = color;
}
}
}
int get_cell(uint32_t board_idx, int row, int col)
{
return (int)board[board_idx][(uint32_t)row % NUM_ROWS][(uint32_t)col % NUM_COLS];
}
int count_neighbors(uint32_t board_idx, int row, int col)
{
int count = 0;
// Row above
count = count + get_cell(board_idx, row - 1, col - 1);
count = count + get_cell(board_idx, row - 1, col );
count = count + get_cell(board_idx, row - 1, col + 1);
// Middle row
count = count + get_cell(board_idx, row, col - 1);
count = count + get_cell(board_idx, row, col + 1);
// Row below
count = count + get_cell(board_idx, row + 1, col - 1);
count = count + get_cell(board_idx, row + 1, col );
count = count + get_cell(board_idx, row + 1, col + 1);
return count;
}
void update()
{
// Clear the screen
memset(frame_buffer, 0, sizeof(frame_buffer));
uint32_t prev_board = gen_no % 2;
uint32_t next_board = (gen_no + 1) % 2;
gen_no = gen_no + 1;
for (int row = 0; row < NUM_ROWS; ++row)
{
for (int col = 0; col < NUM_COLS; ++col)
{
int count = count_neighbors(prev_board, row, col);
int alive = get_cell(prev_board, row, col);
if (alive)
{
if (count < 2)
alive = 0;
else if (count > 3)
alive = 0;
}
else
{
if (count == 3)
alive = 1;
}
board[next_board][row][col] = alive;
if (alive)
{
draw_rect(
col * CELL_SIZE,
row * CELL_SIZE,
CELL_SIZE,
CELL_SIZE,
0x00_EE_00
);
}
}
}
window_draw_frame(0, frame_buffer);
}
void anim_callback()
{
u64 start_time = time_current_ms();
benchmark(update());
// Schedule a fixed rate update for the next frame (20fps)
fixed_rate_update(start_time, 1000 / 20, anim_callback);
}
void main()
{
window_create(FRAME_WIDTH, FRAME_HEIGHT, "Game of Life", 0);
// Randomly initialize the board
srand(time_current_ms());
for (int row = 0; row < NUM_ROWS; ++row)
{
for (int col = 0; col < NUM_COLS; ++col)
{
board[0][row][col] = rand() % 2;
}
}
time_delay_cb(0, anim_callback);
enable_event_loop();
}