COMMAND_LIFE,
COMMAND_BITS,
COMMAND_PATH,
+ COMMAND_TOWER,
+ COMMAND_TOWER_LVL,
+ COMMAND_TOWER_SP,
+ COMMAND_WAVE,
+ COMMAND_ENEMY,
+
+ COMMAND_ADD_TOWER,
+
COMMAND_QUIT,
// error management:
void engine_tick(engine_t *self) {
if (!self->map) {
event_t event;
- init_event(&event, ERROR);
- event.x = EEVENT_NOMAP;
+ init_event(&event, EVENT_ERROR);
+ event.error = EEVENT_MAP_NOT_INITIALISED;
array_push(self->events, &event);
return;
if (enemy && (cw < 0 || cw < i)) {
self->current_wave = i;
event_t event;
- init_event(&event, WAVE);
+ init_event(&event, EVENT_WAVE);
event.x = i,
array_push(self->events, &event);
}
self->bits += bits;
event_t event;
- init_event(&event, BITS);
+ init_event(&event, EVENT_BITS);
event.x = bits;
event.move_to_x = self->bits;
array_push(self->events, &event);
if (!base)
return 0;
- if (self->bits < base->cost)
+ if (self->bits < base->cost) {
+ event_t event;
+ init_event(&event, EVENT_ERROR);
+ event.error = EEVENT_NOT_ENOUGH_BITS;
+ array_push(self->events, &event);
+
return 0;
+ }
tower_t **ptr = array_new(self->map->towers);
*ptr = new_tower(base, x, y);
self->bits -= base->cost;
event_t event;
- init_event(&event, BITS);
+ init_event(&event, EVENT_BITS);
event.x = -base->cost;
event.move_to_x = self->bits;
array_push(self->events, &event);
self->CNAME[sz - 2] = ']';
self->CNAME[sz - 1] = '\0';
- self->type = type;
- self->x = -1;
- self->y = -1;
+ self->type = type;
+ self->error = EEVENT_SUCCESS;
+ self->x = -1;
+ self->y = -1;
self->move_to_x = -1;
self->move_to_y = -1;
const char *event_name(event_t *self) {
switch (self->type) {
- case BITS : return "BITS" ;
- 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 WAVE : return "WAVE" ;
- case WIN : return "WIN" ;
- case LOOSE : return "LOOSE" ;
- case ERROR : return "ERROR" ;
+ case EVENT_BITS : return "BITS" ;
+ case EVENT_FIRE : return "FIRE" ;
+ case EVENT_HIT : return "HIT" ;
+ case EVENT_ENTER : return "ENTER" ;
+ case EVENT_BACKFILL: return "BACKFILL";
+ case EVENT_MOVE : return "MOVE" ;
+ case EVENT_DIE : return "DIE" ;
+ case EVENT_BREACH : return "BREACH" ;
+ case EVENT_WAVE : return "WAVE" ;
+ case EVENT_WIN : return "WIN" ;
+ case EVENT_LOOSE : return "LOOSE" ;
+ case EVENT_ERROR : return "ERROR" ;
}
return "Unknown";
}
+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_ALREADY_CONFIGURED : return "ALREADY_CONFIGURED" ;
+ case EEVENT_NOT_ENOUGH_BITS : return "NOT_ENOUGH_BITS" ;
+ }
+
+ 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:
+ case EVENT_FIRE: case EVENT_HIT: case EVENT_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 BREACH:
+ case EVENT_BACKFILL: case EVENT_BREACH:
cstring_addp(out, "EVENT:%s,%d,%d\n", name, self->x, self->y);
break;
- case DIE:
+ case EVENT_DIE:
cstring_addp(out, "EVENT:%s,%d,%d,%d\n", name,
self->x, self->y, self->move_to_x);
break;
- case BITS:
+ case EVENT_BITS:
cstring_addp(out, "EVENT:%s,%d,%d\n", name,
self->x, self->move_to_x);
break;
- case ENTER: case WAVE:
+ case EVENT_ENTER: case EVENT_WAVE:
cstring_addp(out, "EVENT:%s,%d\n", name, self->x);
break;
- case WIN: case LOOSE:
+ case EVENT_WIN: case EVENT_LOOSE:
cstring_addp(out, "EVENT:%s\n", name);
break;
- case ERROR:
- cstring_addp(out, "ERROR: %d\n", self->x);
+ case EVENT_ERROR:
+ cstring_addp(out, "ERROR: %s\n", event_ename(self));
break;
}
}
* blablabla
*/
typedef enum {
- BITS,
- FIRE,
- HIT,
- ENTER,
- BACKFILL,
- MOVE,
- DIE,
- BREACH,
- WAVE,
- WIN,
- LOOSE,
- ERROR,
+ EVENT_BITS,
+ EVENT_FIRE,
+ EVENT_HIT,
+ EVENT_ENTER,
+ EVENT_BACKFILL,
+ EVENT_MOVE,
+ EVENT_DIE,
+ EVENT_BREACH,
+ EVENT_WAVE,
+ EVENT_WIN,
+ EVENT_LOOSE,
+ EVENT_ERROR,
} event_type;
typedef enum {
- EEVENT_NOMAP,
+ EEVENT_SUCCESS,
+ EEVENT_MAP_NOT_INITIALISED,
+ EEVENT_ALREADY_CONFIGURED,
+ EEVENT_NOT_ENOUGH_BITS,
} eevent_type;
/**
typedef struct {
char CNAME[10];
event_type type;
+ eevent_type error;
int x;
int y;
int move_to_x;
const char *event_name(event_t *self);
+const char *event_ename(event_t *self);
+
void event_output(event_t *self, cstring_t *out);
#endif /* EVENT_H */
array_push(self->alive, &enemy);
event_t event;
- init_event(&event, ENTER);
+ init_event(&event, EVENT_ENTER);
event.x = enemy->id;
array_push(events, &event);
void map_fire_1(map_t *self, int current_tick, array_t *events) {
event_t event;
- init_event(&event, FIRE);
+ init_event(&event, EVENT_FIRE);
array_loop(self->towers, ptr, tower_t*) {
tower_t *tower = *ptr;
int source = enemy->index;
int target = source >= 0 ? source+1 : 0;
event_t event;
- init_event(&event, MOVE);
+ init_event(&event, EVENT_MOVE);
path_t *path_from = NULL;
if (enemy->index >= 0) {
if (target == -1) { // backfill
enemy->alive = 0;
array_push(self->backfill, &enemy);
- event.type = BACKFILL;
+ event.type = EVENT_BACKFILL;
array_push(events, &event);
return;
}
} else { // breached
enemy->alive = 0;
array_push(self->breached, &enemy);
- event.type = BREACH;
+ event.type = EVENT_BREACH;
}
array_push(events, &event);
e->hp = 0;
e->alive = 0;
path->enemy = NULL;
- init_event(&event, DIE);
+ init_event(&event, EVENT_DIE);
bits = e->bits;
event.move_to_x = bits;
} else {
- init_event(&event, HIT);
+ init_event(&event, EVENT_HIT);
}
event.x = path->x;
//
// Note that white space around the separators (':' or ',') are allowed.
//
-// Known commands:
-// > . = will process a tick in the game engine
-// > display = will toggle display (debug) mode
-// > readfile : "file1..." = will read commands from the given file(s)
-// > map : width, height = will setup the map (and reset the path)
-// > life : lives = will set the number of life points
-// > bits : bit_amount = will set the current bits (money) balance
-// > path : x1,y1,x2,y2.. = will setup the enemies path (cumulative)
-// > quit = will immediately exit the game
+// Engine commands:
+// * . : will process a tick in the game engine
+// * readfile : will read commands from the given file(s) -- one minimum
+// > (n) "file1..."
+//
+// Setup commands:
+// * map : will setup the map (and reset the path)
+// > (0) width
+// > (1) height
+// * life : will set the number of life points
+// > (0) lives
+// * bits : will set the current bits (money) balance
+// > (0) bits_amount
+// * path : will setup the enemies path (cumulative and ordered)
+// > (n) x1,y1, x2,y2...
+// * tower : will setup a new tower type
+// > (0) type : the unique identifier for this tower type
+// > (1) base_cost
+// * tower_lvl: will configure a tower upgrade level
+// > (0) type : the unique identifier for this tower type
+// > (1) attack : how many points dealt to enemies
+// > (2) speed : the time needed to rearm after having fired
+// > (3) range : the range in locations ("path")
+// > (4) cost : upgrade cost for this level (for each of atk, spd, rng)
+// * tower_sp : set the Super Power of a tower
+// > (0) type : the unique identifier for this tower type
+// > (1) super_cost
+// > (2) super_power
+// * 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_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
+//
+// Other commands:
+// * display : will toggle display (debug) mode
+// * quit : will immediately exit the game
+//
// TODO: configuration:
// tower: configTower('1', ...)
cmd->type = COMMAND_INVALID;
if ((command_read_count(cmd, line->string) % 2) == 1)
cmd->type = COMMAND_INVALID;
+ } else if (is_cmd(line, "tower")) {
+ cmd->type = COMMAND_TOWER;
+ if (!command_read_int(cmd, line->string, 0, 1))
+ 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;
+ } 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))
+ cmd->type = COMMAND_INVALID;
+ } 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;
} else if (is_cmd(line, "quit")) {
cmd->type = COMMAND_QUIT;
if (command_read_count(cmd, line->string))
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
+ 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);
if (!setup_wave(self, 0, 0))
return 0;
- //TODO: type and eney_base_t
+ //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, ERROR);
- event.x = EEVENT_NOMAP;
+ init_event(&event, EVENT_ERROR);
+ event.error = EEVENT_MAP_NOT_INITIALISED;
array_push(self->events, &event);
return 0;
break;
case COMMAND_PATH:
setup_path(
- engine,
- command_get_int(cmd, 0),
- command_get_int(cmd, 1)
+ engine,
+ command_get_int(cmd, 0),
+ command_get_int(cmd, 1)
+ );
+ break;
+ case COMMAND_TOWER:
+ setup_tower_base(
+ engine,
+ command_get_int(cmd, 0),
+ command_get_int(cmd, 1)
+ );
+ break;
+ case COMMAND_TOWER_LVL:
+ break;
+ case COMMAND_TOWER_SP:
+ // TODO
+ printf("TODO: command_tower_sp\n");
+ break;
+ case COMMAND_WAVE:
+ // TODO
+ printf("TODO: command_wave\n");
+ break;
+ case COMMAND_ENEMY:
+ ;enemy_t *enemy = setup_enemy(
+ 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(
+ engine,
+ command_get_int(cmd, 0),
+ command_get_int(cmd, 1),
+ command_get_int(cmd, 2)
);
break;
case COMMAND_QUIT: