pvjc25/du8/world.c
2025-06-12 13:00:33 +02:00

74 lines
2.6 KiB
C

#include "world.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int TIMEOUT;
void abort_game(const char* message) { endwin(); puts(message); exit(1); }
void check_bounds(const char* source, int x, int y) {
char msg[200];
if (x < 0 || x >= COLS) { sprintf(msg, "%s: width %d out of bounds (0,%d)", source, x, COLS); abort_game(msg); }
if (y < 0 || y >= LINES) { sprintf(msg, "%s: height %d out of bounds (0,%d)", source, y, LINES); abort_game(msg); }
}
void clear_screen() { erase(); }
void game_speed(int value) { if (value < 0) abort_game("game_speed: negative"); TIMEOUT = value; }
void set_message(const char* message, int x, int y) { mvprintw(y, x, "%s", message); }
void set_cell(int character, int x, int y) { set_color_cell(character, x, y, COLOR_WHITE, COLOR_BLACK); }
void set_color_cell(int character, int x, int y, short front_color, short back_color) {
check_bounds("set_color_cell", x, y);
if (has_colors()) {
int pair_id = front_color * 8 + back_color + 1;
attron(COLOR_PAIR(pair_id));
mvaddch(y, x, character);
attroff(COLOR_PAIR(pair_id));
} else {
mvaddch(y, x, character);
}
}
int start_world(void* (*init_game)(), int (*world_event)(struct event* event, void* game), void (*destroy_game)(void* game)) {
srand(time(NULL));
int r = 0;
TIMEOUT = 100;
if (initscr() == NULL) { puts("Curses Error."); return -1; }
noecho(); cbreak(); nodelay(stdscr, TRUE); keypad(stdscr, TRUE); curs_set(FALSE);
if (has_colors()) {
start_color();
for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) init_pair(i * 8 + j + 1, i, j);
}
void* game_state = NULL;
if (init_game != NULL) { game_state = init_game(); assert(game_state != NULL); }
timeout(TIMEOUT);
struct event event;
memset(&event, 0, sizeof(struct event));
event.height = LINES; event.width = COLS; event.type = EVENT_START;
r = world_event(&event, game_state);
refresh();
while (!r) {
memset(&event, 0, sizeof(struct event));
event.height = LINES; event.width = COLS;
event.key = getch();
if (event.key == ERR) event.type = EVENT_TIMEOUT;
else if (event.key == KEY_RESIZE) event.type = EVENT_RESIZE;
else {
event.type = EVENT_KEY;
if (event.key == 27) { int k = getch(); if (k == -1) event.type = EVENT_ESC; else { event.key = k; event.alt_key = 1; } }
}
r = world_event(&event, game_state);
refresh();
timeout(TIMEOUT);
}
if (destroy_game != NULL) destroy_game(game_state);
endwin();
return r;
}