diff options
Diffstat (limited to 'gst/units.c')
-rw-r--r-- | gst/units.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/gst/units.c b/gst/units.c new file mode 100644 index 0000000..72089f2 --- /dev/null +++ b/gst/units.c @@ -0,0 +1,212 @@ +#include <stdlib.h> +#include <stdio.h> +#include <units.h> +#include <string.h> + +#include <vec.h> +#include <jsonparse.h> + +void army_grid_init(army *ar) { + if (ar->grid != NULL) free(ar->grid); + ar->grid = (unit**)malloc(sizeof(unit*)*ar->sx*ar->sy); + memset(ar->grid, NULL, sizeof(unit*)*ar->sx*ar->sy); + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + // not using ptoi, don't have map, why have map anyway? + ar->grid[ar->sx*u->gridpos[1]+u->gridpos[0]] = u; + } +} + +void army_init (army *ar, map *m) { + ar->uslen = 0; + ar->sx = m->sx; ar->sy = m->sy; + army_grid_init(ar); +} + +void army_destory(army *ar) { + free(ar->grid); +} + +void unit_init (infos *info, army *ar, map *m, + int x, int y, info_unit *iu, int owner, unit *u) +{ + u->pos[0] = x*m->ts; u->pos[1] = y*m->ts; + u->gridpos[0] = x; u->gridpos[1] = y; + u->info = *iu; + u->owner = owner; + u->hp = info_unit_get_health(info, iu); + u->move_points = 0; + for (int i=0; i<8; u->cooldown[i] = 1, i++); +} + +void army_spawn (army *ar, map *m, unit u) { + ar->us[ar->uslen] = u; + ar->grid[ptoi(m, u.gridpos)] = ar->us+ar->uslen; + ar->uslen++; +} + +void unit_move (army *ar, map *m, unit *u, int *dest) { + ar->grid[ptoi(m, u->gridpos)] = NULL; + u->gridpos[0] = dest[0]; + u->gridpos[1] = dest[1]; + ar->grid[ptoi(m, u->gridpos)] = u; + u->pos[0] = dest[0]*m->ts; + u->pos[1] = dest[1]*m->ts; +} + +void unit_remove (army *ar, map *m, unit *u) { + unit *t = ar->us+ar->uslen-1; + int ux = u->gridpos[0], uy = u->gridpos[1]; + int tx = t->gridpos[0], ty = t->gridpos[1]; + *u = *t; + ar->uslen--; + ar->grid[xytoi(m, tx, ty)] = u; + ar->grid[xytoi(m, ux, uy)] = NULL; + printf("ar->uslen: %d\n", ar->uslen); +} + +void unit_dead (army *ar, map *m, unit *u) { + ar->grid[ptoi(m, u->gridpos)] = NULL; +} + +void unit_search (infos *info, army *ar, map *m, unit *u, + unit **t, float range) +{ + for (int f=0; f<32; t[f] = NULL, f++); + int mult[4][2] = { {1, 1},{1,-1},{-1,-1},{-1,1} }, x, y, dx, dy, tmp; + *t = NULL; + for (int r=1; r<range*1.42 && *t==NULL; r++) { + for (int k=0; k<4 && *t==NULL; k++) { + for (int j=0; j<r && *t==NULL; j++) { + if (k%2==1) { // invert them if k=1 || k=3 + dx = (j)*mult[k][0]; dy = (r-j)*mult[k][1]; + } else { + dx = (r-j)*mult[k][0]; dy = (j)*mult[k][1]; + } + x = u->gridpos[0]+dx; y = u->gridpos[1]+dy; + //printf(" (%d, %d) -> (%d, %d), %d, %d, %d\n", u->gridpos[0], u->gridpos[1], x, y, r, k, j); + if (!(x>=0 && y>=0 && x<m->sx && y<m->sy)) continue; // oob + *t = ar->grid[xytoi(m, x, y)]; + if (*t!=NULL && (*t)->owner == u->owner) *t = NULL; // owner check + if (*t!=NULL && (*t)->hp <= 0) *t = NULL; // owner check + if (*t!=NULL) { + // range check + float diff[2] = { + u->gridpos[0] - (*t)->gridpos[0], + u->gridpos[1] - (*t)->gridpos[1] + }; float mag = vec2_mag(diff); + if (mag > range) *t = NULL; + } + }}} +} + + +typedef struct { unit *u; int *dir; int done; } mcom; +int army_move_step (infos *info, army *ar, map *m) { + int dirs[4][2] = { {1, 0},{0, 1},{-1,0},{0,-1} }; + mcom mcs[ar->uslen]; + int mclen = 0; + float diff[2]; + int orders = 0; + // planning + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + if (u->move_points <= 0) continue; + if (u->hp <= 0) continue; + // search target + unit *t[32]; + unit_search(info, ar, m, u, t, 100); + if (t[0] != NULL) { + // in range to shoot + diff[0] = u->gridpos[0] - t[0]->gridpos[0]; + diff[1] = u->gridpos[1] - t[0]->gridpos[1]; + if (vec2_mag(diff) > /*info->units[u->who].range*/1) { + // movement command issued + float dist[4] = { 9999, 9999, 9999, 9999 }; + for (int j=0; j<4; j++) { + diff[0] = u->gridpos[0]+dirs[j][0] + - t[0]->gridpos[0]; + diff[1] = u->gridpos[1]+dirs[j][1] + - t[0]->gridpos[1]; + dist[j] = vec2_mag(diff); + } + float min = dist[0]; int minj = 0; + for (int j=1; j<4; j++) { + if (dist[j] < min) { min = dist[j]; minj = j; } + } + mcs[mclen].u = u; + mcs[mclen].dir = dirs[minj]; + mcs[mclen].done = 0; + mclen++; + } + } + } + // execution + int sum = 0, lastsum = -1, step = 0; + for (; step<MAXSOLVESTEPS; step++) { + if (sum == lastsum) { break; } + lastsum = sum; + sum = 0; + for (int i=0; i<mclen; i++) { + int dest[2] = { + mcs[i].u->gridpos[0]+mcs[i].dir[0], + mcs[i].u->gridpos[1]+mcs[i].dir[1] + }; + if (!mcs[i].done && ar->grid[ptoi(m, dest)] == NULL) { + unit_move(ar, m, mcs[i].u, dest); + mcs[i].done = 1; + mcs[i].u->move_points -= 1; + orders++; + } + sum += mcs[i].done; + } + } + if (step == MAXSOLVESTEPS) { printf("army: max steps reached\n"); } + if (orders > 0) return 0; + else return 1; +} + +void army_move (infos *info, army *ar, map *m) { + for (int i=0; i<ar->uslen; i++) { + ar->us[i].move_points += info_unit_get_speed(info, &ar->us[i].info); + } + int iter = 0, finished = 0; + for (; iter<5 && !finished; iter++) { + finished = army_move_step(info, ar, m); + } + //printf("stepped %d %d\n", iter, finished); +} + +void army_fire (infos *info, army *ar, map *m) { + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + for (int j=0; j<info->chassis[u->info.chassis].slot_weapon; j++) { + u->cooldown[j] += 1; + } + } + struct dmg { unit *u; float dam; } dmgs[1024*8]; int dmgslen = 0; + unit *t[32]; + for (int i=0; i<ar->uslen; i++) { + unit *u = ar->us+i; + if (u->hp <= 0) continue; + for (int j=0; j<info->chassis[u->info.chassis].slot_weapon; j++) { + if (u->info.weapons[j] == -1) continue; + if (u->cooldown[j] <= 0) continue; + float range = info_unit_get_range(info, &u->info, j); + unit_search(info, ar, m, u, t, range); + if (t[0]!=NULL) { + dmgs[dmgslen].u = t[0]; + dmgs[dmgslen].dam = info_unit_get_damage_target( + info, &u->info, j, &t[0]->info); + dmgslen++; + u->cooldown[j] -= info_unit_get_cooldown(info, &u->info, j); + } + } + } + for (int i=0; i<dmgslen; i++) { + dmgs[i].u->hp -= dmgs[i].dam; + if (dmgs[i].u->hp <= 0) { + unit_dead(ar, m, dmgs[i].u); + } + } +}
\ No newline at end of file |