Freeciv-3.1: /fast/freeciv/nightly/S3_1/common/combat.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
combat.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 "rand.h"
23#include "log.h"
24
25/* common */
26#include "base.h"
27#include "game.h"
28#include "map.h"
29#include "movement.h"
30#include "packets.h"
31#include "unit.h"
32#include "unitlist.h"
33#include "unittype.h"
34
35#include "combat.h"
36
37/*******************************************************************/
44 static bool can_player_attack_tile(const struct player *pplayer,
45 const struct tile *ptile)
46{
47 struct city *pcity = tile_city(ptile);
48
49 /* 1. Is there anyone there at all? */
50 if (!pcity && unit_list_size((ptile->units)) == 0) {
51 return FALSE;
52 }
53
54 /* 2. If there is a city there, can we attack it? */
55 if (pcity && !pplayers_at_war(city_owner(pcity), pplayer)) {
56 return FALSE;
57 }
58
59 /* 3. Are we allowed to attack _all_ units there? */
60 unit_list_iterate(ptile->units, aunit) {
61 if (!pplayers_at_war(unit_owner(aunit), pplayer)) {
62 /* Enemy hiding behind a human/diplomatic shield */
63 return FALSE;
64 }
65 } unit_list_iterate_end;
66
67 return TRUE;
68}
69
70/*******************************************************************/
73 static bool is_unit_reachable_by_unit(const struct unit *defender,
74 const struct unit *attacker)
75{
76 struct unit_class *dclass = unit_class_get(defender);
77 const struct unit_type *atype = unit_type_get(attacker);
78
79 return BV_ISSET(atype->targets, uclass_index(dclass));
80}
81
82/*******************************************************************/
85 bool is_unit_reachable_at(const struct unit *defender,
86 const struct unit *attacker,
87 const struct tile *location)
88{
89 if (NULL != tile_city(location)) {
90 return TRUE;
91 }
92
93 if (is_unit_reachable_by_unit(defender, attacker)) {
94 return TRUE;
95 }
96
97 if (tile_has_native_base(location, unit_type_get(defender))) {
98 return TRUE;
99 }
100
101 return FALSE;
102}
103
104/*******************************************************************/
121enum unit_attack_result
122unit_attack_unit_at_tile_result(const struct unit *punit,
123 const struct action *paction,
124 const struct unit *pdefender,
125 const struct tile *dest_tile)
126{
127 /* 1. Can we attack _anything_ ? */
128 if (paction == NULL) {
129 if (!(utype_can_do_action(unit_type_get(punit), ACTION_ATTACK)
130 || utype_can_do_action(unit_type_get(punit),
131 ACTION_SUICIDE_ATTACK)
132 /* Needed because ACTION_NUKE_UNITS uses this when evaluating its
133 * hard requirements. */
134 || utype_can_do_action(unit_type_get(punit),
135 ACTION_NUKE_UNITS))) {
136 return ATT_NON_ATTACK;
137 }
138 } else {
139 if (!utype_can_do_action(unit_type_get(punit), paction->id)) {
140 return ATT_NON_ATTACK;
141 }
142 }
143
144 /* 2. Can't attack with ground unit from ocean, except for marines */
145 if (paction == NULL) {
146 if (!is_native_tile(unit_type_get(punit), unit_tile(punit))
147 && !utype_can_do_act_when_ustate(unit_type_get(punit),
148 ACTION_ATTACK,
149 USP_NATIVE_TILE, FALSE)
150 && !utype_can_do_act_when_ustate(unit_type_get(punit),
151 ACTION_SUICIDE_ATTACK,
152 USP_NATIVE_TILE, FALSE)) {
153 return ATT_NONNATIVE_SRC;
154 }
155 } else {
156 if (!is_native_tile(unit_type_get(punit), unit_tile(punit))
157 && !utype_can_do_act_when_ustate(unit_type_get(punit),
158 paction->id,
159 USP_NATIVE_TILE, FALSE)) {
160 return ATT_NONNATIVE_SRC;
161 }
162 }
163
164 /* 3. Most units can not attack non-native terrain.
165 * Most ships can attack land tiles (shore bombardment) */
166 if (!is_native_tile(unit_type_get(punit), dest_tile)
167 && !can_attack_non_native(unit_type_get(punit))) {
168 return ATT_NONNATIVE_DST;
169 }
170
171 /* 4. Only fighters can attack planes, except in city or airbase attacks */
172 if (!is_unit_reachable_at(pdefender, punit, dest_tile)) {
173 return ATT_UNREACHABLE;
174 }
175
176 /* Unreachability check must remain the last check, as callers interpret
177 * ATT_UNREACHABLE as "ATT_OK except that unreachable." */
178
179 return ATT_OK;
180}
181
182/*******************************************************************/
187static enum unit_attack_result
188unit_attack_all_at_tile_result(const struct unit *punit,
189 const struct action *paction,
190 const struct tile *ptile)
191{
192 bool any_reachable_unit = FALSE;
193 bool any_neverprotect_unit = FALSE;
194
195 unit_list_iterate(ptile->units, aunit) {
196 /* HACK: we don't count transported units here. This prevents some
197 * bugs like a submarine carrying a cruise missile being invulnerable
198 * to other sea units. However from a gameplay perspective it's a hack,
199 * since players can load and unload their units manually to protect
200 * their transporters. */
201 if (!unit_transported(aunit)) {
202 enum unit_attack_result result;
203
204 result = unit_attack_unit_at_tile_result(punit, paction,
205 aunit, ptile);
206 if (result == ATT_UNREACHABLE
207 && unit_has_type_flag(aunit, UTYF_NEVER_PROTECTS)) {
208 /* Doesn't prevent us from attacking other units on the tile */
209 any_neverprotect_unit = TRUE;
210 continue;
211 } else if (result != ATT_OK) {
212 return result;
213 }
214 any_reachable_unit = TRUE;
215 }
216 } unit_list_iterate_end;
217
218 /* If there are only unreachable, UTYF_NEVER_PROTECTS units, we still have
219 * to return ATT_UNREACHABLE. */
220 return (any_reachable_unit || !any_neverprotect_unit) ? ATT_OK : ATT_UNREACHABLE;
221}
222
223/*******************************************************************/
228static enum unit_attack_result
229unit_attack_any_at_tile_result(const struct unit *punit,
230 const struct action *paction,
231 const struct tile *ptile)
232{
233 enum unit_attack_result result = ATT_OK;
234
235 unit_list_iterate(ptile->units, aunit) {
236 /* HACK: we don't count transported units here. This prevents some
237 * bugs like a cargoplane carrying a land unit being vulnerable. */
238 if (!unit_transported(aunit)) {
239 result = unit_attack_unit_at_tile_result(punit, paction,
240 aunit, ptile);
241 if (result == ATT_OK) {
242 return result;
243 }
244 }
245 } unit_list_iterate_end;
246
247 /* That's result from check against last unit on tile, not first.
248 * Shouldn't matter. */
249 return result;
250}
251
252/*******************************************************************/
255enum unit_attack_result
256unit_attack_units_at_tile_result(const struct unit *punit,
257 const struct action *paction,
258 const struct tile *ptile)
259{
260 if (game.info.unreachable_protects) {
261 return unit_attack_all_at_tile_result(punit, paction, ptile);
262 } else {
263 return unit_attack_any_at_tile_result(punit, paction, ptile);
264 }
265}
266
267/*******************************************************************/
271 bool can_unit_attack_tile(const struct unit *punit,
272 const struct action *paction,
273 const struct tile *dest_tile)
274{
275 return (can_player_attack_tile(unit_owner(punit), dest_tile)
276 && (unit_attack_units_at_tile_result(punit, paction, dest_tile)
277 == ATT_OK));
278}
279
280/*******************************************************************/
292 double win_chance(int as, int ahp, int afp, int ds, int dhp, int dfp)
293{
294 /* number of rounds a unit can fight without dying */
295 int att_N_lose = (ahp + dfp - 1) / dfp;
296 int def_N_lose = (dhp + afp - 1) / afp;
297 /* Probability of losing one round */
298 double att_P_lose1 = (as + ds == 0) ? 0.5 : (double) ds / (as + ds);
299 double def_P_lose1 = 1 - att_P_lose1;
300
301 /*
302 This calculates
303
304 binomial_coeff(def_N_lose-1 + lr, lr)
305 * def_P_lose1^(def_N_lose-1)
306 * att_P_lose1^(lr)
307 * def_P_lose1
308
309 for each possible number of rounds lost (rl) by the winning unit.
310 rl is of course less than the number of rounds the winning unit
311 should lose to lose all it's hit points.
312 The probabilities are then summed.
313
314 To see this is correct consider the set of series for all valid fights.
315 These series are the type (win, lose, lose...). The possible lengths are
316 def_N_lose to def_N_lose+att_N_lose-1. A series is not valid unless it
317 contains def_N_lose wins, and one of the wins must be the last one, or
318 the series would be equivalent the a shorter series (the attacker would
319 have won one or more fights previously).
320 So since the last fight is a win we disregard it while calculating. Now
321 a series contains def_N_lose-1 wins. So for each possible length of a
322 series we find the probability of every valid series and then sum.
323 For a specific length (a "lr") every series have the probability
324 def_P_lose1^(def_N_lose-1) * att_P_lose1^(lr)
325 and then getting from that to the real series requires a win, ie factor
326 def_N_lose. The number of series with length (def_N_lose-1 + lr) and
327 "lr" lost fights is
328 binomial_coeff(def_N_lose-1 + lr, lr)
329 And by multiplying we get the formula on the top of this code block.
330 Adding the cumulative probability for each valid length then gives the
331 total probability.
332
333 We clearly have all valid series this way. To see that we have counted
334 none twice note that would require a series with a smaller series inbedded.
335 But since the smaller series already included def_N_lose wins, and the
336 larger series ends with a win, it would have too many wins and therefore
337 cannot exist.
338
339 In practice each binomial coefficient for a series length can be calculated
340 from the previous. In the coefficient (n, k) n is increased and k is
341 unchanged.
342 The "* def_P_lose1" is multiplied on the sum afterwards.
343
344 (lots of talk for so little code)
345 */
346
347 double binom_save = pow(def_P_lose1, (double)(def_N_lose - 1));
348 double accum_prob = binom_save; /* lr = 0 */
349
350 int lr; /* the number of Lost Rounds by the attacker */
351 for (lr = 1; lr < att_N_lose; lr++) {
352 /* update the coefficient */
353 int n = lr + def_N_lose - 1;
354 binom_save *= n;
355 binom_save /= lr;
356 binom_save *= att_P_lose1;
357 /* use it for this lr */
358 accum_prob += binom_save;
359 }
360 /* Every element of the sum needs a factor for the very last fight round */
361 accum_prob *= def_P_lose1;
362
363 return accum_prob;
364}
365
366/*******************************************************************/
369 void get_modified_firepower(const struct civ_map *nmap,
370 const struct unit *attacker,
371 const struct unit *defender,
372 int *att_fp, int *def_fp)
373{
374 struct city *pcity = tile_city(unit_tile(defender));
375 const struct unit_type *att_type;
376 const struct unit_type *def_type;
377 struct tile *att_tile;
378
379 att_type = unit_type_get(attacker);
380 def_type = unit_type_get(defender);
381
382 *att_fp = att_type->firepower;
383 *def_fp = def_type->firepower;
384
385 /* Check CityBuster flag */
386 if (unit_has_type_flag(attacker, UTYF_CITYBUSTER) && pcity) {
387 *att_fp *= 2;
388 }
389
390 /*
391 * UTYF_BADWALLATTACKER reduces the firepower of the attacking unit to
392 * badwallattacker firepower if an EFT_DEFEND_BONUS applies
393 * (such as a land unit attacking a city with city walls).
394 */
395 if (unit_has_type_flag(attacker, UTYF_BADWALLATTACKER)
396 && get_unittype_bonus(unit_owner(defender), unit_tile(defender),
397 att_type, NULL,
398 EFT_DEFEND_BONUS) > 0) {
399 *att_fp = MIN(*att_fp, game.info.low_firepower_badwallattacker);
400 }
401
402 /* pearl harbour - defender's firepower is reduced,
403 * attacker's is multiplied by two */
404 if (unit_has_type_flag(defender, UTYF_BADCITYDEFENDER)
405 && tile_city(unit_tile(defender))) {
406 *att_fp *= 2;
407 *def_fp = MIN(*def_fp, game.info.low_firepower_pearl_harbour);
408 }
409
410 /*
411 * When attacked by fighters, helicopters have their firepower
412 * reduced to low firepower bonus.
413 */
414 if (combat_bonus_against(att_type->bonuses, def_type,
415 CBONUS_LOW_FIREPOWER)) {
416 *def_fp = MIN(*def_fp, game.info.low_firepower_combat_bonus);
417 }
418
419 att_tile = unit_tile(attacker);
420
421 /* In land bombardment both units have their firepower reduced.
422 * Land bombardment is always towards tile not native for attacker.
423 * It's initiated either from a tile not native to defender (Ocean for Land unit)
424 * or from a tile where attacker is despite non-native terrain (city, transport) */
425 if (utype_has_class_flag(def_type, UCF_NONNAT_BOMBARD_TGT)
426 && !is_native_tile(att_type, unit_tile(defender))
427 && (!can_exist_at_tile(nmap, def_type, att_tile)
428 || !is_native_tile(att_type, att_tile))) {
429 *att_fp = MIN(*att_fp, game.info.low_firepower_nonnat_bombard);
430 *def_fp = MIN(*def_fp, game.info.low_firepower_nonnat_bombard);
431 }
432}
433
434/*******************************************************************/
438 double unit_win_chance(const struct civ_map *nmap,
439 const struct unit *attacker,
440 const struct unit *defender)
441{
442 int def_power = get_total_defense_power(attacker, defender);
443 int att_power = get_total_attack_power(attacker, defender);
444 double chance;
445 int def_fp, att_fp;
446
447 get_modified_firepower(nmap, attacker, defender, &att_fp, &def_fp);
448
449 chance = win_chance(att_power, attacker->hp, att_fp,
450 def_power, defender->hp, def_fp);
451
452 return chance;
453}
454
455/*******************************************************************/
460 struct city *sdi_try_defend(const struct civ_map *nmap,
461 const struct player *owner,
462 const struct tile *ptile)
463{
464 square_iterate(nmap, ptile, 2, ptile1) {
465 struct city *pcity = tile_city(ptile1);
466
467 if (pcity
468 && fc_rand(100)
469 < get_target_bonus_effects(NULL,
470 &(const struct req_context) {
471 .player = city_owner(pcity),
472 .city = pcity,
473 .tile = ptile,
474 },
475 owner, EFT_NUKE_PROOF)) {
476 return pcity;
477 }
478 } square_iterate_end;
479
480 return NULL;
481}
482
483/*******************************************************************/
486 bool is_tired_attack(int moves_left)
487{
488 return game.info.tired_attack && moves_left < SINGLE_MOVE;
489}
490
491/*******************************************************************/
494 int get_attack_power(const struct unit *punit)
495{
496 return base_get_attack_power(unit_type_get(punit), punit->veteran,
497 punit->moves_left);
498}
499
500/*******************************************************************/
504 int base_get_attack_power(const struct unit_type *punittype,
505 int veteran, int moves_left)
506{
507 int power;
508 const struct veteran_level *vlevel;
509
510 fc_assert_ret_val(punittype != NULL, 0);
511
512 vlevel = utype_veteran_level(punittype, veteran);
513 fc_assert_ret_val(vlevel != NULL, 0);
514
515 power = punittype->attack_strength * POWER_FACTOR
516 * vlevel->power_fact / 100;
517
518 if (is_tired_attack(moves_left)) {
519 power = (power * moves_left) / SINGLE_MOVE;
520 }
521
522 return power;
523}
524
525/*******************************************************************/
528 int base_get_defense_power(const struct unit *punit)
529{
530 const struct veteran_level *vlevel;
531
532 fc_assert_ret_val(punit != NULL, 0);
533
534 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
535 fc_assert_ret_val(vlevel != NULL, 0);
536
537 return unit_type_get(punit)->defense_strength * POWER_FACTOR
538 * vlevel->power_fact / 100;
539}
540
541/*******************************************************************/
546 static int get_defense_power(const struct unit *punit)
547{
548 int db, power = base_get_defense_power(punit);
549 struct tile *ptile = unit_tile(punit);
550 struct unit_class *pclass = unit_class_get(punit);
551
552 if (uclass_has_flag(pclass, UCF_TERRAIN_DEFENSE)) {
553 db = 100 + tile_terrain(ptile)->defense_bonus;
554 power = (power * db) / 100;
555 }
556
557 if (!is_native_tile_to_class(pclass, ptile)) {
558 power = power * pclass->non_native_def_pct / 100;
559 }
560
561 return power;
562}
563
564/*******************************************************************/
567 int get_total_attack_power(const struct unit *attacker,
568 const struct unit *defender)
569{
570 int mod;
571 int attackpower = get_attack_power(attacker);
572
573 mod = 100 + get_unittype_bonus(unit_owner(attacker), unit_tile(defender),
574 unit_type_get(attacker), NULL,
575 EFT_ATTACK_BONUS);
576
577 return attackpower * mod / 100;
578}
579
580/*******************************************************************/
590 static int defense_multiplication(const struct unit_type *att_type,
591 const struct unit *def,
592 const struct player *def_player,
593 const struct tile *ptile,
594 int defensepower)
595{
596 const struct city *pcity = tile_city(ptile);
597 const struct unit_type *def_type = unit_type_get(def);
598
599 fc_assert_ret_val(NULL != def_type, 0);
600
601 if (NULL != att_type) {
602 int scramble_bonus = 0;
603 int defense_divider_pct;
604
605 if (pcity) {
606 scramble_bonus = def_type->cache.scramble_coeff[utype_index(att_type)];
607 }
608
609 if (scramble_bonus) {
610 /* Use type-specific city bonus,
611 * already multiplied on common type-specific bonus */
612 defensepower = defensepower * scramble_bonus / 10000;
613 defensepower = MAX(0, defensepower);
614 } else {
615 /* Use city defense effect */
616 int defense_multiplier_pct = 100
617 + def_type->cache.defense_mp_bonuses_pct[utype_index(att_type)];
618 int mod = 100 + get_unittype_bonus(def_player, ptile,
619 att_type, NULL, EFT_DEFEND_BONUS);
620
621 /* This applies even if pcity is NULL. */
622 defensepower = defensepower * defense_multiplier_pct / 100;
623 defensepower = MAX(0, defensepower * mod / 100);
624 }
625
626 defense_divider_pct = 100 + combat_bonus_against(att_type->bonuses,
627 def_type, CBONUS_DEFENSE_DIVIDER_PCT)
628 + 100 * combat_bonus_against(att_type->bonuses, def_type,
629 CBONUS_DEFENSE_DIVIDER);
630
631 defensepower = defensepower * 100 / defense_divider_pct;
632 }
633
634 defensepower +=
635 defensepower * tile_extras_defense_bonus(ptile, def_type) / 100;
636
637 defensepower = defensepower
638 * (100
639 + get_target_bonus_effects(NULL,
640 &(const struct req_context) {
641 .player = unit_owner(def),
642 .city = pcity,
643 .tile = ptile,
644 .unit = def,
645 .unittype = unit_type_get(def),
646 },
647 NULL,
648 EFT_FORTIFY_DEFENSE_BONUS)) / 100;
649
650 return defensepower;
651}
652
653/*******************************************************************/
657 int get_virtual_defense_power(const struct civ_map *nmap,
658 const struct unit_type *att_type,
659 const struct unit_type *def_type,
660 struct player *def_player,
661 struct tile *ptile,
662 bool fortified, int veteran)
663{
664 int defensepower = def_type->defense_strength;
665 int db;
666 const struct veteran_level *vlevel;
667 struct unit_class *defclass;
668 struct unit *vdef;
669 int def;
670
671 fc_assert_ret_val(def_type != NULL, 0);
672
673 if (!can_exist_at_tile(nmap, def_type, ptile)) {
674 /* Ground units on ship doesn't defend. */
675 return 0;
676 }
677
678 vlevel = utype_veteran_level(def_type, veteran);
679 fc_assert_ret_val(vlevel != NULL, 0);
680
681 defclass = utype_class(def_type);
682
683 vdef = unit_virtual_create(def_player, NULL, def_type, veteran);
684 unit_tile_set(vdef, ptile);
685 if (fortified) {
686 vdef->activity = ACTIVITY_FORTIFIED;
687 }
688
689 db = POWER_FACTOR;
690 if (uclass_has_flag(defclass, UCF_TERRAIN_DEFENSE)) {
691 db += tile_terrain(ptile)->defense_bonus / (100 / POWER_FACTOR);
692 }
693 defensepower *= db;
694 defensepower *= vlevel->power_fact / 100;
695 if (!is_native_tile_to_class(defclass, ptile)) {
696 defensepower = defensepower * defclass->non_native_def_pct / 100;
697 }
698
699 def = defense_multiplication(att_type, vdef, def_player,
700 ptile, defensepower);
701
702 unit_virtual_destroy(vdef);
703
704 return def;
705}
706
707/*******************************************************************/
712 int get_total_defense_power(const struct unit *attacker,
713 const struct unit *defender)
714{
715 return defense_multiplication(unit_type_get(attacker),
716 defender,
717 unit_owner(defender), unit_tile(defender),
718 get_defense_power(defender));
719}
720
721/*******************************************************************/
726 int get_fortified_defense_power(const struct unit *attacker,
727 struct unit *defender)
728{
729 const struct unit_type *att_type = NULL;
730 enum unit_activity real_act;
731 int def;
732 const struct unit_type *utype;
733
734 if (attacker != NULL) {
735 att_type = unit_type_get(attacker);
736 }
737
738 real_act = defender->activity;
739
740 utype = unit_type_get(defender);
741 if (utype_can_do_action_result(utype, ACTRES_FORTIFY)) {
742 defender->activity = ACTIVITY_FORTIFIED;
743 }
744
745 def = defense_multiplication(att_type, defender,
746 unit_owner(defender), unit_tile(defender),
747 get_defense_power(defender));
748
749 defender->activity = real_act;
750
751 return def;
752}
753
754/*******************************************************************/
759 static int get_defense_rating(const struct civ_map *nmap,
760 const struct unit *attacker,
761 const struct unit *defender)
762{
763 int afp, dfp;
764 int rating = get_total_defense_power(attacker, defender);
765
766 get_modified_firepower(nmap, attacker, defender, &afp, &dfp);
767
768 /* How many rounds the defender will last */
769 rating *= (defender->hp + afp-1)/afp;
770
771 rating *= dfp;
772
773 return rating;
774}
775
776/*******************************************************************/
781 struct unit *get_defender(const struct civ_map *nmap,
782 const struct unit *attacker,
783 const struct tile *ptile)
784{
785 struct unit *bestdef = NULL;
786 int bestvalue = -99, best_cost = 0, rating_of_best = 0;
787
788 /* Simply call unit_win_chance() with all the possible defenders in turn, and
789 * take the best one. It currently uses build cost as a tiebreaker in
790 * case 2 units are identical, but this is crude as build cost does not
791 * necessarily have anything to do with the value of a unit. This function
792 * could be improved to take the value of the unit into account. It would
793 * also be nice if the function was a bit more fuzzy about prioritizing,
794 * making it able to fx choose a 1a/9d unit over a 10a/10d unit. It should
795 * also be able to spare units without full hp's to some extent, as these
796 * could be more valuable later. */
797 unit_list_iterate(ptile->units, defender) {
798 /* We used to skip over allied units, but the logic for that is
799 * complicated and is now handled elsewhere. */
800 if (unit_can_defend_here(nmap, defender)
801 && (unit_attack_unit_at_tile_result(attacker, NULL, defender, ptile)
802 == ATT_OK)) {
803 bool change = FALSE;
804 int build_cost = unit_build_shield_cost_base(defender);
805 int defense_rating = get_defense_rating(nmap, attacker, defender);
806 /* This will make units roughly evenly good defenders look alike. */
807 int unit_def
808 = (int) (100000 * (1 - unit_win_chance(nmap, attacker, defender)));
809
810 fc_assert_action(0 <= unit_def, continue);
811
812 if (unit_has_type_flag(defender, UTYF_GAMELOSS)
813 && !is_stack_vulnerable(unit_tile(defender))) {
814 unit_def = -1; /* Then always use leader as last defender. */
815 /* FIXME: Multiple gameloss units with varying defense value
816 * not handled. */
817 }
818
819 if (unit_def > bestvalue) {
820 change = TRUE;
821 } else if (unit_def == bestvalue) {
822 if (build_cost < best_cost) {
823 change = TRUE;
824 } else if (build_cost == best_cost) {
825 if (rating_of_best < defense_rating) {
826 change = TRUE;
827 }
828 }
829 }
830
831 if (change) {
832 bestvalue = unit_def;
833 bestdef = defender;
834 best_cost = build_cost;
835 rating_of_best = defense_rating;
836 }
837 }
838 } unit_list_iterate_end;
839
840 return bestdef;
841}
842
843/*******************************************************************/
849 struct unit *get_attacker(const struct civ_map *nmap,
850 const struct unit *defender,
851 const struct tile *ptile)
852{
853 struct unit *bestatt = 0;
854 int bestvalue = -1, unit_a, best_cost = 0;
855
856 unit_list_iterate(ptile->units, attacker) {
857 int build_cost = unit_build_shield_cost_base(attacker);
858
859 if (pplayers_allied(unit_owner(defender), unit_owner(attacker))) {
860 return NULL;
861 }
862 unit_a = (int) (100000 * (unit_win_chance(nmap, attacker, defender)));
863 if (unit_a > bestvalue
864 || (unit_a == bestvalue && build_cost < best_cost)) {
865 bestvalue = unit_a;
866 bestatt = attacker;
867 best_cost = build_cost;
868 }
869 } unit_list_iterate_end;
870
871 return bestatt;
872}
873
874/**********************************************************************/
882 struct unit *get_diplomatic_defender(const struct unit *act_unit,
883 const struct unit *pvictim,
884 const struct tile *tgt_tile)
885{
886 fc_assert_ret_val(act_unit, NULL);
887 fc_assert_ret_val(tgt_tile, NULL);
888
889 unit_list_iterate(tgt_tile->units, punit) {
890 if (unit_owner(punit) == unit_owner(act_unit)) {
891 /* I can't confirm if we won't deny that we weren't involved.
892 * (Won't defend against its owner.) */
893 continue;
894 }
895
896 if (punit == pvictim
897 && !unit_has_type_flag(punit, UTYF_SUPERSPY)) {
898 /* The victim unit is defenseless unless it's a SuperSpy.
899 * Rationalization: A regular diplomat don't mind being bribed. A
900 * SuperSpy is high enough up the chain that accepting a bribe is
901 * against their own interests. */
902 continue;
903 }
904
905 if (!(unit_has_type_flag(punit, UTYF_DIPLOMAT)
906 || unit_has_type_flag(punit, UTYF_SUPERSPY))) {
907 /* A UTYF_SUPERSPY unit may not actually be a spy, but a superboss
908 * which we cannot allow puny diplomats from getting the better
909 * of. UTYF_SUPERSPY vs UTYF_SUPERSPY in a diplomatic contest always
910 * kills the attacker. */
911
912 /* The unit can't defend in a diplomatic battle. */
913 continue;
914 }
915
916 /* The first potential defender found is chosen. No priority is given
917 * to the best defender. */
918 return punit;
919 } unit_list_iterate_end;
920
921 /* No diplomatic defender found. */
922 return NULL;
923}
924
925/*******************************************************************/
928 bool is_stack_vulnerable(const struct tile *ptile)
929{
930 return (game.info.killstack
931 && !tile_has_extra_flag(ptile, EF_NO_STACK_DEATH)
932 && NULL == tile_city(ptile));
933}
934
935/*******************************************************************/
941 int combat_bonus_against(const struct combat_bonus_list *list,
942 const struct unit_type *enemy,
943 enum combat_bonus_type type)
944{
945 int value = 0;
946
947 combat_bonus_list_iterate(list, pbonus) {
948 if (pbonus->type == type && utype_has_flag(enemy, pbonus->flag)) {
949 value += pbonus->value;
950 }
951 } combat_bonus_list_iterate_end;
952
953 return value;
954}
955
956/*******************************************************************/
959 int unit_bombard_rate(struct unit *punit)
960{
961 const struct unit_type *utype = unit_type_get(punit);
962 int base_bombard_rate = utype->bombard_rate;
963
964 if (game.info.damage_reduces_bombard_rate && base_bombard_rate > 0) {
965 int rate = (base_bombard_rate * punit->hp) / utype->hp;
966
967 return MAX(rate, 1);
968 }
969
970 return base_bombard_rate;
971}
n
#define n
Definition astring.c:77
base.h
bitvector.h
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
city_owner
#define city_owner(_pcity_)
Definition city.h:543
list
static struct fc_sockaddr_list * list
Definition clinet.c:102
is_unit_reachable_at
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:85
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_any_at_tile_result
static enum unit_attack_result unit_attack_any_at_tile_result(const struct unit *punit, const struct action *paction, const struct tile *ptile)
Definition combat.c:229
get_attack_power
int get_attack_power(const struct unit *punit)
Definition combat.c:494
unit_bombard_rate
int unit_bombard_rate(struct unit *punit)
Definition combat.c:959
combat_bonus_against
int combat_bonus_against(const struct combat_bonus_list *list, const struct unit_type *enemy, enum combat_bonus_type type)
Definition combat.c:941
get_fortified_defense_power
int get_fortified_defense_power(const struct unit *attacker, struct unit *defender)
Definition combat.c:726
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_defense_rating
static int get_defense_rating(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender)
Definition combat.c:759
get_attacker
struct unit * get_attacker(const struct civ_map *nmap, const struct unit *defender, const struct tile *ptile)
Definition combat.c:849
base_get_attack_power
int base_get_attack_power(const struct unit_type *punittype, int veteran, int moves_left)
Definition combat.c:504
sdi_try_defend
struct city * sdi_try_defend(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile)
Definition combat.c:460
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_attack_all_at_tile_result
static enum unit_attack_result unit_attack_all_at_tile_result(const struct unit *punit, const struct action *paction, const struct tile *ptile)
Definition combat.c:188
get_defense_power
static int get_defense_power(const struct unit *punit)
Definition combat.c:546
get_diplomatic_defender
struct unit * get_diplomatic_defender(const struct unit *act_unit, const struct unit *pvictim, const struct tile *tgt_tile)
Definition combat.c:882
is_tired_attack
bool is_tired_attack(int moves_left)
Definition combat.c:486
defense_multiplication
static int defense_multiplication(const struct unit_type *att_type, const struct unit *def, const struct player *def_player, const struct tile *ptile, int defensepower)
Definition combat.c:590
win_chance
double win_chance(int as, int ahp, int afp, int ds, int dhp, int dfp)
Definition combat.c:292
get_total_attack_power
int get_total_attack_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:567
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
get_modified_firepower
void get_modified_firepower(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, int *att_fp, int *def_fp)
Definition combat.c:369
can_player_attack_tile
static bool can_player_attack_tile(const struct player *pplayer, const struct tile *ptile)
Definition combat.c:44
is_unit_reachable_by_unit
static bool is_unit_reachable_by_unit(const struct unit *defender, const struct unit *attacker)
Definition combat.c:73
combat.h
POWER_FACTOR
#define POWER_FACTOR
Definition combat.h:32
unit_attack_result
unit_attack_result
Definition combat.h:34
ATT_NONNATIVE_DST
@ ATT_NONNATIVE_DST
Definition combat.h:39
ATT_OK
@ ATT_OK
Definition combat.h:35
ATT_NON_ATTACK
@ ATT_NON_ATTACK
Definition combat.h:36
ATT_UNREACHABLE
@ ATT_UNREACHABLE
Definition combat.h:37
ATT_NONNATIVE_SRC
@ ATT_NONNATIVE_SRC
Definition combat.h:38
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
get_target_bonus_effects
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct player *other_player, enum effect_type effect_type)
Definition effects.c:691
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
game
struct civ_game game
Definition game.c:57
game.h
owner
struct city * owner
Definition citydlg.c:219
type
GType type
Definition repodlgs.c:1312
log.h
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
map.h
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
square_iterate_end
#define square_iterate_end
Definition map.h:388
can_exist_at_tile
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:275
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:316
unit_can_defend_here
bool unit_can_defend_here(const struct civ_map *nmap, const struct unit *punit)
Definition movement.c:175
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
packets.h
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
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
MIN
#define MIN(x, y)
Definition shared.h:55
MAX
#define MAX(x, y)
Definition shared.h:54
action
Definition actions.h:379
action::id
action_id id
Definition actions.h:380
city
Definition city.h:309
city::tile
struct tile * tile
Definition city.h:311
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_map
Definition map_types.h:71
packet_game_info::killstack
bool killstack
Definition packets_gen.h:188
packet_game_info::damage_reduces_bombard_rate
bool damage_reduces_bombard_rate
Definition packets_gen.h:192
packet_game_info::tired_attack
bool tired_attack
Definition packets_gen.h:235
packet_game_info::low_firepower_pearl_harbour
int low_firepower_pearl_harbour
Definition packets_gen.h:194
packet_game_info::low_firepower_nonnat_bombard
int low_firepower_nonnat_bombard
Definition packets_gen.h:196
packet_game_info::low_firepower_combat_bonus
int low_firepower_combat_bonus
Definition packets_gen.h:195
packet_game_info::unreachable_protects
bool unreachable_protects
Definition packets_gen.h:219
packet_game_info::low_firepower_badwallattacker
int low_firepower_badwallattacker
Definition packets_gen.h:193
player
Definition player.h:249
req_context
Definition requirements.h:99
tile
Definition tile.h:49
tile::units
struct unit_list * units
Definition tile.h:57
unit_class
Definition unittype.h:136
unit_class::non_native_def_pct
int non_native_def_pct
Definition unittype.h:143
unit_type
Definition unittype.h:481
unit_type::defense_strength
int defense_strength
Definition unittype.h:496
unit_type::firepower
int firepower
Definition unittype.h:506
unit_type::veteran
struct veteran_system * veteran
Definition unittype.h:525
unit_type::targets
bv_unit_classes targets
Definition unittype.h:542
unit_type::bombard_rate
int bombard_rate
Definition unittype.h:528
unit_type::scramble_coeff
int scramble_coeff[U_LAST]
Definition unittype.h:564
unit_type::cache
struct unit_type::@88 cache
unit_type::hp
int hp
Definition unittype.h:505
unit_type::attack_strength
int attack_strength
Definition unittype.h:495
unit_type::defense_mp_bonuses_pct
int defense_mp_bonuses_pct[U_LAST]
Definition unittype.h:563
unit_type::bonuses
struct combat_bonus_list * bonuses
Definition unittype.h:507
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::hp
int hp
Definition unit.h:151
unit::veteran
int veteran
Definition unit.h:152
veteran_level
Definition unittype.h:467
veteran_level::power_fact
int power_fact
Definition unittype.h:469
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
tile_has_extra_flag
bool tile_has_extra_flag(const struct tile *ptile, enum extra_flag_id flag)
Definition tile.c:871
tile_extras_defense_bonus
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:227
tile_has_native_base
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:318
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:109
unit_virtual_create
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1613
unit_virtual_destroy
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1709
unit_tile_set
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1278
unit_transported
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2405
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
utype_has_class_flag
bool utype_has_class_flag(const struct unit_type *ptype, enum unit_class_flag_id flag)
Definition unittype.c:1709
unit_build_shield_cost_base
int unit_build_shield_cost_base(const struct unit *punit)
Definition unittype.c:1536
utype_can_do_act_when_ustate
bool utype_can_do_act_when_ustate(const struct unit_type *punit_type, const action_id act_id, const enum ustate_prop prop, const bool is_there)
Definition unittype.c:1007
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
utype_veteran_level
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2631
unit_has_type_flag
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
utype_index
Unit_type_id utype_index(const struct unit_type *punittype)
Definition unittype.c:91
utype_can_do_action
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:443
unittype.h
uclass_has_flag
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:753
utype_class
#define utype_class(_t_)
Definition unittype.h:736
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
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
uclass_index
#define uclass_index(_c_)
Definition unittype.h:729