#include "world.h" #include "game.h" #include #include #include #include int TIMEOUT = 100; void abort_game(const char* msg) { endwin(); puts(msg); exit(1); } void check_bounds(const char* tag, int x, int y) { char err[256]; if (x < 0 || x >= COLS) { snprintf(err, sizeof(err), "%s: x=%d out of screen (0,%d)", tag, x, COLS); abort_game(err); } if (y < 0 || y >= LINES) { snprintf(err, sizeof(err), "%s: y=%d out of screen (0,%d)", tag, y, LINES); abort_game(err); } } void clear_screen() { mvaddch(0, 0, ' '); for (int p = 1; p < COLS * LINES; p++) { addch(' '); } } void game_speed(int v) { if (v < 0) abort_game("negative speed?"); TIMEOUT = v; } void set_message(const char* msg, int x, int y) { int n = strlen(msg); for (int i = 0; i < n; i++) { check_bounds("set_message", x + i, y); set_cell(msg[i], x + i, y); } } void assert_message(int ok, const char* msg) { if (!ok) abort_game(msg); } void set_cell(int c, int x, int y) { check_bounds("set_cell", x, y); set_color_cell(c, x, y, COLOR_WHITE, COLOR_BLACK); } void set_color_cell(int c, int x, int y, short fg, short bg) { check_bounds("set_color_cell", x, y); if (has_colors()) { int pair = COLOR_COUNT * fg + bg; attron(COLOR_PAIR(pair)); mvaddch(y, x, c); attroff(COLOR_PAIR(pair)); } else { mvaddch(y, x, c); } } int world_run(void* (*init_game)(), int (*world_event)(struct event* e, void* g)) { void* game = init_game(); if (!game) return -1; timeout(TIMEOUT); struct event ev; memset(&ev, 0, sizeof(ev)); ev.height = LINES; ev.width = COLS; ev.type = EVENT_START; ev.time_ms = clock(); world_event(&ev, game); while (1) { memset(&ev, 0, sizeof(ev)); ev.height = LINES; ev.width = COLS; ev.key = getch(); if (ev.key == ERR) { ev.type = EVENT_TIMEOUT; } else if (ev.key == KEY_MOUSE) { ev.type = EVENT_MOUSE; MEVENT m; if (getmouse(&m) == OK) { ev.mouse_x = m.x; ev.mouse_y = m.y; if (m.bstate & BUTTON1_PRESSED) ev.mouse_left = 1; if (m.bstate & BUTTON2_PRESSED) ev.mouse_middle = 1; if (m.bstate & BUTTON3_PRESSED) ev.mouse_right = 1; } } else if (ev.key == KEY_RESIZE) { ev.type = EVENT_RESIZE; } else { ev.type = EVENT_KEY; if (ev.key == 27) { ev.type = EVENT_ESC; } } ev.time_ms = clock(); world_event(&ev, game); timeout(TIMEOUT); } return 0; } int start_world(void* (*init_game)(), int (*world_event)(struct event*, void*), void (*destroy_game)(void*)) { initscr(); if (initscr() == NULL) { puts("initscr failed"); return -1; } noecho(); cbreak(); keypad(stdscr, TRUE); nodelay(stdscr, TRUE); curs_set(0); mousemask(ALL_MOUSE_EVENTS, NULL); if (has_colors()) { start_color(); for (int i = 0; i < COLOR_COUNT; i++) { for (int j = 0; j < COLOR_COUNT; j++) { init_pair(i * COLOR_COUNT + j, i, j); } } } else { puts("No color support."); } int res = world_run(init_game, world_event); if (destroy_game) { void* g = init_game(); destroy_game(g); } endwin(); return res; }