From: Niki Date: Wed, 9 Apr 2025 06:45:43 +0000 (+0200) Subject: prepare command system X-Git-Url: http://git.nikiroo.be/?a=commitdiff_plain;h=f338fa1f92ba5ed822475bc7931522035d8a9c94;p=tdef.git prepare command system --- diff --git a/src/tdef/command.c b/src/tdef/command.c new file mode 100644 index 0000000..593a474 --- /dev/null +++ b/src/tdef/command.c @@ -0,0 +1,58 @@ +/* + * TDef: small command defense game + * + * Copyright (C) 2025 Niki Roo + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "cutils/cstring.h" +#include "command.h" + + +command_t *new_command(command_type type) { + command_t *self = malloc(sizeof(command_t)); + if (!init_command(self, type)) { + free(self); + self = NULL; + } + + return self; +} + +int init_command(command_t *self, command_type type) { + size_t sz = sizeof(self->CNAME); + strncpy(self->CNAME, "[command ", sz); + self->CNAME[sz - 2] = ']'; + self->CNAME[sz - 1] = '\0'; + + self->type = type; + + return 1; +} + +void free_command(command_t *self) { + if (self) + uninit_command(self); + + free(self); +} + +void uninit_command(command_t *self) { + self->CNAME[0] = '!'; +} + diff --git a/src/tdef/command.h b/src/tdef/command.h new file mode 100644 index 0000000..e5910e9 --- /dev/null +++ b/src/tdef/command.h @@ -0,0 +1,86 @@ +/** + * @file command.h + * @author Niki + * @date 2025 + * + * @brief bla + * + * blablabla + * + */ + +#ifndef COMMAND_H +#define COMMAND_H + +#include +#include "cutils/array.h" + +/** + * @brief bla + * + * blablabla + */ +typedef enum { + TICK, + DISPLAY, + UNKNOWN, + QUIT +} command_type; + +/** + * @brief bla + * + * blablabla + */ +typedef struct { + char CNAME[10]; + command_type type; + array_t *data; +} command_t; + +/** + * Create a new command. + * + * @param type the command type + * + * @note always identical to malloc + init_command + * + * @see malloc() + * @see init_command(command_t *self) + * + * @return a new command (you must later call `free_command()`) + */ +command_t *new_command(command_type type); + +/** + * Initialise a new command. + * + * @param type the command type + */ +int init_command(command_t *self, command_type type); + +/** + * Free the resources held for the given command: you must not use it any more. + * The map will also be free'd. + * + * @note always equivalent to uninit_command + free + * + * @see uninit_command(command_t *self) + * @see free(void *data) + */ +void free_command(command_t *self); + +/** + * Free the resources held for the given command: you must not use it any more + * unless you call init_command on it again. + * The map will also be free'd. + * + * The memory pointed to by self is not free'd. + * + * + * @see init_command(command_t *self) + */ +void uninit_command(command_t *self); + +#endif /* COMMAND_H */ + diff --git a/src/tdef/event.c b/src/tdef/event.c index e707238..8aed395 100644 --- a/src/tdef/event.c +++ b/src/tdef/event.c @@ -73,3 +73,24 @@ const char *event_name(event_t *self) { } return "Unknown"; } + +void event_output(event_t *self, cstring_t *out) { + const char *name = event_name(self); + + switch (self->type) { + case FIRE: case HIT: case MOVE: + cstring_addp(out, "EVENT:%s,%d,%d,%d,%d\n", name, + self->x, self->y, self->move_to_x, self->move_to_y); + break; + case BACKFILL: case DIE: case BREACH: + cstring_addp(out, "EVENT:%s,%d,%d\n", name, self->x, self->y); + break; + case ENTER: case WAVE: + cstring_addp(out, "EVENT:%s,%d\n", name, self->x); + break; + case WIN: case LOOSE: + cstring_addp(out, "EVENT:%s\n", name); + break; + } +} + diff --git a/src/tdef/event.h b/src/tdef/event.h index 7a90d29..f647bfd 100644 --- a/src/tdef/event.h +++ b/src/tdef/event.h @@ -13,6 +13,7 @@ #define EVENT_H #include +#include "cutils/cstring.h" /** * @brief bla @@ -90,4 +91,6 @@ void uninit_event(event_t *self); const char *event_name(event_t *self); +void event_output(event_t *self, cstring_t *out); + #endif /* EVENT_H */ diff --git a/src/tdef/reader.c b/src/tdef/reader.c index dab3b46..602218f 100644 --- a/src/tdef/reader.c +++ b/src/tdef/reader.c @@ -1,5 +1,5 @@ /* - * TDef: small tower defense game + * TDef: small reader defense game * * Copyright (C) 2025 Niki Roo * @@ -26,30 +26,30 @@ // TODO: configuration: // map size -// path: (1,1), (1,2)... +// path: 1,1;1,2;1,3; // basic: setMoney, setLife, start... // tower: configTower('1', ...) // enemy: configEnemy('a', ...) -// TODO: -// display: could be a mode (auto after tick) - -command read_command(FILE *file) { +command_t *reader_readnext(FILE *file) { static cstring_t *line = NULL; - if (!line) line = new_cstring(); + command_t *cmd = NULL; + if (cstring_readline(line, file)) { + cmd = new_command(UNKNOWN); + if (!strcmp(".", line->string)) { - return TICK; - } else if (!strcmp("display", line->string)) { - return DISPLAY; - } else { - return UNKNOWN; + cmd->type = TICK; + } else if (cstring_starts_with("display", line->string, 0)) { + cmd->type = DISPLAY; + } else if (cstring_starts_with("quit", line->string, 0)) { + cmd->type = QUIT; } } - return QUIT; + return cmd; } diff --git a/src/tdef/reader.h b/src/tdef/reader.h index 5c6ea60..c2a7a48 100644 --- a/src/tdef/reader.h +++ b/src/tdef/reader.h @@ -13,15 +13,10 @@ #define READER_H #include +#include "command.h" -typedef enum { - TICK, - DISPLAY, - UNKNOWN, - QUIT -} command; - -command read_command(FILE *file); +// NULL = eof +command_t *reader_readnext(FILE *file); #endif /* READER_H */ diff --git a/src/tdef/tdef.c b/src/tdef/tdef.c index a87d502..9a3d6b8 100644 --- a/src/tdef/tdef.c +++ b/src/tdef/tdef.c @@ -27,6 +27,8 @@ #include "reader.h" #include "event.h" +int displayMode = 0; + void display(map_t *self) { fprintf(stderr, "==========\n\n"); for (int y = 0 ; y < self->height; y++) { @@ -59,37 +61,49 @@ void display(map_t *self) { fprintf(stderr, "\n"); } -void output_event(event_t *self, FILE *file) { - const char *name = event_name(self); +int process_cmd(command_t *cmd, engine_t *engine) { + static cstring_t *out = NULL; + if (!out) + out = new_cstring(); - switch (self->type) { - case FIRE: case HIT: case MOVE: - fprintf(file, "EVENT:%s,%d,%d,%d,%d\n", name, - self->x, self->y, self->move_to_x, self->move_to_y); - break; - case BACKFILL: case DIE: case BREACH: - fprintf(file, "EVENT:%s,%d,%d\n", name, self->x, self->y); + switch(cmd->type) { + case TICK: + engine_tick(engine); + array_loop(engine->events, event, event_t) { + event_output(event, out); + fprintf(stdout, "%s", out->string); + cstring_clear(out); + } + if (displayMode) { + fprintf(stderr, + "Tick is: %zu\n", engine->current_tick); + display(engine->map); + } break; - case ENTER: case WAVE: - fprintf(file, "EVENT:%s,%d\n", name, self->x); + case DISPLAY: + displayMode = !displayMode; + if (displayMode) { + fprintf(stderr, + "Tick is: %zu\n", engine->current_tick); + display(engine->map); + } break; - case WIN: case LOOSE: - fprintf(file, "EVENT:%s\n", name); + case UNKNOWN: + fprintf(stderr, "Unrecognized command\n"); break; + case QUIT: + return 0; } + + return 1; } int main(int argc, char **argv) { map_t *map = new_map(6, 4); - if (!map) { - fprintf(stderr, "Cannot create the map"); - return 1; - } - engine_t *engine = new_engine(map); - if (!engine) { - fprintf(stderr, "Cannot create the engine"); - return 2; + if (!map || !engine) { + fprintf(stderr, "Allocation error"); + return 1; } setup_path(map, 0, 0); @@ -108,39 +122,15 @@ int main(int argc, char **argv) { enemy->speed = 1; setup_enemy(engine, enemy); - - int displayMode = 0; - command cmd = read_command(stdin); - while (cmd != QUIT) { - switch(cmd) { - case TICK: - engine_tick(engine); - array_loop(engine->events, event, event_t) { - output_event(event, stdout); - } - if (displayMode) { - fprintf(stderr, - "Tick is: %zu\n", engine->current_tick); - display(map); - } - break; - case DISPLAY: - displayMode = !displayMode; - if (displayMode) { - fprintf(stderr, - "Tick is: %zu\n", engine->current_tick); - display(map); - } - break; - case UNKNOWN: - fprintf(stderr, "Unrecognized command\n"); - break; - case QUIT: - // cannot happen, but kept for warning purposes - break; + command_t *cmd = reader_readnext(stdin); + while (cmd) { + if (process_cmd(cmd, engine)) { + free_command(cmd); + cmd = reader_readnext(stdin); + } else { + free_command(cmd); + cmd = NULL; } - - cmd = read_command(stdin); } free_engine(engine);