67
69
/***********************************************************************
68
70
Can unit attack other
69
71
***********************************************************************/
70
bool is_unit_reachable_by_unit(const struct unit *defender,
71
const struct unit *attacker)
72
static bool is_unit_reachable_by_unit(const struct unit *defender,
73
const struct unit *attacker)
73
75
struct unit_class *dclass = unit_class(defender);
74
76
struct unit_type *atype = unit_type(attacker);
79
81
/***********************************************************************
82
Can unit attack other at given location
83
***********************************************************************/
84
bool is_unit_reachable_at(const struct unit *defender,
85
const struct unit *attacker,
86
const struct tile *location)
88
if (NULL != tile_city(location)) {
92
if (is_unit_reachable_by_unit(defender, attacker)) {
96
if (tile_has_native_base(location, unit_type(defender))) {
103
/***********************************************************************
80
104
Checks if a unit can physically attack pdefender at the tile
81
105
(assuming it is adjacent and at war).
97
121
const struct unit *pdefender,
98
122
const struct tile *dest_tile)
100
struct city *pcity = tile_city(dest_tile);
102
124
/* 1. Can we attack _anything_ ? */
103
125
if (!is_military_unit(punit) || !is_attack_unit(punit)) {
107
129
/* 2. Only fighters can attack planes, except in city or airbase attacks */
108
if (!is_unit_reachable_by_unit(pdefender, punit)
109
&& !(pcity || tile_has_native_base(dest_tile, unit_type(pdefender)))) {
130
if (!is_unit_reachable_at(pdefender, punit, dest_tile)) {
129
150
/***********************************************************************
151
When unreachable_protects setting is TRUE:
130
152
To attack a stack, unit must be able to attack every unit there (not
131
153
including transported units).
132
154
************************************************************************/
133
bool can_unit_attack_all_at_tile(const struct unit *punit,
134
const struct tile *ptile)
155
static bool can_unit_attack_all_at_tile(const struct unit *punit,
156
const struct tile *ptile)
136
158
unit_list_iterate(ptile->units, aunit) {
137
159
/* HACK: we don't count transported units here. This prevents some
151
173
/***********************************************************************
174
When unreachable_protects setting is FALSE:
175
To attack a stack, unit must be able to attack some unit there (not
176
including transported units).
177
************************************************************************/
178
static bool can_unit_attack_any_at_tile(const struct unit *punit,
179
const struct tile *ptile)
181
unit_list_iterate(ptile->units, aunit) {
182
/* HACK: we don't count transported units here. This prevents some
183
* bugs like a cargoplane carrying a land unit being vulnerable. */
184
if (aunit->transported_by == -1
185
&& can_unit_attack_unit_at_tile(punit, aunit, ptile)) {
188
} unit_list_iterate_end;
193
/***********************************************************************
194
Check if unit can attack unit stack at tile.
195
***********************************************************************/
196
bool can_unit_attack_units_at_tile(const struct unit *punit,
197
const struct tile *ptile)
199
if (game.info.unreachable_protects) {
200
return can_unit_attack_all_at_tile(punit, ptile);
202
return can_unit_attack_any_at_tile(punit, ptile);
206
/***********************************************************************
152
207
Is unit (1) diplomatically allowed to attack and (2) physically able
154
209
***********************************************************************/
155
210
bool can_unit_attack_tile(const struct unit *punit,
156
const struct tile *dest_tile)
211
const struct tile *dest_tile)
158
if (!can_player_attack_tile(unit_owner(punit), dest_tile)) {
162
return can_unit_attack_all_at_tile(punit, dest_tile);
213
return (can_player_attack_tile(unit_owner(punit), dest_tile)
214
&& can_unit_attack_units_at_tile(punit, dest_tile));
165
217
/***********************************************************************
333
385
square_iterate(ptile, 2, ptile1) {
334
386
struct city *pcity = tile_city(ptile1);
335
if (pcity && (!pplayers_allied(city_owner(pcity), owner))
336
&& myrand(100) < get_city_bonus(pcity, EFT_NUKE_PROOF)) {
389
&& !pplayers_allied(city_owner(pcity), owner)
390
&& fc_rand(100) < get_city_bonus(pcity, EFT_NUKE_PROOF)) {
339
393
} square_iterate_end;
427
481
struct city *pcity = tile_city(ptile);
430
CHECK_UNIT_TYPE(def_type);
433
CHECK_UNIT_TYPE(att_type);
484
fc_assert_ret_val(NULL != def_type, 0);
486
if (NULL != att_type) {
435
487
if (utype_has_flag(def_type, F_PIKEMEN)
436
488
&& utype_has_flag(att_type, F_HORSE)) {
437
489
defensepower *= 2;
557
609
unit_list_iterate(ptile->units, defender) {
558
610
/* We used to skip over allied units, but the logic for that is
559
611
* complicated and is now handled elsewhere. */
560
if (unit_can_defend_here(defender)) {
612
if (unit_can_defend_here(defender)
613
&& can_unit_attack_unit_at_tile(attacker, defender, ptile)) {
561
614
bool change = FALSE;
562
615
int build_cost = unit_build_shield_cost(defender);
563
616
int defense_rating = get_defense_rating(attacker, defender);
566
619
= (int) (100000 * (1 - unit_win_chance(attacker, defender)));
568
assert(unit_def >= 0);
621
fc_assert_action(0 <= unit_def, continue);
570
623
if (unit_has_type_flag(defender, F_GAMELOSS)
571
624
&& !is_stack_vulnerable(defender->tile)) {
572
unit_def = -1; // then always use leader as last defender
573
// FIXME: multiple gameloss units with varying defense value not handled
625
unit_def = -1; /* then always use leader as last defender. */
626
/* FIXME: multiple gameloss units with varying defense value
576
630
if (unit_def > bestvalue) {
595
649
} unit_list_iterate_end;
597
if (unit_list_size(ptile->units) > 0 && !bestdef) {
598
struct unit *punit = unit_list_get(ptile->units, 0);
600
freelog(LOG_ERROR, "get_defender bug: %s %s vs %s %s (total %d"
601
" units) on \"%s\" at (%d,%d). ",
602
nation_rule_name(nation_of_unit(attacker)),
603
unit_rule_name(attacker),
604
nation_rule_name(nation_of_unit(punit)),
605
unit_rule_name(punit),
606
unit_list_size(ptile->units),
607
terrain_rule_name(tile_terrain(ptile)),