From: Niki Date: Mon, 7 Apr 2025 21:21:50 +0000 (+0200) Subject: some more work X-Git-Url: http://git.nikiroo.be/?a=commitdiff_plain;h=af33952719bd5bfabd55d1f28190736bb67939bf;p=tdef.git some more work --- diff --git a/src/tdef/any.c b/src/tdef/any.c index 0315baa..5d20b01 100644 --- a/src/tdef/any.c +++ b/src/tdef/any.c @@ -22,8 +22,8 @@ #include "any.h" -path_t *anyloc(any_t *self) { - if (self && self->_.type == 'l') +path_t *anypath(any_t *self) { + if (self && self->_.type == 'p') return (path_t*)(void*)self; return NULL; } @@ -40,7 +40,7 @@ enemy_t *anyenemy(any_t *self) { return NULL; } -any_t *loc2any(path_t *self) { +any_t *path2any(path_t *self) { return (any_t*)(void*)self; } diff --git a/src/tdef/any.h b/src/tdef/any.h index 33a755e..9a1e7b2 100644 --- a/src/tdef/any.h +++ b/src/tdef/any.h @@ -28,13 +28,13 @@ typedef union { enemy_t _e; } any_t; -path_t *anyloc(any_t *self); +path_t *anypath(any_t *self); tower_t *anytower(any_t *self); enemy_t *anyenemy(any_t *self); -any_t *loc2any(path_t *self); +any_t *path2any(path_t *self); any_t *tower2any(tower_t *self); diff --git a/src/tdef/enemy.c b/src/tdef/enemy.c index 79a7302..1918bb8 100644 --- a/src/tdef/enemy.c +++ b/src/tdef/enemy.c @@ -39,7 +39,10 @@ int init_enemy(enemy_t *self, size_t start_tick) { self->CNAME[sz - 1] = '\0'; self->start_tick = start_tick; + self->hp = 1; + self->speed = 1; self->index = -1; + self->alive = 0; return 1; } diff --git a/src/tdef/enemy.h b/src/tdef/enemy.h index 2e1ca96..ee91c2a 100644 --- a/src/tdef/enemy.h +++ b/src/tdef/enemy.h @@ -25,6 +25,7 @@ typedef struct { int hp; int speed; // paths per tick int index; // index in paths + int alive; } enemy_t; /** diff --git a/src/tdef/engine.c b/src/tdef/engine.c index bdc6239..b965d81 100644 --- a/src/tdef/engine.c +++ b/src/tdef/engine.c @@ -21,8 +21,7 @@ #include #include "engine.h" - -void move(engine_t *self, enemy_t *enemy); +#include "event.h" engine_t *new_engine(map_t *map) { engine_t *self = malloc(sizeof(engine_t)); @@ -40,12 +39,19 @@ int init_engine(engine_t *self, map_t *map) { self->CNAME[sz - 2] = ']'; self->CNAME[sz - 1] = '\0'; - self->map = map; + self->map = map; self->current_tick = 0; - self->events = new_array(sizeof(int), 10); - self->last_enemy = NULL; + self->enemies = new_array(sizeof(enemy_t), 100); + self->events = new_array(sizeof(event_t), 20); + self->last_enemy = NULL; + self->life = 10; - return (self->events != NULL); + if (!self->enemies || !self->events) { + uninit_engine(self); + return 0; + } + + return 1; } void free_engine(engine_t *self) { @@ -57,70 +63,45 @@ void free_engine(engine_t *self) { void uninit_engine(engine_t *self) { self->CNAME[0] = '!'; - free_map(self->map); - self->map = NULL; - free_array(self->events); - self->events = NULL; + + if (self->enemies) { + array_loop(self->enemies, enemy, enemy_t) { + uninit_enemy(enemy); + } + } + + free_map(self->map) ; self->map = NULL; + free_array(self->events) ; self->events = NULL; + free_array(self->enemies); self->enemies = NULL; } void engine_tick(engine_t *self) { array_clear(self->events); - // TODO: all the rest - array_deloop(self->map->alive, ptr, enemy_t*) { - enemy_t *alive = *ptr; - move(self, alive); - } - enemy_t *enemy; - if (self->last_enemy) - enemy = array_next(self->map->enemies, self->last_enemy); + if (!self->last_enemy) + enemy = array_first(self->enemies); else - enemy = array_first(self->map->enemies); + enemy = array_next(self->enemies, self->last_enemy); - // We allow only one enemy per tick (because one per path!) - if (enemy && enemy->start_tick == self->current_tick) { + // Note that multiple ennemies per tick will trigger the backfill + while (enemy && enemy->start_tick >= self->current_tick) { self->last_enemy = enemy; - array_push(self->map->alive, &enemy); - move(self, enemy); + map_enemy_enters(self->map, enemy, self->events); + enemy = array_next(self->enemies, enemy); } + map_move_1(self->map, self->events); + map_fire_1(self->map, self->current_tick, self->events); + map_hit_1(self->map, self->current_tick, self->events); + self->current_tick++; } - -void move(engine_t *self, enemy_t *enemy) { - int source = enemy->index; - int target = source >= 0 ? source+1 : 0; - - path_t *path_from = NULL; - if (enemy->index >= 0) - path_from = array_get(self->map->paths, enemy->index); - path_t *path_to = array_get(self->map->paths, target); - - if (path_to && path_to->enemy) - printf("woops: TODO\n"); - - if (path_from) { - if (path_from->enemy != enemy) { - printf("TODO: DATA ERROR\n"); - return; - } - path_from->enemy = NULL; - } +int setup_enemy(engine_t *self, enemy_t *enemy) { + if (!array_push(self->enemies, enemy)) + return 0; - if (!path_to) { - printf("TODO: enemy left!\n"); - return; - } - - if (path_to) { - path_to->enemy = enemy; - enemy->index = path_to->index; - } -printf("enemy moved from %d (%d,%d) to %d (%d,%d)\n", -source, path_from?path_from->x:-1, path_from?path_from->y:-1, -target, path_to ?path_to ->x:-1, path_to ?path_to ->y:-1 -); + return 1; } diff --git a/src/tdef/engine.h b/src/tdef/engine.h index b19d6e9..f01856e 100644 --- a/src/tdef/engine.h +++ b/src/tdef/engine.h @@ -25,8 +25,10 @@ typedef struct { char CNAME[10]; map_t *map; size_t current_tick; + array_t *enemies; array_t *events; enemy_t *last_enemy; + int life; } engine_t; /** @@ -76,5 +78,7 @@ void uninit_engine(engine_t *self); // will clear events on start! void engine_tick(engine_t *self); +int setup_enemy(engine_t *self, enemy_t *enemy); + #endif /* ENGINE_H */ diff --git a/src/tdef/event.c b/src/tdef/event.c new file mode 100644 index 0000000..4c385ef --- /dev/null +++ b/src/tdef/event.c @@ -0,0 +1,74 @@ +/* + * 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 "event.h" + +event_t *new_event(event_type type) { + event_t *self = malloc(sizeof(event_t)); + if (!init_event(self, type)) { + free(self); + self = NULL; + } + + return self; +} + +int init_event(event_t *self, event_type type) { + size_t sz = sizeof(self->CNAME); + strncpy(self->CNAME, "[event ", sz); + self->CNAME[sz - 2] = ']'; + self->CNAME[sz - 1] = '\0'; + + self->type = type; + self->x = -1; + self->y = -1; + self->move_to_x = -1; + self->move_to_y = -1; + + return 1; +} + +void free_event(event_t *self) { + if (self) + uninit_event(self); + + free(self); +} + +void uninit_event(event_t *self) { + self->CNAME[0] = '!'; +} + +const char *event_name(event_t *self) { + switch (self->type) { + case FIRE : return "FIRE" ; + case HIT : return "HIT" ; + case ENTER : return "ENTER" ; + case BACKFILL: return "BACKFILL"; + case MOVE : return "MOVE" ; + case DIE : return "DIE" ; + case BREACH : return "BREACH" ; + case WIN : return "WIN" ; + case LOOSE : return "LOOSE" ; + } + return "Unknown"; +} diff --git a/src/tdef/event.h b/src/tdef/event.h new file mode 100644 index 0000000..0b4b096 --- /dev/null +++ b/src/tdef/event.h @@ -0,0 +1,92 @@ +/** + * @file event.h + * @author Niki + * @date 2025 + * + * @brief bla + * + * blablabla + * + */ + +#ifndef EVENT_H +#define EVENT_H + +#include + +/** + * @brief bla + * + * blablabla + */ +typedef enum { + FIRE, + HIT, + ENTER, + BACKFILL, + MOVE, + DIE, + BREACH, + WIN, + LOOSE, +} event_type; + +/** + * @brief bla + * + * blablabla + */ +typedef struct { + char CNAME[10]; + event_type type; + int x; + int y; + int move_to_x; + int move_to_y; +} event_t; + +/** + * Create a new event. + * + * @param type the kind of event that happended + * + * @note always identical to malloc + init_event + * + * @see malloc() + * @see init_event(event_t *self) + * + * @return a new event (you must later call `free_event()`) + */ +event_t *new_event(event_type type); + +/** + * Initialise a new event. + * + * @param type the kind of event that happended + */ +int init_event(event_t *self, event_type type); + +/** + * Free the resources held for the given event: you must not use it any more. + * + * @note always equivalent to uninit_event + free + * + * @see uninit_event(event_t *self) + * @see free(void *data) + */ +void free_event(event_t *self); + +/** + * Free the resources held for the given event: you must not use it any more + * unless you call init_event on it again. + * + * The memory pointed to by self is not free'd. + * + * + * @see init_event(event_t *self) + */ +void uninit_event(event_t *self); + +const char *event_name(event_t *self); + +#endif /* EVENT_H */ diff --git a/src/tdef/map.c b/src/tdef/map.c index 91c31c8..5bb3a34 100644 --- a/src/tdef/map.c +++ b/src/tdef/map.c @@ -22,6 +22,11 @@ #include #include "map.h" +#include "event.h" +#include "proj.h" + +void move(map_t *self, enemy_t *enemy, array_t *events, int reverse); +void hit(map_t *self, proj_t *proj, array_t *events); map_t *new_map(int width, int height) { map_t *self = malloc(sizeof(map_t)); @@ -43,14 +48,16 @@ int init_map(map_t *self, int width, int height) { self->height = height; self->data = calloc((width*height), sizeof(any_t*)); - self->paths = new_array(sizeof(path_t ), 100); - self->towers = new_array(sizeof(tower_t*), 20); - self->enemies = new_array(sizeof(enemy_t ), 100); - self->alive = new_array(sizeof(enemy_t*), 10); + self->paths = new_array(sizeof(path_t ), 100); + self->towers = new_array(sizeof(tower_t*), 20); + self->alive = new_array(sizeof(enemy_t*), 10); + self->breached = new_array(sizeof(enemy_t*), 20); + self->backfill = new_array(sizeof(enemy_t*), 10); + + self->projs = new_proj(-1, -1); if (!self->data || !self->paths || !self->towers - || !self->enemies || !self->alive - ) { + || !self->alive || !self->breached || !self->backfill) { uninit_map(self); return 0; } @@ -74,20 +81,88 @@ void uninit_map(map_t *self) { } } - if (self->enemies) { - array_loop(self->enemies, enemy, enemy_t) { - uninit_enemy(enemy); + free (self->data ); self->data = NULL; + free_array(self->paths ); self->paths = NULL; + free_array(self->towers ); self->towers = NULL; + free_array(self->alive ); self->alive = NULL; + free_array(self->breached); self->breached = NULL; + free_array(self->backfill); self->backfill = NULL; + + while (self->projs) { + proj_t *p = self->projs; + self->projs = p->next; + free_proj(p); + } +} + +void map_enemy_enters(map_t *self, enemy_t *enemy, array_t *events) { + enemy->alive = 1; + array_push(self->alive, &enemy); + + event_t event; + init_event(&event, ENTER); + array_push(events, &event); + + return; +} + +void map_move_1(map_t *self, array_t *events) { + int dead = 0; + + array_deloop(self->alive, ptr, enemy_t*) { + enemy_t *alive = *ptr; + if (alive->alive) + move(self, alive, events, 0); + else + dead++; + } + + if (dead > self->alive->count) { + dead = 0; + array_deloop(self->alive, ptr, enemy_t*) { + if((*ptr)->alive) + break; + dead++; } + + array_cut_at(self->alive, self->alive->count - dead); } - free (self->data ); self->data = NULL; - free_array(self->paths ); self->paths = NULL; - free_array(self->towers ); self->towers = NULL; - free_array(self->enemies); self->enemies = NULL; - free_array(self->alive) ; self->alive = NULL; + if (self->backfill->count) { + enemy_t **ptr = array_first(self->backfill); + enemy_t *enemy = *ptr; + map_enemy_enters(self, enemy, events); + } } -int map_path(map_t *self, int x, int y) { +void map_fire_1(map_t *self, int current_tick, array_t *events) { + array_loop(self->towers, tower, tower_t) { + tower_rearm(tower); + proj_t *target = tower_fire(tower, current_tick, + self->alive, self->paths); + if (!target) + continue; + target->next = self->projs->next; + self->projs->next = target; + } +} + +void map_hit_1(map_t *self, int current_tick, array_t *events) { + proj_t *prev = self->projs; + for (proj_t *p = prev->next ; p ; p = p->next) { + if (p->boom_tick <= current_tick) { + hit(self, p, events); + + prev->next = p->next; + free_proj(p); + p = prev; + } + + prev = p; + } +} + +int setup_path(map_t *self, int x, int y) { if (x < 0 || y < 0) return 0; if (x >= self->width || y >= self->height) @@ -99,11 +174,11 @@ int map_path(map_t *self, int x, int y) { init_path(loc, x, y); loc->index = self->paths->count - 1; - self->data[y * self->width + x] = loc2any(loc); + self->data[y * self->width + x] = path2any(loc); return 1; } -int map_add_tower(map_t *self, tower_t *tower) { +int setup_tower(map_t *self, tower_t *tower) { int x = tower->x; int y = tower->y; if (x < 0 || y < 0) @@ -120,10 +195,73 @@ int map_add_tower(map_t *self, tower_t *tower) { return 1; } -int map_enemy(map_t *self, enemy_t *enemy) { - if (!array_push(self->enemies, enemy)) - return 0; +void move(map_t *self, enemy_t *enemy, array_t *events, int reverse) { + int source = enemy->index; + int target = source >= 0 ? source+1 : 0; + event_t event; + init_event(&event, MOVE); - return 1; + path_t *path_from = NULL; + if (enemy->index >= 0) { + path_from = array_get(self->paths, enemy->index); + path_from->enemy = NULL; + event.x = path_from->x; + event.y = path_from->y; + } + + if (reverse) { + target = source-1; + if (target == -1) { // backfill + enemy->alive = 0; + array_push(self->backfill, &enemy); + event.type = BACKFILL; + array_push(events, &event); + return; + } + } + + path_t *path_to = array_get(self->paths, target); + if (path_to && path_to->enemy) // replace + move(self, path_to->enemy, events, 1); + + if (path_to) { // move + event.move_to_x = path_to->x; + event.move_to_y = path_to->y; + path_to->enemy = enemy; + enemy->index = path_to->index; + } else { // breached + enemy->alive = 0; + array_push(self->breached, &enemy); + event.type = BREACH; + } + + array_push(events, &event); + + return; +} + +void hit(map_t *self, proj_t *proj, array_t *events) { + // TODO: loop through alive for radius? tower needs the same + any_t *any = self->data[proj->y * self->width + proj->x]; + path_t *path = anypath(any); + enemy_t *e = (path) ? path->enemy : NULL; + + if (e && e->hp > 0) { + e->hp -= proj->desc.damage; + + event_t event; + if (e->hp <= 0) { + e->hp = 0; + e->alive = 0; + path->enemy = NULL; + init_event(&event, DIE); + } else { + init_event(&event, HIT); + } + + event.x = path->x; + event.y = path->y; + array_push(events, &event); + } } diff --git a/src/tdef/map.h b/src/tdef/map.h index e8c4ff1..16899f6 100644 --- a/src/tdef/map.h +++ b/src/tdef/map.h @@ -26,10 +26,12 @@ typedef struct { int width; int height; any_t **data; - array_t *paths; - array_t *towers; - array_t *enemies; - array_t *alive; + array_t *paths; // path + array_t *towers; // tower* + array_t *alive; // enemy* + array_t *breached; // enemy* + array_t *backfill; // enemy* + proj_t *projs; // first one is fake (list head) } map_t; /** @@ -76,11 +78,17 @@ void free_map(map_t *self); */ void uninit_map(map_t *self); -int map_path(map_t *self, int x, int y); +void map_enemy_enters(map_t *self, enemy_t *enemy, array_t *events); -int map_add_tower(map_t *self, tower_t *tower); +void map_move_1(map_t *self, array_t *events); -int map_enemy(map_t *self, enemy_t *enemy); +void map_fire_1(map_t *self, int current_tick, array_t *events); + +void map_hit_1(map_t *self, int current_tick, array_t *events); + +int setup_path(map_t *self, int x, int y); + +int setup_tower(map_t *self, tower_t *tower); #endif /* MAP_H */ diff --git a/src/tdef/path.c b/src/tdef/path.c index 0f8bb82..70cf979 100644 --- a/src/tdef/path.c +++ b/src/tdef/path.c @@ -34,7 +34,7 @@ path_t *new_path(int x, int y) { int init_path(path_t *self, int x, int y) { size_t sz = sizeof(self->CNAME); - strncpy(self->CNAME, "[loc ", sz); + strncpy(self->CNAME, "[path ", sz); self->CNAME[sz - 2] = ']'; self->CNAME[sz - 1] = '\0'; diff --git a/src/tdef/proj.c b/src/tdef/proj.c new file mode 100644 index 0000000..c405dcf --- /dev/null +++ b/src/tdef/proj.c @@ -0,0 +1,74 @@ +/* + * 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 + +#include "proj.h" + +int init_proj_desc(proj_desc_t *self) { + size_t sz = sizeof(self->CNAME); + strncpy(self->CNAME, "[proj_desc ", sz); + self->CNAME[sz - 2] = ']'; + self->CNAME[sz - 1] = '\0'; + + self->damage = 0; + self->splash_damage = 0; + self->radius = 0; + + return 1; +} + +proj_t *new_proj(int x, int y) { + proj_t *self = malloc(sizeof(proj_t)); + if (!init_proj(self, x, y)) { + free(self); + self = NULL; + } + + return self; +} + +int init_proj(proj_t *self, int x, int y) { + size_t sz = sizeof(self->CNAME); + strncpy(self->CNAME, "[proj ", sz); + self->CNAME[sz - 2] = ']'; + self->CNAME[sz - 1] = '\0'; + + self->x = x; + self->y = y; + init_proj_desc(&self->desc); + self->next = NULL; + + return 1; +} + +void free_proj(proj_t *self) { + if (self) + uninit_proj(self); + + free(self); +} + +void uninit_proj(proj_t *self) { + self->CNAME[0] = '!'; + self->desc.CNAME[0] = '!'; +} + diff --git a/src/tdef/proj.h b/src/tdef/proj.h new file mode 100644 index 0000000..8dfb3d3 --- /dev/null +++ b/src/tdef/proj.h @@ -0,0 +1,87 @@ +/** + * @file proj.h + * @author Niki + * @date 2025 + * + * @brief bla + * + * blablabla + * + */ + +#ifndef PROJ_H +#define PROJ_H + +#include "cutils/array.h" + +typedef struct { + char CNAME[10]; + int damage; + int splash_damage; + int radius; // 0 = no splash damage +} proj_desc_t; + +int init_proj_desc(proj_desc_t *self); + +/** + * @brief bla + * + * blablabla + */ +struct proj_struct; +struct proj_struct { + char CNAME[10]; + int x; // target X + int y; // target Y + int boom_tick; + proj_desc_t desc; + struct proj_struct *next; +}; +typedef struct proj_struct proj_t; + +/** + * Create a new proj. + * + * @param x the X coordinate of the projectile's target location + * @param y the Y coordinate of the projectile's target location + * + * @note always identical to malloc + init_proj + * + * @see malloc() + * @see init_proj(proj_t *self) + * + * @return a new proj (you must later call `free_proj()`) + */ +proj_t *new_proj(int x, int y); + +/** + * Initialise a new proj. + * + * @param x the X coordinate of the projectile's target location + * @param y the Y coordinate of the projectile's target location + */ +int init_proj(proj_t *self, int x, int y); + +/** + * Free the resources held for the given proj: you must not use it any more. + * + * @note always equivalent to uninit_proj + free + * + * @see uninit_proj(proj_t *self) + * @see free(void *data) + */ +void free_proj(proj_t *self); + +/** + * Free the resources held for the given proj: you must not use it any more + * unless you call init_proj on it again. + * + * The memory pointed to by self is not free'd. + * + * + * @see init_proj(proj_t *self) + */ +void uninit_proj(proj_t *self); + +#endif /* PROJ_H */ + diff --git a/src/tdef/reader.c b/src/tdef/reader.c index 73a99d5..dab3b46 100644 --- a/src/tdef/reader.c +++ b/src/tdef/reader.c @@ -1,5 +1,5 @@ /* - * TDef: small reader defense game + * TDef: small tower defense game * * Copyright (C) 2025 Niki Roo * @@ -24,6 +24,16 @@ #include "reader.h" +// TODO: configuration: +// map size +// path: (1,1), (1,2)... +// basic: setMoney, setLife, start... +// tower: configTower('1', ...) +// enemy: configEnemy('a', ...) + +// TODO: +// display: could be a mode (auto after tick) + command read_command(FILE *file) { static cstring_t *line = NULL; @@ -33,7 +43,7 @@ command read_command(FILE *file) { if (cstring_readline(line, file)) { if (!strcmp(".", line->string)) { return TICK; - } else if (!strcmp("=", line->string)) { + } else if (!strcmp("display", line->string)) { return DISPLAY; } else { return UNKNOWN; diff --git a/src/tdef/tdef.c b/src/tdef/tdef.c index 8afc523..edfce3b 100644 --- a/src/tdef/tdef.c +++ b/src/tdef/tdef.c @@ -25,37 +25,61 @@ #include "map.h" #include "engine.h" #include "reader.h" +#include "event.h" void display(map_t *self) { - printf("==========\n\n"); + fprintf(stderr, "==========\n\n"); for (int y = 0 ; y < self->height; y++) { for (int x = 0 ; x < self->width ; x++) { any_t *any = self->data[y * self->width + x]; - path_t *path = anyloc(any); + path_t *path = anypath(any); tower_t *tower = anytower(any); if (tower) { - printf("T"); + fprintf(stderr, "T"); } else if (path) { if (path->enemy) { - printf("e"); + fprintf(stderr, "e"); } else if (path->index == 0) { - printf(">"); + fprintf(stderr, ">"); } else if (path->index == self->paths->count - 1) { - printf(">"); + fprintf(stderr, ">"); } else { - printf("#"); + fprintf(stderr, "#"); } } else if (any) { - printf("?"); - //printf("\n<%s>\n", any->CNAME); + fprintf(stderr, "?"); + //fprintf("stderr, \n<%s>\n", any->CNAME); } else { - printf("."); + fprintf(stderr, "."); } } - printf("\n"); + fprintf(stderr, "\n"); } - printf("\n"); + fprintf(stderr, "\n"); +} + +void display_event(event_t *self) { + const char *name = event_name(self); + + switch (self->type) { + case FIRE: case HIT: case MOVE: + fprintf(stderr, "[*] %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(stderr, "[*] %s: (%d,%d)\n", name, self->x, self->y); + break; + case ENTER: case WIN: case LOOSE: + fprintf(stderr, "[*] %s\n", name); + break; + } +} + +void output_event(event_t *self, FILE *file) { + const char *name = event_name(self); + fwrite(name, 1, strlen(name), file); + fwrite("\n",1, 1, file); } int main(int argc, char **argv) { @@ -65,38 +89,57 @@ int main(int argc, char **argv) { return 1; } - map_path(map, 0, 0); - map_path(map, 1, 0); - map_path(map, 2, 0); - map_path(map, 3, 0); - map_path(map, 3, 1); - map_path(map, 3, 2); - map_path(map, 4, 2); - map_path(map, 5, 2); + engine_t *engine = new_engine(map); + if (!engine) { + fprintf(stderr, "Cannot create the engine"); + return 2; + } + + setup_path(map, 0, 0); + setup_path(map, 1, 0); + setup_path(map, 2, 0); + setup_path(map, 3, 0); + setup_path(map, 3, 1); + setup_path(map, 3, 2); + setup_path(map, 4, 2); + setup_path(map, 5, 2); tower_t *tower = new_tower(2, 1); - map_add_tower(map, tower); + setup_tower(map, tower); enemy_t *enemy = new_enemy(1); enemy->speed = 1; - map_enemy(map, enemy); - - engine_t *engine = new_engine(map); + setup_enemy(engine, enemy); - printf("Paths: %d\n", map->paths->count); + int displayMode = 0; command cmd = read_command(stdin); while (cmd != QUIT) { switch(cmd) { case TICK: - printf("Tick is: %d\n", engine->current_tick); engine_tick(engine); + array_loop(engine->events, event, event_t) { + output_event(event, stdout); + } + if (displayMode) { + fprintf(stderr, + "Tick is: %d\n", engine->current_tick); + array_loop(engine->events, event, event_t) { + display_event(event); + } + display(map); + } break; case DISPLAY: - display(map); + displayMode = !displayMode; + if (displayMode) { + fprintf(stderr, + "Tick is: %d\n", engine->current_tick); + display(map); + } break; case UNKNOWN: - printf("Unrecognized command\n"); + fprintf(stderr, "Unrecognized command\n"); break; case QUIT: // cannot happen, but kept for warning purposes @@ -106,7 +149,6 @@ int main(int argc, char **argv) { cmd = read_command(stdin); } - free_engine(engine); return 0; } diff --git a/src/tdef/tower.c b/src/tdef/tower.c index 40aa981..de58076 100644 --- a/src/tdef/tower.c +++ b/src/tdef/tower.c @@ -38,8 +38,15 @@ int init_tower(tower_t *self, int x, int y) { self->CNAME[sz - 2] = ']'; self->CNAME[sz - 1] = '\0'; - self->x = x; - self->y = y; + self->x = x; + self->y = y; + self->range = 0; + self->speed = 0; + self->super = 0; + self->fire_delay = 0; + self->fire_delayed = 0; + + init_proj_desc(&self->projectile); return 1; } @@ -55,3 +62,32 @@ void uninit_tower(tower_t *self) { self->CNAME[0] = '!'; } +void tower_rearm(tower_t *self) { + if (self->fire_delayed > 0) + self->fire_delayed--; +} + +proj_t *tower_fire(tower_t *self, int current_tick, array_t *enemies, + array_t *path) { + + if (self->fire_delayed > 0) + return NULL; + + // TODO: + // select target (3 modes) + // check target expected position + // fire at position if <= range + // (skip to next if not) + + // If not found: return NULL; + + proj_t *proj = new_proj(3, 0); // TODO + proj->desc = self->projectile; + proj->desc.damage = 10; // TODO + proj->boom_tick = current_tick + 3; // TODO: compute from speed + + self->fire_delayed = self->fire_delay; + + return proj; +} + diff --git a/src/tdef/tower.h b/src/tdef/tower.h index 890b454..103b92e 100644 --- a/src/tdef/tower.h +++ b/src/tdef/tower.h @@ -12,6 +12,9 @@ #ifndef TOWER_H #define TOWER_H +#include "cutils/array.h" +#include "proj.h" + /** * @brief bla * @@ -21,6 +24,12 @@ typedef struct { char CNAME[10]; int x; int y; + int range; + int speed; // speed of the proj in locs per tick + int super; + int fire_delay; // in ticks + int fire_delayed; // in ticks still to wait + proj_desc_t projectile; } tower_t; /** @@ -67,4 +76,9 @@ void free_tower(tower_t *self); */ void uninit_tower(tower_t *self); +void tower_rearm(tower_t *self); + +proj_t *tower_fire(tower_t *self, int current_tick, array_t *enemies, + array_t *path); + #endif /* TOWER_H */