From 3e8813d5800e64fcbad1ff4624d10d0cdcfd11cd Mon Sep 17 00:00:00 2001 From: Niki Date: Thu, 17 Apr 2025 07:22:13 +0200 Subject: [PATCH] Move setup back into engine + new things --- src/tdef/command.h | 3 +- src/tdef/enemy.c | 17 +++++--- src/tdef/enemy.h | 17 ++++---- src/tdef/engine.c | 98 +++++++++++++++++++++++++++++++++++++++++++++- src/tdef/engine.h | 15 +++++++ src/tdef/event.c | 1 + src/tdef/event.h | 1 + src/tdef/map.c | 4 +- src/tdef/reader.c | 43 +++++++++++++++----- src/tdef/setup.c | 79 ------------------------------------- src/tdef/setup.h | 25 ------------ src/tdef/tdef.c | 22 ++++++----- src/tdef/tower.c | 5 ++- src/tdef/wave.c | 5 ++- src/tdef/wave.h | 3 +- 15 files changed, 195 insertions(+), 143 deletions(-) delete mode 100644 src/tdef/setup.c delete mode 100644 src/tdef/setup.h diff --git a/src/tdef/command.h b/src/tdef/command.h index 59ee55d..a18caaa 100644 --- a/src/tdef/command.h +++ b/src/tdef/command.h @@ -32,10 +32,11 @@ typedef enum { COMMAND_TOWER, COMMAND_TOWER_LVL, COMMAND_TOWER_SP, - COMMAND_WAVE, COMMAND_ENEMY, + COMMAND_WAVE, COMMAND_ADD_TOWER, + COMMAND_ADD_ENEMY, COMMAND_QUIT, diff --git a/src/tdef/enemy.c b/src/tdef/enemy.c index b60ee60..9fdd2af 100644 --- a/src/tdef/enemy.c +++ b/src/tdef/enemy.c @@ -22,9 +22,9 @@ #include "enemy.h" -enemy_t *new_enemy(int id, size_t start_tick) { +enemy_t *new_enemy(enemy_base_t *base, int id, size_t start_tick) { enemy_t *self = malloc(sizeof(enemy_t)); - if (!init_enemy(self, id, start_tick)) { + if (!init_enemy(self, base, id, start_tick)) { free(self); self = NULL; } @@ -32,18 +32,17 @@ enemy_t *new_enemy(int id, size_t start_tick) { return self; } -int init_enemy(enemy_t *self, int id, size_t start_tick) { +int init_enemy(enemy_t *self, enemy_base_t *base, int id, size_t start_tick) { size_t sz = sizeof(self->CNAME); strncpy(self->CNAME, "[enemy ", sz); self->CNAME[sz - 2] = ']'; self->CNAME[sz - 1] = '\0'; self->start_tick = start_tick; + self->base = base; self->id = id; self->hp = 1; - self->speed = 1; self->index = -1; - self->bits = 0; self->alive = 0; return 1; @@ -60,3 +59,11 @@ void uninit_enemy(enemy_t *self) { self->CNAME[0] = '!'; } +int init_enemy_base(enemy_base_t *self, int type, int hp, int speed, int bits){ + self->type = type; + self->max_hp = hp; + self->speed = speed; + self->bits = bits; + + return 1; +} diff --git a/src/tdef/enemy.h b/src/tdef/enemy.h index cb783cd..6c5faf4 100644 --- a/src/tdef/enemy.h +++ b/src/tdef/enemy.h @@ -16,8 +16,8 @@ typedef struct { int type; // identify the unique enemy type + int max_hp; int speed; // paths per tick - int index; // index in paths int bits; // on death } enemy_base_t; @@ -28,21 +28,19 @@ typedef struct { */ typedef struct { char CNAME[10]; + enemy_base_t *base; size_t start_tick; + int index; // index in paths int id; // unique per wave int hp; - // should move to enemy_base_t - int speed; // paths per tick - int index; // index in paths - int bits; // on death - int alive; } enemy_t; /** * Create a new enemy. * + * @param base the type of enemy (will NOT be free'd by this object) * @param id the unique number (per wave) of this enemy * @param start_tick the tick at which the enemy will start on the map * @@ -53,15 +51,16 @@ typedef struct { * * @return a new enemy (you must later call `free_enemy()`) */ -enemy_t *new_enemy(int id, size_t start_tick); +enemy_t *new_enemy(enemy_base_t *base, int id, size_t start_tick); /** * Initialise a new enemy. * + * @param base the type of enemy (will NOT be free'd by this object) * @param id the unique number (per wave) of this enemy * @param start_tick the tick at which the enemy will start on the map */ -int init_enemy(enemy_t *self, int id, size_t start_tick); +int init_enemy(enemy_t *self, enemy_base_t *base, int id, size_t start_tick); /** * Free the resources held for the given enemy: you must not use it any more. @@ -84,4 +83,6 @@ void free_enemy(enemy_t *self); */ void uninit_enemy(enemy_t *self); +int init_enemy_base(enemy_base_t *self, int type, int hp, int speed, int bits); + #endif /* ENEMY_H */ diff --git a/src/tdef/engine.c b/src/tdef/engine.c index 3bf1a7f..447d63d 100644 --- a/src/tdef/engine.c +++ b/src/tdef/engine.c @@ -152,8 +152,14 @@ int engine_add_tower(engine_t *self, int type, int x, int y) { return 0; tower_base_t *base = engine_get_tower_base(self, type); - if (!base) + if (!base) { + event_t event; + init_event(&event, EVENT_ERROR); + event.error = EEVENT_UNKNOWN_TYPE; + array_push(self->events, &event); + return 0; + } if (self->bits < base->cost) { event_t event; @@ -188,3 +194,93 @@ tower_base_t *engine_get_tower_base(engine_t *self, int type) { return NULL; } +enemy_base_t *engine_get_enemy_base(engine_t *self, int type) { + array_loop (self->ebases, base, enemy_base_t) { + if (base->type == type) + return base; + } + + return NULL; +} + +tower_base_t *setup_tower_base(engine_t *self, int type, int cost) { + tower_base_t *base = engine_get_tower_base(self, type); + if (base) { // already configured + event_t event; + init_event(&event, EVENT_ERROR); + event.error = EEVENT_ALREADY_CONFIGURED; + array_push(self->events, &event); + + return NULL; + } + + base = array_new(self->tbases); + init_tower_base(base, type); + base->cost = cost; + + return base; +} + +int setup_wave(engine_t *self, int start_tick, int bits) { + wave_t *wave = array_new(self->waves); + if (!wave) + return 0; + + init_wave(wave, start_tick); + wave->bits = bits; + + return 1; +} + +enemy_base_t *setup_enemy_base( + engine_t *self, int type, int hp, int speed, int bits) { + enemy_base_t *base = engine_get_enemy_base(self, type); + if (base) { // already configured + event_t event; + init_event(&event, EVENT_ERROR); + event.error = EEVENT_ALREADY_CONFIGURED; + array_push(self->events, &event); + + return NULL; + } + + base = array_new(self->ebases); + init_enemy_base(base, type, hp, speed, bits); + + return base; +} + +enemy_t *setup_enemy(engine_t *self, int type, int id, size_t start_tick) { + if (!self->waves->count) + if (!setup_wave(self, 0, 0)) + return 0; + + //TODO: id must be unique (total, not only per wave) + + enemy_base_t *base = engine_get_enemy_base(self, type); + if (!base) { + event_t event; + init_event(&event, EVENT_ERROR); + event.error = EEVENT_UNKNOWN_TYPE; + array_push(self->events, &event); + + return 0; + } + + wave_t *wave = array_last(self->waves); + return wave_add_enemy(wave, base, id, start_tick); +} + +int setup_path(engine_t *self, int x, int y) { + if (!self->map) { + event_t event; + init_event(&event, EVENT_ERROR); + event.error = EEVENT_MAP_NOT_INITIALISED; + array_push(self->events, &event); + + return 0; + } + + return map_add_path(self->map, x, y); +} + diff --git a/src/tdef/engine.h b/src/tdef/engine.h index 15642f0..4281489 100644 --- a/src/tdef/engine.h +++ b/src/tdef/engine.h @@ -86,5 +86,20 @@ int engine_add_tower(engine_t *self, int type, int x, int y); tower_base_t *engine_get_tower_base(engine_t *self, int type); +enemy_base_t *engine_get_enemy_base(engine_t *self, int type); + +// Setup: + +tower_base_t *setup_tower_base(engine_t *self, int type, int cost); + +int setup_wave(engine_t *self, int start_tick, int bits); + +enemy_base_t *setup_enemy_base( + engine_t *self, int type, int hp, int speed, int bits); + +enemy_t *setup_enemy(engine_t *self, int type, int id, size_t start_tick); + +int setup_path(engine_t *self, int x, int y); + #endif /* ENGINE_H */ diff --git a/src/tdef/event.c b/src/tdef/event.c index 896e605..a3a08a0 100644 --- a/src/tdef/event.c +++ b/src/tdef/event.c @@ -81,6 +81,7 @@ const char *event_ename(event_t *self) { switch(self->x) { case EEVENT_SUCCESS : return "SUCCESS" ; case EEVENT_MAP_NOT_INITIALISED : return "MAP_NOT_INITIALISED"; + case EEVENT_UNKNOWN_TYPE : return "UNKNOWN_TYPE" ; case EEVENT_ALREADY_CONFIGURED : return "ALREADY_CONFIGURED" ; case EEVENT_NOT_ENOUGH_BITS : return "NOT_ENOUGH_BITS" ; } diff --git a/src/tdef/event.h b/src/tdef/event.h index 71b88bb..76a189f 100644 --- a/src/tdef/event.h +++ b/src/tdef/event.h @@ -38,6 +38,7 @@ typedef enum { typedef enum { EEVENT_SUCCESS, EEVENT_MAP_NOT_INITIALISED, + EEVENT_UNKNOWN_TYPE, EEVENT_ALREADY_CONFIGURED, EEVENT_NOT_ENOUGH_BITS, } eevent_type; diff --git a/src/tdef/map.c b/src/tdef/map.c index fa385b6..2b8a460 100644 --- a/src/tdef/map.c +++ b/src/tdef/map.c @@ -199,7 +199,7 @@ int map_hit_1(map_t *self, int current_tick, array_t *events) { void move(map_t *self, enemy_t *enemy, array_t *events, int reverse) { int source = enemy->index; - int target = source >= 0 ? source+1 : 0; + int target = source >= 0 ? (source + enemy->base->speed) : 0; event_t event; init_event(&event, EVENT_MOVE); @@ -258,7 +258,7 @@ int hit(map_t *self, proj_t *proj, array_t *events) { e->alive = 0; path->enemy = NULL; init_event(&event, EVENT_DIE); - bits = e->bits; + bits = e->base->bits; event.move_to_x = bits; } else { init_event(&event, EVENT_HIT); diff --git a/src/tdef/reader.c b/src/tdef/reader.c index a6e0bdb..0bc324b 100644 --- a/src/tdef/reader.c +++ b/src/tdef/reader.c @@ -65,17 +65,22 @@ // > (0) type : the unique identifier for this tower type // > (1) super_cost // > (2) super_power +// * enemy : will setup a new enemy type +// > (0) type : the unique identifier for this enemy type +// > (1) hp : life/hit points the enemy can take +// > (2) speed : speed in paths per tick +// > (3) bits : how much bits received on enemy death // * wave : configure a new wave TODO -// * enemy : add a new enemy in the current wave (can create the first one) -// > type : the enemy type -// > id : the *unique* id of this enemy -// > start_tick : the tick at which it will appear (wave-relative) // -// Runtime commands: +// Add commands: // * add_tower: add a new tower on the map (will cost bits) // > (0) type : the type of tower to add // > (1) X position: the X coordinate // > (2) Y position: the Y coordinate +// * add_enemy : add a new enemy in the current wave (can create the first one) +// > type : the enemy type +// > id : the *unique* id of this enemy +// > start_tick : the tick at which it will appear (wave-relative) // // Other commands: // * display : will toggle display (debug) mode @@ -142,12 +147,16 @@ command_t *reader_readnext(FILE *file) { cmd->type = COMMAND_INVALID; if (command_read_count(cmd, line->string) > 2) cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 1) + cmd->type = COMMAND_INVALID; } else if (is_cmd(line, "bits")) { cmd->type = COMMAND_BITS; if (!command_read_int(cmd, line->string, 0, 0)) cmd->type = COMMAND_INVALID; if (command_read_count(cmd, line->string) > 2) cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 1) + cmd->type = COMMAND_INVALID; } else if (is_cmd(line, "path")) { cmd->type = COMMAND_PATH; if (!command_read_int(cmd, line->string, 0, -1)) @@ -158,28 +167,44 @@ command_t *reader_readnext(FILE *file) { cmd->type = COMMAND_TOWER; if (!command_read_int(cmd, line->string, 0, 1)) cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 2) + cmd->type = COMMAND_INVALID; } else if (is_cmd(line, "tower_lvl")) { cmd->type = COMMAND_TOWER_LVL; if (!command_read_int(cmd, line->string, 0, 4)) cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 5) + cmd->type = COMMAND_INVALID; } else if (is_cmd(line, "tower_sp")) { cmd->type = COMMAND_TOWER_SP; // TODO - } else if (is_cmd(line, "wave")) { - cmd->type = COMMAND_WAVE; - // TODO } else if (is_cmd(line, "enemy")) { cmd->type = COMMAND_ENEMY; - if (!command_read_int(cmd, line->string, 0, 2)) + if (!command_read_int(cmd, line->string, 0, 3)) + cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 4) cmd->type = COMMAND_INVALID; + } else if (is_cmd(line, "wave")) { + cmd->type = COMMAND_WAVE; + // TODO } else if (is_cmd(line, "add_tower")) { cmd->type = COMMAND_ADD_TOWER; if (!command_read_int(cmd, line->string, 0, 2)) cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 3) + cmd->type = COMMAND_INVALID; + } else if (is_cmd(line, "add_enemy")) { + cmd->type = COMMAND_ADD_ENEMY; + if (!command_read_int(cmd, line->string, 0, 2)) + cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string) != 3) + cmd->type = COMMAND_INVALID; } else if (is_cmd(line, "quit")) { cmd->type = COMMAND_QUIT; if (command_read_count(cmd, line->string)) cmd->type = COMMAND_INVALID; + if (command_read_count(cmd, line->string)) + cmd->type = COMMAND_INVALID; } } diff --git a/src/tdef/setup.c b/src/tdef/setup.c deleted file mode 100644 index 19426c6..0000000 --- a/src/tdef/setup.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * TDef: small tower 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 "setup.h" -#include "event.h" - -tower_base_t *setup_tower_base(engine_t *self, int type, int cost) { - tower_base_t *base = engine_get_tower_base(self, type); - if (base) { // already configured - event_t event; - init_event(&event, EVENT_ERROR); - event.error = EEVENT_ALREADY_CONFIGURED; - array_push(self->events, &event); - - return NULL; - } - - base = array_new(self->tbases); - init_tower_base(base, type); - base->cost = cost; - - return base; -} - -int setup_wave(engine_t *self, int start_tick, int bits) { - wave_t *wave = array_new(self->waves); - if (!wave) - return 0; - - init_wave(wave, start_tick); - wave->bits = bits; - - return 1; -} - -enemy_t *setup_enemy(engine_t *self, int type, int id, size_t start_tick) { - if (!self->waves->count) - if (!setup_wave(self, 0, 0)) - return 0; - - //TODO: type and enemy_base_t - //TODO: id must be unique (total, not only per wave) - - wave_t *wave = array_last(self->waves); - return wave_add_enemy(wave, id, start_tick); -} - -int setup_path(engine_t *self, int x, int y) { - if (!self->map) { - event_t event; - init_event(&event, EVENT_ERROR); - event.error = EEVENT_MAP_NOT_INITIALISED; - array_push(self->events, &event); - - return 0; - } - - return map_add_path(self->map, x, y); -} - diff --git a/src/tdef/setup.h b/src/tdef/setup.h deleted file mode 100644 index fc74b98..0000000 --- a/src/tdef/setup.h +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @file setup.h - * @author Niki - * @date 2025 - * - * @brief bla - * - * blablabla - * - */ - -#ifndef SETUP_H -#define SETUP_H - -#include "engine.h" - -tower_base_t *setup_tower_base(engine_t *self, int type, int cost); - -int setup_wave(engine_t *self, int start_tick, int bits); - -enemy_t *setup_enemy(engine_t *self, int type, int id, size_t start_tick); - -int setup_path(engine_t *self, int x, int y); - -#endif /* SETUP_H */ diff --git a/src/tdef/tdef.c b/src/tdef/tdef.c index ebf1195..13227e7 100644 --- a/src/tdef/tdef.c +++ b/src/tdef/tdef.c @@ -27,7 +27,6 @@ #include "reader.h" #include "event.h" #include "command.h" -#include "setup.h" int displayMode = 0; @@ -137,24 +136,29 @@ int process_cmd(command_t *cmd, engine_t *engine) { // TODO printf("TODO: command_tower_sp\n"); break; + case COMMAND_ENEMY: + setup_enemy_base( + engine, + command_get_int(cmd, 0), + command_get_int(cmd, 1), + command_get_int(cmd, 2), + command_get_int(cmd, 3) + ); + break; case COMMAND_WAVE: // TODO printf("TODO: command_wave\n"); break; - case COMMAND_ENEMY: - ;enemy_t *enemy = setup_enemy( + case COMMAND_ADD_TOWER: + engine_add_tower( engine, command_get_int(cmd, 0), command_get_int(cmd, 1), command_get_int(cmd, 2) ); - // TODO: enemy_base: - enemy->speed = 2; - enemy->bits = 5; - // end-of-TODO break; - case COMMAND_ADD_TOWER: - engine_add_tower( + case COMMAND_ADD_ENEMY: + setup_enemy( engine, command_get_int(cmd, 0), command_get_int(cmd, 1), diff --git a/src/tdef/tower.c b/src/tdef/tower.c index dc0956b..6eabe08 100644 --- a/src/tdef/tower.c +++ b/src/tdef/tower.c @@ -93,9 +93,12 @@ proj_t *tower_fire(tower_t *self, int current_tick, array_t *enemies, // If not found: return NULL; + int attack = self->base->stats[self->lvl_attack].attack; + int speed = self->base->stats[self->lvl_speed].speed; + proj_t *proj = new_proj(3, 0); // TODO proj->desc = self->projectile; - proj->desc.damage = 10; // TODO + proj->desc.damage = attack; proj->boom_tick = current_tick + 3; // TODO: compute from speed self->fire_delayed = self->base->stats[self->lvl_speed].attack; diff --git a/src/tdef/wave.c b/src/tdef/wave.c index 9f12a2d..0272dff 100644 --- a/src/tdef/wave.c +++ b/src/tdef/wave.c @@ -69,11 +69,12 @@ void uninit_wave(wave_t *self) { self->last_enemy = NULL; } -enemy_t *wave_add_enemy(wave_t *self, int id, size_t start_tick) { +enemy_t *wave_add_enemy( + wave_t *self, enemy_base_t *base, int id, size_t start_tick) { enemy_t *enemy = array_new(self->enemies); if (!enemy) return NULL; - init_enemy(enemy, id, start_tick); + init_enemy(enemy, base, id, start_tick); return enemy; } diff --git a/src/tdef/wave.h b/src/tdef/wave.h index 58b7cfa..81ead92 100644 --- a/src/tdef/wave.h +++ b/src/tdef/wave.h @@ -73,7 +73,8 @@ void free_wave(wave_t *self); */ void uninit_wave(wave_t *self); -enemy_t *wave_add_enemy(wave_t *self, int id, size_t start_tick); +enemy_t *wave_add_enemy( + wave_t *self, enemy_base_t *base, int id, size_t start_tick); enemy_t *wave_next_enemy(wave_t *self, int tick); -- 2.27.0