commit c3e7299cb951690a1f9db33d1d6b83d1efb43b5d
parent 39fe329a074e151723156bcc186d6d8d15e0da58
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Sun, 19 Jun 2022 19:29:56 +0200
General improvement
- Better error checking
- Better program termination
- Specify default game values at runtime
- Windows bug fixing
Diffstat:
8 files changed, 78 insertions(+), 75 deletions(-)
diff --git a/include/display.h b/include/display.h
@@ -77,8 +77,8 @@ struct imenu_T {
int input(WINDOW *win, char *buffer, int size, input_f crit);
-int display_start(void);
-int display_stop(void);
+void display_start(void);
+void display_stop(void);
void display_menu(window_T wind, char *name, struct menu_T *items, int size,
int title);
diff --git a/include/file.h b/include/file.h
@@ -10,7 +10,7 @@
#include "display.h"
-int file_setup(void);
+void file_setup(void);
void load_files(void);
void free_files(void);
int file_select_extension(char *ext, char ***buffer);
diff --git a/include/pattern.h b/include/pattern.h
@@ -8,7 +8,7 @@
#ifndef PATTERN_H
#define PATTERN_H
-#include "stdlib.h"
+#include <stdlib.h>
/**
* @brief Structure representing one cell pattern to be used in the help menu
diff --git a/include/utils.h b/include/utils.h
@@ -8,7 +8,10 @@
#ifndef UTILS_H
#define UTILS_H
-#include "display.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <curses.h>
/// maximum of the two numbers
#define MAX(a, b) ((a > b) ? a : b)
@@ -32,20 +35,22 @@
#define UNICODE 1
#endif
+static void err(char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
/// Check for memory error, and abort
#define MEM_CHECK(x) \
- if ((x) == NULL) { \
- display_stop(); \
- printf("MEM ERROR"); \
- abort(); \
- }
+ if ((x) == NULL) \
+ err("MEMORY ERROR");
/// Check for file error, and abort
#define FILE_CHECK(x) \
- if ((x) == NULL) { \
- display_stop(); \
- printf("FILE ERROR"); \
- abort(); \
- }
+ if ((x) == NULL) \
+ err("MEMORY ERROR");
#endif
diff --git a/src/display.c b/src/display.c
@@ -296,10 +296,14 @@ redraw:;
* selected while compiling
*/
void curses_start(void) {
- initscr();
+ if (initscr() == NULL)
+ err("Fatal Error: initscr()");
+
window_settings(stdscr);
- start_color();
+ if (!has_colors() || start_color() != OK)
+ err("Fatal Error: Terminal does not support colors");
+
use_default_colors();
curs_set(0);
@@ -357,25 +361,17 @@ void handle_winch(int sig) {
/**
* @brief Start ncurses display and export MAIN_w
*/
-int display_start(void) {
+void display_start(void) {
curses_start();
MAIN_w = window_init(window_new());
-
-#ifdef _WIN32
- resize_term(0, 0);
- handle_winch(10);
-#endif
-
- return 1;
}
/**
* @brief Stop ncurses display and cleanup
*/
-int display_stop(void) {
+void display_stop(void) {
window_free(MAIN_w);
endwin();
- return 1;
}
/**
diff --git a/src/file.c b/src/file.c
@@ -5,10 +5,10 @@
* @brief This file contains functions for handling save files
*
* This file aims to provide a simple interface for interacting with the
- * file system on Linux and Windows systems. After proper game directory has been
- * selected, functions implemented here will read the list of files, filter them
- * based on the extension, create new files for storing a whole game or just a
- * pattern.
+ * file system on Linux and Windows systems. After proper game directory has
+ * been selected, functions implemented here will read the list of files, filter
+ * them based on the extension, create new files for storing a whole game or
+ * just a pattern.
*/
#include <dirent.h>
@@ -46,7 +46,7 @@ int DirectoryExists(const char *path) {
* @brief Try to change the directory to SETTINGS_DIR, if it doesn't exist
* create it. Return 0 on failure.
*/
-int file_setup(void) {
+void file_setup(void) {
char *dir;
MEM_CHECK(dir = malloc(PATH_MAX * sizeof(char)));
@@ -59,17 +59,17 @@ int file_setup(void) {
if (!DirectoryExists(dir)) {
printf("Directory %s does not exists; Trying to create it...\n", dir);
- if (MAKE_DIR(dir) != 0) {
- printf("Cannot create the directory\n");
- return 0;
- }
+ if (MAKE_DIR(dir) != 0)
+ err("Cannot create the directory %s", dir);
}
if (chdir(dir) != 0) {
printf("Cannot change the directory\n");
- return 0;
+ if (MAKE_DIR(dir) != 0)
+ err("Cannot change directory to %s", dir);
}
- return 1;
+
+ free(dir);
}
typedef struct file_T *file_T;
@@ -95,8 +95,10 @@ file_T file_new(char *name) {
file_T f;
MEM_CHECK(f = calloc(1, sizeof(*f)));
- if (name != NULL)
- MEM_CHECK(f->name = strdup(name));
+ if (name != NULL) {
+ MEM_CHECK(f->name = malloc((strlen(name) + 1) * sizeof(char)));
+ strcpy(f->name, name);
+ }
return f;
}
@@ -275,7 +277,7 @@ void file_save_pattern(char *name, int index) {
FILE *f;
char *fname;
- MEM_CHECK(fname = malloc((strlen(name) + 5) * sizeof(char)));
+ MEM_CHECK(fname = malloc((strlen(name) + 6) * sizeof(char)));
sprintf(fname, "%s.part", name);
FILE_CHECK(f = fopen(fname, "w"));
diff --git a/src/game.c b/src/game.c
@@ -20,6 +20,11 @@
#include "utils.h"
#include "window.h"
+#define DEF_GEN_STEP 1
+#define DEF_SCREEN_STEP 1
+#define DEF_TIME_CONST 100
+#define DEF_TIME_STEP 1
+
#ifdef _WIN32
#define TIME_MOD 1
#else
@@ -58,8 +63,10 @@ int height, width;
static int win_height, win_width;
static int screen_offset_x, screen_offset_y;
static int cursor_offset_x, cursor_offset_y;
-static int wrap, gen = 0, gen_step = 1;
-static int play = 0, time_const = 100, time_step = 1;
+static int wrap, gen_step, screen_step;
+static int play, time_const, time_step;
+
+static unsigned gen;
#define y_at(y) y, screen_offset_y, height
#define x_at(x) x, screen_offset_x, width
@@ -183,10 +190,10 @@ void display_status(window_T wind) {
wmove(win, 1, 1);
wprintw(win, " %5s | ", play ? "play" : "pause");
- wprintw(win, wrap ? "Size: %dx%d | " : "Size: unlimited | ", height, width);
- wprintw(win, "Generation: %10d(+%d) | ", gen, gen_step);
+ wprintw(win, wrap ? "Size: %9dx%9d | " : "Size: unlimited | ", height, width);
+ wprintw(win, "Generation: %10u(+%d) | ", gen, gen_step);
wprintw(win, "dt: %4dms | ", time_const);
- wprintw(win, "Cursor: %4dx%-4d | ", cord(y_at(cursor_offset_y)),
+ wprintw(win, "Cursor: %10dx%10d | ", cord(y_at(cursor_offset_y)),
cord(x_at(cursor_offset_x)));
wrefresh(win);
}
@@ -288,6 +295,7 @@ int display_select(window_T wind) {
case 'q':
case 'Q':
flushinp();
+ ret_value = 1;
goto end;
}
flushinp();
@@ -299,8 +307,11 @@ int display_select(window_T wind) {
overlay(win, new);
}
end:;
+
+ if (UNICODE)
+ delwin(new);
+
nodelay(stdscr, 1);
- delwin(new);
return ret_value;
}
@@ -349,6 +360,10 @@ void game(int s_h, int s_w, int mode_index) {
window_T status_w, screen_w, game_w;
+ gen = 0;
+ gen_step = DEF_GEN_STEP, time_const = DEF_TIME_CONST;
+ time_step = DEF_TIME_STEP, screen_step = DEF_SCREEN_STEP;
+
reset_screen:
status_w = window_split(menu_w, 1, 3, 0, "Status", "Game");
screen_w = window_sibiling(status_w);
@@ -536,7 +551,6 @@ redraw:;
save_state();
goto reset_screen;
- break;
// lead pattern
case 'l':
@@ -544,27 +558,27 @@ redraw:;
window_unsplit(menu_w);
setPosition(cord(y_at(cursor_offset_y)), cord(x_at(cursor_offset_x)));
load_pattern();
+
save_state();
goto reset_screen;
- break;
// save game
case 'o':
case 'O':
window_unsplit(menu_w);
save();
+
save_state();
goto reset_screen;
- break;
// help menu
case 'h':
case 'H':
window_unsplit(menu_w);
display_patterns(menu_w);
+
save_state();
goto reset_screen;
- break;
// redraw screen
case 'r':
@@ -581,7 +595,7 @@ redraw:;
case KEY_END:
case KEY_HOME:
case KEY_LEFT:
- screen_offset_x--;
+ screen_offset_x -= screen_step;
screen_change = 1;
break;
case KEY_A3:
@@ -589,7 +603,7 @@ redraw:;
case KEY_NPAGE:
case KEY_PPAGE:
case KEY_RIGHT:
- screen_offset_x++;
+ screen_offset_x += screen_step;
screen_change = 1;
break;
}
@@ -600,7 +614,7 @@ redraw:;
case KEY_HOME:
case KEY_PPAGE:
case KEY_UP:
- screen_offset_y--;
+ screen_offset_y -= screen_step;
screen_change = 1;
break;
case KEY_C1:
@@ -608,7 +622,7 @@ redraw:;
case KEY_DOWN:
case KEY_END:
case KEY_NPAGE:
- screen_offset_y++;
+ screen_offset_y += screen_step;
screen_change = 1;
}
diff --git a/src/main.c b/src/main.c
@@ -17,8 +17,8 @@ window_T menu_w;
void settings(char *pass, int index) {
struct imenu_T imenu_items[] = {
- { "Number of rows", 6, isdigit, NULL},
- {"Number of columns", 6, isdigit, NULL},
+ { "Number of rows", 9, isdigit, NULL},
+ {"Number of columns", 9, isdigit, NULL},
};
int imenu_items_s = sizeof(imenu_items) / sizeof(struct imenu_T);
@@ -133,10 +133,7 @@ void help(char *pass, int index) {
display_patterns(menu_w);
}
-void exitp(char *pass, int index) {
- display_stop();
- exit(0);
-}
+void exitp(char *pass, int index) { exit(0); }
struct menu_T menu_items[] = {
{mode_select, "Start"},
@@ -149,26 +146,15 @@ int menu_items_s = sizeof(menu_items) / sizeof(struct menu_T);
int main(void) {
setlocale(LC_ALL, "");
+ atexit(display_stop);
- if (!file_setup()) {
- printf("File setup error\n");
- abort();
- }
-
- if (!display_start()) {
- printf("Couldn't start the display!\n");
- abort();
- }
+ file_setup();
+ display_start();
menu_w = MAIN_w;
while (TRUE) {
display_menu(menu_w, "Main menu", menu_items, menu_items_s, 1);
}
- if (!display_stop()) {
- printf("Couldn't stop the display!\n");
- abort();
- }
-
return 0;
}