Freeciv-3.1: /fast/freeciv/nightly/S3_1/ai/default/aiunit.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
aiunit.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <math.h>
19
20/* utility */
21#include "bitvector.h"
22#include "log.h"
23#include "mem.h"
24#include "rand.h"
25#include "registry.h"
26#include "shared.h"
27#include "timing.h"
28
29/* common */
30#include "city.h"
31#include "combat.h"
32#include "game.h"
33#include "government.h"
34#include "map.h"
35#include "movement.h"
36#include "packets.h"
37#include "specialist.h"
38#include "traderoutes.h"
39#include "unit.h"
40#include "unitlist.h"
41
42/* common/aicore */
43#include "caravan.h"
44#include "pf_tools.h"
45
46/* server */
47#include "barbarian.h"
48#include "citytools.h"
49#include "cityturn.h"
50#include "diplomats.h"
51#include "maphand.h"
52#include "srv_log.h"
53#include "unithand.h"
54#include "unittools.h"
55
56/* server/advisors */
57#include "advbuilding.h"
58#include "advgoto.h"
59#include "advtools.h"
60#include "autoexplorer.h"
61#include "autosettlers.h"
62
63/* ai */
64#include "difficulty.h"
65#include "handicaps.h"
66
67/* ai/default */
68#include "aiair.h"
69#include "aidata.h"
70#include "aidiplomat.h"
71#include "aiferry.h"
72#include "aiguard.h"
73#include "aihand.h"
74#include "aihunt.h"
75#include "ailog.h"
76#include "aiparatrooper.h"
77#include "aiplayer.h"
78#include "aitools.h"
79#include "daicity.h"
80#include "daieffects.h"
81#include "daimilitary.h"
82
83#include "aiunit.h"
84
85
86#define LOGLEVEL_RECOVERY LOG_DEBUG
87#define LOG_CARAVAN LOG_DEBUG
88#define LOG_CARAVAN2 LOG_DEBUG
89#define LOG_CARAVAN3 LOG_DEBUG
90
91static bool dai_find_boat_for_unit(struct ai_type *ait, struct unit *punit);
92static bool dai_caravan_can_trade_cities_diff_cont(struct player *pplayer,
93 struct unit *punit);
94static void dai_manage_caravan(struct ai_type *ait, struct player *pplayer,
95 struct unit *punit);
96static void dai_manage_barbarian_leader(struct ai_type *ait,
97 struct player *pplayer,
98 struct unit *leader);
99
100static void dai_military_findjob(struct ai_type *ait,
101 struct player *pplayer, struct unit *punit);
102static void dai_military_defend(struct ai_type *ait, struct player *pplayer,
103 struct unit *punit);
104static void dai_military_attack(struct ai_type *ait, struct player *pplayer,
105 struct unit *punit);
106
107static bool unit_role_defender(const struct unit_type *punittype);
108static int unit_def_rating_squared(const struct unit *punit,
109 const struct unit *pdef);
110
111/*
112 * Cached values. Updated by update_simple_ai_types.
113 *
114 * This a hack to enable emulation of old loops previously hardwired
115 * as
116 * for (i = U_WARRIORS; i <= U_BATTLESHIP; i++)
117 *
118 * (Could probably just adjust the loops themselves fairly simply,
119 * but this is safer for regression testing.)
120 *
121 * Not dealing with planes yet.
122 *
123 * Terminated by NULL.
124 */
125 struct unit_type *simple_ai_types[U_LAST];
126
127/**********************************************************************/
137 static struct city *find_neediest_airlift_city(struct ai_type *ait,
138 const struct player *pplayer)
139{
140 struct city *neediest_city = NULL;
141 int most_danger = 0;
142 int most_urgent = 0;
143
144 city_list_iterate(pplayer->cities, pcity) {
145 struct ai_city *city_data = def_ai_city_data(pcity, ait);
146
147 if (pcity->airlift) {
148 if (city_data->urgency > most_urgent) {
149 most_urgent = city_data->urgency;
150 neediest_city = pcity;
151 } else if (0 == most_urgent /* urgency trumps danger */
152 && city_data->danger > most_danger) {
153 most_danger = city_data->danger;
154 neediest_city = pcity;
155 }
156 }
157 } city_list_iterate_end;
158
159 return neediest_city;
160}
161
162/**********************************************************************/
168 static void dai_airlift(struct ai_type *ait, struct player *pplayer)
169{
170 struct city *most_needed;
171 int comparison;
172 struct unit *transported;
173
174 do {
175 most_needed = find_neediest_airlift_city(ait, pplayer);
176 comparison = 0;
177 transported = NULL;
178
179 if (!most_needed) {
180 return;
181 }
182
183 unit_list_iterate(pplayer->units, punit) {
184 struct tile *ptile = (unit_tile(punit));
185 struct city *pcity = tile_city(ptile);
186
187 if (pcity) {
188 struct ai_city *city_data = def_ai_city_data(pcity, ait);
189 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
190 const struct unit_type *ptype = unit_type_get(punit);
191
192 if (city_data->urgency == 0
193 && city_data->danger - DEFENSE_POWER(ptype) < comparison
194 && unit_can_airlift_to(punit, most_needed)
195 && DEFENSE_POWER(ptype) > 2
196 && (unit_data->task == AIUNIT_NONE
197 || unit_data->task == AIUNIT_DEFEND_HOME)
198 && IS_ATTACKER(ptype)) {
199 comparison = city_data->danger;
200 transported = punit;
201 }
202 }
203 } unit_list_iterate_end;
204 if (!transported) {
205 return;
206 }
207 UNIT_LOG(LOG_DEBUG, transported, "airlifted to defend %s",
208 city_name_get(most_needed));
209 unit_do_action(pplayer, transported->id, most_needed->id,
210 0, "", ACTION_AIRLIFT);
211 } while (TRUE);
212}
213
214/**********************************************************************/
220 static bool has_defense(struct city *pcity)
221{
222 struct tile *ptile = city_tile(pcity);
223
224 unit_list_iterate(ptile->units, punit) {
225 if (is_military_unit(punit) && base_get_defense_power(punit) != 0
226 && punit->hp != 0) {
227 struct unit_class *pclass = unit_class_get(punit);
228
229 if (pclass->non_native_def_pct > 0
230 || is_native_tile_to_class(pclass, ptile)) {
231 return TRUE;
232 }
233 }
234 }
235 unit_list_iterate_end;
236
237 return FALSE;
238}
239
240/**********************************************************************/
248 int build_cost_balanced(const struct unit_type *punittype)
249{
250 return 2 * utype_build_shield_cost_base(punittype) * punittype->attack_strength /
251 (punittype->attack_strength + punittype->defense_strength);
252}
253
254/**********************************************************************/
257 static int unit_att_rating_now(const struct unit *punit)
258{
259 return adv_unittype_att_rating(unit_type_get(punit), punit->veteran,
260 punit->moves_left, punit->hp);
261}
262
263/**********************************************************************/
266 static int unit_att_rating_squared(const struct unit *punit)
267{
268 int v = adv_unit_att_rating(punit);
269
270 return v * v;
271}
272
273/**********************************************************************/
276 static int unit_def_rating(const struct unit *attacker,
277 const struct unit *defender)
278{
279 const struct unit_type *def_type = unit_type_get(defender);
280
281 return (get_total_defense_power(attacker, defender)
282 * (attacker->id != 0 ? defender->hp : def_type->hp)
283 * def_type->firepower / POWER_DIVIDER);
284}
285
286/**********************************************************************/
289 static int unit_def_rating_squared(const struct unit *attacker,
290 const struct unit *defender)
291{
292 int v = unit_def_rating(attacker, defender);
293
294 return v * v;
295}
296
297/**********************************************************************/
302 int unittype_def_rating_squared(const struct unit_type *att_type,
303 const struct unit_type *def_type,
304 struct player *def_player,
305 struct tile *ptile, bool fortified,
306 int veteran)
307{
308 struct civ_map *nmap = &(wld.map);
309 int v = get_virtual_defense_power(nmap, att_type, def_type, def_player,
310 ptile, fortified, veteran)
311 * def_type->hp * def_type->firepower / POWER_DIVIDER;
312
313 return v * v;
314}
315
316/**********************************************************************/
340 adv_want kill_desire(adv_want benefit, int attack, int loss, int vuln,
341 int victim_count)
342{
343 adv_want desire;
344
345 /* attractiveness danger */
346 desire = (benefit * attack - loss * vuln) * victim_count
347 * SHIELD_WEIGHTING / (attack + vuln * victim_count);
348
349 return desire;
350}
351
352/**********************************************************************/
364 static int avg_benefit(int benefit, int loss, double chance)
365{
366 return (int)(((benefit + loss) * chance - loss) * SHIELD_WEIGHTING);
367}
368
369/**********************************************************************/
373 static void reinforcements_cost_and_value(struct unit *punit,
374 struct tile *ptile0,
375 int *value, int *cost)
376{
377 *cost = 0;
378 *value = 0;
379 square_iterate(&(wld.map), ptile0, 1, ptile) {
380 unit_list_iterate(ptile->units, aunit) {
381 if (aunit != punit
382 && pplayers_allied(unit_owner(punit), unit_owner(aunit))) {
383 int val = adv_unit_att_rating(aunit);
384
385 if (val != 0) {
386 *value += val;
387 *cost += unit_build_shield_cost_base(aunit);
388 }
389 }
390 } unit_list_iterate_end;
391 } square_iterate_end;
392}
393
394/**********************************************************************/
398 static bool is_my_turn(struct unit *punit, struct unit *pdef)
399{
400 int val = unit_att_rating_now(punit);
401 int cur, d;
402 const struct unit_type *def_type = unit_type_get(pdef);
403 struct tile *def_tile = unit_tile(pdef);
404 struct civ_map *nmap = &(wld.map);
405
406 CHECK_UNIT(punit);
407
408 square_iterate(nmap, def_tile, 1, ptile) {
409 unit_list_iterate(ptile->units, aunit) {
410 if (aunit == punit || unit_owner(aunit) != unit_owner(punit)) {
411 continue;
412 }
413 if ((unit_attack_units_at_tile_result(aunit, NULL, def_tile)
414 != ATT_OK)
415 || (unit_attack_unit_at_tile_result(aunit, NULL,
416 pdef, def_tile)
417 != ATT_OK)) {
418 continue;
419 }
420 d = get_virtual_defense_power(nmap, unit_type_get(aunit), def_type,
421 unit_owner(pdef), def_tile,
422 FALSE, 0);
423 if (d == 0) {
424 return TRUE; /* Thanks, Markus -- Syela */
425 }
426 cur = unit_att_rating_now(aunit) *
427 get_virtual_defense_power(nmap, unit_type_get(punit), def_type,
428 unit_owner(pdef), def_tile,
429 FALSE, 0) / d;
430 if (cur > val && ai_fuzzy(unit_owner(punit), TRUE)) {
431 return FALSE;
432 }
433 } unit_list_iterate_end;
434 } square_iterate_end;
435
436 return TRUE;
437}
438
439/**********************************************************************/
455 static int dai_rampage_want(struct unit *punit, struct tile *ptile)
456{
457 struct player *pplayer = unit_owner(punit);
458 struct unit *pdef;
459 struct civ_map *nmap = &(wld.map);
460
461 CHECK_UNIT(punit);
462
463 if (can_unit_attack_tile(punit, NULL, ptile)
464 && (pdef = get_defender(nmap, punit, ptile))) {
465 /* See description of kill_desire() about these variables. */
466 int attack = unit_att_rating_now(punit);
467 int benefit = stack_cost(punit, pdef);
468 int loss = unit_build_shield_cost_base(punit);
469
470 attack *= attack;
471
472 /* If the victim is in the city/fortress, we correct the benefit
473 * with our health because there could be reprisal attacks. We
474 * shouldn't send already injured units to useless suicide.
475 * Note that we do not specially encourage attacks against
476 * cities: rampage is a hit-n-run operation. */
477 if (!is_stack_vulnerable(ptile)
478 && unit_list_size(ptile->units) > 1) {
479 benefit = (benefit * punit->hp) / unit_type_get(punit)->hp;
480 }
481
482 /* If we have non-zero attack rating... */
483 if (attack > 0 && is_my_turn(punit, pdef)) {
484 double chance = unit_win_chance(nmap, punit, pdef);
485 int desire = avg_benefit(benefit, loss, chance);
486
487 /* No need to amortize, our operation takes one turn. */
488 UNIT_LOG(LOG_DEBUG, punit, "Rampage: Desire %d to kill %s(%d,%d)",
489 desire,
490 unit_rule_name(pdef),
491 TILE_XY(unit_tile(pdef)));
492
493 return MAX(0, desire);
494 }
495 } else if (0 == unit_list_size(ptile->units)) {
496 /* No defender. */
497 struct city *pcity = tile_city(ptile);
498
499 /* ...and free foreign city waiting for us. Who would resist! */
500 if (NULL != pcity
501 && pplayers_at_war(pplayer, city_owner(pcity))
502 && unit_can_take_over(punit)) {
503 return -RAMPAGE_FREE_CITY_OR_BETTER;
504 }
505
506 /* ...or tiny pleasant hut here! */
507 /* FIXME: unhardcode and variate the desire to enter a hut. */
508 if (unit_can_enter_hut(punit, ptile) && !is_barbarian(pplayer)
509 && is_native_tile(unit_type_get(punit), ptile)) {
510 return -RAMPAGE_HUT_OR_BETTER;
511 }
512 }
513
514 return 0;
515}
516
517/**********************************************************************/
520 static struct pf_path *find_rampage_target(struct unit *punit,
521 int thresh_adj, int thresh_move)
522{
523 struct pf_map *tgt_map;
524 struct pf_path *path = NULL;
525 struct pf_parameter parameter;
526 /* Coordinates of the best target (initialize to silence compiler) */
527 struct tile *ptile = unit_tile(punit);
528 /* Want of the best target */
529 int max_want = 0;
530 struct player *pplayer = unit_owner(punit);
531 const struct civ_map *nmap = &(wld.map);
532
533 pft_fill_unit_attack_param(&parameter, nmap, punit);
534 parameter.omniscience = !has_handicap(pplayer, H_MAP);
535 /* When trying to find rampage targets we ignore risks such as
536 * enemy units because we are looking for trouble!
537 * Hence no call ai_avoid_risks()
538 */
539
540 tgt_map = pf_map_new(&parameter);
541 pf_map_move_costs_iterate(tgt_map, iter_tile, move_cost, FALSE) {
542 int want;
543 bool move_needed;
544 int thresh;
545
546 if (move_cost > punit->moves_left) {
547 /* This is too far */
548 break;
549 }
550
551 if (has_handicap(pplayer, H_TARGETS)
552 && !map_is_known_and_seen(iter_tile, pplayer, V_MAIN)) {
553 /* The target is under fog of war */
554 continue;
555 }
556
557 want = dai_rampage_want(punit, iter_tile);
558
559 /* Negative want means move needed even though the tiles are adjacent */
560 move_needed = (!is_tiles_adjacent(unit_tile(punit), iter_tile)
561 || want < 0);
562 /* Select the relevant threshold */
563 thresh = (move_needed ? thresh_move : thresh_adj);
564 want = (want < 0 ? -want : want);
565
566 if (want > max_want && want > thresh) {
567 /* The new want exceeds both the previous maximum
568 * and the relevant threshold, so it's worth recording */
569 max_want = want;
570 ptile = iter_tile;
571 }
572 } pf_map_move_costs_iterate_end;
573
574 if (max_want > 0) {
575 /* We found something */
576 path = pf_map_path(tgt_map, ptile);
577 fc_assert(path != NULL);
578 }
579
580 pf_map_destroy(tgt_map);
581
582 return path;
583}
584
585/**********************************************************************/
599 bool dai_military_rampage(struct unit *punit, int thresh_adj,
600 int thresh_move)
601{
602 int count = punit->moves_left + 1; /* break any infinite loops */
603 struct pf_path *path = NULL;
604
605 TIMING_LOG(AIT_RAMPAGE, TIMER_START);
606 CHECK_UNIT(punit);
607
608 fc_assert_ret_val(thresh_adj <= thresh_move, TRUE);
609 /* This teaches the AI about the dangers inherent in occupychance. */
610 thresh_adj += ((thresh_move - thresh_adj) * game.server.occupychance / 100);
611
612 while (count-- > 0 && punit->moves_left > 0
613 && (path = find_rampage_target(punit, thresh_adj, thresh_move))) {
614 if (!adv_unit_execute_path(punit, path)) {
615 /* Died */
616 count = -1;
617 }
618 pf_path_destroy(path);
619 path = NULL;
620 }
621
622 fc_assert(NULL == path);
623
624 TIMING_LOG(AIT_RAMPAGE, TIMER_STOP);
625 return (count >= 0);
626}
627
628/**********************************************************************/
632 static void dai_military_bodyguard(struct ai_type *ait, struct player *pplayer,
633 struct unit *punit)
634{
635 struct unit *aunit = aiguard_charge_unit(ait, punit);
636 struct city *acity = aiguard_charge_city(ait, punit);
637 struct tile *ptile;
638
639 CHECK_UNIT(punit);
640 CHECK_GUARD(ait, punit);
641
642 if (aunit && unit_owner(aunit) == unit_owner(punit)) {
643 /* protect a unit */
644 if (aunit->goto_tile != NULL) {
645 /* Our charge is going somewhere: maybe we should meet them there */
646 /* FIXME: This probably isn't the best algorithm for this. */
647 int me2them = real_map_distance(unit_tile(punit), unit_tile(aunit));
648 int me2goal = real_map_distance(unit_tile(punit), aunit->goto_tile);
649 int them2goal = real_map_distance(unit_tile(aunit), aunit->goto_tile);
650
651 if (me2goal < me2them
652 || (me2goal/unit_move_rate(punit) < them2goal/unit_move_rate(aunit)
653 && me2goal/unit_move_rate(punit) < me2them/unit_move_rate(punit)
654 && unit_move_rate(punit) > unit_move_rate(aunit))) {
655 ptile = aunit->goto_tile;
656 } else {
657 ptile = unit_tile(aunit);
658 }
659 } else {
660 ptile = unit_tile(aunit);
661 }
662 } else if (acity && city_owner(acity) == unit_owner(punit)) {
663 /* protect a city */
664 ptile = acity->tile;
665 } else {
666 /* should be impossible */
667 BODYGUARD_LOG(ait, LOG_DEBUG, punit, "we lost our charge");
668 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
669 return;
670 }
671
672 if (same_pos(unit_tile(punit), ptile)) {
673 BODYGUARD_LOG(ait, LOG_DEBUG, punit, "at RV");
674 } else {
675 if (goto_is_sane(punit, ptile)) {
676 BODYGUARD_LOG(ait, LOG_DEBUG, punit, "meeting charge");
677 if (!dai_gothere(ait, pplayer, punit, ptile)) {
678 /* We died */
679 return;
680 }
681 } else {
682 BODYGUARD_LOG(ait, LOG_DEBUG, punit, "can not meet charge");
683 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
684 }
685 }
686 /* We might have stopped because of an enemy nearby.
687 * Perhaps we can kill it.*/
688 if (dai_military_rampage(punit, BODYGUARD_RAMPAGE_THRESHOLD,
689 RAMPAGE_FREE_CITY_OR_BETTER)
690 && same_pos(unit_tile(punit), ptile)) {
691 def_ai_unit_data(punit, ait)->done = TRUE; /* Stay with charge */
692 }
693}
694
695/**********************************************************************/
698 static bool unit_role_defender(const struct unit_type *punittype)
699{
700 return (utype_has_role(punittype, L_DEFEND_GOOD));
701}
702
703/**********************************************************************/
713 adv_want look_for_charge(struct ai_type *ait, struct player *pplayer,
714 struct unit *punit,
715 struct unit **aunit, struct city **acity)
716{
717 struct pf_parameter parameter;
718 struct pf_map *pfm;
719 struct city *pcity;
720 struct ai_city *data, *best_data = NULL;
721 const int toughness = adv_unit_def_rating_basic_squared(punit);
722 int def, best_def = -1;
723 /* Arbitrary: 3 turns. */
724 const int max_move_cost = 3 * unit_move_rate(punit);
725 const struct civ_map *nmap = &(wld.map);
726
727 *aunit = NULL;
728 *acity = NULL;
729
730 if (0 == toughness) {
731 /* useless */
732 return 0;
733 }
734
735 pft_fill_unit_parameter(&parameter, nmap, punit);
736 parameter.omniscience = !has_handicap(pplayer, H_MAP);
737 pfm = pf_map_new(&parameter);
738
739 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
740 if (move_cost > max_move_cost) {
741 /* Consider too far. */
742 break;
743 }
744
745 pcity = tile_city(ptile);
746
747 /* Consider unit bodyguard. */
748 unit_list_iterate(ptile->units, buddy) {
749 const struct unit_type *ptype = unit_type_get(punit);
750 const struct unit_type *buddy_type = unit_type_get(buddy);
751
752 /* TODO: allied unit bodyguard? */
753 if (!dai_can_unit_type_follow_unit_type(ptype, buddy_type, ait)
754 || unit_owner(buddy) != pplayer
755 || !aiguard_wanted(ait, buddy)
756 || unit_move_rate(buddy) > unit_move_rate(punit)
757 || DEFENSE_POWER(buddy_type) >= DEFENSE_POWER(ptype)
758 || (utype_can_do_action_result(buddy_type, ACTRES_ATTACK)
759 && 0 == get_transporter_capacity(buddy)
760 && ATTACK_POWER(buddy_type) <= ATTACK_POWER(ptype))) {
761
762 continue;
763 }
764
765 def = (toughness - adv_unit_def_rating_basic_squared(buddy));
766 if (0 >= def) {
767 continue;
768 }
769
770 if (0 == get_transporter_capacity(buddy)) {
771 /* Reduce want based on move cost. We can't do this for
772 * transports since they move around all the time, leading
773 * to hillarious flip-flops. */
774 def >>= move_cost / (2 * unit_move_rate(punit));
775 }
776 if (def > best_def) {
777 *aunit = buddy;
778 *acity = NULL;
779 best_def = def;
780 }
781 } unit_list_iterate_end;
782
783 /* City bodyguard. TODO: allied city bodyguard? */
784 if (ai_fuzzy(pplayer, TRUE)
785 && NULL != pcity
786 && city_owner(pcity) == pplayer
787 && (data = def_ai_city_data(pcity, ait))
788 && 0 < data->urgency) {
789 if (NULL != best_data
790 && (0 < best_data->grave_danger
791 || best_data->urgency > data->urgency
792 || ((best_data->danger > data->danger
793 || AIUNIT_DEFEND_HOME == def_ai_unit_data(punit, ait)->task)
794 && 0 == data->grave_danger))) {
795 /* Chances are we'll be between cities when we are needed the most!
796 * Resuming pf_map_move_costs_iterate()... */
797 continue;
798 }
799 def = (data->danger - assess_defense_quadratic(ait, pcity));
800 if (def <= 0) {
801 continue;
802 }
803 /* Reduce want based on move cost. */
804 def >>= move_cost / (2 * unit_move_rate(punit));
805 if (def > best_def && ai_fuzzy(pplayer, TRUE)) {
806 *acity = pcity;
807 *aunit = NULL;
808 best_def = def;
809 best_data = data;
810 }
811 }
812 } pf_map_move_costs_iterate_end;
813
814 pf_map_destroy(pfm);
815
816 UNIT_LOG(LOGLEVEL_BODYGUARD, punit, "%s(), best_def=%d, type=%s (%d, %d)",
817 __FUNCTION__, best_def * 100 / toughness,
818 (NULL != *acity ? city_name_get(*acity)
819 : (NULL != *aunit ? unit_rule_name(*aunit) : "")),
820 (NULL != *acity ? index_to_map_pos_x(tile_index(city_tile(*acity)))
821 : (NULL != *aunit ?
822 index_to_map_pos_x(tile_index(unit_tile(*aunit))) : -1)),
823 (NULL != *acity ? index_to_map_pos_y(tile_index(city_tile(*acity)))
824 : (NULL != *aunit ?
825 index_to_map_pos_y(tile_index(unit_tile(*aunit))) : -1)));
826
827 return ((best_def * 100) / toughness);
828}
829
830/**********************************************************************/
833 bool dai_can_unit_type_follow_unit_type(const struct unit_type *follower,
834 const struct unit_type *followee,
835 struct ai_type *ait)
836{
837 struct unit_type_ai *utai = utype_ai_data(follower, ait);
838
839 unit_type_list_iterate(utai->potential_charges, pcharge) {
840 if (pcharge == followee) {
841 return TRUE;
842 }
843 } unit_type_list_iterate_end;
844
845 return FALSE;
846}
847
848/**********************************************************************/
851 static void dai_military_findjob(struct ai_type *ait,
852 struct player *pplayer, struct unit *punit)
853{
854 const struct unit_type *punittype = unit_type_get(punit);
855 struct unit_ai *unit_data;
856 const struct civ_map *nmap = &(wld.map);
857
858 CHECK_UNIT(punit);
859
860 /* Keep barbarians aggressive and primitive */
861 if (is_barbarian(pplayer)) {
862 if (can_unit_do_activity(nmap, punit, ACTIVITY_PILLAGE)
863 && is_land_barbarian(pplayer)) {
864 /* Land barbarians pillage */
865 unit_activity_handling(punit, ACTIVITY_PILLAGE);
866 }
867 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
868
869 return;
870 }
871
872 unit_data = def_ai_unit_data(punit, ait);
873
874 /* If I am a bodyguard, check whether I can do my job. */
875 if (unit_data->task == AIUNIT_ESCORT
876 || unit_data->task == AIUNIT_DEFEND_HOME) {
877 aiguard_update_charge(ait, punit);
878 }
879
880 if (aiguard_has_charge(ait, punit)
881 && unit_data->task == AIUNIT_ESCORT) {
882 struct unit *aunit = aiguard_charge_unit(ait, punit);
883 struct city *acity = aiguard_charge_city(ait, punit);
884 struct ai_city *city_data = NULL;
885
886 if (acity != NULL) {
887 city_data = def_ai_city_data(acity, ait);
888 }
889
890 /* Check if the city we are on our way to rescue is still in danger,
891 * or the unit we should protect is still alive... */
892 if ((aunit && (aiguard_has_guard(ait, aunit) || aiguard_wanted(ait, aunit))
893 && adv_unit_def_rating_basic(punit) > adv_unit_def_rating_basic(aunit))
894 || (acity && city_owner(acity) == unit_owner(punit)
895 && city_data->urgency != 0
896 && city_data->danger > assess_defense_quadratic(ait, acity))) {
897 return; /* Yep! */
898 } else {
899 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL); /* Nope! */
900 }
901 }
902
903 /* Is the unit badly damaged? */
904 if ((unit_data->task == AIUNIT_RECOVER
905 && punit->hp < punittype->hp)
906 || punit->hp < punittype->hp * 0.25) { /* WAG */
907 UNIT_LOG(LOGLEVEL_RECOVERY, punit, "set to hp recovery");
908 dai_unit_new_task(ait, punit, AIUNIT_RECOVER, NULL);
909 return;
910 }
911
912 TIMING_LOG(AIT_BODYGUARD, TIMER_START);
913 if (unit_role_defender(unit_type_get(punit))) {
914 /* This is a defending unit that doesn't need to stay put.
915 * It needs to defend something, but not necessarily where it's at.
916 * Therefore, it will consider becoming a bodyguard. -- Syela */
917 struct city *acity;
918 struct unit *aunit;
919
920 look_for_charge(ait, pplayer, punit, &aunit, &acity);
921 if (acity) {
922 dai_unit_new_task(ait, punit, AIUNIT_ESCORT, acity->tile);
923 aiguard_assign_guard_city(ait, acity, punit);
924 BODYGUARD_LOG(ait, LOG_DEBUG, punit, "going to defend city");
925 } else if (aunit) {
926 dai_unit_new_task(ait, punit, AIUNIT_ESCORT, unit_tile(aunit));
927 aiguard_assign_guard_unit(ait, aunit, punit);
928 BODYGUARD_LOG(ait, LOG_DEBUG, punit, "going to defend unit");
929 }
930 }
931 TIMING_LOG(AIT_BODYGUARD, TIMER_STOP);
932}
933
934/**********************************************************************/
943 static void dai_military_defend(struct ai_type *ait, struct player *pplayer,
944 struct unit *punit)
945{
946 struct city *pcity = aiguard_charge_city(ait, punit);
947
948 CHECK_UNIT(punit);
949
950 if (!pcity || city_owner(pcity) != pplayer) {
951 pcity = tile_city(unit_tile(punit));
952 /* Do not stay defending an allied city forever */
953 aiguard_clear_charge(ait, punit);
954 }
955
956 if (!pcity) {
957 /* Try to find a place to rest. Sitting duck out in the wilderness
958 * is generally a bad idea, since we protect no cities that way, and
959 * it looks silly. */
960 pcity = find_closest_city(unit_tile(punit), NULL, pplayer,
961 FALSE, FALSE, FALSE, TRUE, FALSE,
962 unit_class_get(punit));
963 }
964
965 if (!pcity) {
966 pcity = game_city_by_number(punit->homecity);
967 }
968
969 if (dai_military_rampage(punit, BODYGUARD_RAMPAGE_THRESHOLD * 5,
970 RAMPAGE_FREE_CITY_OR_BETTER)) {
971 /* ... we survived */
972 if (pcity) {
973 UNIT_LOG(LOG_DEBUG, punit, "go to defend %s", city_name_get(pcity));
974 if (same_pos(unit_tile(punit), pcity->tile)) {
975 UNIT_LOG(LOG_DEBUG, punit, "go defend successful");
976 def_ai_unit_data(punit, ait)->done = TRUE;
977 } else {
978 (void) dai_gothere(ait, pplayer, punit, pcity->tile);
979 }
980 } else {
981 UNIT_LOG(LOG_VERBOSE, punit, "defending nothing...?");
982 }
983 }
984}
985
986/**********************************************************************/
989 static void single_invader(struct ai_city *city_data,
990 const struct unit_type *utype,
991 int which)
992{
993 int attacks;
994
995 if (utype_action_takes_all_mp(utype,
996 action_by_number(ACTION_ATTACK))) {
997 attacks = 1;
998 } else {
999 attacks = utype->move_rate;
1000 }
1001 city_data->invasion.attack += attacks;
1002 if (which == INVASION_OCCUPY) {
1003 city_data->invasion.occupy++;
1004 }
1005}
1006
1007/**********************************************************************/
1017 static void invasion_funct(struct ai_type *ait, struct unit *punit,
1018 bool dest, int radius, int which)
1019{
1020 struct tile *ptile;
1021 struct player *pplayer = unit_owner(punit);
1022
1023 CHECK_UNIT(punit);
1024
1025 if (dest) {
1026 ptile = punit->goto_tile;
1027 } else {
1028 ptile = unit_tile(punit);
1029 }
1030
1031 square_iterate(&(wld.map), ptile, radius, tile1) {
1032 struct city *pcity = tile_city(tile1);
1033
1034 if (pcity
1035 && POTENTIALLY_HOSTILE_PLAYER(ait, pplayer, city_owner(pcity))
1036 && (dest || !has_defense(pcity))) {
1037 struct ai_city *city_data = def_ai_city_data(pcity, ait);
1038
1039 /* Unit itself */
1040 single_invader(city_data, unit_type_get(punit), which);
1041
1042 /* Cargo */
1043 unit_cargo_iterate(punit, cargo) {
1044 const struct unit_type *utype = unit_type_get(cargo);
1045
1046 if (IS_ATTACKER(utype)) {
1047 single_invader(city_data, utype,
1048 unit_can_take_over(cargo)
1049 ? INVASION_OCCUPY : INVASION_ATTACK);
1050 }
1051 } unit_cargo_iterate_end;
1052 }
1053 } square_iterate_end;
1054}
1055
1056/**********************************************************************/
1059 bool find_beachhead(const struct player *pplayer, struct pf_map *ferry_map,
1060 struct tile *dest_tile,
1061 const struct unit_type *cargo_type,
1062 struct tile **ferry_dest, struct tile **beachhead_tile)
1063{
1064 if (NULL == tile_city(dest_tile)
1065 || can_attack_from_non_native(cargo_type)) {
1066 /* Unit can directly go to 'dest_tile'. */
1067 struct tile *best_tile = NULL;
1068 int best_cost = PF_IMPOSSIBLE_MC, cost;
1069
1070 if (NULL != beachhead_tile) {
1071 *beachhead_tile = dest_tile;
1072 }
1073
1074 adjc_iterate(&(wld.map), dest_tile, ptile) {
1075 cost = pf_map_move_cost(ferry_map, ptile);
1076 if (cost != PF_IMPOSSIBLE_MC
1077 && (NULL == best_tile || cost < best_cost)) {
1078 best_tile = ptile;
1079 best_cost = cost;
1080 }
1081 } adjc_iterate_end;
1082
1083 if (NULL != ferry_dest) {
1084 *ferry_dest = best_tile;
1085 }
1086
1087 return (PF_IMPOSSIBLE_MC != best_cost);
1088 } else {
1089 /* We need to find a beach around 'dest_tile'. */
1090 struct tile *best_tile = NULL, *best_beach = NULL;
1091 struct tile_list *checked_tiles = tile_list_new();
1092 int best_cost = PF_IMPOSSIBLE_MC, cost;
1093
1094 tile_list_append(checked_tiles, dest_tile);
1095 adjc_iterate(&(wld.map), dest_tile, beach) {
1096 if (is_native_tile(cargo_type, beach)) {
1097 /* Can land there. */
1098 adjc_iterate(&(wld.map), beach, ptile) {
1099 if (!tile_list_search(checked_tiles, ptile)
1100 && !is_non_allied_unit_tile(ptile, pplayer)) {
1101 tile_list_append(checked_tiles, ptile);
1102 cost = pf_map_move_cost(ferry_map, ptile);
1103 if (cost != PF_IMPOSSIBLE_MC
1104 && (NULL == best_tile || cost < best_cost)) {
1105 best_beach = beach;
1106 best_tile = ptile;
1107 best_cost = cost;
1108 }
1109 }
1110 } adjc_iterate_end;
1111 }
1112 } adjc_iterate_end;
1113
1114 tile_list_destroy(checked_tiles);
1115
1116 if (NULL != beachhead_tile) {
1117 *beachhead_tile = best_beach;
1118 }
1119 if (NULL != ferry_dest) {
1120 *ferry_dest = best_tile;
1121 }
1122 return (PF_IMPOSSIBLE_MC != best_cost);
1123 }
1124}
1125
1126/**********************************************************************/
1134 adv_want find_something_to_kill(struct ai_type *ait, struct player *pplayer,
1135 struct unit *punit,
1136 struct tile **pdest_tile, struct pf_path **ppath,
1137 struct pf_map **pferrymap,
1138 struct unit **pferryboat,
1139 const struct unit_type **pboattype, int *pmove_time)
1140{
1141 const int attack_value = adv_unit_att_rating(punit); /* basic attack. */
1142 struct pf_parameter parameter;
1143 struct pf_map *punit_map, *ferry_map;
1144 struct pf_position pos;
1145 struct unit_class *punit_class = unit_class_get(punit);
1146 const struct unit_type *punit_type = unit_type_get(punit);
1147 struct tile *punit_tile = unit_tile(punit);
1148 /* Type of our boat (a future one if ferryboat == NULL). */
1149 const struct unit_type *boattype = NULL;
1150 struct unit *ferryboat = NULL;
1151 struct city *pcity;
1152 struct ai_city *acity_data;
1153 int bcost, bcost_bal; /* Build cost of the attacker (+adjustments). */
1154 bool handicap = has_handicap(pplayer, H_TARGETS);
1155 bool unhap = FALSE; /* Do we make unhappy citizen. */
1156 bool harbor = FALSE; /* Do we have access to sea? */
1157 bool go_by_boat; /* Whether we need a boat or not. */
1158 int vulnerability; /* Enemy defense rating. */
1159 adv_want benefit; /* Benefit from killing the target. */
1160 struct unit *pdefender; /* Enemy city defender. */
1161 int move_time; /* Turns needed to target. */
1162 int reserves;
1163 int attack; /* Our total attack value with reinforcements. */
1164 int victim_count; /* Number of enemies there. */
1165 int needferry; /* Cost of building a ferry boat. */
1166 /* This is a kluge, because if we don't set x and y with !punit->id,
1167 * p_a_w isn't called, and we end up not wanting ironclads and therefore
1168 * never learning steam engine, even though ironclads would be very
1169 * useful. -- Syela */
1170 adv_want bk = 0;
1171 adv_want want; /* Want (amortized) of the operaton. */
1172 adv_want best = 0; /* Best of all wants. */
1173 struct tile *goto_dest_tile = NULL;
1174 bool can_occupy;
1175 struct civ_map *nmap = &(wld.map);
1176
1177 /* Very preliminary checks. */
1178 *pdest_tile = punit_tile;
1179 if (NULL != pferrymap) {
1180 *pferrymap = NULL;
1181 }
1182 if (NULL != pferryboat) {
1183 *pferryboat = NULL;
1184 }
1185 if (NULL != pboattype) {
1186 *pboattype = NULL;
1187 }
1188 if (NULL != pmove_time) {
1189 *pmove_time = 0;
1190 }
1191 if (NULL != ppath) {
1192 *ppath = NULL;
1193 }
1194
1195 if (0 == attack_value) {
1196 /* A very poor attacker... probably low on HP. */
1197 return 0;
1198 }
1199
1200 TIMING_LOG(AIT_FSTK, TIMER_START);
1201
1202
1203 /*** Part 1: Calculate targets ***/
1204
1205 /* This horrible piece of code attempts to calculate the attractiveness of
1206 * enemy cities as targets for our units, by checking how many units are
1207 * going towards it or are near it already. */
1208
1209 /* Reset enemy cities data. */
1210 players_iterate(aplayer) {
1211 /* See comment below in next usage of POTENTIALLY_HOSTILE_PLAYER. */
1212 if ((punit->id == 0 && !POTENTIALLY_HOSTILE_PLAYER(ait, pplayer, aplayer))
1213 || (punit->id != 0 && !pplayers_at_war(pplayer, aplayer))) {
1214 continue;
1215 }
1216 city_list_iterate(aplayer->cities, acity) {
1217 struct ai_city *city_data = def_ai_city_data(acity, ait);
1218
1219 reinforcements_cost_and_value(punit, acity->tile,
1220 &city_data->attack,
1221 &city_data->bcost);
1222 city_data->invasion.attack = 0;
1223 city_data->invasion.occupy = 0;
1224 } city_list_iterate_end;
1225 } players_iterate_end;
1226
1227 /* Second, calculate in units on their way there, and mark targets for
1228 * invasion */
1229 unit_list_iterate(pplayer->units, aunit) {
1230 const struct unit_type *atype;
1231
1232 if (aunit == punit) {
1233 continue;
1234 }
1235
1236 atype = unit_type_get(aunit);
1237
1238 /* Dealing with invasion stuff */
1239 if (IS_ATTACKER(atype)) {
1240 if (aunit->activity == ACTIVITY_GOTO) {
1241 invasion_funct(ait, aunit, TRUE, 0,
1242 (unit_can_take_over(aunit)
1243 ? INVASION_OCCUPY : INVASION_ATTACK));
1244 if ((pcity = tile_city(aunit->goto_tile))) {
1245 struct ai_city *city_data = def_ai_city_data(pcity, ait);
1246
1247 city_data->attack += adv_unit_att_rating(aunit);
1248 city_data->bcost += unit_build_shield_cost_base(aunit);
1249 }
1250 }
1251 invasion_funct(ait, aunit, FALSE, unit_move_rate(aunit) / SINGLE_MOVE,
1252 (unit_can_take_over(aunit)
1253 ? INVASION_OCCUPY : INVASION_ATTACK));
1254 } else if (def_ai_unit_data(aunit, ait)->passenger != 0
1255 && !same_pos(unit_tile(aunit), unit_tile(punit))) {
1256 /* It's a transport with reinforcements */
1257 if (aunit->activity == ACTIVITY_GOTO) {
1258 invasion_funct(ait, aunit, TRUE, 1, INVASION_OCCUPY);
1259 }
1260 invasion_funct(ait, aunit, FALSE, 2, INVASION_OCCUPY);
1261 }
1262 } unit_list_iterate_end;
1263 /* end horrible initialization subroutine */
1264
1265
1266 /*** Part 2: Now pick one target ***/
1267
1268 /* We first iterate through all cities, then all units, looking
1269 * for a viable target. We also try to gang up on the target
1270 * to avoid spreading out attacks too widely to be inefficient.
1271 */
1272
1273 pcity = tile_city(punit_tile);
1274 if (NULL != pcity && (0 == punit->id || pcity->id == punit->homecity)) {
1275 /* I would have thought unhappiness should be taken into account
1276 * irrespectfully the city in which it will surface... -- GB */
1277 unhap = dai_assess_military_unhappiness(pcity);
1278 }
1279
1280 bcost = unit_build_shield_cost_base(punit);
1281 bcost_bal = build_cost_balanced(punit_type);
1282
1283 pft_fill_unit_attack_param(&parameter, nmap, punit);
1284 parameter.omniscience = !has_handicap(pplayer, H_MAP);
1285 punit_map = pf_map_new(&parameter);
1286
1287 if (MOVE_NONE == punit_class->adv.sea_move) {
1288 /* We need boat to move over sea. */
1289 ferryboat = unit_transport_get(punit);
1290
1291 /* First check if we can use the boat we are currently loaded to. */
1292 if (ferryboat == NULL || !is_boat_free(ait, ferryboat, punit, 0)) {
1293 /* No, we cannot control current boat */
1294 ferryboat = NULL;
1295 }
1296
1297 if (NULL == ferryboat) {
1298 /* Try to find new boat */
1299 ferryboat = player_unit_by_number(pplayer,
1300 aiferry_find_boat(ait, punit, 1, NULL));
1301 }
1302
1303 if (punit->id == 0 && is_terrain_class_near_tile(nmap, punit_tile, TC_OCEAN)) {
1304 harbor = TRUE;
1305 }
1306 }
1307
1308 if (NULL != ferryboat) {
1309 boattype = unit_type_get(ferryboat);
1310 pft_fill_unit_overlap_param(&parameter, nmap, ferryboat);
1311 parameter.omniscience = !has_handicap(pplayer, H_MAP);
1312 ferry_map = pf_map_new(&parameter);
1313 } else {
1314 boattype = best_role_unit_for_player(pplayer, L_FERRYBOAT);
1315 if (NULL == boattype) {
1316 /* We pretend that we can have the simplest boat to stimulate tech. */
1317 boattype = get_role_unit(L_FERRYBOAT, 0);
1318 }
1319 if (NULL != boattype && harbor) {
1320 /* Let's simulate a boat at 'punit' position. */
1321 pft_fill_utype_overlap_param(&parameter, nmap, boattype,
1322 punit_tile, pplayer);
1323 parameter.omniscience = !has_handicap(pplayer, H_MAP);
1324 ferry_map = pf_map_new(&parameter);
1325 } else {
1326 ferry_map = NULL;
1327 }
1328 }
1329
1330 can_occupy = unit_can_take_over(punit);
1331
1332 players_iterate(aplayer) {
1333 /* For the virtual unit case, which is when we are called to evaluate
1334 * which units to build, we want to calculate in danger and which
1335 * players we want to make war with in the future. We do _not_ want
1336 * to do this when actually making attacks. */
1337 if ((punit->id == 0 && !POTENTIALLY_HOSTILE_PLAYER(ait, pplayer, aplayer))
1338 || (punit->id != 0 && !pplayers_at_war(pplayer, aplayer))) {
1339 continue; /* Not an enemy. */
1340 }
1341
1342 city_list_iterate(aplayer->cities, acity) {
1343 struct tile *atile = city_tile(acity);
1344
1345 if (!is_native_tile(punit_type, atile)
1346 && !can_attack_non_native(punit_type)) {
1347 /* Can't attack this city. It is on land. */
1348 continue;
1349 }
1350
1351 if (handicap && !map_is_known(atile, pplayer)) {
1352 /* Can't see it */
1353 continue;
1354 }
1355
1356 if (pf_map_position(punit_map, atile, &pos)) {
1357 go_by_boat = FALSE;
1358 move_time = pos.turn;
1359 } else if (NULL == ferry_map) {
1360 continue; /* Impossible to handle. */
1361 } else {
1362 struct tile *dest, *beach;
1363
1364 if (!find_beachhead(pplayer, ferry_map, atile, punit_type,
1365 &dest, &beach)) {
1366 continue; /* Impossible to go by boat. */
1367 }
1368 if (!pf_map_position(ferry_map, dest, &pos)) {
1369 fc_assert(pf_map_position(ferry_map, dest, &pos));
1370 continue;
1371 }
1372 move_time = pos.turn; /* Sailing time. */
1373 if (dest != beach) {
1374 move_time++; /* Land time. */
1375 }
1376 if (NULL != ferryboat && unit_tile(ferryboat) != punit_tile) {
1377 if (pf_map_position(punit_map, unit_tile(ferryboat), &pos)) {
1378 move_time += pos.turn; /* Time to reach the boat. */
1379 } else {
1380 continue; /* Cannot reach the boat. */
1381 }
1382 }
1383 go_by_boat = TRUE;
1384 }
1385
1386 if (can_unit_attack_tile(punit, NULL, city_tile(acity))
1387 && (pdefender = get_defender(nmap, punit, city_tile(acity)))) {
1388 vulnerability = unit_def_rating_squared(punit, pdefender);
1389 benefit = unit_build_shield_cost_base(pdefender);
1390 } else {
1391 pdefender = NULL;
1392 vulnerability = 0;
1393 benefit = 0;
1394 }
1395
1396 if (1 < move_time) {
1397 struct unit_type *def_type = dai_choose_defender_versus(acity, punit);
1398
1399 if (def_type) {
1400 int v = unittype_def_rating_squared(
1401 punit_type, def_type, aplayer, atile, FALSE,
1402 city_production_unit_veteran_level(acity, def_type));
1403 if (v > vulnerability) {
1404 /* They can build a better defender! */
1405 vulnerability = v;
1406 benefit = utype_build_shield_cost(acity, NULL, def_type);
1407 }
1408 }
1409 }
1410
1411 acity_data = def_ai_city_data(acity, ait);
1412
1413 reserves = (acity_data->invasion.attack
1414 - unit_list_size(acity->tile->units));
1415
1416 if (punit->id == 0) {
1417 /* Real unit would add to reserves once built. */
1418 if (utype_action_takes_all_mp(unit_type_get(punit),
1419 action_by_number(ACTION_ATTACK))) {
1420 reserves++;
1421 } else {
1422 reserves += punit_type->move_rate;
1423 }
1424 }
1425
1426 if (0 < reserves && (can_occupy
1427 || 0 < acity_data->invasion.occupy)) {
1428 /* There are units able to occupy the city after all defenders
1429 * are killed! */
1430 benefit += acity_data->worth * reserves / 5;
1431 }
1432
1433 attack = attack_value + acity_data->attack;
1434 attack *= attack;
1435 /* Avoiding handling upkeep aggregation this way -- Syela */
1436
1437 /* AI was not sending enough reinforcements to totally wipe out a city
1438 * and conquer it in one turn.
1439 * This variable enables total carnage. -- Syela */
1440 victim_count = unit_list_size(atile->units);
1441
1442 if (!can_occupy && NULL == pdefender) {
1443 /* Nothing there to bash and we can't occupy!
1444 * Not having this check caused warships yoyoing */
1445 want = 0;
1446 } else if (10 < move_time) {
1447 /* Too far! */
1448 want = 0;
1449 } else if (can_occupy && 0 == acity_data->invasion.occupy
1450 && (0 < acity_data->invasion.attack
1451 || victim_count == 0)) {
1452 /* Units able to occupy really needed there! */
1453 want = bcost * SHIELD_WEIGHTING;
1454 } else {
1455 want = kill_desire(benefit, attack, bcost + acity_data->bcost,
1456 vulnerability, victim_count + 1);
1457 }
1458 want -= move_time * (unhap ? SHIELD_WEIGHTING + 2 * TRADE_WEIGHTING
1459 : SHIELD_WEIGHTING);
1460 /* Build_cost of ferry. */
1461 needferry = (go_by_boat && NULL == ferryboat
1462 ? utype_build_shield_cost(acity, NULL, boattype) : 0);
1463 /* FIXME: add time to build the ferry? */
1464 want = military_amortize(pplayer, game_city_by_number(punit->homecity),
1465 want, MAX(1, move_time),
1466 bcost_bal + needferry);
1467
1468 /* BEGIN STEAM-ENGINES-ARE-OUR-FRIENDS KLUGE. */
1469 if (0 >= want && 0 == punit->id && 0 >= best) {
1470 adv_want bk_e = military_amortize(pplayer,
1471 game_city_by_number(punit->homecity),
1472 benefit * SHIELD_WEIGHTING,
1473 MAX(1, move_time),
1474 bcost_bal + needferry);
1475
1476 if (bk_e > bk) {
1477 *pdest_tile = atile;
1478 if (NULL != pferrymap) {
1479 *pferrymap = go_by_boat ? ferry_map : NULL;
1480 }
1481 if (NULL != pferryboat) {
1482 *pferryboat = go_by_boat ? ferryboat : NULL;
1483 }
1484 if (NULL != pboattype) {
1485 *pboattype = go_by_boat ? boattype : NULL;
1486 }
1487 if (NULL != pmove_time) {
1488 *pmove_time = move_time;
1489 }
1490 goto_dest_tile = (go_by_boat && NULL != ferryboat
1491 ? unit_tile(ferryboat) : atile);
1492 bk = bk_e;
1493 }
1494 }
1495 /* END STEAM-ENGINES KLUGE */
1496
1497 if (0 != punit->id
1498 && NULL != ferryboat
1499 && punit_class->adv.sea_move == MOVE_NONE) {
1500 UNIT_LOG(LOG_DEBUG, punit,
1501 "%s(): with boat %s@(%d, %d) -> %s@(%d, %d)"
1502 " (go_by_boat = %d, move_time = %d, want = " ADV_WANT_PRINTF
1503 ", best = " ADV_WANT_PRINTF ")",
1504 __FUNCTION__, unit_rule_name(ferryboat),
1505 TILE_XY(unit_tile(ferryboat)), city_name_get(acity),
1506 TILE_XY(atile), go_by_boat, move_time, want, best);
1507 }
1508
1509 if (want > best && ai_fuzzy(pplayer, TRUE)) {
1510 /* Yes, we like this target */
1511 best = want;
1512 *pdest_tile = atile;
1513 if (NULL != pferrymap) {
1514 *pferrymap = go_by_boat ? ferry_map : NULL;
1515 }
1516 if (NULL != pferryboat) {
1517 *pferryboat = go_by_boat ? ferryboat : NULL;
1518 }
1519 if (NULL != pboattype) {
1520 *pboattype = go_by_boat ? boattype : NULL;
1521 }
1522 if (NULL != pmove_time) {
1523 *pmove_time = move_time;
1524 }
1525 goto_dest_tile = (go_by_boat && NULL != ferryboat
1526 ? unit_tile(ferryboat) : atile);
1527 }
1528 } city_list_iterate_end;
1529
1530 attack = unit_att_rating_squared(punit);
1531 /* I'm not sure the following code is good but it seems to be adequate.
1532 * I am deliberately not adding ferryboat code to the unit_list_iterate.
1533 * -- Syela */
1534 unit_list_iterate(aplayer->units, aunit) {
1535 struct tile *atile = unit_tile(aunit);
1536
1537 if (NULL != tile_city(atile)) {
1538 /* already dealt with it. */
1539 continue;
1540 }
1541
1542 if (handicap && !map_is_known(atile, pplayer)) {
1543 /* Can't see the target. */
1544 continue;
1545 }
1546
1547 if (!utype_acts_hostile(unit_type_get(aunit))
1548 && 0 == punit->id) {
1549 /* We will not build units just to chase caravans and
1550 * ambassadors. */
1551 continue;
1552 }
1553
1554 /* We have to assume the attack is diplomatically ok.
1555 * We cannot use can_player_attack_tile, because we might not
1556 * be at war with aplayer yet */
1557 if (!can_unit_attack_tile(punit, NULL, atile)
1558 || aunit != get_defender(nmap, punit, atile)) {
1559 /* We cannot attack it, or it is not the main defender. */
1560 continue;
1561 }
1562
1563 if (!pf_map_position(punit_map, atile, &pos)) {
1564 /* Cannot reach it. */
1565 continue;
1566 }
1567
1568 vulnerability = unit_def_rating_squared(punit, aunit);
1569 benefit = unit_build_shield_cost_base(aunit);
1570
1571 move_time = pos.turn;
1572 if (10 < move_time) {
1573 /* Too far. */
1574 want = 0;
1575 } else {
1576 want = kill_desire(benefit, attack, bcost, vulnerability, 1);
1577 /* Take into account maintainance of the unit. */
1578 /* FIXME: Depends on the government. */
1579 want -= move_time * SHIELD_WEIGHTING;
1580 /* Take into account unhappiness
1581 * (costs 2 luxuries to compensate). */
1582 want -= (unhap ? 2 * move_time * TRADE_WEIGHTING : 0);
1583 }
1584 want = military_amortize(pplayer, game_city_by_number(punit->homecity),
1585 want, MAX(1, move_time), bcost_bal);
1586 if (want > best && ai_fuzzy(pplayer, TRUE)) {
1587 best = want;
1588 *pdest_tile = atile;
1589 if (NULL != pferrymap) {
1590 *pferrymap = NULL;
1591 }
1592 if (NULL != pferryboat) {
1593 *pferryboat = NULL;
1594 }
1595 if (NULL != pboattype) {
1596 *pboattype = NULL;
1597 }
1598 if (NULL != pmove_time) {
1599 *pmove_time = move_time;
1600 }
1601 goto_dest_tile = atile;
1602 }
1603 } unit_list_iterate_end;
1604 } players_iterate_end;
1605
1606 if (NULL != ppath) {
1607 *ppath = (NULL != goto_dest_tile && goto_dest_tile != punit_tile
1608 ? pf_map_path(punit_map, goto_dest_tile) : NULL);
1609 }
1610
1611 pf_map_destroy(punit_map);
1612 if (NULL != ferry_map
1613 && (NULL == pferrymap || *pferrymap != ferry_map)) {
1614 pf_map_destroy(ferry_map);
1615 }
1616
1617 TIMING_LOG(AIT_FSTK, TIMER_STOP);
1618
1619 return best;
1620}
1621
1622/**********************************************************************/
1630 struct city *find_nearest_safe_city(struct unit *punit)
1631{
1632 struct pf_parameter parameter;
1633 struct pf_map *pfm;
1634 struct player *pplayer = unit_owner(punit);
1635 struct city *pcity, *best_city = NULL;
1636 int best = FC_INFINITY, cur;
1637 const struct civ_map *nmap = &(wld.map);
1638
1639 pft_fill_unit_parameter(&parameter, nmap, punit);
1640 parameter.omniscience = !has_handicap(pplayer, H_MAP);
1641 pfm = pf_map_new(&parameter);
1642
1643 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
1644 if (move_cost > best) {
1645 /* We already found a better city. No need to continue. */
1646 break;
1647 }
1648
1649 pcity = tile_city(ptile);
1650 if (NULL == pcity || !pplayers_allied(pplayer, city_owner(pcity))) {
1651 continue;
1652 }
1653
1654 /* Score based on the move cost. */
1655 cur = move_cost;
1656
1657 /* Note the unit owner may be different from the city owner. */
1658 if (0 == get_unittype_bonus(unit_owner(punit), ptile,
1659 unit_type_get(punit), NULL,
1660 EFT_HP_REGEN)) {
1661 /* If we cannot regen fast our hit points here, let's make some
1662 * penalty. */
1663 cur *= 3;
1664 }
1665
1666 if (cur < best) {
1667 best_city = pcity;
1668 best = cur;
1669 }
1670 } pf_map_move_costs_iterate_end;
1671
1672 pf_map_destroy(pfm);
1673 return best_city;
1674}
1675
1676/**********************************************************************/
1681 static void dai_military_attack_barbarian(struct ai_type *ait,
1682 struct player *pplayer,
1683 struct unit *punit)
1684{
1685 struct city *pc;
1686 bool only_continent = TRUE;
1687
1688 if (unit_transported(punit)) {
1689 /* If we are in transport, we can go to any continent.
1690 * Actually, we are not currently in a continent where to stay. */
1691 only_continent = FALSE;
1692 }
1693
1694 if ((pc = find_closest_city(unit_tile(punit), NULL, pplayer, FALSE,
1695 only_continent, FALSE, FALSE, TRUE, NULL))) {
1696 if (can_unit_exist_at_tile(&(wld.map), punit, unit_tile(punit))) {
1697 UNIT_LOG(LOG_DEBUG, punit, "Barbarian heading to conquer %s",
1698 city_name_get(pc));
1699 (void) dai_gothere(ait, pplayer, punit, pc->tile);
1700 } else {
1701 struct unit *ferry = NULL;
1702
1703 if (unit_transported(punit)) {
1704 ferry = unit_transport_get(punit);
1705
1706 /* We already are in a boat so it needs no
1707 * free capacity */
1708 if (!is_boat_free(ait, ferry, punit, 0)) {
1709 /* We cannot control our ferry. */
1710 ferry = NULL;
1711 }
1712 } else {
1713 /* We are not in a boat yet. Search for one. */
1714 unit_list_iterate(unit_tile(punit)->units, aunit) {
1715 if (is_boat_free(ait, aunit, punit, 1)
1716 && unit_transport_load(punit, aunit, FALSE)) {
1717 ferry = aunit;
1718 break;
1719 }
1720 } unit_list_iterate_end;
1721 }
1722
1723 if (ferry) {
1724 UNIT_LOG(LOG_DEBUG, punit, "Barbarian sailing to conquer %s",
1725 city_name_get(pc));
1726 (void) aiferry_goto_amphibious(ait, ferry, punit, pc->tile);
1727 } else {
1728 /* This is not an error. Somebody else might be in charge
1729 * of the ferry. */
1730 UNIT_LOG(LOG_DEBUG, punit, "unable to find barbarian ferry");
1731 }
1732 }
1733 } else {
1734 UNIT_LOG(LOG_DEBUG, punit, "Barbarian find no target city");
1735 }
1736}
1737
1738/**********************************************************************/
1744 static void dai_military_attack(struct ai_type *ait, struct player *pplayer,
1745 struct unit *punit)
1746{
1747 struct tile *dest_tile;
1748 int id = punit->id;
1749 int ct = 10;
1750 struct city *pcity = NULL;
1751
1752 CHECK_UNIT(punit);
1753
1754 /* Barbarians pillage, and might keep on doing that so they sometimes
1755 * even finish it. */
1756 if (punit->activity == ACTIVITY_PILLAGE && is_barbarian(pplayer)
1757 && fc_rand(2) == 1) {
1758 return;
1759 }
1760
1761 /* First find easy nearby enemies, anything better than pillage goes.
1762 * NB: We do not need to repeat dai_military_rampage, it is repeats itself
1763 * until it runs out of targets. */
1764 /* FIXME: 1. dai_military_rampage never checks if it should defend newly
1765 * conquered cities.
1766 * FIXME: 2. would be more convenient if it returned FALSE if we run out
1767 * of moves too.*/
1768 if (!dai_military_rampage(punit, RAMPAGE_ANYTHING, RAMPAGE_ANYTHING)) {
1769 return; /* we died */
1770 }
1771
1772 if (punit->moves_left <= 0) {
1773 return;
1774 }
1775
1776 /* Main attack loop */
1777 do {
1778 struct tile *start_tile = unit_tile(punit);
1779 struct pf_path *path;
1780 struct unit *ferryboat;
1781
1782 /* Then find enemies the hard way */
1783 find_something_to_kill(ait, pplayer, punit, &dest_tile, &path,
1784 NULL, &ferryboat, NULL, NULL);
1785 if (!same_pos(unit_tile(punit), dest_tile)) {
1786 if (!is_tiles_adjacent(unit_tile(punit), dest_tile)
1787 || !can_unit_attack_tile(punit, NULL, dest_tile)) {
1788
1789 /* Adjacent and can't attack usually means we are not marines
1790 * and on a ferry. This fixes the problem (usually). */
1791 UNIT_LOG(LOG_DEBUG, punit, "mil att gothere -> (%d, %d)",
1792 TILE_XY(dest_tile));
1793
1794 /* Set ACTIVITY_GOTO more permanently than just inside
1795 * adv_follow_path(). This way other units will know we're
1796 * on our way even if we don't reach target yet. */
1797 punit->goto_tile = dest_tile;
1798 unit_activity_handling(punit, ACTIVITY_GOTO);
1799 if (NULL != path && !adv_follow_path(punit, path, dest_tile)) {
1800 /* Died. */
1801 pf_path_destroy(path);
1802 return;
1803 }
1804 if (NULL != ferryboat) {
1805 /* Need a boat. */
1806 aiferry_gobyboat(ait, pplayer, punit, dest_tile, FALSE);
1807 pf_path_destroy(path);
1808 return;
1809 }
1810 if (0 >= punit->moves_left) {
1811 /* No moves left. */
1812 pf_path_destroy(path);
1813 return;
1814 }
1815
1816 /* Either we're adjacent or we sitting on the tile. We might be
1817 * sitting on the tile if the enemy that _was_ sitting there
1818 * attacked us and died _and_ we had enough movement to get there */
1819 if (same_pos(unit_tile(punit), dest_tile)) {
1820 UNIT_LOG(LOG_DEBUG, punit, "mil att made it -> (%d, %d)",
1821 TILE_XY(dest_tile));
1822 pf_path_destroy(path);
1823 break;
1824 }
1825 }
1826
1827 if (is_tiles_adjacent(unit_tile(punit), dest_tile)) {
1828 /* Close combat. fstk sometimes want us to attack an adjacent
1829 * enemy that rampage wouldn't */
1830 UNIT_LOG(LOG_DEBUG, punit, "mil att bash -> (%d, %d)",
1831 TILE_XY(dest_tile));
1832 if (!dai_unit_attack(ait, punit, dest_tile)) {
1833 /* Died */
1834 pf_path_destroy(path);
1835 return;
1836 }
1837 } else if (!same_pos(start_tile, unit_tile(punit))) {
1838 /* Got stuck. Possibly because of adjacency to an
1839 * enemy unit. Perhaps we are in luck and are now next to a
1840 * tempting target? Let's find out... */
1841 (void) dai_military_rampage(punit,
1842 RAMPAGE_ANYTHING, RAMPAGE_ANYTHING);
1843 pf_path_destroy(path);
1844 return;
1845 }
1846
1847 } else {
1848 /* FIXME: This happens a bit too often! */
1849 UNIT_LOG(LOG_DEBUG, punit, "fstk didn't find us a worthy target!");
1850 /* No worthy enemies found, so abort loop */
1851 ct = 0;
1852 }
1853 pf_path_destroy(path);
1854
1855 ct--; /* infinite loops from railroads must be stopped */
1856 } while (punit->moves_left > 0 && ct > 0);
1857
1858 /* Cleanup phase */
1859 if (punit->moves_left == 0) {
1860 return;
1861 }
1862 pcity = find_nearest_safe_city(punit);
1863 if (pcity != NULL
1864 && (dai_is_ferry(punit, ait)
1865 || punit->hp < unit_type_get(punit)->hp * 0.50)) { /* WAG */
1866 /* Go somewhere safe */
1867 UNIT_LOG(LOG_DEBUG, punit, "heading to nearest safe house.");
1868 (void) dai_unit_goto(ait, punit, pcity->tile);
1869 } else if (!is_barbarian(pplayer)) {
1870 /* Nothing else to do, so try exploring. */
1871 switch (manage_auto_explorer(punit)) {
1872 case MR_DEATH:
1873 /* don't use punit! */
1874 return;
1875 case MR_OK:
1876 UNIT_LOG(LOG_DEBUG, punit, "nothing else to do, so exploring");
1877 break;
1878 default:
1879 UNIT_LOG(LOG_DEBUG, punit, "nothing to do - no more exploring either");
1880 break;
1881 };
1882 } else {
1883 /* You can still have some moves left here, but barbarians should
1884 not sit helplessly, but advance towards nearest known enemy city */
1885 UNIT_LOG(LOG_DEBUG, punit, "attack: barbarian");
1886 dai_military_attack_barbarian(ait, pplayer, punit);
1887 }
1888 if ((punit = game_unit_by_number(id)) && punit->moves_left > 0) {
1889 UNIT_LOG(LOG_DEBUG, punit, "attack: giving up unit to defense");
1890 dai_military_defend(ait, pplayer, punit);
1891 }
1892}
1893
1894/**********************************************************************/
1898 static bool dai_find_boat_for_unit(struct ai_type *ait, struct unit *punit)
1899{
1900 bool alive = TRUE;
1901 int ferryboat = 0;
1902 struct pf_path *path_to_ferry = NULL;
1903
1904 UNIT_LOG(LOG_CARAVAN, punit, "requesting a boat!");
1905 ferryboat = aiferry_find_boat(ait, punit, 1, &path_to_ferry);
1906 /* going to meet the boat */
1907 if ((ferryboat <= 0)) {
1908 UNIT_LOG(LOG_CARAVAN, punit,
1909 "in find_boat_for_unit cannot find any boats.");
1910 /* if we are undefended on the country side go to a city */
1911 struct city *current_city = tile_city(unit_tile(punit));
1912 if (current_city == NULL) {
1913 struct city *city_near = find_nearest_safe_city(punit);
1914 if (city_near != NULL) {
1915 alive = dai_unit_goto(ait, punit, city_near->tile);
1916 }
1917 }
1918 } else {
1919 if (path_to_ferry != NULL) {
1920 if (!adv_unit_execute_path(punit, path_to_ferry)) {
1921 /* Died. */
1922 pf_path_destroy(path_to_ferry);
1923 path_to_ferry = NULL;
1924 alive = FALSE;
1925 } else {
1926 pf_path_destroy(path_to_ferry);
1927 path_to_ferry = NULL;
1928 alive = TRUE;
1929 }
1930 }
1931 }
1932 return alive;
1933}
1934
1935/**********************************************************************/
1943 bool uclass_need_trans_between(struct unit_class *pclass,
1944 struct tile *ctile, struct tile *ptile)
1945{
1946 /* We usually have Inaccessible terrain, so not testing MOVE_FULL == */
1947 bool lm = MOVE_NONE != pclass->adv.land_move,
1948 sm = MOVE_NONE != pclass->adv.sea_move;
1949 struct civ_map *pmap = &(wld.map);
1950
1951 if (lm && sm) {
1952 return FALSE;
1953 }
1954
1955 /* We could use adjc_iterate() but likely often tiles are on the same
1956 * continent and it will be more time to find where they connect */
1957 iterate_outward(pmap, ctile, 1, atile) {
1958 Continent_id acont = tile_continent(atile);
1959
1960 if (is_ocean_tile(atile) ? sm : lm) {
1961 iterate_outward(pmap, ptile, 1, btile) {
1962 if (tile_continent(btile) == acont) {
1963 return FALSE;
1964 }
1965 } iterate_outward_end;
1966 }
1967 } iterate_outward_end;
1968
1969 if (is_tiles_adjacent(ctile, ptile)) {
1970 return FALSE;
1971 }
1972
1973 return TRUE;
1974}
1975
1976/**********************************************************************/
1982 static void dai_caravan_goto(struct ai_type *ait, struct player *pplayer,
1983 struct unit *punit,
1984 const struct city *dest_city,
1985 bool help_wonder,
1986 bool required_boat, bool request_boat)
1987{
1988 bool alive = TRUE;
1989 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
1990 const struct civ_map *nmap = &(wld.map);
1991
1992 fc_assert_ret(NULL != dest_city);
1993
1994 /* if we're not there yet, and we can move, move... */
1995 if (!same_pos(dest_city->tile, unit_tile(punit))
1996 && punit->moves_left != 0) {
1997 log_base(LOG_CARAVAN, "%s %s[%d](%d,%d) task %s going to %s in %s %s",
1998 nation_rule_name(nation_of_unit(punit)),
1999 unit_rule_name(punit), punit->id, TILE_XY(unit_tile(punit)),
2000 dai_unit_task_rule_name(unit_data->task),
2001 help_wonder ? "help a wonder" : "trade", city_name_get(dest_city),
2002 required_boat ? "with a boat" : "");
2003 if (required_boat) {
2004 /* to trade with boat */
2005 if (request_boat) {
2006 /* Try to find new boat */
2007 alive = dai_find_boat_for_unit(ait, punit);
2008 } else {
2009 /* if we are not being transported then ask for a boat again */
2010 alive = TRUE;
2011 if (!unit_transported(punit)
2012 && uclass_need_trans_between(unit_class_get(punit),
2013 unit_tile(punit), dest_city->tile)) {
2014 alive = dai_find_boat_for_unit(ait, punit);
2015 }
2016 }
2017 if (alive) {
2018 /* FIXME: sometimes we get FALSE here just because
2019 * a trireme that we've boarded can't go over an ocean. */
2020 alive = dai_gothere(ait, pplayer, punit, dest_city->tile);
2021 }
2022 } else {
2023 /* to trade without boat */
2024 alive = dai_unit_goto(ait, punit, dest_city->tile);
2025 }
2026 }
2027
2028 /* if moving didn't kill us, and we got to the destination, handle it. */
2029 if (alive && real_map_distance(dest_city->tile, unit_tile(punit)) <= 1) {
2030 /* release the boat! */
2031 if (unit_transported(punit)) {
2032 aiferry_clear_boat(ait, punit);
2033 }
2034 if (help_wonder && is_action_enabled_unit_on_city(nmap, ACTION_HELP_WONDER,
2035 punit, dest_city)) {
2036 /*
2037 * We really don't want to just drop all caravans in immediately.
2038 * Instead, we want to aggregate enough caravans to build instantly.
2039 * -AJS, 990704
2040 */
2041 log_base(LOG_CARAVAN, "%s %s[%d](%d,%d) helps build wonder in %s",
2042 nation_rule_name(nation_of_unit(punit)),
2043 unit_rule_name(punit),
2044 punit->id,
2045 TILE_XY(unit_tile(punit)),
2046 city_name_get(dest_city));
2047 unit_do_action(pplayer, punit->id, dest_city->id,
2048 0, "", ACTION_HELP_WONDER);
2049 } else if (is_action_enabled_unit_on_city(nmap, ACTION_TRADE_ROUTE,
2050 punit, dest_city)) {
2051 log_base(LOG_CARAVAN, "%s %s[%d](%d,%d) creates trade route in %s",
2052 nation_rule_name(nation_of_unit(punit)),
2053 unit_rule_name(punit),
2054 punit->id,
2055 TILE_XY(unit_tile(punit)),
2056 city_name_get(dest_city));
2057 unit_do_action(pplayer, punit->id, dest_city->id,
2058 0, "", ACTION_TRADE_ROUTE);
2059 } else if (is_action_enabled_unit_on_city(nmap, ACTION_MARKETPLACE,
2060 punit, dest_city)) {
2061 /* Get the one time bonus. */
2062 log_base(LOG_CARAVAN, "%s %s[%d](%d,%d) enters marketplace of %s",
2063 nation_rule_name(nation_of_unit(punit)),
2064 unit_rule_name(punit),
2065 punit->id,
2066 TILE_XY(unit_tile(punit)),
2067 city_name_get(dest_city));
2068 unit_do_action(pplayer, punit->id, dest_city->id,
2069 0, "", ACTION_MARKETPLACE);
2070 } else {
2071 enum log_level level = LOG_NORMAL;
2072
2073 if (help_wonder) {
2074 /* A Caravan ordered to help build wonder may arrive after
2075 * enough shields to build the wonder is produced. */
2076 level = LOG_VERBOSE;
2077 }
2078
2079 log_base(level,
2080 "%s %s[%d](%d,%d) unable to trade with %s",
2081 nation_rule_name(nation_of_unit(punit)),
2082 unit_rule_name(punit),
2083 punit->id,
2084 TILE_XY(unit_tile(punit)),
2085 city_name_get(dest_city));
2086 }
2087 }
2088}
2089
2090/**********************************************************************/
2094 static void caravan_optimize_callback(const struct caravan_result *result,
2095 void *data)
2096{
2097 const struct unit *caravan = data;
2098
2099 log_base(LOG_CARAVAN3, "%s %s[%d](%d,%d) %s: %s %s worth %g",
2100 nation_rule_name(nation_of_unit(caravan)),
2101 unit_rule_name(caravan),
2102 caravan->id,
2103 TILE_XY(unit_tile(caravan)),
2104 city_name_get(result->src),
2105 result->help_wonder ? "wonder in" : "trade to",
2106 city_name_get(result->dest),
2107 result->value);
2108}
2109
2110/**********************************************************************/
2113 static bool dai_is_unit_tired_waiting_boat(struct ai_type *ait,
2114 struct unit *punit)
2115{
2116 struct tile *src = NULL, *dest = NULL, *src_home_city = NULL;
2117 struct city *phome_city = NULL;
2118 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
2119
2120 if ((unit_data->task != AIUNIT_NONE)) {
2121 src = unit_tile(punit);
2122 phome_city = game_city_by_number(punit->homecity);
2123 if (phome_city != NULL) {
2124 src_home_city = city_tile(phome_city);
2125 }
2126 dest = punit->goto_tile;
2127
2128 if (src == NULL || dest == NULL) {
2129 return FALSE;
2130 }
2131
2132 /* If we have a home continent, and are not there.
2133 * (FIXME: well, why?)
2134 * (I guess because home continent is which we were supposed to leave,
2135 * not the target continent) */
2136 if (src_home_city != NULL
2137 && tile_continent(src) != tile_continent(src_home_city)) {
2138 return FALSE;
2139 }
2140
2141 if (!goto_is_sane(punit, dest)) {
2142 if (unit_transported(punit)) {
2143 /* if we're being transported */
2144 return FALSE;
2145 }
2146 if ((punit->server.birth_turn + 15 < game.info.turn)) {
2147 /* we are tired of waiting */
2148 int ferrys = aiferry_avail_boats(ait, punit->owner);
2149
2150 if (ferrys <= 0) {
2151 /* there are no ferrys available... give up */
2152 return TRUE;
2153 } else {
2154 if (punit->server.birth_turn + 20 < game.info.turn) {
2155 /* we are feed up! */
2156 return TRUE;
2157 }
2158 }
2159 }
2160 }
2161 }
2162
2163 return FALSE;
2164}
2165
2166/**********************************************************************/
2172 static bool dai_caravan_can_trade_cities_diff_cont(struct player *pplayer,
2173 struct unit *punit)
2174{
2175 struct city *pcity = game_city_by_number(punit->homecity);
2176 Continent_id continent;
2177
2178 fc_assert(pcity != NULL);
2179
2180 if (unit_class_get(punit)->adv.ferry_types <= 0) {
2181 /* There is just no possible transporters. */
2182 return FALSE;
2183 }
2184 continent = tile_continent(pcity->tile);
2185
2186 /* Look for proper destination city at different continent. */
2187 city_list_iterate(pplayer->cities, acity) {
2188 if (can_cities_trade(pcity, acity)) {
2189 if (tile_continent(acity->tile) != continent) {
2190 return TRUE;
2191 }
2192 }
2193 } city_list_iterate_end;
2194
2195 players_iterate(aplayer) {
2196 if (aplayer == pplayer || !aplayer->is_alive) {
2197 continue;
2198 }
2199 if (pplayers_allied(pplayer, aplayer)) {
2200 city_list_iterate(aplayer->cities, acity) {
2201 if (can_cities_trade(pcity, acity)) {
2202 if (tile_continent(acity->tile) != continent) {
2203 return TRUE;
2204 }
2205 }
2206 } city_list_iterate_end;
2207 } players_iterate_end;
2208 }
2209
2210 return FALSE;
2211}
2212
2213/**********************************************************************/
2217 static bool search_homecity_for_caravan(struct ai_type *ait, struct unit *punit)
2218{
2219 struct city *nearest = NULL;
2220 int min_dist = FC_INFINITY;
2221 struct tile *current_loc = unit_tile(punit);
2222 Continent_id continent = tile_continent(current_loc);
2223 bool alive = TRUE;
2224
2225 city_list_iterate(punit->owner->cities, pcity) {
2226 struct tile *ctile = city_tile(pcity);
2227
2228 if (tile_continent(ctile) == continent) {
2229 int this_dist = map_distance(current_loc, ctile);
2230
2231 if (this_dist < min_dist) {
2232 min_dist = this_dist;
2233 nearest = pcity;
2234 }
2235 }
2236 } city_list_iterate_end;
2237
2238 if (nearest != NULL) {
2239 alive = dai_unit_goto(ait, punit, nearest->tile);
2240 if (alive && same_pos(unit_tile(punit), nearest->tile)) {
2241 dai_unit_make_homecity(punit, nearest);
2242 }
2243 }
2244
2245 return alive;
2246}
2247
2248/**********************************************************************/
2254 static void dai_manage_caravan(struct ai_type *ait, struct player *pplayer,
2255 struct unit *punit)
2256{
2257 struct caravan_parameter parameter;
2258 struct caravan_result result;
2259 const struct city *homecity;
2260 const struct city *dest = NULL;
2261 struct unit_ai *unit_data;
2262 struct unit_class *pclass = unit_class_get(punit);
2263 bool expect_boats = pclass->adv.ferry_types > 0;
2264 /* TODO: will pplayer have a boat for punit in a reasonable time? */
2265 bool help_wonder = FALSE;
2266 bool required_boat = FALSE;
2267 bool request_boat = FALSE;
2268 bool tired_of_waiting_boat = FALSE;
2269 const struct civ_map *nmap = &(wld.map);
2270
2271 CHECK_UNIT(punit);
2272
2273 if (!unit_can_do_action(punit, ACTION_TRADE_ROUTE)
2274 && !unit_can_do_action(punit, ACTION_MARKETPLACE)
2275 && !unit_can_do_action(punit, ACTION_HELP_WONDER)) {
2276 /* we only want units that can establish trade, enter marketplace or
2277 * help build wonders */
2278 return;
2279 }
2280
2281 unit_data = def_ai_unit_data(punit, ait);
2282
2283 log_base(LOG_CARAVAN2, "%s %s[%d](%d,%d) task %s to (%d,%d)",
2284 nation_rule_name(nation_of_unit(punit)),
2285 unit_rule_name(punit), punit->id, TILE_XY(unit_tile(punit)),
2286 dai_unit_task_rule_name(unit_data->task),
2287 TILE_XY(punit->goto_tile));
2288
2289 homecity = game_city_by_number(punit->homecity);
2290 if (homecity == NULL && unit_data->task == AIUNIT_TRADE) {
2291 if (!search_homecity_for_caravan(ait, punit)) {
2292 return;
2293 }
2294 homecity = game_city_by_number(punit->homecity);
2295 if (homecity == NULL) {
2296 return;
2297 }
2298 }
2299
2300 if ((unit_data->task == AIUNIT_TRADE
2301 || unit_data->task == AIUNIT_WONDER)) {
2302 /* we are moving to our destination */
2303 /* we check to see if our current goal is feasible */
2304 struct city *city_dest = tile_city(punit->goto_tile);
2305
2306 if ((city_dest == NULL)
2307 || !pplayers_allied(unit_owner(punit), city_dest->owner)
2308 || (unit_data->task == AIUNIT_TRADE
2309 && !(can_cities_trade(homecity, city_dest)
2310 && can_establish_trade_route(homecity, city_dest)))
2311 || (unit_data->task == AIUNIT_WONDER
2312 /* Helping the (new) production is illegal. */
2313 && !city_production_gets_caravan_shields(&city_dest->production))
2314 || (unit_data->task == AIUNIT_TRADE
2315 && real_map_distance(city_dest->tile, unit_tile(punit)) <= 1
2316 && !(is_action_enabled_unit_on_city(nmap, ACTION_TRADE_ROUTE,
2317 punit, city_dest)
2318 || is_action_enabled_unit_on_city(nmap, ACTION_MARKETPLACE,
2319 punit, city_dest)))
2320 || (unit_data->task == AIUNIT_WONDER
2321 && real_map_distance(city_dest->tile, unit_tile(punit)) <= 1
2322 && !is_action_enabled_unit_on_city(nmap, ACTION_HELP_WONDER,
2323 punit, city_dest))) {
2324 /* destination invalid! */
2325 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2326 log_base(LOG_CARAVAN2, "%s %s[%d](%d,%d) destination invalid!",
2327 nation_rule_name(nation_of_unit(punit)),
2328 unit_rule_name(punit), punit->id, TILE_XY(unit_tile(punit)));
2329 } else {
2330 /* destination valid, are we tired of waiting for a boat? */
2331 if (expect_boats && dai_is_unit_tired_waiting_boat(ait, punit)) {
2332 aiferry_clear_boat(ait, punit);
2333 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2334 log_base(LOG_CARAVAN2, "%s %s[%d](%d,%d) unit tired of waiting!",
2335 nation_rule_name(nation_of_unit(punit)),
2336 unit_rule_name(punit), punit->id, TILE_XY(unit_tile(punit)));
2337 tired_of_waiting_boat = TRUE;
2338 } else {
2339 dest = city_dest;
2340 help_wonder = (unit_data->task == AIUNIT_WONDER) ? TRUE : FALSE;
2341 required_boat = uclass_need_trans_between(pclass, unit_tile(punit), dest->tile);
2342 request_boat = FALSE;
2343 }
2344 }
2345 }
2346
2347 if (unit_data->task == AIUNIT_NONE) {
2348 if (homecity == NULL) {
2349 /* FIXME: We shouldn't bother in getting homecity for
2350 * caravan that will then be used for wonder building. */
2351 if (!search_homecity_for_caravan(ait, punit)) {
2352 return;
2353 }
2354 homecity = game_city_by_number(punit->homecity);
2355 if (homecity == NULL) {
2356 return;
2357 }
2358 }
2359
2360 caravan_parameter_init_from_unit(&parameter, punit);
2361 /* Make more trade with allies than other peaceful nations
2362 * by considering only allies 50% of the time.
2363 * (the other 50% allies are still considered, but so are other nations) */
2364 if (fc_rand(2)) {
2365 /* Be optimistic about development of relations with no-contact and
2366 * cease-fire nations. */
2367 parameter.allow_foreign_trade = FTL_NONWAR;
2368 } else {
2369 parameter.allow_foreign_trade = FTL_ALLIED;
2370 }
2371
2372 if (log_do_output_for_level(LOG_CARAVAN2)) {
2373 parameter.callback = caravan_optimize_callback;
2374 parameter.callback_data = punit;
2375 }
2376 if (dai_caravan_can_trade_cities_diff_cont(pplayer, punit)) {
2377 parameter.ignore_transit_time = TRUE;
2378 }
2379 if (tired_of_waiting_boat) {
2380 parameter.allow_foreign_trade = FTL_NATIONAL_ONLY;
2381 parameter.ignore_transit_time = FALSE;
2382 }
2383 caravan_find_best_destination(nmap, punit, &parameter, &result,
2384 !has_handicap(pplayer, H_MAP));
2385 if (result.dest != NULL) {
2386 /* We did find a new destination for the unit */
2387 dest = result.dest;
2388 help_wonder = result.help_wonder;
2389 required_boat = uclass_need_trans_between(pclass, unit_tile(punit), dest->tile);
2390 request_boat = required_boat;
2391 dai_unit_new_task(ait, punit,
2392 (help_wonder) ? AIUNIT_WONDER : AIUNIT_TRADE,
2393 dest->tile);
2394 } else {
2395 dest = NULL;
2396 }
2397 }
2398
2399 if (required_boat && !expect_boats) {
2400 /* Would require boat, but can't have them. Render destination invalid. */
2401 dest = NULL;
2402 }
2403
2404 if (dest != NULL) {
2405 dai_caravan_goto(ait, pplayer, punit, dest, help_wonder,
2406 required_boat, request_boat);
2407 return; /* that may have clobbered the unit */
2408 } else {
2409 /* We have nowhere to go! */
2410 log_base(LOG_CARAVAN2, "%s %s[%d](%d,%d), nothing to do!",
2411 nation_rule_name(nation_of_unit(punit)),
2412 unit_rule_name(punit), punit->id,
2413 TILE_XY(unit_tile(punit)));
2414 /* Should we become a defensive unit? */
2415 }
2416}
2417
2418/**********************************************************************/
2422 static void dai_manage_hitpoint_recovery(struct ai_type *ait,
2423 struct unit *punit)
2424{
2425 struct player *pplayer = unit_owner(punit);
2426 struct city *pcity = tile_city(unit_tile(punit));
2427 struct city *safe = NULL;
2428 const struct unit_type *punittype = unit_type_get(punit);
2429 bool no_recovery;
2430
2431 CHECK_UNIT(punit);
2432
2433 if (pcity != NULL) {
2434 /* Rest in the city until the hitpoints are recovered, but attempt
2435 * to protect city from attack (and be opportunistic too)*/
2436 if (dai_military_rampage(punit, RAMPAGE_ANYTHING,
2437 RAMPAGE_FREE_CITY_OR_BETTER)) {
2438 UNIT_LOG(LOGLEVEL_RECOVERY, punit, "recovering hit points.");
2439 } else {
2440 return; /* We died heroically defending our city */
2441 }
2442 } else {
2443 /* Goto to nearest city to recover hit points */
2444 /* Just before, check to see if we can occupy an undefended enemy city */
2445 if (!dai_military_rampage(punit, RAMPAGE_FREE_CITY_OR_BETTER,
2446 RAMPAGE_FREE_CITY_OR_BETTER)) {
2447 return; /* Oops, we died */
2448 }
2449
2450 /* Find a city to stay and go there */
2451 safe = find_nearest_safe_city(punit);
2452 if (safe) {
2453 UNIT_LOG(LOGLEVEL_RECOVERY, punit, "going to %s to recover",
2454 city_name_get(safe));
2455 if (!dai_unit_goto(ait, punit, safe->tile)) {
2456 log_base(LOGLEVEL_RECOVERY, "died trying to hide and recover");
2457 return;
2458 }
2459 } else {
2460 /* Oops */
2461 UNIT_LOG(LOGLEVEL_RECOVERY, punit, "didn't find a city to recover in!");
2462 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2463 dai_military_attack(ait, pplayer, punit);
2464 return;
2465 }
2466 }
2467
2468 /* Is the unit still damaged? If true, and could recover hit points, do so.
2469 * Don't wait if would be losing hitpoints that way! */
2470 no_recovery = FALSE;
2471 if (punit->hp == punittype->hp) {
2472 no_recovery = TRUE;
2473 } else {
2474 int gain = unit_gain_hitpoints(punit);
2475
2476 if (gain < 0) {
2477 no_recovery = TRUE;
2478 } else if (gain == 0 && !punit->moved) {
2479 /* Isn't gaining even though has not moved. */
2480 no_recovery = TRUE;
2481 }
2482 }
2483 if (no_recovery) {
2484 /* We are ready to go out and kick ass again */
2485 UNIT_LOG(LOGLEVEL_RECOVERY, punit, "ready to kick ass again!");
2486 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2487 return;
2488 } else {
2489 def_ai_unit_data(punit, ait)->done = TRUE; /* Sit tight */
2490 }
2491}
2492
2493/**********************************************************************/
2497 void dai_manage_military(struct ai_type *ait, struct player *pplayer,
2498 struct unit *punit)
2499{
2500 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
2501 int id = punit->id;
2502
2503 CHECK_UNIT(punit);
2504
2505 /* "Escorting" aircraft should not do anything. They are activated
2506 * by their transport or charge. We do _NOT_ set them to 'done'
2507 * since they may need be activated once our charge moves. */
2508 if (unit_data->task == AIUNIT_ESCORT
2509 && utype_fuel(unit_type_get(punit))) {
2510 return;
2511 }
2512
2513 if ((punit->activity == ACTIVITY_SENTRY
2514 || punit->activity == ACTIVITY_FORTIFIED)
2515 && has_handicap(pplayer, H_AWAY)) {
2516 /* Don't move sentried or fortified units controlled by a player
2517 * in away mode. */
2518 unit_data->done = TRUE;
2519 return;
2520 }
2521
2522 /* Since military units re-evaluate their actions every turn,
2523 we must make sure that previously reserved ferry is freed. */
2524 aiferry_clear_boat(ait, punit);
2525
2526 TIMING_LOG(AIT_HUNTER, TIMER_START);
2527 /* Try hunting with this unit */
2528 if (dai_hunter_qualify(pplayer, punit)) {
2529 int result, sanity = punit->id;
2530
2531 UNIT_LOG(LOGLEVEL_HUNT, punit, "is qualified as hunter");
2532 result = dai_hunter_manage(ait, pplayer, punit);
2533 if (NULL == game_unit_by_number(sanity)) {
2534 TIMING_LOG(AIT_HUNTER, TIMER_STOP);
2535 return; /* died */
2536 }
2537 if (result == -1) {
2538 (void) dai_hunter_manage(ait, pplayer, punit); /* More carnage */
2539 TIMING_LOG(AIT_HUNTER, TIMER_STOP);
2540 return;
2541 } else if (result >= 1) {
2542 TIMING_LOG(AIT_HUNTER, TIMER_STOP);
2543 return; /* Done moving */
2544 } else if (unit_data->task == AIUNIT_HUNTER) {
2545 /* This should be very rare */
2546 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2547 }
2548 } else if (unit_data->task == AIUNIT_HUNTER) {
2549 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2550 }
2551 TIMING_LOG(AIT_HUNTER, TIMER_STOP);
2552
2553 /* Do we have a specific job for this unit? If not, we default
2554 * to attack. */
2555 dai_military_findjob(ait, pplayer, punit);
2556
2557 switch (unit_data->task) {
2558 case AIUNIT_AUTO_SETTLER:
2559 case AIUNIT_BUILD_CITY:
2560 fc_assert(FALSE); /* This is not the place for this role */
2561 break;
2562 case AIUNIT_DEFEND_HOME:
2563 TIMING_LOG(AIT_DEFENDERS, TIMER_START);
2564 dai_military_defend(ait, pplayer, punit);
2565 TIMING_LOG(AIT_DEFENDERS, TIMER_STOP);
2566 break;
2567 case AIUNIT_ATTACK:
2568 case AIUNIT_NONE:
2569 TIMING_LOG(AIT_ATTACK, TIMER_START);
2570 dai_military_attack(ait, pplayer, punit);
2571 TIMING_LOG(AIT_ATTACK, TIMER_STOP);
2572 break;
2573 case AIUNIT_ESCORT:
2574 TIMING_LOG(AIT_BODYGUARD, TIMER_START);
2575 dai_military_bodyguard(ait, pplayer, punit);
2576 TIMING_LOG(AIT_BODYGUARD, TIMER_STOP);
2577 break;
2578 case AIUNIT_EXPLORE:
2579 switch (manage_auto_explorer(punit)) {
2580 case MR_DEATH:
2581 /* don't use punit! */
2582 return;
2583 case MR_OK:
2584 UNIT_LOG(LOG_DEBUG, punit, "more exploring");
2585 break;
2586 default:
2587 UNIT_LOG(LOG_DEBUG, punit, "no more exploring either");
2588 break;
2589 };
2590 def_ai_unit_data(punit, ait)->done = (punit->moves_left <= 0);
2591 break;
2592 case AIUNIT_RECOVER:
2593 TIMING_LOG(AIT_RECOVER, TIMER_START);
2594 dai_manage_hitpoint_recovery(ait, punit);
2595 TIMING_LOG(AIT_RECOVER, TIMER_STOP);
2596 break;
2597 case AIUNIT_HUNTER:
2598 fc_assert(FALSE); /* dealt with above */
2599 break;
2600 default:
2601 fc_assert(FALSE);
2602 }
2603
2604 /* If we are still alive, either sentry or fortify. */
2605 if ((punit = game_unit_by_number(id))) {
2606 unit_data = def_ai_unit_data(punit, ait);
2607 struct city *pcity = tile_city(unit_tile(punit));
2608
2609 if (unit_list_find(unit_tile(punit)->units,
2610 unit_data->ferryboat)) {
2611 unit_activity_handling(punit, ACTIVITY_SENTRY);
2612 } else if (pcity || punit->activity == ACTIVITY_IDLE) {
2613 /* We do not need to fortify in cities - we fortify and sentry
2614 * according to home defense setup, for easy debugging. */
2615 if (!pcity || unit_data->task == AIUNIT_DEFEND_HOME) {
2616 if (punit->activity == ACTIVITY_IDLE
2617 || punit->activity == ACTIVITY_SENTRY) {
2618 unit_activity_handling(punit, ACTIVITY_FORTIFYING);
2619 }
2620 } else {
2621 unit_activity_handling(punit, ACTIVITY_SENTRY);
2622 }
2623 }
2624 }
2625}
2626
2627/**********************************************************************/
2630 static void dai_manage_settler(struct ai_type *ait, struct player *pplayer,
2631 struct unit *punit)
2632{
2633 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
2634
2635 unit_server_side_agent_set(pplayer, punit, SSA_AUTOSETTLER);
2636 unit_data->done = TRUE; /* we will manage this unit later... ugh */
2637 /* if BUILD_CITY must remain BUILD_CITY, otherwise turn into autosettler */
2638 if (unit_data->task == AIUNIT_NONE) {
2639 adv_unit_new_task(punit, AUT_AUTO_SETTLER, NULL);
2640 }
2641 return;
2642}
2643
2644/**********************************************************************/
2652 void dai_manage_unit(struct ai_type *ait, struct player *pplayer,
2653 struct unit *punit)
2654{
2655 struct unit_ai *unit_data;
2656 struct unit *bodyguard = aiguard_guard_of(ait, punit);
2657 bool is_ferry = FALSE;
2658 const struct unit_type *ptype;
2659
2660 CHECK_UNIT(punit);
2661
2662 /* Don't manage the unit if it is under human orders. */
2663 if (unit_has_orders(punit)) {
2664 unit_data = def_ai_unit_data(punit, ait);
2665
2666 UNIT_LOG(LOG_VERBOSE, punit, "is under human orders, aborting AI control.");
2667 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2668 unit_data->done = TRUE;
2669 return;
2670 }
2671
2672 /* Check if we have lost our bodyguard. If we never had one, all
2673 * fine. If we had one and lost it, ask for a new one. */
2674 if (!bodyguard && aiguard_has_guard(ait, punit)) {
2675 UNIT_LOG(LOGLEVEL_BODYGUARD, punit, "lost bodyguard, asking for new");
2676 aiguard_request_guard(ait, punit);
2677 }
2678
2679 unit_data = def_ai_unit_data(punit, ait);
2680
2681 if (punit->moves_left <= 0) {
2682 /* Can do nothing */
2683 unit_data->done = TRUE;
2684 return;
2685 }
2686
2687 is_ferry = dai_is_ferry(punit, ait);
2688
2689 ptype = unit_type_get(punit);
2690
2691 if (utype_has_flag(ptype, UTYF_DIPLOMAT)) {
2692 TIMING_LOG(AIT_DIPLOMAT, TIMER_START);
2693 dai_manage_diplomat(ait, pplayer, punit);
2694 TIMING_LOG(AIT_DIPLOMAT, TIMER_STOP);
2695 return;
2696 } else if (ptype->adv.worker
2697 || unit_is_cityfounder(punit)) {
2698 dai_manage_settler(ait, pplayer, punit);
2699 return;
2700 } else if (unit_can_do_action(punit, ACTION_TRADE_ROUTE)
2701 || unit_can_do_action(punit, ACTION_MARKETPLACE)
2702 || unit_can_do_action(punit, ACTION_HELP_WONDER)) {
2703 TIMING_LOG(AIT_CARAVAN, TIMER_START);
2704 dai_manage_caravan(ait, pplayer, punit);
2705 TIMING_LOG(AIT_CARAVAN, TIMER_STOP);
2706 return;
2707 } else if (unit_has_type_role(punit, L_BARBARIAN_LEADER)) {
2708 dai_manage_barbarian_leader(ait, pplayer, punit);
2709 return;
2710 } else if (unit_can_do_action_result(punit, ACTRES_PARADROP)
2711 || unit_can_do_action_result(punit, ACTRES_PARADROP_CONQUER)) {
2712 dai_manage_paratrooper(ait, pplayer, punit);
2713 return;
2714 } else if (is_ferry && unit_data->task != AIUNIT_HUNTER) {
2715 TIMING_LOG(AIT_FERRY, TIMER_START);
2716 dai_manage_ferryboat(ait, pplayer, punit);
2717 TIMING_LOG(AIT_FERRY, TIMER_STOP);
2718 return;
2719 } else if (utype_fuel(ptype)
2720 && unit_data->task != AIUNIT_ESCORT) {
2721 TIMING_LOG(AIT_AIRUNIT, TIMER_START);
2722 dai_manage_airunit(ait, pplayer, punit);
2723 TIMING_LOG(AIT_AIRUNIT, TIMER_STOP);
2724 return;
2725 } else if (is_losing_hp(punit)) {
2726 /* This unit is losing hitpoints over time */
2727
2728 /* TODO: We can try using air-unit code for helicopters, just
2729 * pretend they have fuel = HP / 3 or something. */
2730 unit_data->done = TRUE; /* we did our best, which was ...
2731 nothing */
2732 return;
2733 } else if (is_military_unit(punit)) {
2734 TIMING_LOG(AIT_MILITARY, TIMER_START);
2735 UNIT_LOG(LOG_DEBUG, punit, "recruit unit for the military");
2736 dai_manage_military(ait, pplayer, punit);
2737 TIMING_LOG(AIT_MILITARY, TIMER_STOP);
2738 return;
2739 } else {
2740 /* what else could this be? -- Syela */
2741 switch (manage_auto_explorer(punit)) {
2742 case MR_DEATH:
2743 /* don't use punit! */
2744 break;
2745 case MR_OK:
2746 UNIT_LOG(LOG_DEBUG, punit, "now exploring");
2747 break;
2748 default:
2749 UNIT_LOG(LOG_DEBUG, punit, "fell through all unit tasks, defending");
2750 dai_unit_new_task(ait, punit, AIUNIT_DEFEND_HOME, NULL);
2751 dai_military_defend(ait, pplayer, punit);
2752 break;
2753 };
2754 return;
2755 }
2756}
2757
2758/**********************************************************************/
2764 static void dai_set_defenders(struct ai_type *ait, struct player *pplayer)
2765{
2766 city_list_iterate(pplayer->cities, pcity) {
2767 /* The idea here is that we should never keep more than two
2768 * units in permanent defense. */
2769 int total_defense = 0;
2770 int total_attack = def_ai_city_data(pcity, ait)->danger;
2771 bool emergency = FALSE;
2772 int count = 0;
2773 int mart_max = get_city_bonus(pcity, EFT_MARTIAL_LAW_MAX);
2774 int mart_each = get_city_bonus(pcity, EFT_MARTIAL_LAW_EACH);
2775 int martless_unhappy = pcity->feel[CITIZEN_UNHAPPY][FEELING_NATIONALITY]
2776 + pcity->feel[CITIZEN_ANGRY][FEELING_NATIONALITY];
2777 int entertainers = 0;
2778 bool enough = FALSE;
2779
2780 specialist_type_iterate(sp) {
2781 if (get_specialist_output(pcity, sp, O_LUXURY) > 0) {
2782 entertainers += pcity->specialists[sp];
2783 }
2784 } specialist_type_iterate_end;
2785
2786 martless_unhappy += entertainers; /* We want to use martial law instead
2787 * of entertainers. */
2788
2789 while (!enough
2790 && (total_defense <= total_attack
2791 || (count < mart_max && mart_each > 0
2792 && martless_unhappy > mart_each * count))) {
2793 int best_want = 0;
2794 struct unit *best = NULL;
2795 bool defense_needed = total_defense <= total_attack; /* Defense or martial */
2796
2797 unit_list_iterate(pcity->tile->units, punit) {
2798 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
2799
2800 if ((unit_data->task == AIUNIT_NONE || emergency)
2801 && unit_data->task != AIUNIT_DEFEND_HOME
2802 && unit_owner(punit) == pplayer) {
2803 int want = assess_defense_unit(ait, pcity, punit, FALSE);
2804
2805 if (want > best_want) {
2806 best_want = want;
2807 best = punit;
2808 }
2809 }
2810 } unit_list_iterate_end;
2811
2812 if (best == NULL) {
2813 if (defense_needed) {
2814 /* Ooops - try to grab any unit as defender! */
2815 if (emergency) {
2816 CITY_LOG(LOG_DEBUG, pcity, "Not defended properly");
2817 break;
2818 }
2819 emergency = TRUE;
2820 } else {
2821 break;
2822 }
2823 } else {
2824 const struct unit_type *btype = unit_type_get(best);
2825
2826 if ((martless_unhappy < mart_each * count
2827 || count >= mart_max || mart_each <= 0)
2828 && ((count >= 2
2829 && btype->attack_strength > btype->defense_strength)
2830 || (count >= 4
2831 && btype->attack_strength == btype->defense_strength))) {
2832 /* In this case attack would be better defense than fortifying
2833 * to city. */
2834 enough = TRUE;
2835 } else {
2836 int loglevel = pcity->server.debug ? LOG_AI_TEST : LOG_DEBUG;
2837
2838 total_defense += best_want;
2839 UNIT_LOG(loglevel, best, "Defending city");
2840 dai_unit_new_task(ait, best, AIUNIT_DEFEND_HOME, pcity->tile);
2841 count++;
2842 }
2843 }
2844 }
2845 CITY_LOG(LOG_DEBUG, pcity, "Evaluating defense: %d defense, %d incoming"
2846 ", %d defenders (out of %d)", total_defense, total_attack, count,
2847 unit_list_size(pcity->tile->units));
2848 } city_list_iterate_end;
2849}
2850
2851/**********************************************************************/
2859 void dai_manage_units(struct ai_type *ait, struct player *pplayer)
2860{
2861 TIMING_LOG(AIT_AIRLIFT, TIMER_START);
2862 dai_airlift(ait, pplayer);
2863 TIMING_LOG(AIT_AIRLIFT, TIMER_STOP);
2864
2865 /* Clear previous orders, if desirable, here. */
2866 unit_list_iterate(pplayer->units, punit) {
2867 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
2868
2869 unit_data->done = FALSE;
2870 if (unit_data->task == AIUNIT_DEFEND_HOME) {
2871 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
2872 }
2873 } unit_list_iterate_end;
2874
2875 /* Find and set city defenders first - figure out which units are
2876 * allowed to leave home. */
2877 dai_set_defenders(ait, pplayer);
2878
2879 unit_list_iterate_safe(pplayer->units, punit) {
2880 if ((!unit_transported(punit) || unit_owner(unit_transport_get(punit)) != pplayer)
2881 && !def_ai_unit_data(punit, ait)->done) {
2882 /* Though it is usually the passenger who drives the transport,
2883 * the transporter is responsible for managing its passengers. */
2884 dai_manage_unit(ait, pplayer, punit);
2885 }
2886 } unit_list_iterate_safe_end;
2887}
2888
2889/**********************************************************************/
2894 const struct impr_type *utype_needs_improvement(const struct unit_type *putype,
2895 const struct city *pcity)
2896{
2897 const struct impr_type *impr_req = NULL;
2898 const struct req_context context = {
2899 .player = city_owner(pcity),
2900 .city = pcity,
2901 .tile = city_tile(pcity),
2902 .unittype = putype,
2903 };
2904
2905 requirement_vector_iterate(&putype->build_reqs, preq) {
2906 if (is_req_active(&context, NULL, preq, RPT_CERTAIN)) {
2907 /* Already there. */
2908 continue;
2909 }
2910 if (!dai_can_requirement_be_met_in_city(preq,
2911 city_owner(pcity), pcity)) {
2912 /* The unit type can't be built at all. */
2913 return NULL;
2914 }
2915 if (VUT_IMPROVEMENT == preq->source.kind && preq->present) {
2916 /* This is (one of) the building(s) required. */
2917 impr_req = preq->source.value.building;
2918 }
2919 } requirement_vector_iterate_end;
2920
2921 return impr_req;
2922}
2923
2924/**********************************************************************/
2928 bool is_on_unit_upgrade_path(const struct unit_type *test,
2929 const struct unit_type *base)
2930{
2931 /* This is the real function: */
2932 do {
2933 base = base->obsoleted_by;
2934 if (base == test) {
2935 return TRUE;
2936 }
2937 } while (base);
2938 return FALSE;
2939}
2940
2941/**********************************************************************/
2946 static void dai_manage_barbarian_leader(struct ai_type *ait,
2947 struct player *pplayer,
2948 struct unit *leader)
2949{
2950 struct tile *leader_tile = unit_tile(leader), *safest_tile;
2951 struct pf_parameter parameter;
2952 struct pf_map *pfm;
2953 struct pf_reverse_map *pfrm;
2954 struct unit *worst_danger;
2955 int move_cost, best_move_cost;
2956 int body_guards;
2957 bool alive = TRUE;
2958 const struct civ_map *nmap = &(wld.map);
2959
2960 CHECK_UNIT(leader);
2961
2962 if (leader->moves_left == 0
2963 || (can_unit_survive_at_tile(&(wld.map), leader, leader_tile)
2964 && 1 < unit_list_size(leader_tile->units))) {
2965 unit_activity_handling(leader, ACTIVITY_SENTRY);
2966
2967 return;
2968 }
2969
2970 if (is_boss_of_boat(ait, leader)) {
2971 /* We are in charge. Of course, since we are the leader...
2972 * But maybe somebody more militaristic should lead our ship to battle! */
2973
2974 /* First release boat from leaders lead */
2975 aiferry_clear_boat(ait, leader);
2976
2977 unit_list_iterate(leader_tile->units, warrior) {
2978 if (!unit_has_type_role(warrior, L_BARBARIAN_LEADER)
2979 && get_transporter_capacity(warrior) == 0
2980 && warrior->moves_left > 0) {
2981 /* This seems like a good warrior to lead us in to conquest! */
2982 dai_manage_unit(ait, pplayer, warrior);
2983
2984 /* If we reached our destination, ferryboat already called
2985 * ai_manage_unit() for leader. So no need to continue here.
2986 * Leader might even be dead.
2987 * If this return is removed, surronding unit_list_iterate()
2988 * has to be replaced with unit_list_iterate_safe()*/
2989 return;
2990 }
2991 } unit_list_iterate_end;
2992 }
2993
2994 /* If we are not in charge of the boat, continue as if we
2995 * were not in a boat - we may want to leave the ship now. */
2996
2997 /* Check the total number of units able to protect our leader. */
2998 body_guards = 0;
2999 unit_list_iterate(pplayer->units, punit) {
3000 if (!unit_has_type_role(punit, L_BARBARIAN_LEADER)
3001 && goto_is_sane(punit, leader_tile)) {
3002 body_guards++;
3003 }
3004 } unit_list_iterate_end;
3005
3006 if (0 < body_guards) {
3007 pft_fill_unit_parameter(&parameter, nmap, leader);
3008 parameter.omniscience = !has_handicap(pplayer, H_MAP);
3009 pfm = pf_map_new(&parameter);
3010
3011 /* Find the closest body guard.
3012 * FIXME: maybe choose the strongest too? */
3013 pf_map_tiles_iterate(pfm, ptile, FALSE) {
3014 unit_list_iterate(ptile->units, punit) {
3015 if (unit_owner(punit) == pplayer
3016 && !unit_has_type_role(punit, L_BARBARIAN_LEADER)
3017 && goto_is_sane(punit, leader_tile)) {
3018 struct pf_path *path = pf_map_path(pfm, ptile);
3019
3020 adv_follow_path(leader, path, ptile);
3021 pf_path_destroy(path);
3022 pf_map_destroy(pfm);
3023 return;
3024 }
3025 } unit_list_iterate_end;
3026 } pf_map_tiles_iterate_end;
3027
3028 pf_map_destroy(pfm);
3029 }
3030
3031 UNIT_LOG(LOG_DEBUG, leader, "Barbarian leader needs to flee");
3032
3033 /* Check for units we could fear. */
3034 pfrm = pf_reverse_map_new(pplayer, leader_tile, 3,
3035 !has_handicap(pplayer, H_MAP), &(wld.map));
3036 worst_danger = NULL;
3037 best_move_cost = FC_INFINITY;
3038
3039 players_iterate(other_player) {
3040 if (other_player == pplayer) {
3041 continue;
3042 }
3043
3044 unit_list_iterate(other_player->units, punit) {
3045 move_cost = pf_reverse_map_unit_move_cost(pfrm, punit);
3046 if (PF_IMPOSSIBLE_MC != move_cost && move_cost < best_move_cost) {
3047 best_move_cost = move_cost;
3048 worst_danger = punit;
3049 }
3050 } unit_list_iterate_end;
3051 } players_iterate_end;
3052
3053 pf_reverse_map_destroy(pfrm);
3054
3055 if (NULL == worst_danger) {
3056 unit_activity_handling(leader, ACTIVITY_IDLE);
3057 UNIT_LOG(LOG_DEBUG, leader, "Barbarian leader: no close enemy.");
3058 return;
3059 }
3060
3061 pft_fill_unit_parameter(&parameter, nmap, worst_danger);
3062 parameter.omniscience = !has_handicap(pplayer, H_MAP);
3063 pfm = pf_map_new(&parameter);
3064 best_move_cost = pf_map_move_cost(pfm, leader_tile);
3065
3066 /* Try to escape. */
3067 do {
3068 safest_tile = leader_tile;
3069
3070 UNIT_LOG(LOG_DEBUG, leader, "Barbarian leader: moves left: %d.",
3071 leader->moves_left);
3072
3073 adjc_iterate(&(wld.map), leader_tile, near_tile) {
3074 if (adv_could_unit_move_to_tile(leader, near_tile) != 1) {
3075 continue;
3076 }
3077
3078 move_cost = pf_map_move_cost(pfm, near_tile);
3079 if (PF_IMPOSSIBLE_MC != move_cost
3080 && move_cost > best_move_cost) {
3081 UNIT_LOG(LOG_DEBUG, leader,
3082 "Barbarian leader: safest is (%d, %d), safeness %d",
3083 TILE_XY(near_tile), best_move_cost);
3084 best_move_cost = move_cost;
3085 safest_tile = near_tile;
3086 }
3087 } adjc_iterate_end;
3088
3089 UNIT_LOG(LOG_DEBUG, leader, "Barbarian leader: fleeing to (%d, %d).",
3090 TILE_XY(safest_tile));
3091 if (same_pos(unit_tile(leader), safest_tile)) {
3092 UNIT_LOG(LOG_DEBUG, leader,
3093 "Barbarian leader: reached the safest position.");
3094 unit_activity_handling(leader, ACTIVITY_IDLE);
3095 pf_map_destroy(pfm);
3096 return;
3097 }
3098
3099 alive = dai_unit_goto(ait, leader, safest_tile);
3100 if (alive) {
3101 if (same_pos(unit_tile(leader), leader_tile)) {
3102 /* Didn't move. No point to retry. */
3103 pf_map_destroy(pfm);
3104 return;
3105 }
3106 leader_tile = unit_tile(leader);
3107 }
3108 } while (alive && 0 < leader->moves_left);
3109
3110 pf_map_destroy(pfm);
3111}
3112
3113/**********************************************************************/
3119 void dai_consider_tile_dangerous(struct ai_type *ait, struct tile *ptile,
3120 struct unit *punit,
3121 enum override_bool *result)
3122{
3123 int a = 0, d, db;
3124 struct player *pplayer = unit_owner(punit);
3125 struct city *pcity = tile_city(ptile);
3126 int extras_bonus = 0;
3127
3128 if (is_human(pplayer)) {
3129 /* Use advisors code for humans. */
3130 return;
3131 }
3132
3133 if (pcity && pplayers_allied(city_owner(pcity), unit_owner(punit))
3134 && !is_non_allied_unit_tile(ptile, pplayer)) {
3135 /* We will be safe in a friendly city */
3136 *result = OVERRIDE_FALSE;
3137 return;
3138 }
3139
3140 /* Calculate how well we can defend at (x,y) */
3141 db = 10 + tile_terrain(ptile)->defense_bonus / 10;
3142 extras_bonus += tile_extras_defense_bonus(ptile, unit_type_get(punit));
3143
3144 db += (db * extras_bonus) / 100;
3145 d = adv_unit_def_rating_basic_squared(punit) * db;
3146
3147 adjc_iterate(&(wld.map), ptile, ptile1) {
3148 if (has_handicap(pplayer, H_FOG)
3149 && !map_is_known_and_seen(ptile1, unit_owner(punit), V_MAIN)) {
3150 /* We cannot see danger at (ptile1) => assume there is none */
3151 continue;
3152 }
3153 unit_list_iterate(ptile1->units, enemy) {
3154 if (pplayers_at_war(unit_owner(enemy), unit_owner(punit))
3155 && (unit_attack_unit_at_tile_result(enemy, NULL, punit, ptile)
3156 == ATT_OK)
3157 && (unit_attack_units_at_tile_result(enemy, NULL, ptile)
3158 == ATT_OK)) {
3159 a += adv_unit_att_rating(enemy);
3160 if ((a * a * 10) >= d) {
3161 /* The enemies combined strength is too big! */
3162 *result = OVERRIDE_TRUE;
3163 return;
3164 }
3165 }
3166 } unit_list_iterate_end;
3167 } adjc_iterate_end;
3168
3169 *result = OVERRIDE_FALSE;
3170}
3171
3172/**********************************************************************/
3175 static void update_simple_ai_types(void)
3176{
3177 int i = 0;
3178
3179 unit_type_iterate(punittype) {
3180 struct unit_class *pclass = utype_class(punittype);
3181
3182 if (A_NEVER != punittype->require_advance
3183 && !utype_has_flag(punittype, UTYF_CIVILIAN)
3184 && !utype_can_do_action(punittype, ACTION_SUICIDE_ATTACK)
3185 && !(pclass->adv.land_move == MOVE_NONE
3186 && !can_attack_non_native(punittype))
3187 && !utype_fuel(punittype)
3188 && punittype->transport_capacity < 8) {
3189 simple_ai_types[i] = punittype;
3190 i++;
3191 }
3192 } unit_type_iterate_end;
3193
3194 simple_ai_types[i] = NULL;
3195}
3196
3197/**********************************************************************/
3200 void dai_units_ruleset_init(struct ai_type *ait)
3201{
3202 /* TODO: remove the simple_ai_types cache or merge it with a general ai
3203 * cache; see the comment to struct unit_type *simple_ai_types at
3204 * the beginning of this file. */
3205 update_simple_ai_types();
3206
3207 unit_type_iterate(ptype) {
3208 struct unit_type_ai *utai = fc_malloc(sizeof(*utai));
3209
3210 utai->low_firepower = FALSE;
3211 utai->ferry = FALSE;
3212 utai->missile_platform = FALSE;
3213 utai->carries_occupiers = FALSE;
3214 utai->potential_charges = unit_type_list_new();
3215
3216 utype_set_ai_data(ptype, ait, utai);
3217 } unit_type_iterate_end;
3218
3219 unit_type_iterate(punittype) {
3220 struct unit_class *pclass = utype_class(punittype);
3221
3222 /* Confirm firepower */
3223 combat_bonus_list_iterate(punittype->bonuses, pbonus) {
3224 if (pbonus->type == CBONUS_LOW_FIREPOWER) {
3225 unit_type_iterate(penemy) {
3226 if (utype_has_flag(penemy, pbonus->flag)) {
3227 struct unit_type_ai *utai = utype_ai_data(penemy, ait);
3228
3229 utai->low_firepower = TRUE;
3230 }
3231 } unit_type_iterate_end;
3232 }
3233 } combat_bonus_list_iterate_end;
3234
3235 /* Consider potential cargo */
3236 if (punittype->transport_capacity > 0) {
3237 struct unit_type_ai *utai = utype_ai_data(punittype, ait);
3238
3239 unit_type_iterate(pctype) {
3240 struct unit_class *pcargo = utype_class(pctype);
3241
3242 if (can_unit_type_transport(punittype, pcargo)) {
3243 if (utype_can_do_action(pctype, ACTION_SUICIDE_ATTACK)) {
3244 utai->missile_platform = TRUE;
3245 } else if (pclass->adv.sea_move != MOVE_NONE
3246 && pcargo->adv.land_move != MOVE_NONE) {
3247 if (pcargo->adv.sea_move != MOVE_FULL) {
3248 utai->ferry = TRUE;
3249 } else {
3250 if (0 != utype_fuel(pctype)) {
3251 utai->ferry = TRUE;
3252 }
3253 }
3254 }
3255
3256 if (utype_can_take_over(pctype)) {
3257 utai->carries_occupiers = TRUE;
3258 }
3259 }
3260 } unit_type_iterate_end;
3261 }
3262
3263 /* Consider potential charges */
3264 unit_type_iterate(pcharge) {
3265 bool can_move_like_charge = FALSE;
3266
3267 if (0 < utype_fuel(punittype)
3268 && (0 == utype_fuel(pcharge)
3269 || utype_fuel(pcharge) > utype_fuel(punittype))) {
3270 continue;
3271 }
3272
3273 unit_class_list_iterate(pclass->cache.subset_movers, chgcls) {
3274 if (chgcls == utype_class(pcharge)) {
3275 can_move_like_charge = TRUE;
3276 }
3277 } unit_class_list_iterate_end;
3278
3279 if (can_move_like_charge) {
3280 struct unit_type_ai *utai = utype_ai_data(punittype, ait);
3281 unit_type_list_append(utai->potential_charges, pcharge);
3282 }
3283
3284 } unit_type_iterate_end;
3285 } unit_type_iterate_end;
3286}
3287
3288/**********************************************************************/
3291 void dai_units_ruleset_close(struct ai_type *ait)
3292{
3293 unit_type_iterate(ptype) {
3294 struct unit_type_ai *utai = utype_ai_data(ptype, ait);
3295
3296 if (utai == NULL) {
3297 continue;
3298 }
3299 utype_set_ai_data(ptype, ait, NULL);
3300
3301 unit_type_list_destroy(utai->potential_charges);
3302 free(utai);
3303 } unit_type_iterate_end;
3304}
3305
3306/**********************************************************************/
3309 void dai_unit_init(struct ai_type *ait, struct unit *punit)
3310{
3311 /* Make sure that contents of unit_ai structure are correctly initialized,
3312 * if you ever allocate it by some other mean than fc_calloc() */
3313 struct unit_ai *unit_data = fc_calloc(1, sizeof(struct unit_ai));
3314
3315 unit_data->done = FALSE;
3316 unit_data->cur_pos = NULL;
3317 unit_data->prev_pos = NULL;
3318 unit_data->target = 0;
3319 BV_CLR_ALL(unit_data->hunted);
3320 unit_data->ferryboat = 0;
3321 unit_data->passenger = 0;
3322 unit_data->bodyguard = 0;
3323 unit_data->charge = 0;
3324
3325 unit_set_ai_data(punit, ait, unit_data);
3326}
3327
3328/**********************************************************************/
3331 void dai_unit_turn_end(struct ai_type *ait, struct unit *punit)
3332{
3333 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
3334
3335 fc_assert_ret(unit_data != NULL);
3336
3337 BV_CLR_ALL(unit_data->hunted);
3338}
3339
3340/**********************************************************************/
3343 void dai_unit_close(struct ai_type *ait, struct unit *punit)
3344{
3345 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
3346
3347 fc_assert_ret(unit_data != NULL);
3348
3349 aiguard_clear_charge(ait, punit);
3350 aiguard_clear_guard(ait, punit);
3351
3352 if (unit_data != NULL) {
3353 unit_set_ai_data(punit, ait, NULL);
3354 FC_FREE(unit_data);
3355 }
3356}
3357
3358/**********************************************************************/
3361 void dai_unit_save(struct ai_type *ait, const char *aitstr,
3362 struct section_file *file,
3363 const struct unit *punit, const char *unitstr)
3364{
3365 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
3366
3367 secfile_insert_int(file, unit_data->passenger, "%s.%spassenger",
3368 unitstr, aitstr);
3369 secfile_insert_int(file, unit_data->ferryboat, "%s.%sferryboat",
3370 unitstr, aitstr);
3371 secfile_insert_int(file, unit_data->charge, "%s.%scharge",
3372 unitstr, aitstr);
3373 secfile_insert_int(file, unit_data->bodyguard, "%s.%sbodyguard",
3374 unitstr, aitstr);
3375}
3376
3377/**********************************************************************/
3380 void dai_unit_load(struct ai_type *ait, const char *aitstr,
3381 const struct section_file *file,
3382 struct unit *punit, const char *unitstr)
3383{
3384 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
3385
3386 unit_data->passenger
3387 = secfile_lookup_int_default(file, 0, "%s.%spassenger",
3388 unitstr, aitstr);
3389 unit_data->ferryboat
3390 = secfile_lookup_int_default(file, 0, "%s.%sferryboat",
3391 unitstr, aitstr);
3392 unit_data->charge
3393 = secfile_lookup_int_default(file, 0, "%s.%scharge",
3394 unitstr, aitstr);
3395 unit_data->bodyguard
3396 = secfile_lookup_int_default(file, 0, "%s.%sbodyguard",
3397 unitstr, aitstr);
3398}
3399
3400 struct role_unit_cb_data
3401{
3402 enum terrain_class tc;
3403 struct city *build_city;
3404};
3405
3406/**********************************************************************/
3409 static bool role_unit_cb(struct unit_type *ptype, void *data)
3410{
3411 struct role_unit_cb_data *cb_data = (struct role_unit_cb_data *)data;
3412 struct unit_class *pclass = utype_class(ptype);
3413
3414 if ((cb_data->tc == TC_LAND && pclass->adv.land_move == MOVE_NONE)
3415 || (cb_data->tc == TC_OCEAN && pclass->adv.sea_move == MOVE_NONE)) {
3416 return FALSE;
3417 }
3418
3419 if (cb_data->build_city == NULL
3420 || can_city_build_unit_now(cb_data->build_city, ptype)) {
3421 return TRUE;
3422 }
3423
3424 return FALSE;
3425}
3426
3427/**********************************************************************/
3430 struct unit_type *dai_role_utype_for_terrain_class(struct city *pcity, int role,
3431 enum terrain_class tc)
3432{
3433 struct role_unit_cb_data cb_data = { .build_city = pcity, .tc = tc };
3434
3435 return role_units_iterate_backwards(role, role_unit_cb, &cb_data);
3436}
3437
3438/**********************************************************************/
3441 bool dai_unit_can_strike_my_unit(const struct unit *attacker,
3442 const struct unit *defender)
3443{
3444 struct pf_parameter parameter;
3445 struct pf_map *pfm;
3446 const struct tile *ptarget = unit_tile(defender);
3447 int max_move_cost = attacker->moves_left;
3448 bool able_to_strike = FALSE;
3449 const struct civ_map *nmap = &(wld.map);
3450
3451 pft_fill_unit_parameter(&parameter, nmap, attacker);
3452 parameter.omniscience = !has_handicap(unit_owner(defender), H_MAP);
3453 pfm = pf_map_new(&parameter);
3454
3455 pf_map_move_costs_iterate(pfm, ptile, move_cost, FALSE) {
3456 if (move_cost > max_move_cost) {
3457 break;
3458 }
3459
3460 if (ptile == ptarget) {
3461 able_to_strike = TRUE;
3462 break;
3463 }
3464 } pf_map_move_costs_iterate_end;
3465
3466 pf_map_destroy(pfm);
3467
3468 return able_to_strike;
3469}
3470
3471/**********************************************************************/
3474 void dai_switch_to_explore(struct ai_type *ait, struct unit *punit,
3475 struct tile *target, enum override_bool *allow)
3476{
3477 struct unit_ai *udata = def_ai_unit_data(punit, ait);
3478
3479 if (udata->task != AIUNIT_NONE && udata->task != AIUNIT_EXPLORE) {
3480 *allow = OVERRIDE_FALSE;
3481
3482 return;
3483 }
3484}
is_action_enabled_unit_on_city
bool is_action_enabled_unit_on_city(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct city *target_city)
Definition actions.c:4755
action_by_number
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
advbuilding.h
TRADE_WEIGHTING
#define TRADE_WEIGHTING
Definition advbuilding.h:21
SHIELD_WEIGHTING
#define SHIELD_WEIGHTING
Definition advbuilding.h:20
adv_follow_path
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
adv_unit_def_rating_basic_squared
int adv_unit_def_rating_basic_squared(const struct unit *punit)
Definition advgoto.c:404
adv_unit_def_rating_basic
int adv_unit_def_rating_basic(const struct unit *punit)
Definition advgoto.c:395
adv_unittype_att_rating
int adv_unittype_att_rating(const struct unit_type *punittype, int veteran, int moves_left, int hp)
Definition advgoto.c:374
adv_unit_att_rating
int adv_unit_att_rating(const struct unit *punit)
Definition advgoto.c:385
adv_could_unit_move_to_tile
int adv_could_unit_move_to_tile(struct unit *punit, struct tile *dest_tile)
Definition advgoto.c:348
adv_unit_execute_path
bool adv_unit_execute_path(struct unit *punit, struct pf_path *path)
Definition advgoto.c:82
advgoto.h
advtools.h
POWER_DIVIDER
#define POWER_DIVIDER
Definition advtools.h:32
dai_manage_airunit
void dai_manage_airunit(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiair.c:488
aiair.h
aidata.h
dai_manage_diplomat
void dai_manage_diplomat(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aidiplomat.c:721
aidiplomat.h
aiferry_gobyboat
bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
Definition aiferry.c:766
aiferry_find_boat
int aiferry_find_boat(struct ai_type *ait, struct unit *punit, int cap, struct pf_path **path)
Definition aiferry.c:497
dai_manage_ferryboat
void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiferry.c:1111
is_boat_free
bool is_boat_free(struct ai_type *ait, struct unit *boat, struct unit *punit, int cap)
Definition aiferry.c:440
aiferry_goto_amphibious
bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile)
Definition aiferry.c:732
is_boss_of_boat
bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:473
aiferry_avail_boats
int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:355
dai_is_ferry
bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
Definition aiferry.c:161
aiferry_clear_boat
void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:253
aiferry.h
aiguard_charge_city
struct city * aiguard_charge_city(struct ai_type *ait, struct unit *guard)
Definition aiguard.c:290
aiguard_clear_charge
void aiguard_clear_charge(struct ai_type *ait, struct unit *guard)
Definition aiguard.c:118
aiguard_request_guard
void aiguard_request_guard(struct ai_type *ait, struct unit *punit)
Definition aiguard.c:228
aiguard_has_guard
bool aiguard_has_guard(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:260
aiguard_assign_guard_unit
void aiguard_assign_guard_unit(struct ai_type *ait, struct unit *charge, struct unit *guard)
Definition aiguard.c:174
aiguard_wanted
bool aiguard_wanted(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:242
aiguard_assign_guard_city
void aiguard_assign_guard_city(struct ai_type *ait, struct city *charge, struct unit *guard)
Definition aiguard.c:197
aiguard_charge_unit
struct unit * aiguard_charge_unit(struct ai_type *ait, struct unit *guard)
Definition aiguard.c:280
aiguard_clear_guard
void aiguard_clear_guard(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:147
aiguard_guard_of
struct unit * aiguard_guard_of(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:270
aiguard_has_charge
bool aiguard_has_charge(struct ai_type *ait, struct unit *guard)
Definition aiguard.c:251
aiguard_update_charge
void aiguard_update_charge(struct ai_type *ait, struct unit *guard)
Definition aiguard.c:300
aiguard.h
CHECK_GUARD
#define CHECK_GUARD(ait, guard)
Definition aiguard.h:21
aihand.h
dai_hunter_qualify
bool dai_hunter_qualify(struct player *pplayer, struct unit *punit)
Definition aihunt.c:289
dai_hunter_manage
int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aihunt.c:437
aihunt.h
ailog.h
BODYGUARD_LOG
#define BODYGUARD_LOG(ait, loglevel, punit, msg,...)
Definition ailog.h:69
dai_manage_paratrooper
void dai_manage_paratrooper(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiparatrooper.c:198
aiparatrooper.h
aiplayer.h
def_ai_city_data
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition aiplayer.h:42
def_ai_unit_data
static struct unit_ai * def_ai_unit_data(const struct unit *punit, struct ai_type *deftype)
Definition aiplayer.h:48
stack_cost
int stack_cost(struct unit *pattacker, struct unit *pdefender)
Definition aitools.c:1262
goto_is_sane
bool goto_is_sane(struct unit *punit, struct tile *ptile)
Definition aitools.c:428
dai_assess_military_unhappiness
bool dai_assess_military_unhappiness(struct city *pcity)
Definition aitools.c:1397
dai_unit_attack
bool dai_unit_attack(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:816
dai_unit_goto
bool dai_unit_goto(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:604
dai_unit_new_task
void dai_unit_new_task(struct ai_type *ait, struct unit *punit, enum ai_unit_task task, struct tile *ptile)
Definition aitools.c:642
dai_unit_make_homecity
bool dai_unit_make_homecity(struct unit *punit, struct city *pcity)
Definition aitools.c:754
dai_unit_task_rule_name
const char * dai_unit_task_rule_name(const enum ai_unit_task task)
Definition aitools.c:77
military_amortize
adv_want military_amortize(struct player *pplayer, struct city *pcity, adv_want value, int delay, int build_cost)
Definition aitools.c:118
dai_gothere
bool dai_gothere(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile *dest_tile)
Definition aitools.c:243
aitools.h
dai_unit_save
void dai_unit_save(struct ai_type *ait, const char *aitstr, struct section_file *file, const struct unit *punit, const char *unitstr)
Definition aiunit.c:3361
has_defense
static bool has_defense(struct city *pcity)
Definition aiunit.c:220
kill_desire
adv_want kill_desire(adv_want benefit, int attack, int loss, int vuln, int victim_count)
Definition aiunit.c:340
dai_manage_military
void dai_manage_military(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2497
search_homecity_for_caravan
static bool search_homecity_for_caravan(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:2217
dai_caravan_goto
static void dai_caravan_goto(struct ai_type *ait, struct player *pplayer, struct unit *punit, const struct city *dest_city, bool help_wonder, bool required_boat, bool request_boat)
Definition aiunit.c:1982
unittype_def_rating_squared
int unittype_def_rating_squared(const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, struct tile *ptile, bool fortified, int veteran)
Definition aiunit.c:302
unit_role_defender
static bool unit_role_defender(const struct unit_type *punittype)
Definition aiunit.c:698
dai_units_ruleset_init
void dai_units_ruleset_init(struct ai_type *ait)
Definition aiunit.c:3200
LOG_CARAVAN
#define LOG_CARAVAN
Definition aiunit.c:87
unit_att_rating_now
static int unit_att_rating_now(const struct unit *punit)
Definition aiunit.c:257
dai_military_attack_barbarian
static void dai_military_attack_barbarian(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:1681
invasion_funct
static void invasion_funct(struct ai_type *ait, struct unit *punit, bool dest, int radius, int which)
Definition aiunit.c:1017
update_simple_ai_types
static void update_simple_ai_types(void)
Definition aiunit.c:3175
utype_needs_improvement
const struct impr_type * utype_needs_improvement(const struct unit_type *putype, const struct city *pcity)
Definition aiunit.c:2894
dai_switch_to_explore
void dai_switch_to_explore(struct ai_type *ait, struct unit *punit, struct tile *target, enum override_bool *allow)
Definition aiunit.c:3474
dai_find_boat_for_unit
static bool dai_find_boat_for_unit(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:1898
reinforcements_cost_and_value
static void reinforcements_cost_and_value(struct unit *punit, struct tile *ptile0, int *value, int *cost)
Definition aiunit.c:373
simple_ai_types
struct unit_type * simple_ai_types[U_LAST]
Definition aiunit.c:125
dai_airlift
static void dai_airlift(struct ai_type *ait, struct player *pplayer)
Definition aiunit.c:168
build_cost_balanced
int build_cost_balanced(const struct unit_type *punittype)
Definition aiunit.c:248
dai_unit_can_strike_my_unit
bool dai_unit_can_strike_my_unit(const struct unit *attacker, const struct unit *defender)
Definition aiunit.c:3441
is_on_unit_upgrade_path
bool is_on_unit_upgrade_path(const struct unit_type *test, const struct unit_type *base)
Definition aiunit.c:2928
dai_military_bodyguard
static void dai_military_bodyguard(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:632
single_invader
static void single_invader(struct ai_city *city_data, const struct unit_type *utype, int which)
Definition aiunit.c:989
LOG_CARAVAN3
#define LOG_CARAVAN3
Definition aiunit.c:89
dai_manage_units
void dai_manage_units(struct ai_type *ait, struct player *pplayer)
Definition aiunit.c:2859
look_for_charge
adv_want look_for_charge(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct unit **aunit, struct city **acity)
Definition aiunit.c:713
dai_manage_caravan
static void dai_manage_caravan(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2254
find_something_to_kill
adv_want find_something_to_kill(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile **pdest_tile, struct pf_path **ppath, struct pf_map **pferrymap, struct unit **pferryboat, const struct unit_type **pboattype, int *pmove_time)
Definition aiunit.c:1134
dai_set_defenders
static void dai_set_defenders(struct ai_type *ait, struct player *pplayer)
Definition aiunit.c:2764
dai_manage_unit
void dai_manage_unit(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2652
role_unit_cb
static bool role_unit_cb(struct unit_type *ptype, void *data)
Definition aiunit.c:3409
dai_military_attack
static void dai_military_attack(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:1744
dai_unit_turn_end
void dai_unit_turn_end(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:3331
dai_manage_settler
static void dai_manage_settler(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2630
avg_benefit
static int avg_benefit(int benefit, int loss, double chance)
Definition aiunit.c:364
LOG_CARAVAN2
#define LOG_CARAVAN2
Definition aiunit.c:88
find_neediest_airlift_city
static struct city * find_neediest_airlift_city(struct ai_type *ait, const struct player *pplayer)
Definition aiunit.c:137
unit_def_rating
static int unit_def_rating(const struct unit *attacker, const struct unit *defender)
Definition aiunit.c:276
dai_is_unit_tired_waiting_boat
static bool dai_is_unit_tired_waiting_boat(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:2113
dai_rampage_want
static int dai_rampage_want(struct unit *punit, struct tile *ptile)
Definition aiunit.c:455
dai_can_unit_type_follow_unit_type
bool dai_can_unit_type_follow_unit_type(const struct unit_type *follower, const struct unit_type *followee, struct ai_type *ait)
Definition aiunit.c:833
find_nearest_safe_city
struct city * find_nearest_safe_city(struct unit *punit)
Definition aiunit.c:1630
dai_manage_barbarian_leader
static void dai_manage_barbarian_leader(struct ai_type *ait, struct player *pplayer, struct unit *leader)
Definition aiunit.c:2946
dai_manage_hitpoint_recovery
static void dai_manage_hitpoint_recovery(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:2422
unit_att_rating_squared
static int unit_att_rating_squared(const struct unit *punit)
Definition aiunit.c:266
find_rampage_target
static struct pf_path * find_rampage_target(struct unit *punit, int thresh_adj, int thresh_move)
Definition aiunit.c:520
is_my_turn
static bool is_my_turn(struct unit *punit, struct unit *pdef)
Definition aiunit.c:398
unit_def_rating_squared
static int unit_def_rating_squared(const struct unit *punit, const struct unit *pdef)
Definition aiunit.c:289
dai_unit_init
void dai_unit_init(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:3309
dai_consider_tile_dangerous
void dai_consider_tile_dangerous(struct ai_type *ait, struct tile *ptile, struct unit *punit, enum override_bool *result)
Definition aiunit.c:3119
dai_military_findjob
static void dai_military_findjob(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:851
uclass_need_trans_between
bool uclass_need_trans_between(struct unit_class *pclass, struct tile *ctile, struct tile *ptile)
Definition aiunit.c:1943
dai_unit_load
void dai_unit_load(struct ai_type *ait, const char *aitstr, const struct section_file *file, struct unit *punit, const char *unitstr)
Definition aiunit.c:3380
caravan_optimize_callback
static void caravan_optimize_callback(const struct caravan_result *result, void *data)
Definition aiunit.c:2094
LOGLEVEL_RECOVERY
#define LOGLEVEL_RECOVERY
Definition aiunit.c:86
dai_unit_close
void dai_unit_close(struct ai_type *ait, struct unit *punit)
Definition aiunit.c:3343
dai_units_ruleset_close
void dai_units_ruleset_close(struct ai_type *ait)
Definition aiunit.c:3291
dai_role_utype_for_terrain_class
struct unit_type * dai_role_utype_for_terrain_class(struct city *pcity, int role, enum terrain_class tc)
Definition aiunit.c:3430
find_beachhead
bool find_beachhead(const struct player *pplayer, struct pf_map *ferry_map, struct tile *dest_tile, const struct unit_type *cargo_type, struct tile **ferry_dest, struct tile **beachhead_tile)
Definition aiunit.c:1059
dai_military_defend
static void dai_military_defend(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:943
dai_military_rampage
bool dai_military_rampage(struct unit *punit, int thresh_adj, int thresh_move)
Definition aiunit.c:599
dai_caravan_can_trade_cities_diff_cont
static bool dai_caravan_can_trade_cities_diff_cont(struct player *pplayer, struct unit *punit)
Definition aiunit.c:2172
aiunit.h
POTENTIALLY_HOSTILE_PLAYER
#define POTENTIALLY_HOSTILE_PLAYER(ait, pplayer, aplayer)
Definition aiunit.h:72
AIUNIT_BUILD_CITY
@ AIUNIT_BUILD_CITY
Definition aiunit.h:27
AIUNIT_NONE
@ AIUNIT_NONE
Definition aiunit.h:27
AIUNIT_ATTACK
@ AIUNIT_ATTACK
Definition aiunit.h:28
AIUNIT_EXPLORE
@ AIUNIT_EXPLORE
Definition aiunit.h:29
AIUNIT_HUNTER
@ AIUNIT_HUNTER
Definition aiunit.h:29
AIUNIT_RECOVER
@ AIUNIT_RECOVER
Definition aiunit.h:29
AIUNIT_TRADE
@ AIUNIT_TRADE
Definition aiunit.h:30
AIUNIT_DEFEND_HOME
@ AIUNIT_DEFEND_HOME
Definition aiunit.h:28
AIUNIT_ESCORT
@ AIUNIT_ESCORT
Definition aiunit.h:28
AIUNIT_AUTO_SETTLER
@ AIUNIT_AUTO_SETTLER
Definition aiunit.h:27
AIUNIT_WONDER
@ AIUNIT_WONDER
Definition aiunit.h:30
RAMPAGE_ANYTHING
#define RAMPAGE_ANYTHING
Definition aiunit.h:85
RAMPAGE_FREE_CITY_OR_BETTER
#define RAMPAGE_FREE_CITY_OR_BETTER
Definition aiunit.h:87
INVASION_ATTACK
#define INVASION_ATTACK
Definition aiunit.h:81
INVASION_OCCUPY
#define INVASION_OCCUPY
Definition aiunit.h:80
RAMPAGE_HUT_OR_BETTER
#define RAMPAGE_HUT_OR_BETTER
Definition aiunit.h:86
DEFENSE_POWER
#define DEFENSE_POWER(ptype)
Definition aiunit.h:66
IS_ATTACKER
#define IS_ATTACKER(ptype)
Definition aiunit.h:70
BODYGUARD_RAMPAGE_THRESHOLD
#define BODYGUARD_RAMPAGE_THRESHOLD
Definition aiunit.h:88
ATTACK_POWER
#define ATTACK_POWER(ptype)
Definition aiunit.h:68
manage_auto_explorer
enum unit_move_result manage_auto_explorer(struct unit *punit)
Definition autoexplorer.c:273
autoexplorer.h
adv_unit_new_task
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
Definition autosettlers.c:1267
autosettlers.h
is_land_barbarian
bool is_land_barbarian(struct player *pplayer)
Definition barbarian.c:75
barbarian.h
bitvector.h
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
caravan_find_best_destination
void caravan_find_best_destination(const struct civ_map *nmap, const struct unit *caravan, const struct caravan_parameter *parameter, struct caravan_result *result, bool omniscient)
Definition caravan.c:750
caravan_parameter_init_from_unit
void caravan_parameter_init_from_unit(struct caravan_parameter *parameter, const struct unit *caravan)
Definition caravan.c:53
caravan.h
FTL_ALLIED
@ FTL_ALLIED
Definition caravan.h:31
FTL_NATIONAL_ONLY
@ FTL_NATIONAL_ONLY
Definition caravan.h:30
FTL_NONWAR
@ FTL_NONWAR
Definition caravan.h:33
city_production_gets_caravan_shields
bool city_production_gets_caravan_shields(const struct universal *tgt)
Definition city.c:1829
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1111
city_production_unit_veteran_level
int city_production_unit_veteran_level(struct city *pcity, const struct unit_type *punittype)
Definition city.c:789
can_city_build_unit_now
bool can_city_build_unit_now(const struct city *pcity, const struct unit_type *punittype)
Definition city.c:928
city.h
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:488
city_tile
#define city_tile(_pcity_)
Definition city.h:544
CITIZEN_ANGRY
@ CITIZEN_ANGRY
Definition city.h:263
CITIZEN_UNHAPPY
@ CITIZEN_UNHAPPY
Definition city.h:262
city_owner
#define city_owner(_pcity_)
Definition city.h:543
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:490
FEELING_NATIONALITY
@ FEELING_NATIONALITY
Definition city.h:274
find_closest_city
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Definition citytools.c:849
citytools.h
cityturn.h
is_stack_vulnerable
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:928
get_virtual_defense_power
int get_virtual_defense_power(const struct civ_map *nmap, const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, struct tile *ptile, bool fortified, int veteran)
Definition combat.c:657
unit_attack_units_at_tile_result
enum unit_attack_result unit_attack_units_at_tile_result(const struct unit *punit, const struct action *paction, const struct tile *ptile)
Definition combat.c:256
get_total_defense_power
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:712
unit_attack_unit_at_tile_result
enum unit_attack_result unit_attack_unit_at_tile_result(const struct unit *punit, const struct action *paction, const struct unit *pdefender, const struct tile *dest_tile)
Definition combat.c:122
unit_win_chance
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender)
Definition combat.c:438
can_unit_attack_tile
bool can_unit_attack_tile(const struct unit *punit, const struct action *paction, const struct tile *dest_tile)
Definition combat.c:271
base_get_defense_power
int base_get_defense_power(const struct unit *punit)
Definition combat.c:528
get_defender
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile)
Definition combat.c:781
combat.h
ATT_OK
@ ATT_OK
Definition combat.h:35
daicity.h
dai_can_requirement_be_met_in_city
bool dai_can_requirement_be_met_in_city(const struct requirement *preq, const struct player *pplayer, const struct city *pcity)
Definition daieffects.c:718
daieffects.h
dai_choose_defender_versus
struct unit_type * dai_choose_defender_versus(struct city *pcity, struct unit *attacker)
Definition daimilitary.c:91
assess_defense_quadratic
int assess_defense_quadratic(struct ai_type *ait, struct city *pcity)
Definition daimilitary.c:279
assess_defense_unit
int assess_defense_unit(struct ai_type *ait, struct city *pcity, struct unit *punit, bool igwall)
Definition daimilitary.c:313
daimilitary.h
attack
static void attack(QVariant data1, QVariant data2)
Definition dialogs.cpp:2917
base
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2839
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
cost
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int cost
Definition dialogs_g.h:73
ai_fuzzy
bool ai_fuzzy(const struct player *pplayer, bool normal_decision)
Definition difficulty.c:339
difficulty.h
diplomats.h
get_city_bonus
int get_city_bonus(const struct city *pcity, enum effect_type effect_type)
Definition effects.c:789
get_unittype_bonus
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, const struct action *paction, enum effect_type effect_type)
Definition effects.c:957
unit_can_enter_hut
bool unit_can_enter_hut(const struct unit *punit, const struct tile *ptile)
Definition extras.c:687
adv_want
float adv_want
Definition fc_types.h:1206
RPT_CERTAIN
@ RPT_CERTAIN
Definition fc_types.h:586
AUT_AUTO_SETTLER
@ AUT_AUTO_SETTLER
Definition fc_types.h:340
ADV_WANT_PRINTF
#define ADV_WANT_PRINTF
Definition fc_types.h:1207
O_LUXURY
@ O_LUXURY
Definition fc_types.h:91
Continent_id
signed short Continent_id
Definition fc_types.h:342
override_bool
override_bool
Definition fc_types.h:84
OVERRIDE_TRUE
@ OVERRIDE_TRUE
Definition fc_types.h:84
OVERRIDE_FALSE
@ OVERRIDE_FALSE
Definition fc_types.h:84
game
struct civ_game game
Definition game.c:57
wld
struct world wld
Definition game.c:58
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:111
game_city_by_number
struct city * game_city_by_number(int id)
Definition game.c:102
game.h
government.h
pos
static struct tile * pos
Definition finddlg.c:53
has_handicap
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
handicaps.h
H_MAP
@ H_MAP
Definition handicaps.h:28
H_TARGETS
@ H_TARGETS
Definition handicaps.h:24
H_AWAY
@ H_AWAY
Definition handicaps.h:19
H_FOG
@ H_FOG
Definition handicaps.h:26
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_do_output_for_level
#define log_do_output_for_level(level)
Definition log.h:89
log_base
#define log_base(level, message,...)
Definition log.h:94
log_level
log_level
Definition log.h:28
LOG_DEBUG
@ LOG_DEBUG
Definition log.h:34
LOG_NORMAL
@ LOG_NORMAL
Definition log.h:32
LOG_VERBOSE
@ LOG_VERBOSE
Definition log.h:33
is_tiles_adjacent
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:929
same_pos
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
real_map_distance
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:628
map_distance
int map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:652
map.h
iterate_outward
#define iterate_outward(nmap, start_tile, max_dist, itr_tile)
Definition map.h:361
iterate_outward_end
#define iterate_outward_end
Definition map.h:365
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:427
index_to_map_pos_y
static int index_to_map_pos_y(int mindex)
Definition map.h:696
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
square_iterate_end
#define square_iterate_end
Definition map.h:388
index_to_map_pos_x
static int index_to_map_pos_x(int mindex)
Definition map.h:687
pmap
#define pmap(_tile)
Definition mapgen_utils.c:66
map_is_known
bool map_is_known(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:886
map_is_known_and_seen
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:900
maphand.h
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:316
unit_move_rate
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
can_attack_from_non_native
bool can_attack_from_non_native(const struct unit_type *utype)
Definition movement.c:215
can_unit_survive_at_tile
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:476
can_unit_type_transport
bool can_unit_type_transport(const struct unit_type *transporter, const struct unit_class *transported)
Definition movement.c:826
can_attack_non_native
bool can_attack_non_native(const struct unit_type *utype)
Definition movement.c:202
movement.h
SINGLE_MOVE
#define SINGLE_MOVE
Definition movement.h:24
is_native_tile_to_class
static bool is_native_tile_to_class(const struct unit_class *punitclass, const struct tile *ptile)
Definition movement.h:80
MR_OK
@ MR_OK
Definition movement.h:33
MR_DEATH
@ MR_DEATH
Definition movement.h:34
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
nation_of_unit
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:462
packets.h
pf_path_destroy
void pf_path_destroy(struct pf_path *path)
Definition path_finding.c:3411
pf_map_new
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
Definition path_finding.c:3182
pf_map_path
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
Definition path_finding.c:3235
pf_reverse_map_new
struct pf_reverse_map * pf_reverse_map_new(const struct player *pplayer, struct tile *target_tile, int max_turns, bool omniscient, const struct civ_map *nmap)
Definition path_finding.c:3688
pf_map_position
bool pf_map_position(struct pf_map *pfm, struct tile *ptile, struct pf_position *pos)
Definition path_finding.c:3267
pf_reverse_map_destroy
void pf_reverse_map_destroy(struct pf_reverse_map *pfrm)
Definition path_finding.c:3727
pf_reverse_map_unit_move_cost
int pf_reverse_map_unit_move_cost(struct pf_reverse_map *pfrm, const struct unit *punit)
Definition path_finding.c:3866
pf_map_destroy
void pf_map_destroy(struct pf_map *pfm)
Definition path_finding.c:3206
pf_map_move_cost
int pf_map_move_cost(struct pf_map *pfm, struct tile *ptile)
Definition path_finding.c:3219
PF_IMPOSSIBLE_MC
#define PF_IMPOSSIBLE_MC
Definition path_finding.h:266
pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate_end
Definition path_finding.h:592
pf_map_move_costs_iterate
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
Definition path_finding.h:582
pf_map_tiles_iterate
#define pf_map_tiles_iterate(ARG_pfm, NAME_tile, COND_from_start)
Definition path_finding.h:561
pf_map_tiles_iterate_end
#define pf_map_tiles_iterate_end
Definition path_finding.h:568
pft_fill_unit_parameter
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
pft_fill_unit_attack_param
void pft_fill_unit_attack_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:949
pft_fill_unit_overlap_param
void pft_fill_unit_overlap_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:891
pft_fill_utype_overlap_param
void pft_fill_utype_overlap_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit_type *punittype, struct tile *pstart_tile, struct player *pplayer)
Definition pf_tools.c:876
pf_tools.h
player_unit_by_number
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1205
pplayers_at_war
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1364
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
players_iterate_end
#define players_iterate_end
Definition player.h:535
players_iterate
#define players_iterate(_pplayer)
Definition player.h:530
is_barbarian
static bool is_barbarian(const struct player *pplayer)
Definition player.h:488
is_human
#define is_human(plr)
Definition player.h:233
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
registry.h
secfile_lookup_int_default
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Definition registry_ini.c:1937
secfile_insert_int
#define secfile_insert_int(secfile, value, path,...)
Definition registry_ini.h:116
is_req_active
bool is_req_active(const struct req_context *context, const struct player *other_player, const struct requirement *req, const enum req_problem_type prob_type)
Definition requirements.c:4268
requirement_vector_iterate_end
#define requirement_vector_iterate_end
Definition requirements.h:93
requirement_vector_iterate
#define requirement_vector_iterate(req_vec, preq)
Definition requirements.h:91
level
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:183
shared.h
FC_INFINITY
#define FC_INFINITY
Definition shared.h:36
MAX
#define MAX(x, y)
Definition shared.h:54
get_specialist_output
int get_specialist_output(const struct city *pcity, Specialist_type_id sp, Output_type_id otype)
Definition specialist.c:217
specialist.h
specialist_type_iterate_end
#define specialist_type_iterate_end
Definition specialist.h:79
specialist_type_iterate
#define specialist_type_iterate(sp)
Definition specialist.h:73
srv_log.h
CITY_LOG
#define CITY_LOG(loglevel, pcity, msg,...)
Definition srv_log.h:83
LOGLEVEL_HUNT
#define LOGLEVEL_HUNT
Definition srv_log.h:35
UNIT_LOG
#define UNIT_LOG(loglevel, punit, msg,...)
Definition srv_log.h:98
LOG_AI_TEST
#define LOG_AI_TEST
Definition srv_log.h:38
AIT_RECOVER
@ AIT_RECOVER
Definition srv_log.h:68
AIT_FSTK
@ AIT_FSTK
Definition srv_log.h:54
AIT_CARAVAN
@ AIT_CARAVAN
Definition srv_log.h:56
AIT_RAMPAGE
@ AIT_RAMPAGE
Definition srv_log.h:71
AIT_ATTACK
@ AIT_ATTACK
Definition srv_log.h:66
AIT_HUNTER
@ AIT_HUNTER
Definition srv_log.h:57
AIT_BODYGUARD
@ AIT_BODYGUARD
Definition srv_log.h:69
AIT_DEFENDERS
@ AIT_DEFENDERS
Definition srv_log.h:55
AIT_AIRUNIT
@ AIT_AIRUNIT
Definition srv_log.h:60
AIT_FERRY
@ AIT_FERRY
Definition srv_log.h:70
AIT_MILITARY
@ AIT_MILITARY
Definition srv_log.h:67
AIT_DIPLOMAT
@ AIT_DIPLOMAT
Definition srv_log.h:59
AIT_AIRLIFT
@ AIT_AIRLIFT
Definition srv_log.h:58
TIMER_STOP
@ TIMER_STOP
Definition srv_log.h:76
TIMER_START
@ TIMER_START
Definition srv_log.h:76
TIMING_LOG
#define TIMING_LOG(timer, activity)
Definition srv_log.h:125
LOGLEVEL_BODYGUARD
#define LOGLEVEL_BODYGUARD
Definition srv_log.h:30
ai_city
Definition daicity.h:34
ai_city::danger
unsigned int danger
Definition daicity.h:47
ai_city::bcost
int bcost
Definition daicity.h:44
ai_city::urgency
unsigned int urgency
Definition daicity.h:49
ai_city::worth
adv_want worth
Definition daicity.h:35
ai_city::attack
int attack
Definition daicity.h:44
ai_city::invasion
struct ai_invasion invasion
Definition daicity.h:43
ai_city::grave_danger
unsigned int grave_danger
Definition daicity.h:48
ai_invasion::attack
int attack
Definition daicity.h:30
ai_invasion::occupy
int occupy
Definition daicity.h:31
ai_type
Definition ai.h:50
caravan_parameter
Definition caravan.h:61
caravan_parameter::callback
void(* callback)(const struct caravan_result *result, void *data)
Definition caravan.h:124
caravan_parameter::allow_foreign_trade
enum foreign_trade_limit allow_foreign_trade
Definition caravan.h:99
caravan_parameter::ignore_transit_time
bool ignore_transit_time
Definition caravan.h:108
caravan_parameter::callback_data
void * callback_data
Definition caravan.h:125
caravan_result
Definition caravan.h:51
caravan_result::src
const struct city * src
Definition caravan.h:52
caravan_result::dest
const struct city * dest
Definition caravan.h:53
caravan_result::help_wonder
bool help_wonder
Definition caravan.h:57
caravan_result::value
double value
Definition caravan.h:56
city
Definition city.h:309
city::id
int id
Definition city.h:315
city::owner
struct player * owner
Definition city.h:312
city::production
struct universal production
Definition city.h:382
city::adv
struct adv_city * adv
Definition city.h:435
city::tile
struct tile * tile
Definition city.h:311
civ_game::server
struct civ_game::@30::@34 server
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::occupychance
int occupychance
Definition game.h:169
civ_map
Definition map_types.h:71
impr_type
Definition improvement.h:68
packet_game_info::turn
int turn
Definition packets_gen.h:241
pf_map
Definition path_finding.c:78
pf_parameter
Definition path_finding.h:357
pf_parameter::omniscience
bool omniscience
Definition path_finding.h:376
pf_path
Definition path_finding.h:344
pf_position
Definition path_finding.h:327
pf_reverse_map
Definition path_finding.c:3587
player
Definition player.h:249
player::cities
struct city_list * cities
Definition player.h:281
player::units
struct unit_list * units
Definition player.h:282
player::is_alive
bool is_alive
Definition player.h:268
req_context
Definition requirements.h:99
req_context::player
const struct player * player
Definition requirements.h:100
role_unit_cb_data
Definition aiunit.c:3401
role_unit_cb_data::tc
enum terrain_class tc
Definition aiunit.c:3402
role_unit_cb_data::build_city
struct city * build_city
Definition aiunit.c:3403
section_file
Definition section_file.h:36
tile
Definition tile.h:49
tile::units
struct unit_list * units
Definition tile.h:57
tile::continent
Continent_id continent
Definition tile.h:53
unit_ai
Definition aiunit.h:32
unit_ai::prev_pos
struct tile ** prev_pos
Definition aiunit.h:40
unit_ai::bodyguard
int bodyguard
Definition aiunit.h:36
unit_ai::hunted
bv_player hunted
Definition aiunit.h:43
unit_ai::done
bool done
Definition aiunit.h:44
unit_ai::ferryboat
int ferryboat
Definition aiunit.h:34
unit_ai::task
enum ai_unit_task task
Definition aiunit.h:46
unit_ai::cur_pos
struct tile ** cur_pos
Definition aiunit.h:40
unit_ai::passenger
int passenger
Definition aiunit.h:35
unit_ai::charge
int charge
Definition aiunit.h:37
unit_ai::target
int target
Definition aiunit.h:42
unit_class
Definition unittype.h:136
unit_class::non_native_def_pct
int non_native_def_pct
Definition unittype.h:143
unit_class::sea_move
enum move_level sea_move
Definition unittype.h:150
unit_class::subset_movers
struct unit_class_list * subset_movers
Definition unittype.h:160
unit_class::cache
struct unit_class::@85 cache
unit_class::ferry_types
int ferry_types
Definition unittype.h:151
unit_class::land_move
enum move_level land_move
Definition unittype.h:149
unit_class::adv
struct unit_class::@84 adv
unit_type_ai
Definition aiunit.h:50
unit_type_ai::carries_occupiers
bool carries_occupiers
Definition aiunit.h:54
unit_type_ai::potential_charges
struct unit_type_list * potential_charges
Definition aiunit.h:55
unit_type_ai::ferry
bool ferry
Definition aiunit.h:52
unit_type_ai::missile_platform
bool missile_platform
Definition aiunit.h:53
unit_type_ai::low_firepower
bool low_firepower
Definition aiunit.h:51
unit_type
Definition unittype.h:481
unit_type::adv
struct unit_type::@87 adv
unit_type::build_reqs
struct requirement_vector build_reqs
Definition unittype.h:501
unit_type::defense_strength
int defense_strength
Definition unittype.h:496
unit_type::cargo
bv_unit_classes cargo
Definition unittype.h:539
unit_type::firepower
int firepower
Definition unittype.h:506
unit_type::worker
bool worker
Definition unittype.h:556
unit_type::veteran
struct veteran_system * veteran
Definition unittype.h:525
unit_type::move_rate
int move_rate
Definition unittype.h:497
unit_type::hp
int hp
Definition unittype.h:505
unit_type::attack_strength
int attack_strength
Definition unittype.h:495
unit
Definition unit.h:138
unit::activity
enum unit_activity activity
Definition unit.h:157
unit::moves_left
int moves_left
Definition unit.h:150
unit::id
int id
Definition unit.h:145
unit::moved
bool moved
Definition unit.h:173
unit::hp
int hp
Definition unit.h:151
unit::tile
struct tile * tile
Definition unit.h:140
unit::server
struct unit::@80::@83 server
unit::homecity
int homecity
Definition unit.h:146
unit::birth_turn
int birth_turn
Definition unit.h:235
unit::goto_tile
struct tile * goto_tile
Definition unit.h:155
unit::veteran
int veteran
Definition unit.h:152
unit::owner
struct player * owner
Definition unit.h:143
world::map
struct civ_map map
Definition world_object.h:38
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
A_NEVER
#define A_NEVER
Definition tech.h:51
is_terrain_class_near_tile
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:600
is_ocean_tile
#define is_ocean_tile(ptile)
Definition terrain.h:289
tile_extras_defense_bonus
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:227
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_index
#define tile_index(_pt_)
Definition tile.h:87
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:109
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:42
tile_continent
#define tile_continent(_tile)
Definition tile.h:91
timing.h
can_cities_trade
bool can_cities_trade(const struct city *pc1, const struct city *pc2)
Definition traderoutes.c:214
can_establish_trade_route
bool can_establish_trade_route(const struct city *pc1, const struct city *pc2)
Definition traderoutes.c:275
traderoutes.h
unit_set_ai_data
void unit_set_ai_data(struct unit *punit, const struct ai_type *ai, void *data)
Definition unit.c:2276
unit_transport_load
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2356
is_losing_hp
bool is_losing_hp(const struct unit *punit)
Definition unit.c:2214
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2427
unit_gain_hitpoints
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2169
is_military_unit
bool is_military_unit(const struct unit *punit)
Definition unit.c:322
unit_is_cityfounder
bool unit_is_cityfounder(const struct unit *punit)
Definition unit.c:2625
unit_can_do_action
bool unit_can_do_action(const struct unit *punit, const action_id act_id)
Definition unit.c:331
unit_can_do_action_result
bool unit_can_do_action_result(const struct unit *punit, enum action_result result)
Definition unit.c:341
get_transporter_capacity
int get_transporter_capacity(const struct unit *punit)
Definition unit.c:302
unit_can_airlift_to
bool unit_can_airlift_to(const struct unit *punit, const struct city *pdest_city)
Definition unit.c:188
can_unit_do_activity
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:873
unit_transported
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2411
unit_has_orders
bool unit_has_orders(const struct unit *punit)
Definition unit.c:207
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
unit_cargo_iterate_end
#define unit_cargo_iterate_end
Definition unit.h:562
unit_cargo_iterate
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:559
CHECK_UNIT
#define CHECK_UNIT(punit)
Definition unit.h:268
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:423
unit_activity_handling
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6176
unit_do_action
void unit_do_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id, const char *name, const action_id action_type)
Definition unithand.c:3153
unit_server_side_agent_set
bool unit_server_side_agent_set(struct player *pplayer, struct unit *punit, enum server_side_agent agent)
Definition unithand.c:6076
unithand.h
unit_list_find
struct unit * unit_list_find(const struct unit_list *punitlist, int unit_id)
Definition unitlist.c:30
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_safe
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_list_iterate_safe_end
#define unit_list_iterate_safe_end
Definition unitlist.h:61
unittools.h
utype_action_takes_all_mp
bool utype_action_takes_all_mp(const struct unit_type *putype, struct action *paction)
Definition unittype.c:1243
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
role_units_iterate_backwards
struct unit_type * role_units_iterate_backwards(int role, role_unit_callback cb, void *data)
Definition unittype.c:2284
get_role_unit
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2301
unit_rule_name
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1639
utype_has_role
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:193
utype_build_shield_cost_base
int utype_build_shield_cost_base(const struct unit_type *punittype)
Definition unittype.c:1520
unit_build_shield_cost_base
int unit_build_shield_cost_base(const struct unit *punit)
Definition unittype.c:1536
best_role_unit_for_player
struct unit_type * best_role_unit_for_player(const struct player *pplayer, int role)
Definition unittype.c:2345
unit_class_get
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2546
utype_can_do_action_result
bool utype_can_do_action_result(const struct unit_type *putype, enum action_result result)
Definition unittype.c:459
unit_has_type_role
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:202
unit_can_take_over
bool unit_can_take_over(const struct unit *punit)
Definition unittype.c:258
utype_ai_data
void * utype_ai_data(const struct unit_type *ptype, const struct ai_type *ai)
Definition unittype.c:2741
utype_can_take_over
bool utype_can_take_over(const struct unit_type *punittype)
Definition unittype.c:270
utype_set_ai_data
void utype_set_ai_data(struct unit_type *ptype, const struct ai_type *ai, void *data)
Definition unittype.c:2749
utype_build_shield_cost
int utype_build_shield_cost(const struct city *pcity, const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1490
utype_acts_hostile
bool utype_acts_hostile(const struct unit_type *putype)
Definition unittype.c:515
utype_can_do_action
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:443
utype_class
#define utype_class(_t_)
Definition unittype.h:736
utype_fuel
#define utype_fuel(ptype)
Definition unittype.h:822
combat_bonus_list_iterate_end
#define combat_bonus_list_iterate_end
Definition unittype.h:463
combat_bonus_list_iterate
#define combat_bonus_list_iterate(bonuslist, pbonus)
Definition unittype.h:461
MOVE_FULL
@ MOVE_FULL
Definition unittype.h:131
MOVE_NONE
@ MOVE_NONE
Definition unittype.h:131
unit_type_list_iterate
#define unit_type_list_iterate(utype_list, ptype)
Definition unittype.h:908
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
unit_class_list_iterate
#define unit_class_list_iterate(uclass_list, pclass)
Definition unittype.h:900
unit_type_iterate
#define unit_type_iterate(_p)
Definition unittype.h:838
unit_type_list_iterate_end
#define unit_type_list_iterate_end
Definition unittype.h:910
U_LAST
#define U_LAST
Definition unittype.h:40
unit_type_iterate_end
#define unit_type_iterate_end
Definition unittype.h:845
unit_class_list_iterate_end
#define unit_class_list_iterate_end
Definition unittype.h:902