gol

Implementation of Conway's Game of Life writen in C
git clone git://git.dimitrijedobrota.com/gol.git
Log | Files | Refs | README

commit 3db973191cc6ad64c2ddc07c303477c0c419c5f6
parent f10581d443ba92b50564adbe45ad54eb2cdaba8d
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Wed,  1 Jun 2022 01:29:08 +0200

Display game hooks onto the new logic interface

- Big performance improvement in game display
- On-demand cursor and board redraw
- Fix wrapping logic
- Expand logic interface and reface existing one

Diffstat:
Minclude/display.h | 11++++++-----
Minclude/logic.h | 13+++++++------
Minclude/utils.h | 4++++
Msrc/display.c | 334++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/logic.c | 94+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/main.c | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
6 files changed, 340 insertions(+), 203 deletions(-)

diff --git a/include/display.h b/include/display.h @@ -1,7 +1,6 @@ #ifndef DISPLAY_H #define DISPLAY_H -#include "logic.h" #include "window.h" extern window_T MAIN_w; @@ -21,7 +20,6 @@ struct imenu_T { }; extern int screen_offset_x, screen_offset_y; -extern int cursor_offset_x, cursor_offset_y; int input(WINDOW *win, char *buffer, int size, input_f crit); @@ -30,12 +28,15 @@ int display_stop(void); void display_menu(window_T wind, char *name, struct menu_T *items, int size); int display_imenu(window_T wind, struct imenu_T *items, int size); -void display_game(window_T wind, cell **mat, int h, int w, int ph, int pw); -void display_select(window_T wind, cell **mat, int w, int h); +void display_game(WINDOW *win, int h, int w, int ph, int pw, int redraw); +void display_select(window_T wind, int w, int h); void display_status(window_T wind, unsigned long int generation, int gen_step, int height, int wight, int play, int dt, int cursor_y, - int cursor_x); + int cursor_x, int expanded); +void display_cursor(WINDOW *win, int h, int w, int ph, int pw); void handle_winch(int sig); +void display_state_set(int i, int j, int val); + #endif diff --git a/include/logic.h b/include/logic.h @@ -5,12 +5,13 @@ extern char *evolution_names[]; extern int evolution_cells[]; extern int evolution_size; -int logic_init(int w, int h, int isWrapping); -int evolution_init(int index); -int do_evolution(int steps); -int logic_free(void); -void toggleAt(int i, int j) +int logic_init(int w, int h, int isWrapping); +int evolution_init(int index); +int do_evolution(int steps); +int logic_free(void); +int toggleAt(int i, int j); +int getAt(int i, int j); void deleteAt(int i, int j); -int getNext(int *row, int *col, int *value, int reset); +int getNext(int *row, int *col, int *value, int reset); #endif diff --git a/include/utils.h b/include/utils.h @@ -22,4 +22,8 @@ handle_winch(10); \ } #endif + +#define MAX_SCREEN_H 512 +#define MAX_SCREEN_W 1888 + #endif diff --git a/src/display.c b/src/display.c @@ -12,13 +12,218 @@ #define center_horizontal(y, n) wcenter_horizontal(MAIN_W, y, n); #define CHAR_BLANK " " +#define CHAR_CURSOR "<>" #define CHAR_CIRCLE "\u26AB" #define CHAR_SQUARE "\u2B1B" #define CHAR_SQUARED "\u2B1C" #define CHAR_CIRCLE_DOT "\u2299" +#define CHAR_ACTIVE CHAR_SQUARE + window_T MAIN_w = NULL; +#define y_at(y) (y + screen_offset_y + h) % h +#define x_at(x) (x + screen_offset_x + w) % w + +#define for_each_cell(start_i, end_i, start_j, end_j) \ + for (int i = start_i; i < end_i; i++) \ + for (int j = start_j; j < end_j; j++) + +#ifndef NO_UNICODE +#define print_cell(win, blank) \ + if (val) \ + waddstr(win, CHAR_ACTIVE); \ + else \ + waddstr(win, blank); +#else +#define print_cell(win, blank) waddstr(win, blank); +#endif + +// expects val to to be set with value at cordinates +#define mvprint_cell(win, i, j, color_offset, blank) \ + { \ + wmove(win, i + 1, j * 2 + 1); \ + wattrset(win, COLOR_PAIR(val + color_offset)); \ + print_cell(win, blank); \ + } + +#define print_cells(win, start_i, end_i, start_j, end_j, color_offset, blank) \ + for (int i = start_i; i < end_i; i++) { \ + wmove(win, i + 1, 1 + start_j * 2); \ + for (int j = start_j; j < end_j; j++) { \ + int val = getAt(y_at(i), x_at(j)); \ + wattrset(win, COLOR_PAIR(val + color_offset)); \ + print_cell(win, blank); \ + } \ + } + +int screen_offset_x, screen_offset_y; +int cursor_offset_x, cursor_offset_y; + +int get_screen_position(int value, int screen_offset, int screen_size, + int board_size) { + int overshoot = screen_offset + screen_size - board_size; + if (overshoot > 0) { + if (value < screen_offset && value > overshoot) + return -1; + if (value >= screen_offset) { + return value - screen_offset; + } else { + return value + screen_size - overshoot; + } + } else { + if (value < screen_offset || value > screen_offset + screen_size) + return -1; + return value - screen_offset; + } +} + +void display_game(WINDOW *win, int h, int w, int ph, int pw, int redraw) { + werase(win); + + wattrset(win, COLOR_PAIR(0)); + box(win, ACS_VLINE, ACS_HLINE); + + int row, col, val; + getNext(&row, &col, &val, 1); + while (getNext(&row, &col, &val, 0)) { + wattrset(win, COLOR_PAIR(val + 2)); + + if ((row = get_screen_position(row, screen_offset_y, ph, h)) == -1) + continue; + if ((col = get_screen_position(col, screen_offset_x, pw, w)) == -1) + continue; + + mvprint_cell(win, row, col, 2, CHAR_BLANK); + } + + wrefresh(win); +} + +void display_cursor(WINDOW *win, int h, int w, int ph, int pw) { + static int prev_x = 0, prev_y = 0; + int val; + + val = getAt(y_at(prev_y), x_at(prev_x)); + mvprint_cell(win, prev_y, prev_x, 2, CHAR_BLANK); + + val = getAt(y_at(cursor_offset_y), x_at(cursor_offset_x)); + mvprint_cell(win, cursor_offset_y, cursor_offset_x, 5, CHAR_CURSOR); + wrefresh(win); + + prev_y = cursor_offset_y; + prev_x = cursor_offset_x; +} + +void display_select(window_T wind, int w, int h) { + int current_offset_y = cursor_offset_y; + int current_offset_x = cursor_offset_x; + +redraw:; + int CLINES = LINES, CCOLS = COLS; + WINDOW *new = WINDOW_new(wind); + WINDOW *win = window_win(wind); + + overlay(win, new); + wrefresh(new); + + int ph = window_height(wind), pw = window_wight(wind) / 2; + nodelay(stdscr, 0); + while (TRUE) { + int start_i = MIN(cursor_offset_y, current_offset_y); + int end_i = MAX(cursor_offset_y, current_offset_y); + int start_j = MIN(cursor_offset_x, current_offset_x); + int end_j = MAX(cursor_offset_x, current_offset_x); + + print_cells(new, start_i, end_i + 1, start_j, end_j + 1, 8, CHAR_BLANK); + wrefresh(new); + + if (is_term_resized(CLINES, CCOLS)) { + flushinp(); + delwin(new); + HANDLE_RESIZE; + ph = window_height(wind), pw = window_wight(wind) / 2; + display_game(win, w, h, ph, pw, 1); + goto redraw; + } + + int c = getch(); + switch (c) { + // offset selection + case 'w': + case 'W': + current_offset_y--; + break; + case 's': + case 'S': + current_offset_y++; + break; + case 'a': + case 'A': + current_offset_x--; + break; + case 'd': + case 'D': + current_offset_x++; + break; + + // delete selection + case 'x': + case 'X': + for_each_cell(start_i, end_i + 1, start_j, end_j + 1) + deleteAt(y_at(i), x_at(j)); + goto end; + + // toggle selection + case 't': + case 'T': + for_each_cell(start_i, end_i + 1, start_j, end_j + 1) + toggleAt(y_at(i), x_at(j)); + goto end; + + // confirm and save slection + case '\n': + save_pattern(); + goto end; + + // quit + case 27: + case 'q': + case 'Q': + goto end; + defalut: + flushinp(); + continue; + } + flushinp(); + + CLAMP(current_offset_y, 0, ph - 1); + CLAMP(current_offset_x, 0, pw - 1); + + wclear(new); + overlay(win, new); + } +end:; + nodelay(stdscr, 1); + delwin(new); + return; +} + +void display_status(window_T wind, unsigned long int gen, int gen_step, + int height, int wight, int play, int dt, int cursor_y, + int cursor_x, int expanded) { + WINDOW *win = window_win(wind); + + wmove(win, 1, 1); + wprintw(win, " | %5s | ", play ? "play" : "pause"); + wprintw(win, "Size: %dx%d | ", height, wight); + wprintw(win, "Generation: %10lu(+%d) | ", gen, gen_step); + wprintw(win, "dt: %4dms | ", dt); + wprintw(win, "Cursor: %4dx%-4d | ", cursor_y, cursor_x); + wprintw(win, "Expanded: %4d | ", expanded); + wrefresh(win); +} + int input(WINDOW *win, char *buffer, int size, input_f crit) { int CLINES = LINES, CCOLS = COLS; int ch, read = strlen(buffer); @@ -167,135 +372,6 @@ redraw:; } } -#define y_at(y) (y + screen_offset_y + h) % h + 1 -#define x_at(x) (x + screen_offset_x + w) % w + 1 -#define at(y, x) mat[y_at(y)][x_at(x)] -#define at_offset(off) mat[y_at(off##_y)][x_at(off##_x)] - -#ifndef NO_UNICODE -#define print_cell(win, k, l, blank) \ - if (at(k, l)) \ - waddstr(win, CHAR_CIRCLE); \ - else \ - waddstr(win, blank); -#else -#define print_cell(win, i, j, blank) waddstr(win, blank); -#endif - -#define print_cells(win, start_i, end_i, start_j, end_j, color_offset, blank) \ - for (int i = start_i; i < end_i; i++) { \ - wmove(win, i + 1, 1 + start_j * 2); \ - for (int j = start_j; j < end_j; j++) { \ - wattrset(win, COLOR_PAIR((mat[y_at(i)][x_at(j)]) + color_offset)); \ - print_cell(win, i, j, blank); \ - } \ - } - -int screen_offset_x, screen_offset_y; -int cursor_offset_x, cursor_offset_y; - -void display_game(window_T wind, cell **mat, int h, int w, int ph, int pw) { - WINDOW *win = window_win(wind); -#ifdef _WIN32 - window_clear(wind); -#endif - print_cells(win, 0, ph, 0, pw, 2, CHAR_BLANK); - - wmove(win, cursor_offset_y + 1, cursor_offset_x * 2 + 1); - wattrset(win, COLOR_PAIR(at_offset(cursor_offset) + 5)); - - print_cell(win, cursor_offset_y, cursor_offset_x, "<>"); - - wrefresh(win); -} - -void display_select(window_T wind, cell **mat, int w, int h) { - int current_offset_y = cursor_offset_y; - int current_offset_x = cursor_offset_x; - -redraw:; - int CLINES = LINES, CCOLS = COLS; - WINDOW *new = WINDOW_new(wind); - WINDOW *win = window_win(wind); - - overlay(win, new); - wrefresh(new); - - int ph = window_height(wind), pw = window_wight(wind) / 2; - nodelay(stdscr, 0); - while (TRUE) { - int start_i = MIN(cursor_offset_y, current_offset_y); - int end_i = MAX(cursor_offset_y, current_offset_y); - int start_j = MIN(cursor_offset_x, current_offset_x); - int end_j = MAX(cursor_offset_x, current_offset_x); - - print_cells(new, start_i, end_i + 1, start_j, end_j + 1, 8, CHAR_BLANK); - wrefresh(new); - - if (is_term_resized(CLINES, CCOLS)) { - flushinp(); - delwin(new); - HANDLE_RESIZE; - ph = window_height(wind), pw = window_wight(wind) / 2; - display_game(wind, mat, w, h, ph, pw); - goto redraw; - } - - int c = getch(); - switch (c) { - // offset selection - case 'w': - case 'W': - current_offset_y--; - break; - case 's': - case 'S': - current_offset_y++; - break; - case 'a': - case 'A': - current_offset_x--; - break; - case 'd': - case 'D': - current_offset_x++; - break; - case '\n': - save_pattern(); - - // quit - case 27: - case 'q': - case 'Q': - nodelay(stdscr, 1); - delwin(new); - return; - defalut: - continue; - } - - CLAMP(current_offset_y, 0, ph - 1); - CLAMP(current_offset_x, 0, pw - 1); - - wclear(new); - overlay(win, new); - } -} - -void display_status(window_T wind, unsigned long int gen, int gen_step, - int height, int wight, int play, int dt, int cursor_y, - int cursor_x) { - WINDOW *win = window_win(wind); - - wmove(win, 1, 1); - wprintw(win, " | %5s | ", play ? "play" : "pause"); - wprintw(win, "Size: %dx%d | ", height, wight); - wprintw(win, "Generation: %10lu(+%d) | ", gen, gen_step); - wprintw(win, "dt: %4dms | ", dt); - wprintw(win, "Cursor: %4dx%-4d | ", cursor_y, cursor_x); - wrefresh(win); -} - void curses_start(void) { initscr(); window_settings(stdscr); diff --git a/src/logic.c b/src/logic.c @@ -20,11 +20,14 @@ int WIDTH, HEIGHT; int cells_size; int temp_size; int counter; +int isExpanding; char *evolution_names[] = {"Normal", "CoExsistance", "Predator", "Virus", "Unknown"}; int evolution_cells[] = {2, 3, 3, 3, 3}; int evolution_size = 5; +int toggle_mod = 2; + static void (*evolve)(void); static void (*addToCells)(int i, int j, int value); @@ -78,28 +81,30 @@ void addToCellsWrap(int i, int j, int value) { break; } - for (int k = (i - 1 + HEIGHT) % HEIGHT; k <= (i + 1 + HEIGHT) % HEIGHT; k++) { - for (int l = (j - 1 + WIDTH) % WIDTH; l <= (j + 1 + WIDTH) % WIDTH; l++) { + for (int k = i - 1; k <= i + 1; k++) { + for (int l = j - 1; l <= j + 1; l++) { + int a = (k + HEIGHT) % HEIGHT; + int b = (l + WIDTH) % WIDTH; for (int m = 0; m < temp_size; m++) - if (temp_cells[m].row == k && temp_cells[m].col == l) { + if (temp_cells[m].row == a && temp_cells[m].col == b) { temp_cells[m].val += mod; - if (k == i && l == j) { + if (a == i && b == j) { temp_cells[m].val -= mod; temp_cells[m].val += value; } goto Kontinue; } - if (k == i && l == j) { + if (a == i && b == j) { temp_cells[temp_size].val = value; - temp_cells[temp_size].row = k; - temp_cells[temp_size].col = l; + temp_cells[temp_size].row = a; + temp_cells[temp_size].col = b; temp_size++; continue; } temp_cells[temp_size].val = mod; - temp_cells[temp_size].row = k; - temp_cells[temp_size].col = l; + temp_cells[temp_size].row = a; + temp_cells[temp_size].col = b; temp_size++; Kontinue: continue; @@ -302,6 +307,26 @@ static void (*evolution_modes[])() = { static void (*addition_modes[])(int i, int j, int value) = {addToCellsNormal, addToCellsWrap}; +int shouldExpand(void) { + for (int i = 0; i < cells_size; i++) { + if (cells[i].row == 0 || cells[i].row == HEIGHT - 1 || cells[i].col == 0 || + cells[i].col == WIDTH - 1) { + return 1; + } + } + return 0; +} + +void expandMatrix(int size) { + WIDTH += 2 * size; + HEIGHT += 2 * size; + cells = realloc(cells, WIDTH * HEIGHT * sizeof(*cells)); + for (int cellIndex = 0; cellIndex < cells_size; cellIndex++) { + cells[cellIndex].row += size; + cells[cellIndex].col += size; + } +} + int do_evolution(int steps) { int times_resized = 0; counter = 0; @@ -310,8 +335,8 @@ int do_evolution(int steps) { temp_size = 0; temp_cells = calloc(temp_alloc, sizeof(*temp_cells)); if (!counter) { - if (shouldExpand()) { - expand_matrix(SIZE_TO_EXPAND); + if (isExpanding && shouldExpand()) { + expandMatrix(SIZE_TO_EXPAND); times_resized++; counter = SIZE_TO_EXPAND; } else { @@ -329,10 +354,9 @@ int do_evolution(int steps) { int logic_init(int w, int h, int isWrapping) { WIDTH = w; HEIGHT = h; - addToCells = addition_modes[0]; - if (isWrapping) { - addToCells = addition_modes[1]; - } + + addToCells = addition_modes[isWrapping]; + isExpanding = !isWrapping; cells = malloc(WIDTH * HEIGHT * sizeof(*cells)); return 1; @@ -340,38 +364,19 @@ int logic_init(int w, int h, int isWrapping) { int evolution_init(int index) { evolve = evolution_modes[index]; + toggle_mod = evolution_cells[index]; return 1; } -int shouldExpand(void) { - for (int i = 0; i < cells_size; i++) { - if (cells[i].row == 0 || cells[i].row == HEIGHT - 1 || cells[i].col == 0 || - cells[i].col == WIDTH - 1) { - return 1; - } - } - return 0; -} - -void expand_matrix(int size) { - WIDTH += 2 * size; - HEIGHT += 2 * size; - cells = realloc(cells, WIDTH * HEIGHT * sizeof(*cells)); - for (int cellIndex = 0; cellIndex < cells_size; cellIndex++) { - cells[cellIndex].row += size; - cells[cellIndex].col += size; - } -} - int logic_free(void) { free(cells); return 1; } -void toggleAt(int i, int j) { +int toggleAt(int i, int j) { for (int k = 0; k < cells_size; k++) { if (cells[k].row == i && cells[k].col == j) { - cells[k].val = (cells[k].val + 1) % 3; + cells[k].val = (cells[k].val + 1) % toggle_mod; if (cells[k].val == 0) { for (int t = k + 1; t < cells_size; t++) { cells[t - 1].val = cells[t].val; @@ -379,14 +384,16 @@ void toggleAt(int i, int j) { cells[t - 1].col = cells[t].col; } cells_size--; + return 0; // since the cell was deleted it's value is 0 } - return; + return cells[k].val; // only return value if it hasn't been deleted } } cells[cells_size].val = 1; cells[cells_size].row = i; cells[cells_size].col = j; cells_size++; + return 1; } void deleteAt(int i, int j) { @@ -403,6 +410,13 @@ void deleteAt(int i, int j) { } } +int getAt(int i, int j) { + for (int k = 0; k < cells_size; k++) + if (cells[k].row == i && cells[k].col == j) + return cells[k].val; + return 0; +} + int getNext(int *row, int *col, int *value, int reset) { static int index = 0; if (reset) { @@ -417,4 +431,5 @@ int getNext(int *row, int *col, int *value, int reset) { *col = cells[index].col; *value = cells[index].val; index++; -} -\ No newline at end of file + return 1; +} diff --git a/src/main.c b/src/main.c @@ -21,7 +21,6 @@ #endif extern window_T MAIN_w; -extern cell **mat; extern char *evolution_names[]; extern int evolution_cells[]; extern int evolution_size; @@ -32,15 +31,18 @@ int top_space = 5; void load_pattern(void); void save_pattern(void); -#define y_at(y) (y + screen_offset_y + h) % h + 1 -#define x_at(x) (x + screen_offset_x + w) % w + 1 +#define y_at(y) (y + screen_offset_y + h) % h +#define x_at(x) (x + screen_offset_x + w) % w extern int screen_offset_x, screen_offset_y; extern int cursor_offset_x, cursor_offset_y; +extern short int **mat; + void game(int h, int w, char *name, int ncells) { unsigned long int gen = 0; int gen_step = 1, play = 0, time_const = 100, time_step = 1; + int expanded; window_T status_w, screen_w, game_w; @@ -53,23 +55,56 @@ void game(int h, int w, char *name, int ncells) { clock_t start_t, end_t = 0, total_t; + screen_offset_x = screen_offset_y = 0; + + cursor_offset_y = window_height(game_w) / 2; + cursor_offset_x = window_wight(game_w) / 4; + redraw:; - int CLINES = LINES, CCOLS = COLS; - int ph = window_height(game_w), pw = window_wight(game_w) / 2; + int CLINES = LINES, CCOLS = COLS; + int ph = window_height(game_w), pw = window_wight(game_w) / 2; + WINDOW *game_W = window_win(game_w); + + window_clear(menu_w); + window_clear(screen_w); + window_clear(status_w); window_clear(game_w); + CLAMP(cursor_offset_y, 0, ph - 1); + CLAMP(cursor_offset_x, 0, pw - 1); + + display_game(game_W, h, w, ph, pw, 1); + display_cursor(game_W, h, w, ph, pw); + + int screen_change = 0; + int cursor_change = 0; + while (TRUE) { start_t = clock(); - display_status(status_w, gen, gen_step, h, w, play, time_const, - y_at(cursor_offset_y), x_at(cursor_offset_x)); - display_game(game_w, mat, h, w, ph, pw); - if (play) { - do_evolution(gen_step); + expanded = do_evolution(gen_step); + screen_change = 1; + + screen_offset_x += expanded; + screen_offset_y += expanded; gen += gen_step; } + display_status(status_w, gen, gen_step, h, w, play, time_const, + y_at(cursor_offset_y), x_at(cursor_offset_x), expanded); + + if (play || screen_change) { + display_game(game_W, h, w, ph, pw, 0); + screen_change = 0; + cursor_change = 1; + } + + if (cursor_change) { + display_cursor(game_W, h, w, ph, pw); + cursor_change = 0; + } + while ((total_t = (long int)(end_t - start_t)) < time_const * TIME_MOD) { refresh(); int c = getch(); @@ -85,7 +120,9 @@ redraw:; case 'l': case 'L': load_pattern(); + window_set_title(screen_w, name); + window_set_title(menu_w, NULL); goto redraw; break; @@ -119,37 +156,37 @@ redraw:; case 'w': case 'W': cursor_offset_y--; + cursor_change = 1; break; case 's': case 'S': cursor_offset_y++; + cursor_change = 1; break; case 'a': case 'A': cursor_offset_x--; + cursor_change = 1; break; case 'd': case 'D': cursor_offset_x++; + cursor_change = 1; break; // toggle cell case ' ': - mat[y_at(cursor_offset_y)][x_at(cursor_offset_x)] += 1; - mat[y_at(cursor_offset_y)][x_at(cursor_offset_x)] %= ncells; + toggleAt(y_at(cursor_offset_y), x_at(cursor_offset_x)); + cursor_change = 1; break; // visual selection case 'v': case 'V': - display_select(game_w, mat, h, h); + display_select(game_w, h, h); - // clear up the screen afterwards window_set_title(menu_w, NULL); - window_clear(menu_w); - window_clear(screen_w); - window_clear(status_w); - window_clear(game_w); + goto redraw; break; } } @@ -162,6 +199,7 @@ redraw:; case KEY_HOME: case KEY_LEFT: screen_offset_x--; + screen_change = 1; break; case KEY_A3: case KEY_C3: @@ -169,6 +207,7 @@ redraw:; case KEY_PPAGE: case KEY_RIGHT: screen_offset_x++; + screen_change = 1; break; } @@ -179,6 +218,7 @@ redraw:; case KEY_PPAGE: case KEY_UP: screen_offset_y--; + screen_change = 1; break; case KEY_C1: case KEY_C3: @@ -186,6 +226,7 @@ redraw:; case KEY_END: case KEY_NPAGE: screen_offset_y++; + screen_change = 1; } screen_offset_x = (screen_offset_x + w) % w; @@ -194,8 +235,8 @@ redraw:; CLAMP(cursor_offset_y, 0, ph - 1); CLAMP(cursor_offset_x, 0, pw - 1); - CLAMP(gen_step, 1, 10); - CLAMP(time_const, 1, 1000); + CLAMP(gen_step, 1, 100); + CLAMP(time_const, 0, 1000); if (is_term_resized(CLINES, CCOLS)) { flushinp(); @@ -210,8 +251,8 @@ redraw:; void settings(char *pass, int index) { struct imenu_T imenu_items[] = { - { "Number of rows", 4, isdigit, NULL}, - {"Number of columns", 4, isdigit, NULL}, + { "Number of rows", 6, isdigit, NULL}, + {"Number of columns", 6, isdigit, NULL}, }; int imenu_items_s = sizeof(imenu_items) / sizeof(struct imenu_T); @@ -223,7 +264,7 @@ void settings(char *pass, int index) { if (!row || !column) continue; - logic_init(column, row); + logic_init(column, row, 1); evolution_init(index); game(row, column, pass, evolution_cells[index]);