~ubuntu-branches/debian/sid/freeciv/sid

« back to all changes in this revision

Viewing changes to common/combat.c

  • Committer: Package Import Robot
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2011-08-28 22:40:00 UTC
  • mfrom: (1.2.19 upstream)
  • Revision ID: package-import@ubuntu.com-20110828224000-j2r1erewlem25dox
Tags: 2.3.0-1
[ Karl Goetz ]
* New upstream version.
* Fix themes_sdl_use_system_fonts.diff to apply cleanly on 2.3.0
* Massage work_around_unity_induced_breakage.diff to get it
  applying to the new codebase (The patch assumes commits made
  after 2.3.0 was tagged upstream).

[ Clint Adams ]
* Fudge build system to think there is no libtool mismatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#include <config.h>
16
16
#endif
17
17
 
18
 
#include <assert.h>
19
18
#include <math.h>
20
19
 
 
20
/* utility */
 
21
#include "bitvector.h"
21
22
#include "rand.h"
 
23
#include "log.h"
22
24
 
 
25
/* common */
23
26
#include "base.h"
24
27
#include "game.h"
25
 
#include "log.h"
26
28
#include "map.h"
27
29
#include "movement.h"
28
30
#include "packets.h"
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)
72
74
{
73
75
  struct unit_class *dclass = unit_class(defender);
74
76
  struct unit_type *atype = unit_type(attacker);
77
79
}
78
80
 
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)
 
87
{
 
88
  if (NULL != tile_city(location)) {
 
89
    return TRUE;
 
90
  }
 
91
 
 
92
  if (is_unit_reachable_by_unit(defender, attacker)) {
 
93
    return TRUE;
 
94
  }
 
95
 
 
96
  if (tile_has_native_base(location, unit_type(defender))) {
 
97
    return TRUE;
 
98
  }
 
99
 
 
100
  return FALSE;
 
101
}
 
102
 
 
103
/***********************************************************************
80
104
  Checks if a unit can physically attack pdefender at the tile
81
105
  (assuming it is adjacent and at war).
82
106
 
97
121
                                  const struct unit *pdefender,
98
122
                                  const struct tile *dest_tile)
99
123
{
100
 
  struct city *pcity = tile_city(dest_tile);
101
 
 
102
124
  /* 1. Can we attack _anything_ ? */
103
125
  if (!is_military_unit(punit) || !is_attack_unit(punit)) {
104
126
    return FALSE;
105
127
  }
106
128
 
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)) {
110
131
    return FALSE;
111
132
  }
112
133
 
127
148
}
128
149
 
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)
135
157
{
136
158
  unit_list_iterate(ptile->units, aunit) {
137
159
    /* HACK: we don't count transported units here.  This prevents some
149
171
}
150
172
 
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)
 
180
{
 
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)) {
 
186
      return TRUE;
 
187
    }
 
188
  } unit_list_iterate_end;
 
189
 
 
190
  return FALSE;
 
191
}
 
192
 
 
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)
 
198
{
 
199
  if (game.info.unreachable_protects) {
 
200
    return can_unit_attack_all_at_tile(punit, ptile);
 
201
  } else {
 
202
    return can_unit_attack_any_at_tile(punit, ptile);
 
203
  }
 
204
}
 
205
 
 
206
/***********************************************************************
152
207
  Is unit (1) diplomatically allowed to attack and (2) physically able
153
208
  to do so?
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)
157
212
{
158
 
  if (!can_player_attack_tile(unit_owner(punit), dest_tile)) {
159
 
    return FALSE;
160
 
  }
161
 
 
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));
163
215
}
164
216
 
165
217
/***********************************************************************
332
384
{
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)) {
 
387
 
 
388
    if (pcity
 
389
        && !pplayers_allied(city_owner(pcity), owner)
 
390
        && fc_rand(100) < get_city_bonus(pcity, EFT_NUKE_PROOF)) {
337
391
      return pcity;
338
392
    }
339
393
  } square_iterate_end;
427
481
  struct city *pcity = tile_city(ptile);
428
482
  int mod;
429
483
 
430
 
  CHECK_UNIT_TYPE(def_type);
431
 
 
432
 
  if (att_type) {
433
 
    CHECK_UNIT_TYPE(att_type);
434
 
 
 
484
  fc_assert_ret_val(NULL != def_type, 0);
 
485
 
 
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);
565
618
      int unit_def 
566
619
        = (int) (100000 * (1 - unit_win_chance(attacker, defender)));
567
620
 
568
 
      assert(unit_def >= 0);
 
621
      fc_assert_action(0 <= unit_def, continue);
569
622
 
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
 
627
         * not handled. */
574
628
      }
575
629
 
576
630
      if (unit_def > bestvalue) {
594
648
    }
595
649
  } unit_list_iterate_end;
596
650
 
597
 
  if (unit_list_size(ptile->units) > 0 && !bestdef) {
598
 
    struct unit *punit = unit_list_get(ptile->units, 0);
599
 
 
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)),
608
 
            TILE_XY(ptile));
609
 
  }
610
 
 
611
651
  return bestdef;
612
652
}
613
653