#include #include #include #include #include #include #include #include #include #include #include struct Cell { bool state; bool new_state; }; static int g_num_rows = 40; static int g_num_columns = 60; static Cell* g_cells; static ui::Window* g_window; static Result fill_cells() { g_cells = (Cell*)TRY(calloc_impl(g_num_rows, g_num_columns * sizeof(Cell), false)); for (isize i = 0; i < (g_num_rows * g_num_columns); i++) { auto value = rand() % 2; g_cells[i].state = g_cells[i].new_state = value; } return {}; } static Cell& find_cell(int row, int column) { assert(row < g_num_rows); assert(column < g_num_columns); return g_cells[row * g_num_columns + column]; } static constexpr int BYTES_PER_PIXEL = sizeof(u32); static constexpr ui::Color activated_cell_color = ui::CYAN; static constexpr ui::Color deactivated_cell_color = ui::Color::from_rgb(40, 40, 40); static void draw_cells() { const int CELL_WIDTH = g_window->canvas().width / g_num_columns; const int CELL_HEIGHT = g_window->canvas().height / g_num_rows; auto canvas = g_window->canvas(); for (int i = 0; i < g_num_rows; i++) { for (int j = 0; j < g_num_columns; j++) { auto subcanvas = canvas.subcanvas(ui::Rect { j * CELL_WIDTH, i * CELL_HEIGHT, CELL_WIDTH, CELL_HEIGHT }); auto& cell = find_cell(i, j); ui::Color color = cell.state ? activated_cell_color : deactivated_cell_color; subcanvas.fill(color); } } g_window->update(); } static int find_neighbors(int row, int column) { int sum = 0; if (row > 0 && column > 0) sum += find_cell(row - 1, column - 1).state; if (row > 0) sum += find_cell(row - 1, column).state; if (row > 0 && (column + 1) < g_num_columns) sum += find_cell(row - 1, column + 1).state; if (column > 0) sum += find_cell(row, column - 1).state; if ((column + 1) < g_num_columns) sum += find_cell(row, column + 1).state; if ((row + 1) < g_num_rows && column > 0) sum += find_cell(row + 1, column - 1).state; if ((row + 1) < g_num_rows) sum += find_cell(row + 1, column).state; if ((row + 1) < g_num_rows && (column + 1) < g_num_columns) sum += find_cell(row + 1, column + 1).state; return sum; } static void next_generation() { for (int i = 0; i < g_num_rows; i++) { for (int j = 0; j < g_num_columns; j++) { auto& cell = find_cell(i, j); int neighbors = find_neighbors(i, j); if (!cell.state && neighbors == 3) cell.new_state = true; else if (cell.state && (neighbors < 2 || neighbors > 3)) cell.new_state = false; } } for (isize i = 0; i < (g_num_rows * g_num_columns); i++) g_cells[i].state = g_cells[i].new_state; } static void update() { next_generation(); draw_cells(); } Result luna_main(int argc, char** argv) { ui::App app; TRY(app.init(argc, argv)); g_window = TRY(ui::Window::create(ui::Rect { 200, 200, 600, 400 })); g_window->set_title("Game of Life"); app.set_main_window(g_window); TRY(fill_cells()); update(); auto timer = TRY(os::Timer::create_repeating(100, update)); return app.run(); }