I18n markup: TRANS comments and missing no-c-format.
[freeciv.git] / common / combat.c
blob60a30293d769236bce7f026b1c3efb583fbf81b4
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <math.h>
20 /* utility */
21 #include "bitvector.h"
22 #include "rand.h"
23 #include "log.h"
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"
35 #include "combat.h"
37 /***********************************************************************
38 Checks if player is restricted diplomatically from attacking the tile.
39 Returns FLASE if
40 1) the tile is empty or
41 2) the tile contains a non-enemy city or
42 3) the tile contains a non-enemy unit
43 ***********************************************************************/
44 bool can_player_attack_tile(const struct player *pplayer,
45 const struct tile *ptile)
47 struct city *pcity = tile_city(ptile);
49 /* 1. Is there anyone there at all? */
50 if (!pcity && unit_list_size((ptile->units)) == 0) {
51 return FALSE;
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;
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;
65 } unit_list_iterate_end;
67 return TRUE;
70 /***********************************************************************
71 Can unit attack other
72 ***********************************************************************/
73 static bool is_unit_reachable_by_unit(const struct unit *defender,
74 const struct unit *attacker)
76 struct unit_class *dclass = unit_class(defender);
77 struct unit_type *atype = unit_type(attacker);
79 return BV_ISSET(atype->targets, uclass_index(dclass));
82 /***********************************************************************
83 Can unit attack other at given location
84 ***********************************************************************/
85 bool is_unit_reachable_at(const struct unit *defender,
86 const struct unit *attacker,
87 const struct tile *location)
89 if (NULL != tile_city(location)) {
90 return TRUE;
93 if (is_unit_reachable_by_unit(defender, attacker)) {
94 return TRUE;
97 if (tile_has_native_base(location, unit_type(defender))) {
98 return TRUE;
101 return FALSE;
104 /***********************************************************************
105 Checks if a unit can physically attack pdefender at the tile
106 (assuming it is adjacent and at war).
108 Unit can NOT attack if:
109 1) it does not have any attack power.
110 2) it is not a fighter and defender is a flying unit (except city/airbase).
111 3) it is a ground unit without marine ability and it attacks from ocean.
112 4) it is a ground unit and it attacks a target on an ocean square.
113 5) it is a sailing unit without shore bombardment capability and it
114 attempts to attack land.
116 Does NOT check:
117 1) Moves left
118 2) Adjacency
119 3) Diplomatic status
120 ***********************************************************************/
121 enum unit_attack_result unit_attack_unit_at_tile_result(const struct unit *punit,
122 const struct unit *pdefender,
123 const struct tile *dest_tile)
125 /* 1. Can we attack _anything_ ? */
126 if (!is_military_unit(punit) || !is_attack_unit(punit)) {
127 return ATT_NON_ATTACK;
130 /* 2. Only fighters can attack planes, except in city or airbase attacks */
131 if (!is_unit_reachable_at(pdefender, punit, dest_tile)) {
132 return ATT_UNREACHABLE;
135 /* 3. Can't attack with ground unit from ocean, except for marines */
136 if (!is_native_tile(unit_type(punit), unit_tile(punit))
137 && !can_attack_from_non_native(unit_type(punit))) {
138 return ATT_NONNATIVE_SRC;
141 /* 4. Most units can not attack non-native terrain.
142 * Most ships can attack land tiles (shore bombardment) */
143 if (!is_native_tile(unit_type(punit), dest_tile)
144 && !can_attack_non_native(unit_type(punit))) {
145 return ATT_NONNATIVE_DST;
148 return ATT_OK;
151 /***********************************************************************
152 When unreachable_protects setting is TRUE:
153 To attack a stack, unit must be able to attack every unit there (not
154 including transported units).
155 ************************************************************************/
156 static enum unit_attack_result unit_attack_all_at_tile_result(const struct unit *punit,
157 const struct tile *ptile)
159 unit_list_iterate(ptile->units, aunit) {
160 /* HACK: we don't count transported units here. This prevents some
161 * bugs like a submarine carrying a cruise missile being invulnerable
162 * to other sea units. However from a gameplay perspective it's a hack,
163 * since players can load and unload their units manually to protect
164 * their transporters. */
165 if (!unit_transported(aunit)) {
166 enum unit_attack_result result;
168 result = unit_attack_unit_at_tile_result(punit, aunit, ptile);
169 if (result != ATT_OK) {
170 return result;
173 } unit_list_iterate_end;
175 return ATT_OK;
178 /***********************************************************************
179 When unreachable_protects setting is FALSE:
180 To attack a stack, unit must be able to attack some unit there (not
181 including transported units).
182 ************************************************************************/
183 static enum unit_attack_result unit_attack_any_at_tile_result(const struct unit *punit,
184 const struct tile *ptile)
186 enum unit_attack_result result = ATT_OK;
188 unit_list_iterate(ptile->units, aunit) {
189 /* HACK: we don't count transported units here. This prevents some
190 * bugs like a cargoplane carrying a land unit being vulnerable. */
191 if (!unit_transported(aunit)) {
192 result = unit_attack_unit_at_tile_result(punit, aunit, ptile);
193 if (result == ATT_OK) {
194 return result;
197 } unit_list_iterate_end;
199 /* That's result from check against last unit on tile, not first.
200 * Shouldn't matter. */
201 return result;
204 /***********************************************************************
205 Check if unit can attack unit stack at tile.
206 ***********************************************************************/
207 enum unit_attack_result unit_attack_units_at_tile_result(const struct unit *punit,
208 const struct tile *ptile)
210 if (game.info.unreachable_protects) {
211 return unit_attack_all_at_tile_result(punit, ptile);
212 } else {
213 return unit_attack_any_at_tile_result(punit, ptile);
217 /***********************************************************************
218 Is unit (1) diplomatically allowed to attack and (2) physically able
219 to do so?
220 ***********************************************************************/
221 bool can_unit_attack_tile(const struct unit *punit,
222 const struct tile *dest_tile)
224 return (can_player_attack_tile(unit_owner(punit), dest_tile)
225 && unit_attack_units_at_tile_result(punit, dest_tile) == ATT_OK);
228 /***********************************************************************
229 Returns the chance of the attacker winning, a number between 0 and 1.
230 If you want the chance that the defender wins just use 1-chance(...)
232 NOTE: this number can be _very_ small, fx in a battle between an
233 ironclad and a battleship the ironclad has less than 1/100000 chance of
234 winning.
236 The algoritm calculates the probability of each possible number of HP's
237 the attacker has left. Maybe that info should be preserved for use in
238 the AI.
239 ***********************************************************************/
240 double win_chance(int as, int ahp, int afp, int ds, int dhp, int dfp)
242 /* number of rounds a unit can fight without dying */
243 int att_N_lose = (ahp + dfp - 1) / dfp;
244 int def_N_lose = (dhp + afp - 1) / afp;
245 /* Probability of losing one round */
246 double att_P_lose1 = (as + ds == 0) ? 0.5 : (double) ds / (as + ds);
247 double def_P_lose1 = 1 - att_P_lose1;
250 This calculates
252 binomial_coeff(def_N_lose-1 + lr, lr)
253 * def_P_lose1^(def_N_lose-1)
254 * att_P_lose1^(lr)
255 * def_P_lose1
257 for each possible number of rounds lost (rl) by the winning unit.
258 rl is of course less than the number of rounds the winning unit
259 should lose to lose all it's hit points.
260 The probabilities are then summed.
262 To see this is correct consider the set of series for all valid fights.
263 These series are the type (win, lose, lose...). The possible lenghts are
264 def_N_lose to def_N_lose+att_N_lose-1. A series is not valid unless it
265 contains def_N_lose wins, and one of the wins must be the last one, or
266 the series would be equivalent the a shorter series (the attacker would
267 have won one or more fights previously).
268 So since the last fight is a win we disregard it while calculating. Now
269 a series contains def_N_lose-1 wins. So for each possible lenght of a
270 series we find the probability of every valid series and then sum.
271 For a specific lenght (a "lr") every series have the probability
272 def_P_lose1^(def_N_lose-1) * att_P_lose1^(lr)
273 and then getting from that to the real series requires a win, ie factor
274 def_N_lose. The number of series with lenght (def_N_lose-1 + lr) and
275 "lr" lost fights is
276 binomial_coeff(def_N_lose-1 + lr, lr)
277 And by multiplying we get the formula on the top of this code block.
278 Adding the cumulative probability for each valid lenght then gives the
279 total probability.
281 We clearly have all valid series this way. To see that we have counted
282 none twice note that would require a series with a smaller series inbedded.
283 But since the smaller series already included def_N_lose wins, and the
284 larger series ends with a win, it would have too many wins and therefore
285 cannot exist.
287 In practice each binomial coefficient for a series lenght can be calculated
288 from the previous. In the coefficient (n, k) n is increased and k is
289 unchanged.
290 The "* def_P_lose1" is multiplied on the sum afterwards.
292 (lots of talk for so little code)
295 double binom_save = pow(def_P_lose1, (double)(def_N_lose - 1));
296 double accum_prob = binom_save; /* lr = 0 */
298 int lr; /* the number of Lost Rounds by the attacker */
299 for (lr = 1; lr < att_N_lose; lr++) {
300 /* update the coefficient */
301 int n = lr + def_N_lose - 1;
302 binom_save *= n;
303 binom_save /= lr;
304 binom_save *= att_P_lose1;
305 /* use it for this lr */
306 accum_prob += binom_save;
308 /* Every element of the sum needs a factor for the very last fight round */
309 accum_prob *= def_P_lose1;
311 return accum_prob;
314 /**************************************************************************
315 A unit's effective firepower depend on the situation.
316 **************************************************************************/
317 void get_modified_firepower(const struct unit *attacker,
318 const struct unit *defender,
319 int *att_fp, int *def_fp)
321 struct city *pcity = tile_city(unit_tile(defender));
323 *att_fp = unit_type(attacker)->firepower;
324 *def_fp = unit_type(defender)->firepower;
326 /* Check CityBuster flag */
327 if (unit_has_type_flag(attacker, UTYF_CITYBUSTER) && pcity) {
328 *att_fp *= 2;
332 * UTYF_BADWALLATTACKER sets the firepower of the attacking unit to 1 if
333 * an EFT_DEFEND_BONUS applies (such as a land unit attacking a city with
334 * city walls).
336 if (unit_has_type_flag(attacker, UTYF_BADWALLATTACKER)
337 && get_unittype_bonus(unit_owner(defender), unit_tile(defender),
338 unit_type(attacker), EFT_DEFEND_BONUS) > 0) {
339 *att_fp = 1;
342 /* pearl harbour - defender's firepower is reduced to one,
343 * attacker's is multiplied by two */
344 if (unit_has_type_flag(defender, UTYF_BADCITYDEFENDER)
345 && tile_city(unit_tile(defender))) {
346 *att_fp *= 2;
347 *def_fp = 1;
351 * When attacked by fighters, helicopters have their firepower
352 * reduced to 1.
354 if (combat_bonus_against(unit_type(attacker)->bonuses, unit_type(defender),
355 CBONUS_FIREPOWER1)) {
356 *def_fp = 1;
359 /* In land bombardment both units have their firepower reduced to 1 */
360 if (is_sailing_unit(attacker)
361 && !is_ocean_tile(unit_tile(defender))
362 && is_ground_unit(defender)) {
363 *att_fp = 1;
364 *def_fp = 1;
368 /**************************************************************************
369 Returns a double in the range [0;1] indicating the attackers chance of
370 winning. The calculation takes all factors into account.
371 **************************************************************************/
372 double unit_win_chance(const struct unit *attacker,
373 const struct unit *defender)
375 int def_power = get_total_defense_power(attacker, defender);
376 int att_power = get_total_attack_power(attacker, defender);
378 double chance;
380 int def_fp, att_fp;
381 get_modified_firepower(attacker, defender, &att_fp, &def_fp);
383 chance = win_chance(att_power, attacker->hp, att_fp,
384 def_power, defender->hp, def_fp);
386 return chance;
389 /**************************************************************************
390 Try defending against nuclear attack, if succed return a city which
391 had enough luck and EFT_NUKE_PROOF.
392 If the attack was succesful return NULL.
393 **************************************************************************/
394 struct city *sdi_try_defend(const struct player *owner,
395 const struct tile *ptile)
397 square_iterate(ptile, 2, ptile1) {
398 struct city *pcity = tile_city(ptile1);
400 if (pcity
401 && !pplayers_allied(city_owner(pcity), owner)
402 && fc_rand(100) < get_city_bonus(pcity, EFT_NUKE_PROOF)) {
403 return pcity;
405 } square_iterate_end;
407 return NULL;
410 /**************************************************************************
411 Convenience wrapper for base_get_attack_power.
412 **************************************************************************/
413 int get_attack_power(const struct unit *punit)
415 return base_get_attack_power(unit_type(punit), punit->veteran,
416 punit->moves_left);
419 /**************************************************************************
420 Returns the attack power, modified by moves left, and veteran
421 status.
422 **************************************************************************/
423 int base_get_attack_power(const struct unit_type *punittype,
424 int veteran, int moves_left)
426 int power;
427 const struct veteran_level *vlevel;
429 fc_assert_ret_val(punittype != NULL, 0);
431 vlevel = utype_veteran_level(punittype, veteran);
432 fc_assert_ret_val(vlevel != NULL, 0);
434 power = punittype->attack_strength * POWER_FACTOR
435 * vlevel->power_fact / 100;
437 if (game.info.tired_attack && moves_left < SINGLE_MOVE) {
438 power = (power * moves_left) / SINGLE_MOVE;
441 return power;
444 /**************************************************************************
445 Returns the defense power, modified by veteran status.
446 **************************************************************************/
447 int base_get_defense_power(const struct unit *punit)
449 const struct veteran_level *vlevel;
451 fc_assert_ret_val(punit != NULL, 0);
453 vlevel = utype_veteran_level(unit_type(punit), punit->veteran);
454 fc_assert_ret_val(vlevel != NULL, 0);
456 return unit_type(punit)->defense_strength * POWER_FACTOR
457 * vlevel->power_fact / 100;
460 /**************************************************************************
461 Returns the defense power, modified by terrain and veteran status.
462 Note that rivers as special road types are not handled here as
463 terrain property.
464 **************************************************************************/
465 static int get_defense_power(const struct unit *punit)
467 int db, power = base_get_defense_power(punit);
468 struct tile *ptile = unit_tile(punit);
469 struct unit_class *pclass = unit_class(punit);
471 if (uclass_has_flag(unit_class(punit), UCF_TERRAIN_DEFENSE)) {
472 db = 10 + tile_terrain(ptile)->defense_bonus / 10;
473 power = (power * db) / 10;
476 if (!is_native_tile_to_class(pclass, ptile)) {
477 power = power * pclass->non_native_def_pct / 100;
480 return power;
483 /***************************************************************************
484 return the modified attack power of a unit. Currently they aren't any
485 modifications...
486 ***************************************************************************/
487 int get_total_attack_power(const struct unit *attacker,
488 const struct unit *defender)
490 int attackpower = get_attack_power(attacker);
492 return attackpower;
495 /**************************************************************************
496 Return an increased defensepower. Effects which increase the
497 defensepower are:
498 - unit type effects (horse vs pikemen for example)
499 - defender in a fortress
500 - fortified defender
502 May be called with a non-existing att_type to avoid any unit type
503 effects.
504 **************************************************************************/
505 static int defense_multiplication(const struct unit_type *att_type,
506 const struct unit_type *def_type,
507 const struct player *def_player,
508 const struct tile *ptile,
509 int defensepower, bool fortified)
511 struct city *pcity = tile_city(ptile);
512 int mod;
514 fc_assert_ret_val(NULL != def_type, 0);
516 if (NULL != att_type) {
517 int defense_divider;
518 int defense_multiplier = 1 + combat_bonus_against(def_type->bonuses, att_type,
519 CBONUS_DEFENSE_MULTIPLIER);
521 defensepower *= defense_multiplier;
523 if (!utype_has_flag(att_type, UTYF_IGWALL)) {
524 /* This applies even if pcity is NULL. */
525 mod = 100 + get_unittype_bonus(def_player, ptile,
526 att_type, EFT_DEFEND_BONUS);
527 defensepower = MAX(0, defensepower * mod / 100);
530 defense_divider = 1 + combat_bonus_against(att_type->bonuses, def_type,
531 CBONUS_DEFENSE_DIVIDER);
532 defensepower /= defense_divider;
535 defensepower +=
536 defensepower * tile_extras_defense_bonus(ptile, def_type) / 100;
538 if ((pcity || fortified)
539 && uclass_has_flag(utype_class(def_type), UCF_CAN_FORTIFY)) {
540 defensepower = (defensepower * 3) / 2;
543 return defensepower;
546 /**************************************************************************
547 May be called with a non-existing att_type to avoid any effects which
548 depend on the attacker.
549 **************************************************************************/
550 int get_virtual_defense_power(const struct unit_type *att_type,
551 const struct unit_type *def_type,
552 const struct player *def_player,
553 const struct tile *ptile,
554 bool fortified, int veteran)
556 int defensepower = def_type->defense_strength;
557 int db;
558 const struct veteran_level *vlevel;
559 struct unit_class *defclass;
561 fc_assert_ret_val(def_type != NULL, 0);
563 if (!can_exist_at_tile(def_type, ptile)) {
564 /* Ground units on ship doesn't defend. */
565 return 0;
568 vlevel = utype_veteran_level(def_type, veteran);
569 fc_assert_ret_val(vlevel != NULL, 0);
571 defclass = utype_class(def_type);
573 db = POWER_FACTOR;
574 if (uclass_has_flag(defclass, UCF_TERRAIN_DEFENSE)) {
575 db += tile_terrain(ptile)->defense_bonus / (100 / POWER_FACTOR);
577 defensepower *= db;
578 defensepower *= vlevel->power_fact / 100;
579 if (!is_native_tile_to_class(defclass, ptile)) {
580 defensepower = defensepower * defclass->non_native_def_pct / 100;
583 return defense_multiplication(att_type, def_type, def_player,
584 ptile, defensepower,
585 fortified);
588 /***************************************************************************
589 return the modified defense power of a unit.
590 An veteran aegis cruiser in a mountain city with SAM and SDI defense
591 being attacked by a missile gets defense 288.
592 ***************************************************************************/
593 int get_total_defense_power(const struct unit *attacker,
594 const struct unit *defender)
596 return defense_multiplication(unit_type(attacker), unit_type(defender),
597 unit_owner(defender), unit_tile(defender),
598 get_defense_power(defender),
599 defender->activity == ACTIVITY_FORTIFIED);
602 /***************************************************************************
603 Return total defense power of the unit if it fortifies, if possible,
604 where it is. attacker might be NULL to skip calculating attacker specific
605 bonuses.
606 ***************************************************************************/
607 int get_fortified_defense_power(const struct unit *attacker,
608 const struct unit *defender)
610 struct unit_type *att_type = NULL;
612 if (attacker != NULL) {
613 att_type = unit_type(attacker);
616 return defense_multiplication(att_type, unit_type(defender),
617 unit_owner(defender), unit_tile(defender),
618 get_defense_power(defender),
619 TRUE);
622 /**************************************************************************
623 A number indicating the defense strength.
624 Unlike the one got from win chance this doesn't potentially get insanely
625 small if the units are unevenly matched, unlike win_chance.
626 **************************************************************************/
627 static int get_defense_rating(const struct unit *attacker,
628 const struct unit *defender)
630 int afp, dfp;
632 int rating = get_total_defense_power(attacker, defender);
633 get_modified_firepower(attacker, defender, &afp, &dfp);
635 /* How many rounds the defender will last */
636 rating *= (defender->hp + afp-1)/afp;
638 rating *= dfp;
640 return rating;
643 /**************************************************************************
644 Finds the best defender on the tile, given an attacker. The diplomatic
645 relationship of attacker and defender is ignored; the caller should check
646 this.
647 **************************************************************************/
648 struct unit *get_defender(const struct unit *attacker,
649 const struct tile *ptile)
651 struct unit *bestdef = NULL;
652 int bestvalue = -99, best_cost = 0, rating_of_best = 0;
654 /* Simply call win_chance with all the possible defenders in turn, and
655 * take the best one. It currently uses build cost as a tiebreaker in
656 * case 2 units are identical, but this is crude as build cost does not
657 * neccesarily have anything to do with the value of a unit. This function
658 * could be improved to take the value of the unit into account. It would
659 * also be nice if the function was a bit more fuzzy about prioritizing,
660 * making it able to fx choose a 1a/9d unit over a 10a/10d unit. It should
661 * also be able to spare units without full hp's to some extent, as these
662 * could be more valuable later. */
663 unit_list_iterate(ptile->units, defender) {
664 /* We used to skip over allied units, but the logic for that is
665 * complicated and is now handled elsewhere. */
666 if (unit_can_defend_here(defender)
667 && unit_attack_unit_at_tile_result(attacker, defender, ptile) == ATT_OK) {
668 bool change = FALSE;
669 int build_cost = unit_build_shield_cost(defender);
670 int defense_rating = get_defense_rating(attacker, defender);
671 /* This will make units roughly evenly good defenders look alike. */
672 int unit_def
673 = (int) (100000 * (1 - unit_win_chance(attacker, defender)));
675 fc_assert_action(0 <= unit_def, continue);
677 if (unit_has_type_flag(defender, UTYF_GAMELOSS)
678 && !is_stack_vulnerable(unit_tile(defender))) {
679 unit_def = -1; /* then always use leader as last defender. */
680 /* FIXME: multiple gameloss units with varying defense value
681 * not handled. */
684 if (unit_def > bestvalue) {
685 change = TRUE;
686 } else if (unit_def == bestvalue) {
687 if (build_cost < best_cost) {
688 change = TRUE;
689 } else if (build_cost == best_cost) {
690 if (rating_of_best < defense_rating) {
691 change = TRUE;
696 if (change) {
697 bestvalue = unit_def;
698 bestdef = defender;
699 best_cost = build_cost;
700 rating_of_best = defense_rating;
703 } unit_list_iterate_end;
705 return bestdef;
708 /**************************************************************************
709 get unit at (x, y) that wants to kill defender.
711 Works like get_defender; see comment there.
712 This function is mostly used by the AI.
713 **************************************************************************/
714 struct unit *get_attacker(const struct unit *defender,
715 const struct tile *ptile)
717 struct unit *bestatt = 0;
718 int bestvalue = -1, unit_a, best_cost = 0;
720 unit_list_iterate(ptile->units, attacker) {
721 int build_cost = unit_build_shield_cost(attacker);
723 if (pplayers_allied(unit_owner(defender), unit_owner(attacker))) {
724 return NULL;
726 unit_a = (int) (100000 * (unit_win_chance(attacker, defender)));
727 if (unit_a > bestvalue ||
728 (unit_a == bestvalue && build_cost < best_cost)) {
729 bestvalue = unit_a;
730 bestatt = attacker;
731 best_cost = build_cost;
733 } unit_list_iterate_end;
735 return bestatt;
738 /**************************************************************************
739 Is it a city/fortress/air base or will the whole stack die in an attack
740 **************************************************************************/
741 bool is_stack_vulnerable(const struct tile *ptile)
743 return (game.info.killstack
744 && !tile_has_base_flag(ptile, BF_NO_STACK_DEATH)
745 && NULL == tile_city(ptile));
748 /**************************************************************************
749 Get bonus value against given unit type from bonus list.
750 **************************************************************************/
751 int combat_bonus_against(const struct combat_bonus_list *list,
752 const struct unit_type *enemy,
753 enum combat_bonus_type type)
755 int value = 0;
757 combat_bonus_list_iterate(list, pbonus) {
758 if (pbonus->type == type && utype_has_flag(enemy, pbonus->flag)) {
759 value += pbonus->value;
761 } combat_bonus_list_iterate_end;
763 return value;