#include <ncurses.h>
#include <stdio.h>
#define HEIGHT 25
#define WIDTH 80
#define INITIAL_DELAY 250
#define MIN_DELAY 50
#define MAX_DELAY 1000
#define DELAY_STEP 50
void read_board(int board[HEIGHT][WIDTH]) {
for (int row = 0; row < HEIGHT; row++) {
for (int column = 0; column < WIDTH; column++) {
scanf("%1d", &board[row][column]);
}
}
}
int count_neighbors(const int board[HEIGHT][WIDTH], int row, int column) {
int neighbors = 0;
for (int row_shift = -1; row_shift <= 1; row_shift++) {
for (int column_shift = -1; column_shift <= 1; column_shift++) {
if (row_shift != 0 || column_shift != 0) {
int neighbor_row = (row + row_shift + HEIGHT) % HEIGHT;
int neighbor_column = (column + column_shift + WIDTH) % WIDTH;
neighbors += board[neighbor_row][neighbor_column];
}
}
}
return neighbors;
}
void update_board(int board[HEIGHT][WIDTH]) {
int next[HEIGHT][WIDTH] = {0};
for (int row = 0; row < HEIGHT; row++) {
for (int column = 0; column < WIDTH; column++) {
int neighbors = count_neighbors(board, row, column);
if (neighbors == 3 || (board[row][column] == 1 && neighbors == 2)) {
next[row][column] = 1;
}
}
}
for (int row = 0; row < HEIGHT; row++) {
for (int column = 0; column < WIDTH; column++) {
board[row][column] = next[row][column];
}
}
}
void draw_border(void) {
mvaddch(0, 0, '+');
mvaddch(0, WIDTH + 1, '+');
mvaddch(HEIGHT + 1, 0, '+');
mvaddch(HEIGHT + 1, WIDTH + 1, '+');
for (int column = 1; column <= WIDTH; column++) {
mvaddch(0, column, '-');
mvaddch(HEIGHT + 1, column, '-');
}
for (int row = 1; row <= HEIGHT; row++) {
mvaddch(row, 0, '|');
mvaddch(row, WIDTH + 1, '|');
}
}
void draw_board(const int board[HEIGHT][WIDTH], int delay) {
clear();
draw_border();
for (int row = 0; row < HEIGHT; row++) {
for (int column = 0; column < WIDTH; column++) {
char symbol = ' ';
if (board[row][column] == 1) {
symbol = '#';
}
mvaddch(row + 1, column + 1, symbol);
}
}
if (LINES > HEIGHT + 2) {
mvprintw(HEIGHT + 2, 0, "Delay: %d ms | A: faster | Z: slower | SPACE: quit", delay);
}
refresh();
}
void play_game(int board[HEIGHT][WIDTH]) {
int delay = INITIAL_DELAY;
int running = 1;
nodelay(stdscr, TRUE);
while (running != 0) {
draw_board(board, delay);
napms(delay);
int key = getch();
if (key == ' ') {
running = 0;
} else {
if ((key == 'a' || key == 'A') && delay > MIN_DELAY) {
delay -= DELAY_STEP;
} else if ((key == 'z' || key == 'Z') && delay < MAX_DELAY) {
delay += DELAY_STEP;
}
update_board(board);
}
}
}
int main(void) {
int board[HEIGHT][WIDTH] = {0};
read_board(board);
freopen("/dev/tty", "r", stdin);
initscr();
cbreak();
noecho();
curs_set(0);
play_game(board);
endwin();
return 0;
}