#include <stdlib.h>
#include "tower.h"
+#include "path.h"
+
+array_t *enemies_in_range(tower_t *self, array_t *enemies);
+array_t *paths_in_range(tower_t *self, array_t *paths);
+int at_p_in(int x, int y, path_t *path, int speed);
+path_t *get_target(tower_t *self, array_t *enemies, array_t *paths);
tower_t *new_tower(tower_base_t *base, int x, int y) {
tower_t *self = malloc(sizeof(tower_t));
}
proj_t *tower_fire(tower_t *self, int current_tick, array_t *enemies,
- array_t *path) {
+ array_t *paths) {
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;
+ path_t *target = get_target(self, enemies, paths);
+ if (!target)
+ return NULL;
int attack = self->base->stats[self->lvl_attack].attack;
- int speed = self->base->stats[self->lvl_speed].speed;
+ int speed = self->base->stats[self->lvl_speed ].speed;
+ int range = self->base->stats[self->lvl_range ].range;
- proj_t *proj = new_proj(3, 0); // TODO
+ proj_t *proj = new_proj(target->x, target->y);
proj->desc = self->projectile;
proj->desc.damage = attack;
proj->boom_tick = current_tick + 3; // TODO: compute from speed
- self->fire_delayed = self->base->stats[self->lvl_speed].attack;
+ self->fire_delayed = speed;
return proj;
}
+array_t *enemies_in_range(tower_t *self, array_t *enemies) {
+ array_t *in_range = new_array(sizeof(enemy_t*), enemies->count/2+1);
+
+ return in_range;
+}
+
+array_t *paths_in_range(tower_t *self, array_t *paths) {
+ array_t *in_range = new_array(sizeof(path_t *), paths->count/2+1);
+
+ return in_range;
+}
+
+int at_p_in(int x, int y, path_t *path, int speed) {
+ // TODO
+ return 1;
+}
+
+path_t *get_target(tower_t *self, array_t *enemies, array_t *paths) {
+ enemy_t *e_target = NULL;
+ path_t *p_target = NULL;
+
+ // TODO: move to configurable
+ #define TARGET_FIRST 0
+ #define TARGET_LAST 1
+ #define TARGET_WEAKER 2
+ #define TARGET_STRONGER 3
+ int mode = TARGET_FIRST;
+
+
+ // TODO: move paths_in_range as a member of tower_t, cache it
+ array_t *e_in_range = enemies_in_range(self, enemies);
+ array_t *p_in_range = (e_in_range->count) ?
+ paths_in_range(self, paths)
+ : new_array(sizeof(enemy_t*), 0);
+
+ if (e_in_range->count && p_in_range->count)
+ array_loop (p_in_range, pptr, path_t*) {
+ path_t *p = *pptr;
+ int proj_at_p_in = at_p_in(
+ self->x, self->y, p, self->proj_speed
+ );
+
+ array_loop (e_in_range, eptr, enemy_t*) {
+ enemy_t *e = *eptr;
+ path_t *e_p = (path_t*)array_get(paths, e->index);
+ int enemy_at_p_in = at_p_in(
+ e_p->x, e_p->y, p, e->base->speed
+ );
+
+ if (proj_at_p_in == enemy_at_p_in) {
+ int take_it = 0;
+ switch(mode) {
+ case TARGET_FIRST:
+ if (!e_target)
+ take_it = 1;
+ break;
+ case TARGET_LAST:
+ take_it = 1;
+ break;
+ case TARGET_WEAKER:
+ if (!e_target || e->hp < e_target->hp)
+ take_it = 1;
+ break;
+ case TARGET_STRONGER:
+ if (!e_target || e->hp > e_target->hp)
+ take_it = 1;
+ break;
+ }
+
+ if (take_it) {
+ e_target = e;
+ p_target = p;
+ }
+ }
+ }
+ }
+
+ free_array(p_in_range);
+ free_array(e_in_range);
+
+ return p_target;
+}
+