#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;
}
return NULL;
}
-any_t *loc2any(path_t *self) {
+any_t *path2any(path_t *self) {
return (any_t*)(void*)self;
}
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);
self->CNAME[sz - 1] = '\0';
self->start_tick = start_tick;
+ self->hp = 1;
+ self->speed = 1;
self->index = -1;
+ self->alive = 0;
return 1;
}
int hp;
int speed; // paths per tick
int index; // index in paths
+ int alive;
} enemy_t;
/**
#include <stdlib.h>
#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));
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) {
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;
}
char CNAME[10];
map_t *map;
size_t current_tick;
+ array_t *enemies;
array_t *events;
enemy_t *last_enemy;
+ int life;
} engine_t;
/**
// will clear events on start!
void engine_tick(engine_t *self);
+int setup_enemy(engine_t *self, enemy_t *enemy);
+
#endif /* ENGINE_H */
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#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";
+}
--- /dev/null
+/**
+ * @file event.h
+ * @author Niki
+ * @date 2025
+ *
+ * @brief bla
+ *
+ * blablabla
+ *
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <stddef.h>
+
+/**
+ * @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 <tt>malloc</tt> + <tt>init_event</tt>
+ *
+ * @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 <tt>uninit_event</tt> + <tt>free</tt>
+ *
+ * @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 <tt>init_event</tt> on it again.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_event(event_t *self)
+ */
+void uninit_event(event_t *self);
+
+const char *event_name(event_t *self);
+
+#endif /* EVENT_H */
#include <string.h>
#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));
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;
}
}
}
- 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)
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)
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);
+ }
}
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;
/**
*/
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 */
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';
--- /dev/null
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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] = '!';
+}
+
--- /dev/null
+/**
+ * @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 <tt>malloc</tt> + <tt>init_proj</tt>
+ *
+ * @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 <tt>uninit_proj</tt> + <tt>free</tt>
+ *
+ * @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 <tt>init_proj</tt> on it again.
+ *
+ * The memory pointed to by <tt>self</tt> is <i>not</i> free'd.
+ *
+ *
+ * @see init_proj(proj_t *self)
+ */
+void uninit_proj(proj_t *self);
+
+#endif /* PROJ_H */
+
/*
- * TDef: small reader defense game
+ * TDef: small tower defense game
*
* Copyright (C) 2025 Niki Roo
*
#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;
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;
#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) {
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
cmd = read_command(stdin);
}
-
free_engine(engine);
return 0;
}
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;
}
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;
+}
+
#ifndef TOWER_H
#define TOWER_H
+#include "cutils/array.h"
+#include "proj.h"
+
/**
* @brief bla
*
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;
/**
*/
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 */