1 #include "formation_enemy.h"
2
3 #include "building/building.h"
4 #include "city/buildings.h"
5 #include "city/figures.h"
6 #include "city/gods.h"
7 #include "city/message.h"
8 #include "core/calc.h"
9 #include "core/random.h"
10 #include "figure/enemy_army.h"
11 #include "figure/figure.h"
12 #include "figure/formation.h"
13 #include "figure/formation_layout.h"
14 #include "figure/route.h"
15 #include "map/figure.h"
16 #include "map/grid.h"
17 #include "map/routing.h"
18 #include "map/routing_path.h"
19 #include "map/soldier_strength.h"
20 #include "map/terrain.h"
21
22 #define INFINITE 10000
23
24 static const int ENEMY_ATTACK_PRIORITY[4][100] = {
25 {
26 BUILDING_GRANARY, BUILDING_WAREHOUSE, BUILDING_MARKET,
27 BUILDING_WHEAT_FARM, BUILDING_VEGETABLE_FARM, BUILDING_FRUIT_FARM,
28 BUILDING_OLIVE_FARM, BUILDING_VINES_FARM, BUILDING_PIG_FARM, 0
29 },
30 {
31 BUILDING_SENATE_UPGRADED, BUILDING_SENATE,
32 BUILDING_FORUM_UPGRADED, BUILDING_FORUM, 0
33 },
34 {
35 BUILDING_GOVERNORS_PALACE, BUILDING_GOVERNORS_VILLA, BUILDING_GOVERNORS_HOUSE,
36 BUILDING_HOUSE_LUXURY_PALACE, BUILDING_HOUSE_LARGE_PALACE,
37 BUILDING_HOUSE_MEDIUM_PALACE, BUILDING_HOUSE_SMALL_PALACE,
38 BUILDING_HOUSE_GRAND_VILLA, BUILDING_HOUSE_LARGE_VILLA,
39 BUILDING_HOUSE_MEDIUM_VILLA, BUILDING_HOUSE_SMALL_VILLA,
40 BUILDING_HOUSE_GRAND_INSULA, BUILDING_HOUSE_LARGE_INSULA,
41 BUILDING_HOUSE_MEDIUM_INSULA, BUILDING_HOUSE_SMALL_INSULA,
42 BUILDING_HOUSE_LARGE_CASA, BUILDING_HOUSE_SMALL_CASA,
43 BUILDING_HOUSE_LARGE_HOVEL, BUILDING_HOUSE_SMALL_HOVEL,
44 BUILDING_HOUSE_LARGE_SHACK, BUILDING_HOUSE_SMALL_SHACK,
45 BUILDING_HOUSE_LARGE_TENT, BUILDING_HOUSE_SMALL_TENT, 0
46 },
47 {
48 BUILDING_MILITARY_ACADEMY, BUILDING_PREFECTURE, 0
49 }
50 };
51
52 static const int RIOTER_ATTACK_PRIORITY[29] = {
53 BUILDING_GOVERNORS_PALACE,
54 BUILDING_GOVERNORS_VILLA,
55 BUILDING_GOVERNORS_HOUSE,
56 BUILDING_AMPHITHEATER,
57 BUILDING_THEATER,
58 BUILDING_HOSPITAL,
59 BUILDING_ACADEMY,
60 BUILDING_BATHHOUSE,
61 BUILDING_LIBRARY,
62 BUILDING_SCHOOL,
63 BUILDING_DOCTOR,
64 BUILDING_GLADIATOR_SCHOOL,
65 BUILDING_ACTOR_COLONY,
66 BUILDING_CHARIOT_MAKER,
67 BUILDING_LION_HOUSE,
68 BUILDING_BARBER,
69 BUILDING_TAVERN,
70 BUILDING_ARENA,
71 BUILDING_HORSE_STATUE,
72 BUILDING_LEGION_STATUE,
73 BUILDING_LARGE_STATUE,
74 BUILDING_MEDIUM_STATUE,
75 BUILDING_OBELISK,
76 BUILDING_HOUSE_LUXURY_PALACE,
77 BUILDING_HOUSE_LARGE_PALACE,
78 BUILDING_HOUSE_MEDIUM_PALACE,
79 BUILDING_HOUSE_SMALL_PALACE,
80 BUILDING_HOUSE_GRAND_VILLA,
81 BUILDING_HOUSE_LARGE_VILLA,
82 };
83
84 static const int LAYOUT_ORIENTATION_OFFSETS[13][4][40] = {
85 {
86 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
87 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
88 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
89 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
90 },
91 {
92 {0, 0, -6, 0, 6, 0, -6, 2, 6, 2, -2, 4, 4, 6, 0},
93 {0, 0, 0, -6, 0, 6, 2, -6, 2, 6, 4, -2, 6, 4, 0},
94 {0, 0, -6, 0, 6, 0, -6, -2, 6, -2, -4, -6, 4, -6, 0},
95 {0, 0, 0, -6, 0, 6, -2, -6, -2, 6, -6, -4, -6, 4, 0},
96 },
97 {
98 {0, 0, -6, 0, 6, 0, -6, 2, 6, 2, -2, 4, 4, 6, 0},
99 {0, 0, 0, -6, 0, 6, 2, -6, 2, 6, 4, -2, 6, 4, 0},
100 {0, 0, -6, 0, 6, 0, -6, -2, 6, -2, -4, -6, 4, -6, 0},
101 {0, 0, 0, -6, 0, 6, -2, -6, -2, 6, -6, -4, -6, 4, 0},
102 },
103 {
104 {0, 0, -6, 0, 6, 0, -6, 2, 6, 2, -2, 4, 4, 6, 0},
105 {0, 0, 0, -6, 0, 6, 2, -6, 2, 6, 4, -2, 6, 4, 0},
106 {0, 0, -6, 0, 6, 0, -6, -2, 6, -2, -4, -6, 4, -6, 0},
107 {0, 0, 0, -6, 0, 6, -2, -6, -2, 6, -6, -4, -6, 4, 0},
108 },
109 {
110 {0, 0, -6, 0, 6, 0, -6, 2, 6, 2, -2, 4, 4, 6, 0},
111 {0, 0, 0, -6, 0, 6, 2, -6, 2, 6, 4, -2, 6, 4, 0},
112 {0, 0, -6, 0, 6, 0, -6, -2, 6, -2, -4, -6, 4, -6, 0},
113 {0, 0, 0, -6, 0, 6, -2, -6, -2, 6, -6, -4, -6, 4, 0},
114 },
115 {
116 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
117 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
118 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
119 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
120 },
121 {
122 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
123 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
124 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
125 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
126 },
127 {
128 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
129 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
130 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
131 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
132 },
133 {
134 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
135 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
136 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
137 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
138 },
139 {
140 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
141 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
142 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
143 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
144 },
145 {
146 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
147 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
148 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
149 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
150 },
151 {
152 {0, 0, -4, 0, 4, 0, -12, 0, 12, 0, -4, 12, 4, 12, 0},
153 {0, 0, 0, -4, 0, 4, 0, -12, 0, 12, 12, -4, 12, 4, 0},
154 {0, 0, -4, 0, 4, 0, -12, 0, 12, 0, -4, -12, 4, -12, 0},
155 {0, 0, 0, -4, 0, 4, 0, -12, 0, 12, -12, -4, -12, 4, 0},
156 },
157 {
158 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, 8, 3, 8, 0},
159 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, 8, -3, 8, 3, 0},
160 {0, 0, -3, 0, 3, 0, -8, 0, 8, 0, -3, -8, 3, -8, 0},
161 {0, 0, 0, -3, 0, 3, 0, -8, 0, 8, -8, -3, -8, 3, 0},
162 }
163 };
164
get_best_building(const int * priority_order,int max)165 static building *get_best_building(const int *priority_order, int max)
166 {
167 for (int i = 0; i < max; i++) {
168 building_type type = priority_order[i];
169 for (building *b = building_first_of_type(type); b; b = b->next_of_type) {
170 if (b->state == BUILDING_STATE_IN_USE) {
171 return b;
172 }
173 }
174 }
175 return 0;
176 }
177
get_best_and_closest_building(int x,int y,const int * priority_order,int max)178 static building *get_best_and_closest_building(int x, int y, const int *priority_order, int max)
179 {
180 int min_distance = INFINITE;
181 for (int i = 0; i < max; i++) {
182 building_type type = priority_order[i];
183 building *best_building = 0;
184 for (building *b = building_first_of_type(type); b; b = b->next_of_type) {
185 if (b->state != BUILDING_STATE_IN_USE) {
186 continue;
187 }
188 int distance = calc_maximum_distance(x, y, b->x, b->y);
189 if (distance < min_distance) {
190 best_building = b;
191 min_distance = distance;
192 }
193 }
194 if (best_building) {
195 return best_building;
196 }
197 }
198 return 0;
199 }
200
formation_rioter_get_target_building(int * x_tile,int * y_tile)201 int formation_rioter_get_target_building(int *x_tile, int *y_tile)
202 {
203 building *best_building = get_best_building(RIOTER_ATTACK_PRIORITY, 29);
204 if (!best_building) {
205 return 0;
206 }
207 *x_tile = best_building->x;
208 *y_tile = best_building->y;
209 return best_building->id;
210 }
211
formation_rioter_get_target_building_for_robbery(int x,int y,int * x_tile,int * y_tile)212 int formation_rioter_get_target_building_for_robbery(int x, int y, int *x_tile, int *y_tile)
213 {
214 building *best_building = 0;
215 int closest = INFINITE;
216
217 static const building_type building_targets[] = { BUILDING_SENATE, BUILDING_FORUM };
218 for (int i = 0; i < 2; i++) {
219 building_type type = building_targets[i];
220 for (building *b = building_first_of_type(type); b; b = b->next_of_type) {
221 if (b->state != BUILDING_STATE_IN_USE) {
222 continue;
223 }
224 int distance = calc_maximum_distance(x, y, b->x, b->y);
225 if (distance >= 150) {
226 continue;
227 }
228 if (distance < closest) {
229 closest = distance;
230 best_building = b;
231 }
232 }
233 }
234 if (!best_building) {
235 return 0;
236 }
237
238 *x_tile = best_building->road_access_x;
239 *y_tile = best_building->road_access_y;
240
241 return best_building->id;
242 }
243
set_enemy_target_building(formation * m)244 static void set_enemy_target_building(formation *m)
245 {
246 int attack = m->attack_type;
247 if (attack == FORMATION_ATTACK_RANDOM) {
248 attack = random_byte() & 3;
249 }
250 building *best_building = get_best_and_closest_building(m->x_home, m->y_home, ENEMY_ATTACK_PRIORITY[attack], 100);
251
252 if (!best_building) {
253 // no target buildings left: take rioter attack priority
254 best_building = get_best_and_closest_building(m->x_home, m->y_home, RIOTER_ATTACK_PRIORITY, 29);
255 }
256 if (best_building) {
257 if (best_building->type == BUILDING_WAREHOUSE) {
258 formation_set_destination_building(m, best_building->x + 1, best_building->y, best_building->id + 1);
259 } else {
260 formation_set_destination_building(m, best_building->x, best_building->y, best_building->id);
261 }
262 }
263 }
264
set_native_target_building(formation * m)265 static void set_native_target_building(formation *m)
266 {
267 int meeting_x, meeting_y;
268 city_buildings_main_native_meeting_center(&meeting_x, &meeting_y);
269 building *min_building = 0;
270 int min_distance = INFINITE;
271 for (int i = 1; i < building_count(); i++) {
272 building *b = building_get(i);
273 if (b->state != BUILDING_STATE_IN_USE) {
274 continue;
275 }
276 switch (b->type) {
277 case BUILDING_MISSION_POST:
278 case BUILDING_NATIVE_HUT:
279 case BUILDING_NATIVE_CROPS:
280 case BUILDING_NATIVE_MEETING:
281 case BUILDING_WAREHOUSE:
282 case BUILDING_FORT:
283 case BUILDING_ROADBLOCK:
284 case BUILDING_GARDEN_WALL_GATE:
285 break;
286 default:
287 {
288 int distance = calc_maximum_distance(meeting_x, meeting_y, b->x, b->y);
289 if (distance < min_distance) {
290 min_building = b;
291 min_distance = distance;
292 }
293 }
294 break;
295 }
296 }
297 if (min_building) {
298 formation_set_destination_building(m, min_building->x, min_building->y, min_building->id);
299 }
300 }
301
set_figures_to_initial(const formation * m)302 static void set_figures_to_initial(const formation *m)
303 {
304 for (int i = 0; i < MAX_FORMATION_FIGURES; i++) {
305 if (m->figures[i] > 0) {
306 figure *f = figure_get(m->figures[i]);
307 if (f->action_state != FIGURE_ACTION_149_CORPSE &&
308 f->action_state != FIGURE_ACTION_150_ATTACK) {
309 f->action_state = FIGURE_ACTION_151_ENEMY_INITIAL;
310 f->wait_ticks = 0;
311 }
312 }
313 }
314 }
315
formation_enemy_move_formation_to(const formation * m,int x,int y,int * x_tile,int * y_tile)316 int formation_enemy_move_formation_to(const formation *m, int x, int y, int *x_tile, int *y_tile)
317 {
318 int base_offset = map_grid_offset(
319 formation_layout_position_x(m->layout, 0),
320 formation_layout_position_y(m->layout, 0));
321 int figure_offsets[50];
322 figure_offsets[0] = 0;
323 for (int i = 1; i < m->num_figures; i++) {
324 figure_offsets[i] = map_grid_offset(
325 formation_layout_position_x(m->layout, i),
326 formation_layout_position_y(m->layout, i)) - base_offset;
327 }
328 map_routing_noncitizen_can_travel_over_land(x, y, -1, -1, 0, 600);
329 for (int r = 0; r <= 10; r++) {
330 int x_min, y_min, x_max, y_max;
331 map_grid_get_area(x, y, 1, r, &x_min, &y_min, &x_max, &y_max);
332 for (int yy = y_min; yy <= y_max; yy++) {
333 for (int xx = x_min; xx <= x_max; xx++) {
334 int can_move = 1;
335 for (int fig = 0; fig < m->num_figures; fig++) {
336 int grid_offset = map_grid_offset(xx, yy) + figure_offsets[fig];
337 if (!map_grid_is_valid_offset(grid_offset)) {
338 can_move = 0;
339 break;
340 }
341 if (map_terrain_is(grid_offset, TERRAIN_IMPASSABLE_ENEMY)) {
342 can_move = 0;
343 break;
344 }
345 if (map_routing_distance(grid_offset) <= 0) {
346 can_move = 0;
347 break;
348 }
349 if (map_has_figure_at(grid_offset) &&
350 figure_get(map_figure_at(grid_offset))->formation_id != m->id) {
351 can_move = 0;
352 break;
353 }
354 }
355 if (can_move) {
356 *x_tile = xx;
357 *y_tile = yy;
358 return 1;
359 }
360 }
361 }
362 }
363 return 0;
364 }
365
mars_kill_enemies(void)366 static void mars_kill_enemies(void)
367 {
368 int to_kill = city_god_spirit_of_mars_power();
369 if (to_kill <= 0) {
370 return;
371 }
372 int grid_offset = 0;
373 for (int i = 1; i < figure_count() && to_kill > 0; i++) {
374 figure *f = figure_get(i);
375 if (f->state != FIGURE_STATE_ALIVE) {
376 continue;
377 }
378 if (figure_is_enemy(f) && f->type != FIGURE_ENEMY54_GLADIATOR) {
379 f->action_state = FIGURE_ACTION_149_CORPSE;
380 to_kill--;
381 if (!grid_offset) {
382 grid_offset = f->grid_offset;
383 }
384 }
385 }
386 city_god_spirit_of_mars_mark_used();
387 city_message_post(1, MESSAGE_SPIRIT_OF_MARS, 0, grid_offset);
388 }
389
update_enemy_movement(formation * m,int roman_distance)390 static void update_enemy_movement(formation *m, int roman_distance)
391 {
392 const enemy_army *army = enemy_army_get(m->invasion_id);
393 formation_state *state = &m->enemy_state;
394 int regroup = 0;
395 int halt = 0;
396 int pursue_target = 0;
397 int advance = 0;
398 int target_formation_id = 0;
399 if (m->missile_fired) {
400 halt = 1;
401 } else if (m->missile_attack_timeout) {
402 pursue_target = 1;
403 target_formation_id = m->missile_attack_formation_id;
404 } else if (m->wait_ticks < 32) {
405 regroup = 1;
406 state->duration_advance = 4;
407 } else if (army->ignore_roman_soldiers) {
408 halt = 0;
409 regroup = 0;
410 advance = 1;
411 } else {
412 int halt_duration, advance_duration, regroup_duration;
413 if (army->layout == FORMATION_ENEMY_MOB || army->layout == FORMATION_ENEMY12) {
414 switch (m->enemy_legion_index) {
415 case 0:
416 case 1:
417 regroup_duration = 2;
418 advance_duration = 4;
419 halt_duration = 2;
420 break;
421 case 2:
422 case 3:
423 regroup_duration = 2;
424 advance_duration = 5;
425 halt_duration = 3;
426 break;
427 default:
428 regroup_duration = 2;
429 advance_duration = 6;
430 halt_duration = 4;
431 break;
432 }
433 if (!roman_distance) {
434 advance_duration += 6;
435 halt_duration--;
436 regroup_duration--;
437 }
438 } else {
439 if (roman_distance) {
440 regroup_duration = 6;
441 advance_duration = 4;
442 halt_duration = 2;
443 } else {
444 regroup_duration = 1;
445 advance_duration = 12;
446 halt_duration = 1;
447 }
448 }
449 if (state->duration_halt) {
450 state->duration_advance = 0;
451 state->duration_regroup = 0;
452 halt = 1;
453 state->duration_halt--;
454 if (state->duration_halt <= 0) {
455 state->duration_regroup = regroup_duration;
456 set_figures_to_initial(m);
457 regroup = 0;
458 halt = 1;
459 }
460 } else if (state->duration_regroup) {
461 state->duration_advance = 0;
462 state->duration_halt = 0;
463 regroup = 1;
464 state->duration_regroup--;
465 if (state->duration_regroup <= 0) {
466 state->duration_advance = advance_duration;
467 set_figures_to_initial(m);
468 advance = 1;
469 regroup = 0;
470 }
471 } else {
472 state->duration_regroup = 0;
473 state->duration_halt = 0;
474 advance = 1;
475 state->duration_advance--;
476 if (state->duration_advance <= 0) {
477 state->duration_halt = halt_duration;
478 set_figures_to_initial(m);
479 halt = 1;
480 advance = 0;
481 }
482 }
483 }
484
485 if (m->wait_ticks > 32) {
486 mars_kill_enemies();
487 }
488 if (halt) {
489 formation_set_destination(m, m->x_home, m->y_home);
490 } else if (pursue_target) {
491 if (target_formation_id > 0) {
492 const formation *target = formation_get(target_formation_id);
493 if (target->num_figures > 0) {
494 formation_set_destination(m, target->x_home, target->y_home);
495 }
496 } else {
497 formation_set_destination(m, army->destination_x, army->destination_y);
498 }
499 } else if (regroup) {
500 int layout = army->layout;
501 int x_offset = LAYOUT_ORIENTATION_OFFSETS[layout][m->orientation / 2][2 * m->enemy_legion_index] +
502 army->home_x;
503 int y_offset = LAYOUT_ORIENTATION_OFFSETS[layout][m->orientation / 2][2 * m->enemy_legion_index + 1] +
504 army->home_y;
505 int x_tile, y_tile;
506 if (formation_enemy_move_formation_to(m, x_offset, y_offset, &x_tile, &y_tile)) {
507 formation_set_destination(m, x_tile, y_tile);
508 }
509 } else if (advance) {
510 int layout = army->layout;
511 int x_offset = LAYOUT_ORIENTATION_OFFSETS[layout][m->orientation / 2][2 * m->enemy_legion_index] +
512 army->destination_x;
513 int y_offset = LAYOUT_ORIENTATION_OFFSETS[layout][m->orientation / 2][2 * m->enemy_legion_index + 1] +
514 army->destination_y;
515 int x_tile, y_tile;
516 if (formation_enemy_move_formation_to(m, x_offset, y_offset, &x_tile, &y_tile)) {
517 formation_set_destination(m, x_tile, y_tile);
518 }
519 }
520 }
521
update_enemy_formation(formation * m,int * roman_distance)522 static void update_enemy_formation(formation *m, int *roman_distance)
523 {
524 enemy_army *army = enemy_army_get_editable(m->invasion_id);
525 if (enemy_army_is_stronger_than_legions()) {
526 if (m->figure_type != FIGURE_FORT_JAVELIN) {
527 army->ignore_roman_soldiers = 1;
528 }
529 }
530 formation_decrease_monthly_counters(m);
531 if (city_figures_soldiers() <= 0) {
532 formation_clear_monthly_counters(m);
533 }
534 for (int n = 0; n < MAX_FORMATION_FIGURES; n++) {
535 figure *f = figure_get(m->figures[n]);
536 if (f->action_state == FIGURE_ACTION_150_ATTACK) {
537 figure *opponent = figure_get(f->opponent_id);
538 if (!figure_is_dead(opponent) && figure_is_legion(opponent)) {
539 formation_record_fight(m);
540 }
541 }
542 }
543 if (formation_has_low_morale(m)) {
544 for (int n = 0; n < MAX_FORMATION_FIGURES; n++) {
545 figure *f = figure_get(m->figures[n]);
546 if (f->action_state != FIGURE_ACTION_150_ATTACK &&
547 f->action_state != FIGURE_ACTION_149_CORPSE &&
548 f->action_state != FIGURE_ACTION_148_FLEEING) {
549 f->action_state = FIGURE_ACTION_148_FLEEING;
550 figure_route_remove(f);
551 }
552 }
553 return;
554 }
555 if (m->figures[0]) {
556 figure *f = figure_get(m->figures[0]);
557 if (f->state == FIGURE_STATE_ALIVE) {
558 formation_set_home(m, f->x, f->y);
559 }
560 }
561 if (!army->formation_id) {
562 army->formation_id = m->id;
563 army->home_x = m->x_home;
564 army->home_y = m->y_home;
565 army->layout = m->layout;
566 *roman_distance = 0;
567 map_routing_noncitizen_can_travel_over_land(m->x_home, m->y_home, -2, -2, 100000, 300);
568 int x_tile, y_tile;
569 if (map_soldier_strength_get_max(m->x_home, m->y_home, 16, &x_tile, &y_tile)) {
570 *roman_distance = 1;
571 } else if (map_soldier_strength_get_max(m->x_home, m->y_home, 32, &x_tile, &y_tile)) {
572 *roman_distance = 2;
573 }
574 if (army->ignore_roman_soldiers) {
575 *roman_distance = 0;
576 }
577 if (*roman_distance == 1) {
578 // attack roman legion
579 army->destination_x = x_tile;
580 army->destination_y = y_tile;
581 army->destination_building_id = 0;
582 } else {
583 set_enemy_target_building(m);
584 army->destination_x = m->destination_x;
585 army->destination_y = m->destination_y;
586 army->destination_building_id = m->destination_building_id;
587 }
588 }
589 m->enemy_legion_index = army->num_legions++;
590 m->wait_ticks++;
591 formation_set_destination_building(m,
592 army->destination_x, army->destination_y, army->destination_building_id
593 );
594
595 update_enemy_movement(m, *roman_distance);
596 }
597
formation_enemy_update(void)598 void formation_enemy_update(void)
599 {
600 if (enemy_army_total_enemy_formations() <= 0) {
601 enemy_armies_clear_ignore_roman_soldiers();
602 } else {
603 enemy_army_calculate_roman_influence();
604 enemy_armies_clear_formations();
605 int roman_distance = 0;
606 for (int i = 1; i < formation_count(); i++) {
607 formation *m = formation_get(i);
608 if (m->in_use && !m->is_herd && !m->is_legion) {
609 update_enemy_formation(m, &roman_distance);
610 }
611 }
612 }
613 set_native_target_building(formation_get(0));
614 }
615