From ea86d13e9fc8ff63ae6aad2a43d33eeef2516018 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B0=D1=88=D0=B0?= Date: Fri, 2 May 2025 20:07:54 +0200 Subject: [PATCH] refresh --- a4/game.c | 91 ++++++++++++++++++++++------- a4/game.h | 16 +++-- a4/world.c | 169 ++++++++++++++++++++++++++++++----------------------- 3 files changed, 175 insertions(+), 101 deletions(-) diff --git a/a4/game.c b/a4/game.c index be6a505..78191a5 100644 --- a/a4/game.c +++ b/a4/game.c @@ -2,43 +2,92 @@ #include "world.h" #include #include +#include +#include #include +#define MOUSE_COUNT 5 + void* init_game(void) { - struct game* obj = calloc(1, sizeof(struct game)); - if (!obj) return NULL; + struct game* g = calloc(1, sizeof(struct game)); + if (!g) return NULL; - obj->cat_x = 5; - obj->cat_y = 3; - obj->mouse_x = 20; - obj->mouse_y = 10; - obj->cat_dx = 1; - obj->cat_dy = 1; - snprintf(obj->message, sizeof(obj->message), "Лови меня, если сможешь!"); + g->cat_x = 5; + g->cat_y = 5; - return obj; + for (int i = 0; i < MOUSE_COUNT; i++) { + g->mouse_x[i] = 10 + rand() % (COLS - 12); + g->mouse_y[i] = 2 + rand() % (LINES - 4); + g->mouse_alive[i] = 1; + } + + g->caught = 0; + snprintf(g->message, sizeof(g->message), "Catch all mice (%d left)", MOUSE_COUNT); + return g; } -int game_event(struct event* e, void* data) { - struct game* g = (struct game*)data; +int game_event(struct event* e, void* state) { + struct game* g = (struct game*)state; + if (!g) return 0; if (e->type == EVENT_KEY) { - if (e->key == KEY_UP) g->cat_y--; - if (e->key == KEY_DOWN) g->cat_y++; - if (e->key == KEY_LEFT) g->cat_x--; + if (e->key == KEY_UP) g->cat_y--; + if (e->key == KEY_DOWN) g->cat_y++; + if (e->key == KEY_LEFT) g->cat_x--; if (e->key == KEY_RIGHT) g->cat_x++; } - g->mouse_x += (rand() % 3) - 1; - g->mouse_y += (rand() % 3) - 1; + if (g->cat_x < 1) g->cat_x = 1; + if (g->cat_y < 1) g->cat_y = 1; + if (g->cat_x >= COLS - 1) g->cat_x = COLS - 2; + if (g->cat_y >= LINES - 1) g->cat_y = LINES - 2; - if (g->cat_x == g->mouse_x && g->cat_y == g->mouse_y) { - snprintf(g->message, sizeof(g->message), "Поймал! Финита."); + for (int i = 0; i < MOUSE_COUNT; i++) { + if (!g->mouse_alive[i]) continue; + + g->mouse_x[i] += (rand() % 3) - 1; + g->mouse_y[i] += (rand() % 3) - 1; + + if (g->mouse_x[i] < 1) g->mouse_x[i] = 1; + if (g->mouse_y[i] < 1) g->mouse_y[i] = 1; + if (g->mouse_x[i] >= COLS - 1) g->mouse_x[i] = COLS - 2; + if (g->mouse_y[i] >= LINES - 1) g->mouse_y[i] = LINES - 2; + + if (g->mouse_x[i] == g->cat_x && g->mouse_y[i] == g->cat_y) { + g->mouse_alive[i] = 0; + g->caught++; + } } clear_screen(); - set_cell('C', g->cat_x, g->cat_y); - set_cell('M', g->mouse_x, g->mouse_y); + + box(stdscr, 0, 0); + + set_color_cell('C', g->cat_x, g->cat_y, COLOR_CYAN, COLOR_BLACK); + + for (int i = 0; i < MOUSE_COUNT; i++) { + if (g->mouse_alive[i]) { + set_color_cell('M', g->mouse_x[i], g->mouse_y[i], COLOR_RED, COLOR_BLACK); + } + } + + if (g->caught == MOUSE_COUNT) { + clear_screen(); + box(stdscr, 0, 0); + const char* msg = "Congratulations! You won!"; + int len = strlen(msg); + int cx = (COLS - len) / 2; + int cy = LINES / 2; + for (int i = 0; i < len; i++) { + set_color_cell(msg[i], cx + i, cy, COLOR_YELLOW, COLOR_BLACK); + } + refresh(); + napms(4000); + endwin(); + exit(0); + } + + snprintf(g->message, sizeof(g->message), "Caught: %d / %d", g->caught, MOUSE_COUNT); set_message(g->message, 2, 0); return 0; diff --git a/a4/game.h b/a4/game.h index 8b1d6ca..b7fa4be 100644 --- a/a4/game.h +++ b/a4/game.h @@ -3,16 +3,20 @@ #include "world.h" +#define MOUSE_COUNT 5 + struct game { - int cat_dx, cat_dy; - int cat_x, cat_y; - int mouse_x, mouse_y; - int cat_dx_position, cat_dy_position; + int cat_x; + int cat_y; + int mouse_x[MOUSE_COUNT]; + int mouse_y[MOUSE_COUNT]; + int mouse_alive[MOUSE_COUNT]; + int caught; char message[100]; }; -void* init_game(void); +void* init_game(); int game_event(struct event* event, void* game); #endif - + diff --git a/a4/world.c b/a4/world.c index 5a770fd..ac533c3 100644 --- a/a4/world.c +++ b/a4/world.c @@ -7,129 +7,150 @@ int TIMEOUT = 100; -void abort_game(const char* message) { +void abort_game(const char* msg) { endwin(); - puts(message); + puts(msg); exit(1); } -void check_bounds(const char* source, int x, int y) { - char msg[200]; +void check_bounds(const char* tag, int x, int y) { + char err[256]; if (x < 0 || x >= COLS) { - snprintf(msg, sizeof(msg), "%s: width %d is out of bounds (0,%d)", source, x, COLS); - abort_game(msg); + snprintf(err, sizeof(err), "%s: x=%d out of screen (0,%d)", tag, x, COLS); + abort_game(err); } if (y < 0 || y >= LINES) { - snprintf(msg, sizeof(msg), "%s: height %d is out of bounds (0,%d)", source, y, LINES); - abort_game(msg); + snprintf(err, sizeof(err), "%s: y=%d out of screen (0,%d)", tag, y, LINES); + abort_game(err); } } void clear_screen() { mvaddch(0, 0, ' '); - int screenchars = LINES * COLS; - for (int i = 1; i < screenchars; i++) { + for (int p = 1; p < COLS * LINES; p++) { addch(' '); } } -void game_speed(int value) { - if (value < 0) { - abort_game("world_seed:: cannot be negative\n"); - } - TIMEOUT = value; +void game_speed(int v) { + if (v < 0) abort_game("negative speed?"); + TIMEOUT = v; } -void set_message(const char* message, int x, int y) { - int l = strlen(message); - for (int i = 0; i < l; i++) { +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(message[i], x + i, y); + set_cell(msg[i], x + i, y); } } -void assert_message(int event, const char* message) { - if (event == 0) { - abort_game(message); - } +void assert_message(int ok, const char* msg) { + if (!ok) abort_game(msg); } -void set_cell(int character, int x, int y) { +void set_cell(int c, int x, int y) { check_bounds("set_cell", x, y); - set_color_cell(character, x, y, COLOR_WHITE, COLOR_BLACK); + set_color_cell(c, x, y, COLOR_WHITE, COLOR_BLACK); } -void set_color_cell(int character, int x, int y, short front_color, short back_color) { +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 * front_color + back_color; + int pair = COLOR_COUNT * fg + bg; attron(COLOR_PAIR(pair)); - mvaddch(y, x, character); + mvaddch(y, x, c); attroff(COLOR_PAIR(pair)); } else { - mvaddch(y, x, character); + mvaddch(y, x, c); } } -int world_run(void* (*init_game)(), int (*world_event)(struct event* event, void* game)) { +int world_run(void* (*init_game)(), int (*world_event)(struct event* e, void* g)) { void* game = init_game(); - if (!game) { - return -1; - } + if (!game) return -1; timeout(TIMEOUT); - struct event event; - memset(&event, 0, sizeof(struct event)); - event.height = LINES; - event.width = COLS; - event.type = EVENT_START; - clock_t start_time = clock(); - clock_t last_timeout = start_time; - event.time_ms = start_time; + + 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(&event, 0, sizeof(struct event)); - event.height = LINES; - event.width = COLS; - event.type = EVENT_START; - event.time_ms = clock(); + memset(&ev, 0, sizeof(ev)); + ev.height = LINES; + ev.width = COLS; + ev.key = getch(); - world_event(&event, game); - - if (event.key == ERR) { - event.type = EVENT_TIMEOUT; - last_timeout = clock(); - event.time_ms = last_timeout + TIMEOUT; - } else if (event.key == KEY_MOUSE) { - event.type = EVENT_MOUSE; - MEVENT mouse_event; - if (getmouse(&mouse_event) == OK) { - event.mouse_x = mouse_event.x; - event.mouse_y = mouse_event.y; - if (mouse_event.bstate & BUTTON1_PRESSED) { - event.mouse_left = 1; - } - if (mouse_event.bstate & BUTTON2_PRESSED) { - event.mouse_middle = 1; - } - if (mouse_event.bstate & BUTTON3_PRESSED) { - event.mouse_right = 1; - } + 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 (event.key == KEY_RESIZE) { - event.type = EVENT_RESIZE; + } else if (ev.key == KEY_RESIZE) { + ev.type = EVENT_RESIZE; } else { - event.type = EVENT_KEY; - if (event.key == 27) { // ESC key - event.type = EVENT_ESC; + ev.type = EVENT_KEY; + if (ev.key == 27) { + ev.type = EVENT_ESC; } } - event.time_ms = clock(); - world_event(&event, game); + 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; +} +