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

« back to all changes in this revision

Viewing changes to ai/aiunit.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2010-02-23 22:09:02 UTC
  • mfrom: (7.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20100223220902-s3spqi1x4e190y0t
[ Karl Goetz ]
* Remove civserver files in /etc/ggzd/ (Closes: 523772, 517787)
* Adding ${misc:Depends} to all binary packages (lintian warnings)

[ Clint Adams ]
* New upstream version.
  - Drop data_dsc_use_bindir.diff (binary pathnames have changed).

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#include "unithand.h"
47
47
#include "unittools.h"
48
48
 
49
 
#include "path_finding.h"
50
 
#include "pf_tools.h"
51
 
 
52
49
#include "advmilitary.h"
53
50
#include "aiair.h"
54
51
#include "aicity.h"
115
112
    transported = NULL;
116
113
 
117
114
    city_list_iterate(pplayer->cities, pcity) {
118
 
      if (pcity->ai.urgency > comparison && pcity->airlift) {
119
 
        comparison = pcity->ai.urgency;
 
115
      if (pcity->ai->urgency > comparison && pcity->airlift) {
 
116
        comparison = pcity->ai->urgency;
120
117
        most_needed = pcity;
121
118
      }
122
119
    } city_list_iterate_end;
123
120
    if (!most_needed) {
124
121
      comparison = 0;
125
122
      city_list_iterate(pplayer->cities, pcity) {
126
 
        if (pcity->ai.danger > comparison && pcity->airlift) {
127
 
          comparison = pcity->ai.danger;
 
123
        if (pcity->ai->danger > comparison && pcity->airlift) {
 
124
          comparison = pcity->ai->danger;
128
125
          most_needed = pcity;
129
126
        }
130
127
      } city_list_iterate_end;
135
132
    comparison = 0;
136
133
    unit_list_iterate(pplayer->units, punit) {
137
134
      struct tile *ptile = (punit->tile);
 
135
      struct city *pcity = tile_city(ptile);
138
136
 
139
 
      if (ptile->city && ptile->city->ai.urgency == 0
140
 
          && ptile->city->ai.danger - DEFENCE_POWER(punit) < comparison
 
137
      if (pcity
 
138
          && pcity->ai->urgency == 0
 
139
          && pcity->ai->danger - DEFENCE_POWER(punit) < comparison
141
140
          && unit_can_airlift_to(punit, most_needed)
142
141
          && DEFENCE_POWER(punit) > 2
143
142
          && (punit->ai.ai_role == AIUNIT_NONE
144
143
              || punit->ai.ai_role == AIUNIT_DEFEND_HOME)
145
144
          && IS_ATTACKER(punit)) {
146
 
        comparison = ptile->city->ai.danger;
 
145
        comparison = pcity->ai->danger;
147
146
        transported = punit;
148
147
      }
149
148
    } unit_list_iterate_end;
176
175
    return FALSE;
177
176
 
178
177
  adjc_iterate(ptile, atile) {
179
 
    if (!is_ocean(tile_get_terrain(atile))
 
178
    if (!is_ocean_tile(atile)
180
179
        && is_non_allied_unit_tile(atile, unit_owner(myunit))) {
181
180
      return FALSE;
182
181
    }
264
263
{
265
264
  int move_time;
266
265
  int move_rate = unit_move_rate(punit);
 
266
  struct unit_class *pclass = unit_class(punit);
267
267
 
268
 
  switch (unit_type(punit)->move_type) {
269
 
  case LAND_MOVING:
270
 
  
271
 
   /* FIXME: IGTER units should have their move rates multiplied by 
272
 
    * igter_speedup. Note: actually, igter units should never have their 
273
 
    * move rates multiplied. The correct behaviour is to have every tile 
274
 
    * they cross cost 1/3 of a movement point. ---RK */
275
 
 
 
268
  if (!uclass_has_flag(pclass, UCF_TERRAIN_SPEED)) {
 
269
    /* Unit does not care about terrain */
 
270
    move_time = real_map_distance(punit->tile, ptile) * SINGLE_MOVE / move_rate;
 
271
  } else {
276
272
    if (unit_has_type_flag(punit, F_IGTER)) {
 
273
      /* FIXME: IGTER units should have their move rates multiplied by 
 
274
       * igter_speedup. Note: actually, igter units should never have their 
 
275
       * move rates multiplied. The correct behaviour is to have every tile 
 
276
       * they cross cost 1/3 of a movement point. ---RK */
277
277
      move_rate *= 3;
278
278
    }
279
 
    move_time = WARMAP_COST(ptile) / move_rate;
280
 
    break;
281
 
 
282
 
  case SEA_MOVING:
283
 
    move_time = WARMAP_SEACOST(ptile) / move_rate;
284
 
    break;
285
 
 
286
 
  case HELI_MOVING:
287
 
  case AIR_MOVING:
288
 
     move_time = real_map_distance(punit->tile, ptile) 
289
 
                   * SINGLE_MOVE / move_rate;
290
 
     break;
291
 
 
292
 
  default:
293
 
    die("ai/aiunit.c:unit_move_turns: illegal move type %d",
294
 
        unit_type(punit)->move_type);
295
 
    move_time = 0;
 
279
 
 
280
    if (uclass_move_type(pclass) == SEA_MOVING) {
 
281
      move_time = WARMAP_SEACOST(ptile) / move_rate;
 
282
    } else {
 
283
      move_time = WARMAP_COST(ptile) / move_rate;
 
284
    }
296
285
  }
297
286
  return move_time;
298
287
}
307
296
*********************************************************************/
308
297
int build_cost_balanced(const struct unit_type *punittype)
309
298
{
310
 
  return 2 * unit_build_shield_cost(punittype) * punittype->attack_strength /
 
299
  return 2 * utype_build_shield_cost(punittype) * punittype->attack_strength /
311
300
      (punittype->attack_strength + punittype->defense_strength);
312
301
}
313
302
 
475
464
 
476
465
        if (val != 0) {
477
466
          *value += val;
478
 
          *cost += unit_build_shield_cost(unit_type(aunit));
 
467
          *cost += unit_build_shield_cost(aunit);
479
468
        }
480
469
      }
481
470
    } unit_list_iterate_end;
549
538
      /* See description of kill_desire() about these variables. */
550
539
      int attack = unit_att_rating_now(punit);
551
540
      int benefit = stack_cost(pdef);
552
 
      int loss = unit_build_shield_cost(unit_type(punit));
 
541
      int loss = unit_build_shield_cost(punit);
553
542
 
554
543
      attack *= attack;
555
544
      
579
568
    }
580
569
    
581
570
  } else {
582
 
    struct city *pcity = tile_get_city(ptile);
 
571
    struct city *pcity = tile_city(ptile);
583
572
    
584
573
    /* No defender... */
585
574
    
619
608
   * enemy units because we are looking for trouble!
620
609
   * Hence no call ai_avoid_risks()
621
610
   */
622
 
  
623
 
  tgt_map = pf_create_map(&parameter);
624
 
  while (pf_next(tgt_map)) {
625
 
    struct pf_position pos;
 
611
 
 
612
  tgt_map = pf_map_new(&parameter);
 
613
  pf_map_iterate_move_costs(tgt_map, iter_tile, move_cost, FALSE) {
626
614
    int want;
627
615
    bool move_needed;
628
616
    int thresh;
629
617
 
630
 
    pf_next_get_position(tgt_map, &pos);
631
 
    
632
 
    if (pos.total_MC > punit->moves_left) {
 
618
    if (move_cost > punit->moves_left) {
633
619
      /* This is too far */
634
620
      break;
635
621
    }
636
622
 
637
623
    if (ai_handicap(pplayer, H_TARGETS) 
638
 
        && !map_is_known_and_seen(pos.tile, pplayer, V_MAIN)) {
 
624
        && !map_is_known_and_seen(iter_tile, pplayer, V_MAIN)) {
639
625
      /* The target is under fog of war */
640
626
      continue;
641
627
    }
642
628
    
643
 
    want = ai_rampage_want(punit, pos.tile);
 
629
    want = ai_rampage_want(punit, iter_tile);
644
630
 
645
631
    /* Negative want means move needed even though the tiles are adjacent */
646
 
    move_needed = (!is_tiles_adjacent(punit->tile, pos.tile)
 
632
    move_needed = (!is_tiles_adjacent(punit->tile, iter_tile)
647
633
                   || want < 0);
648
634
    /* Select the relevant threshold */
649
635
    thresh = (move_needed ? thresh_move : thresh_adj);
653
639
      /* The new want exceeds both the previous maximum 
654
640
       * and the relevant threshold, so it's worth recording */
655
641
      max_want = want;
656
 
      ptile = pos.tile;
 
642
      ptile = iter_tile;
657
643
    }
658
 
  }
 
644
  } pf_map_iterate_move_costs_end;
659
645
 
660
646
  if (max_want > 0) {
661
647
    /* We found something */
662
 
    path = pf_get_path(tgt_map, ptile);
 
648
    path = pf_map_get_path(tgt_map, ptile);
663
649
    assert(path != NULL);
664
650
  }
665
651
 
666
 
  pf_destroy_map(tgt_map);
 
652
  pf_map_destroy(tgt_map);
667
653
  
668
654
  return path;
669
655
}
683
669
  Returns TRUE if survived the rampage session.
684
670
**************************************************************************/
685
671
bool ai_military_rampage(struct unit *punit, int thresh_adj, 
686
 
                                int thresh_move)
 
672
                         int thresh_move)
687
673
{
688
674
  int count = punit->moves_left + 1; /* break any infinite loops */
689
675
  struct pf_path *path = NULL;
701
687
      /* Died */
702
688
      count = -1;
703
689
    }
704
 
    pf_destroy_path(path);
 
690
    pf_path_destroy(path);
705
691
    path = NULL;
706
692
  }
707
693
 
781
767
  CHECK_UNIT(punit);
782
768
 
783
769
  adjc_iterate(dest_tile, tile1) {
784
 
    struct terrain *pterrain = tile_get_terrain(tile1);
 
770
    struct terrain *pterrain = tile_terrain(tile1);
785
771
 
786
772
    ok = 0;
787
773
    if (WARMAP_SEACOST(tile1) <= 6 * THRESHOLD && !is_ocean(pterrain)) {
788
774
      /* accessible beachhead */
789
775
      adjc_iterate(tile1, tile2) {
790
 
        if (is_ocean(tile_get_terrain(tile2))
 
776
        if (is_ocean_tile(tile2)
791
777
            && is_my_zoc(unit_owner(punit), tile2)) {
792
778
          ok++;
793
779
          goto OK;
824
810
**************************************************************************/
825
811
static bool unit_role_defender(const struct unit_type *punittype)
826
812
{
827
 
  if (punittype->move_type != LAND_MOVING) {
 
813
  if (utype_move_type(punittype) != LAND_MOVING) {
828
814
    return FALSE; /* temporary kluge */
829
815
  }
830
816
  return (utype_has_role(punittype, L_DEFEND_GOOD));
861
847
        || DEFENCE_POWER(buddy) >= DEFENCE_POWER(punit)
862
848
        || (is_military_unit(buddy) && get_transporter_capacity(buddy) == 0
863
849
            && ATTACK_POWER(buddy) <= ATTACK_POWER(punit))
864
 
        || unit_type(buddy)->move_type != unit_type(punit)->move_type) { 
 
850
        || uclass_move_type(unit_class(buddy)) != uclass_move_type(unit_class(punit))) { 
865
851
      continue;
866
852
    }
867
 
    if (punit->tile->city
 
853
    if (tile_city(punit->tile)
868
854
        && punit->ai.ai_role == AIUNIT_DEFEND_HOME) {
869
855
      /* FIXME: Not even if it is an allied city?
870
856
       * And why is this *inside* the loop ?*/
888
874
  } unit_list_iterate_end;
889
875
 
890
876
  /* City bodyguard */
891
 
  if (unit_type(punit)->move_type == LAND_MOVING) {
 
877
  if (uclass_move_type(unit_class(punit)) == LAND_MOVING) {
 
878
    struct city *pcity = tile_city(punit->tile);
 
879
 
892
880
   city_list_iterate(pplayer->cities, mycity) {
893
881
    if (!goto_is_sane(punit, mycity->tile, TRUE)
894
 
        || mycity->ai.urgency == 0) {
 
882
        || mycity->ai->urgency == 0) {
895
883
      continue;
896
884
    }
897
 
    if (punit->tile->city
898
 
        && (punit->tile->city->ai.grave_danger > 0
899
 
            || punit->tile->city->ai.urgency > mycity->ai.urgency
900
 
            || ((punit->tile->city->ai.danger > mycity->ai.danger
 
885
    if (pcity
 
886
        && (pcity->ai->grave_danger > 0
 
887
            || pcity->ai->urgency > mycity->ai->urgency
 
888
            || ((pcity->ai->danger > mycity->ai->danger
901
889
                 || punit->ai.ai_role == AIUNIT_DEFEND_HOME)
902
 
                && mycity->ai.grave_danger == 0))) {
 
890
                && mycity->ai->grave_danger == 0))) {
903
891
      /* Do not yoyo between cities in need of defense. Chances are
904
892
       * we'll be between cities when we are needed the most! */
905
893
      continue;
906
894
    }
907
895
    dist = unit_move_turns(punit, mycity->tile);
908
 
    def = (mycity->ai.danger - assess_defense_quadratic(mycity));
 
896
    def = (mycity->ai->danger - assess_defense_quadratic(mycity));
909
897
    if (def <= 0) {
910
898
      continue;
911
899
    }
954
942
    if (can_unit_do_activity(punit, ACTIVITY_PILLAGE)
955
943
        && is_land_barbarian(pplayer)) {
956
944
      /* land barbarians pillage */
957
 
      handle_unit_activity_request(punit, ACTIVITY_PILLAGE);
 
945
      unit_activity_handling(punit, ACTIVITY_PILLAGE);
958
946
    }
959
947
    ai_unit_new_role(punit, AIUNIT_NONE, NULL);
960
948
    return;
974
962
     * or the unit we should protect is still alive... */
975
963
    if ((aunit && (aiguard_has_guard(aunit) || aiguard_wanted(aunit))
976
964
         && unit_def_rating_basic(punit) > unit_def_rating_basic(aunit)) 
977
 
        || (acity && city_owner(acity) == unit_owner(punit) && acity->ai.urgency != 0 
978
 
            && acity->ai.danger > assess_defense_quadratic(acity))) {
 
965
        || (acity && city_owner(acity) == unit_owner(punit)
 
966
            && acity->ai->urgency != 0 
 
967
            && acity->ai->danger > assess_defense_quadratic(acity))) {
979
968
      return; /* Yep! */
980
969
    } else {
981
970
      ai_unit_new_role(punit, AIUNIT_NONE, NULL); /* Nope! */
1002
991
    struct unit *aunit = NULL;
1003
992
    int val;
1004
993
 
1005
 
    generate_warmap(tile_get_city(punit->tile), punit);
 
994
    generate_warmap(tile_city(punit->tile), punit);
1006
995
 
1007
996
    val = look_for_charge(pplayer, punit, &aunit, &acity);
1008
997
    if (acity) {
1034
1023
  CHECK_UNIT(punit);
1035
1024
 
1036
1025
  if (!pcity || city_owner(pcity) != pplayer) {
1037
 
    pcity = punit->tile->city;
 
1026
    pcity = tile_city(punit->tile);
1038
1027
    /* Do not stay defending an allied city forever */
1039
1028
    aiguard_clear_charge(punit);
1040
1029
  }
1078
1067
                        int speed, bool go_by_boat, 
1079
1068
                        struct unit *boat, const struct unit_type *boattype)
1080
1069
{
1081
 
  switch (our_type->move_type) {
1082
 
  case LAND_MOVING:
1083
 
    if (go_by_boat) {
1084
 
      int boatspeed = boattype->move_rate;
1085
 
      int move_time = (WARMAP_SEACOST(acity->tile)) / boatspeed;
1086
 
      
1087
 
      if (utype_has_flag(boattype, F_TRIREME) && move_time > 2) {
1088
 
        /* FIXME: Should also check for LIGHTHOUSE */
1089
 
        /* Return something prohibitive */
1090
 
        return 999;
1091
 
      }
1092
 
      if (boat) {
1093
 
        /* Time to get to the boat */
1094
 
        move_time += (WARMAP_COST(boat->tile) + speed - 1) / speed;
1095
 
      }
1096
 
      
1097
 
      if (!utype_has_flag(our_type, F_MARINES)) {
1098
 
        /* Time to get off the boat (Marines do it from the vessel) */
1099
 
        move_time += 1;
1100
 
      }
1101
 
      
1102
 
      return move_time;
1103
 
    } else {
1104
 
      /* We are walking */
1105
 
      return (WARMAP_COST(acity->tile) + speed - 1) / speed;
1106
 
    }
1107
 
  case SEA_MOVING:
 
1070
  struct unit_class *pclass = utype_class(our_type);
 
1071
 
 
1072
  if (pclass->ai.sea_move == MOVE_NONE && go_by_boat) {
 
1073
    int boatspeed = boattype->move_rate;
 
1074
    int move_time = (WARMAP_SEACOST(acity->tile)) / boatspeed;
 
1075
      
 
1076
    if (utype_has_flag(boattype, F_TRIREME) && move_time > 2) {
 
1077
      /* Return something prohibitive */
 
1078
      return 999;
 
1079
    }
 
1080
    if (boat) {
 
1081
      /* Time to get to the boat */
 
1082
      move_time += (WARMAP_COST(boat->tile) + speed - 1) / speed;
 
1083
    }
 
1084
      
 
1085
    if (!utype_has_flag(our_type, F_MARINES)) {
 
1086
      /* Time to get off the boat (Marines do it from the vessel) */
 
1087
      move_time += 1;
 
1088
    }
 
1089
      
 
1090
    return move_time;
 
1091
  }
 
1092
 
 
1093
  if (pclass->ai.land_move == MOVE_NONE
 
1094
      && pclass->ai.sea_move != MOVE_NONE) {
1108
1095
    /* We are a boat: time to sail */
1109
1096
    return (WARMAP_SEACOST(acity->tile) + speed - 1) / speed;
1110
 
  default: 
1111
 
    freelog(LOG_ERROR, "ERROR: Unsupported move_type in time_to_enemy_city");
1112
 
    /* Return something prohibitive */
1113
 
    return 999;
1114
1097
  }
1115
1098
 
 
1099
  return (WARMAP_COST(acity->tile) + speed - 1) / speed;
1116
1100
}
1117
1101
 
1118
1102
/************************************************************************
1125
1109
                        int speed, struct tile *ptile,
1126
1110
                        const struct unit_type *enemy_type)
1127
1111
{
 
1112
  struct unit_class *pclass = utype_class(our_type);
1128
1113
  int dist;
1129
1114
 
1130
 
  switch (our_type->move_type) {
1131
 
  case LAND_MOVING:
 
1115
  if (pclass->ai.land_move != MOVE_NONE) {
1132
1116
    dist = WARMAP_COST(ptile);
1133
 
    break;
1134
 
  case SEA_MOVING:
 
1117
  } else {
1135
1118
    dist = WARMAP_SEACOST(ptile);
1136
 
    break;
1137
 
  default:
1138
 
    /* Compiler warning */
1139
 
    dist = 0; 
1140
 
    freelog(LOG_ERROR, "ERROR: Unsupported unit_type in time_to_enemy_city");
1141
 
    /* Return something prohibitive */
1142
 
    return 999;
1143
1119
  }
1144
1120
 
1145
1121
  /* if dist <= move_rate, we hit the enemy right now */    
1158
1134
  Mark invasion possibilities of punit in the surrounding cities. The
1159
1135
  given radius limites the area which is searched for cities. The
1160
1136
  center of the area is either the unit itself (dest == FALSE) or the
1161
 
  destiniation of the current goto (dest == TRUE). The invasion threat
1162
 
  is marked in pcity->ai.invasion via ORing the "which" argument (to
1163
 
  tell attack from sea apart from ground unit attacks). Note that
1164
 
  "which" should only have one bit set.
 
1137
  destination of the current goto (dest == TRUE). The invasion threat
 
1138
  is marked in pcity->ai.invasion by setting the "which" bit (to
 
1139
  tell attack which can only kill units from occupy possibility).
1165
1140
 
1166
1141
  If dest == TRUE then a valid goto is presumed.
1167
1142
**************************************************************************/
1181
1156
  }
1182
1157
 
1183
1158
  square_iterate(ptile, radius, tile1) {
1184
 
    struct city *pcity = tile_get_city(tile1);
 
1159
    struct city *pcity = tile_city(tile1);
1185
1160
 
1186
1161
    if (pcity
1187
1162
        && HOSTILE_PLAYER(pplayer, ai, city_owner(pcity))
1188
 
        && (pcity->ai.invasion & which) != which
1189
1163
        && (dest || !has_defense(pcity))) {
1190
 
      pcity->ai.invasion |= which;
 
1164
      int attacks;
 
1165
 
 
1166
      if (unit_has_type_flag(punit, F_ONEATTACK)) {
 
1167
        attacks = 1;
 
1168
      } else {
 
1169
        attacks = unit_type(punit)->move_rate;
 
1170
      }
 
1171
      pcity->ai->invasion.attack += attacks;
 
1172
      if (which == INVASION_OCCUPY) {
 
1173
        pcity->ai->invasion.occupy++;
 
1174
      }
1191
1175
    }
1192
1176
  } square_iterate_end;
1193
1177
}
1219
1203
  /* Our total attack value with reinforcements */
1220
1204
  int attack;
1221
1205
  int move_time, move_rate;
1222
 
  Continent_id con = tile_get_continent(punit->tile);
 
1206
  Continent_id con = tile_continent(punit->tile);
1223
1207
  struct unit *pdef;
1224
1208
  int maxd, needferry;
1225
1209
  /* Do we have access to sea? */
1226
1210
  bool harbor = FALSE;
1227
 
  struct tile *best_tile = NULL;
1228
1211
  /* Build cost of the attacker (+adjustments) */
1229
1212
  int bcost, bcost_bal;
1230
1213
  bool handicap = ai_handicap(pplayer, H_TARGETS);
1238
1221
   * never learning steam engine, even though ironclads would be very 
1239
1222
   * useful. -- Syela */
1240
1223
  int bk = 0; 
 
1224
  struct unit_class *pclass = unit_class(punit);
1241
1225
 
1242
1226
  /*** Very preliminary checks */
1243
1227
  *dest_tile = punit->tile;
1244
1228
 
1245
 
  if (!is_ground_unit(punit) && !is_sailing_unit(punit)) {
 
1229
  if (utype_fuel(unit_type(punit)) || is_losing_hp(punit)) {
1246
1230
    /* Don't know what to do with them! */
1247
1231
    /* This is not LOG_ERROR in stable branch, as calling
1248
1232
     * fstk is in many cases right thing to do when custom
1277
1261
    }
1278
1262
    city_list_iterate(aplayer->cities, acity) {
1279
1263
      reinforcements_cost_and_value(punit, acity->tile,
1280
 
                                    &acity->ai.attack, &acity->ai.bcost);
1281
 
      acity->ai.invasion = 0;
 
1264
                                    &acity->ai->attack, &acity->ai->bcost);
 
1265
      acity->ai->invasion.attack = 0;
 
1266
      acity->ai->invasion.occupy = 0;
1282
1267
    } city_list_iterate_end;
1283
1268
  } players_iterate_end;
1284
1269
 
1292
1277
    /* dealing with invasion stuff */
1293
1278
    if (IS_ATTACKER(aunit)) {
1294
1279
      if (aunit->activity == ACTIVITY_GOTO) {
1295
 
        invasion_funct(aunit, TRUE, 0, (COULD_OCCUPY(aunit) ? 1 : 2));
1296
 
        if ((pcity = tile_get_city(aunit->goto_tile))) {
1297
 
          pcity->ai.attack += unit_att_rating(aunit);
1298
 
          pcity->ai.bcost += unit_build_shield_cost(unit_type(aunit));
 
1280
        invasion_funct(aunit, TRUE, 0,
 
1281
                       (COULD_OCCUPY(aunit) ? INVASION_OCCUPY : INVASION_ATTACK));
 
1282
        if ((pcity = tile_city(aunit->goto_tile))) {
 
1283
          pcity->ai->attack += unit_att_rating(aunit);
 
1284
          pcity->ai->bcost += unit_build_shield_cost(aunit);
1299
1285
        } 
1300
1286
      }
1301
1287
      invasion_funct(aunit, FALSE, unit_move_rate(aunit) / SINGLE_MOVE,
1302
 
                     (COULD_OCCUPY(aunit) ? 1 : 2));
 
1288
                     (COULD_OCCUPY(aunit) ? INVASION_OCCUPY : INVASION_ATTACK));
1303
1289
    } else if (aunit->ai.passenger != 0 &&
1304
1290
               !same_pos(aunit->tile, punit->tile)) {
1305
1291
      /* It's a transport with reinforcements */
1306
1292
      if (aunit->activity == ACTIVITY_GOTO) {
1307
 
        invasion_funct(aunit, TRUE, 1, 1);
 
1293
        invasion_funct(aunit, TRUE, 1, INVASION_OCCUPY);
1308
1294
      }
1309
 
      invasion_funct(aunit, FALSE, 2, 1);
 
1295
      invasion_funct(aunit, FALSE, 2, INVASION_OCCUPY);
1310
1296
    }
1311
1297
  } unit_list_iterate_end;
1312
1298
  /* end horrible initialization subroutine */
1317
1303
   * to avoid spreading out attacks too widely to be inefficient.
1318
1304
   */
1319
1305
 
1320
 
  pcity = tile_get_city(punit->tile);
 
1306
  pcity = tile_city(punit->tile);
1321
1307
 
1322
1308
  if (pcity && (punit->id == 0 || pcity->id == punit->homecity)) {
1323
1309
    /* I would have thought unhappiness should be taken into account 
1324
1310
     * irrespectfully the city in which it will surface...  GB */ 
1325
 
    unhap = ai_assess_military_unhappiness(pcity, government_of_player(pplayer));
 
1311
    unhap = ai_assess_military_unhappiness(pcity);
1326
1312
  }
1327
1313
 
1328
1314
  move_rate = unit_move_rate(punit);
1332
1318
 
1333
1319
  maxd = MIN(6, move_rate) * THRESHOLD + 1;
1334
1320
 
1335
 
  bcost = unit_build_shield_cost(unit_type(punit));
 
1321
  bcost = unit_build_shield_cost(punit);
1336
1322
  bcost_bal = build_cost_balanced(unit_type(punit));
1337
1323
 
1338
1324
  /* most flexible but costs milliseconds */
1339
 
  generate_warmap(tile_get_city(*dest_tile), punit);
1340
 
 
1341
 
  if (is_ground_unit(punit)) {
1342
 
    int boatid = find_boat(pplayer, &best_tile, 2);
1343
 
    ferryboat = player_find_unit_by_id(pplayer, boatid);
 
1325
  generate_warmap(tile_city(*dest_tile), punit);
 
1326
 
 
1327
  if (pclass->ai.sea_move == MOVE_NONE) {
 
1328
    /* We need boat to move over sea */
 
1329
 
 
1330
    /* First check if we can use the boat we are currently loaded to */
 
1331
    if (punit->transported_by != -1) {
 
1332
      ferryboat = player_find_unit_by_id(unit_owner(punit),
 
1333
                                         punit->transported_by);
 
1334
 
 
1335
      /* We are already in, so don't ask for free capacity */
 
1336
      if (ferryboat == NULL || !is_boat_free(ferryboat, punit, 0)) {
 
1337
        /* No, we cannot control current boat */
 
1338
        ferryboat = NULL;
 
1339
      }
 
1340
    }
 
1341
 
 
1342
    if (ferryboat == NULL) {
 
1343
      /* Try to find new boat */
 
1344
      int boatid = aiferry_find_boat(punit, 1, NULL);
 
1345
      ferryboat = player_find_unit_by_id(pplayer, boatid);
 
1346
    }
1344
1347
  }
1345
1348
 
1346
1349
  if (ferryboat) {
1347
1350
    boattype = unit_type(ferryboat);
1348
 
    really_generate_warmap(tile_get_city(ferryboat->tile),
1349
 
                           ferryboat, SEA_MOVING);
 
1351
    generate_warmap(tile_city(ferryboat->tile), ferryboat);
1350
1352
  } else {
1351
1353
    boattype = best_role_unit_for_player(pplayer, L_FERRYBOAT);
1352
1354
    if (boattype == NULL) {
1355
1357
    }
1356
1358
  }
1357
1359
 
1358
 
  if (is_ground_unit(punit) && punit->id == 0 
 
1360
  if (pclass->ai.sea_move == MOVE_NONE
 
1361
      && punit->id == 0 
1359
1362
      && is_ocean_near_tile(punit->tile)) {
1360
1363
    harbor = TRUE;
1361
1364
  }
1362
1365
 
1363
1366
  players_iterate(aplayer) {
 
1367
    int reserves;
 
1368
 
1364
1369
    /* For the virtual unit case, which is when we are called to evaluate
1365
1370
     * which units to build, we want to calculate in danger and which
1366
1371
     * players we want to make war with in the future. We do _not_ want
1372
1377
    }
1373
1378
 
1374
1379
    city_list_iterate(aplayer->cities, acity) {
1375
 
      bool go_by_boat = (is_ground_unit(punit)
 
1380
      bool go_by_boat = (pclass->ai.sea_move == MOVE_NONE
1376
1381
                         && !(goto_is_sane(punit, acity->tile, TRUE) 
1377
1382
                              && WARMAP_COST(acity->tile) < maxd));
1378
1383
 
1379
 
      if (!is_ocean(tile_get_terrain(acity->tile))
1380
 
          && unit_has_type_flag(punit, F_NO_LAND_ATTACK)) {
 
1384
      if (!is_native_tile(unit_type(punit), acity->tile)
 
1385
          && !can_attack_non_native(unit_type(punit))) {
1381
1386
        /* Can't attack this city. It is on land. */
1382
1387
        continue;
1383
1388
      }
1394
1399
        continue;
1395
1400
      }
1396
1401
      
1397
 
      if (is_sailing_unit(punit) 
 
1402
      if (pclass->ai.land_move == MOVE_NONE
1398
1403
          && WARMAP_SEACOST(acity->tile) >= maxd) {
1399
1404
        /* Too far to sail */
1400
1405
        continue;
1402
1407
      
1403
1408
      if ((pdef = get_defender(punit, acity->tile))) {
1404
1409
        vuln = unit_def_rating_sq(punit, pdef);
1405
 
        benefit = unit_build_shield_cost(unit_type(pdef));
 
1410
        benefit = unit_build_shield_cost(pdef);
1406
1411
      } else { 
1407
1412
        vuln = 0; 
1408
1413
        benefit = 0; 
1412
1417
                                      go_by_boat, ferryboat, boattype);
1413
1418
 
1414
1419
      if (move_time > 1) {
1415
 
        struct unit_type *def_type
1416
 
          = ai_choose_defender_versus(acity, unit_type(punit));
 
1420
        struct unit_type *def_type = ai_choose_defender_versus(acity, punit);
1417
1421
 
1418
1422
        if (def_type) {
1419
1423
          int v = unittype_def_rating_sq(unit_type(punit), def_type,
1422
1426
          if (v > vuln) {
1423
1427
            /* They can build a better defender! */ 
1424
1428
            vuln = v; 
1425
 
            benefit = unit_build_shield_cost(def_type); 
 
1429
            benefit = utype_build_shield_cost(def_type); 
1426
1430
          }
1427
1431
        }
1428
1432
      }
1429
1433
 
1430
 
      if (COULD_OCCUPY(punit) || TEST_BIT(acity->ai.invasion, 0)) {
1431
 
        /* There are units able to occupy the city! */
1432
 
        benefit += 40;
 
1434
      reserves = acity->ai->invasion.attack -
 
1435
        unit_list_size(acity->tile->units);
 
1436
 
 
1437
      if (reserves >= 0) {
 
1438
        /* We have enough units to kill all the units in the city */
 
1439
        if (reserves > 0
 
1440
            && (COULD_OCCUPY(punit) || acity->ai->invasion.occupy > 0)) {
 
1441
          /* There are units able to occupy the city after all defenders
 
1442
           * are killed! */
 
1443
          benefit += 60;
 
1444
        }
1433
1445
      }
1434
1446
 
1435
 
      attack = (attack_value + acity->ai.attack) 
1436
 
        * (attack_value + acity->ai.attack);
 
1447
      attack = (attack_value + acity->ai->attack) 
 
1448
        * (attack_value + acity->ai->attack);
1437
1449
      /* Avoiding handling upkeep aggregation this way -- Syela */
1438
1450
      
1439
1451
      /* AI was not sending enough reinforcements to totally wipe out a city
1449
1461
      } else if (move_time > THRESHOLD) {
1450
1462
        /* Too far! */
1451
1463
        want = 0;
1452
 
      } else if (COULD_OCCUPY(punit) && acity->ai.invasion == 2) {
 
1464
      } else if (COULD_OCCUPY(punit)
 
1465
                 && acity->ai->invasion.attack > 0
 
1466
                 && acity->ai->invasion.occupy == 0) {
1453
1467
        /* Units able to occupy really needed there! */
1454
1468
        want = bcost * SHIELD_WEIGHTING;
1455
1469
      } else {
1456
 
        int a_squared = acity->ai.attack * acity->ai.attack;
 
1470
        int a_squared = acity->ai->attack * acity->ai->attack;
1457
1471
        
1458
 
        want = kill_desire(benefit, attack, (bcost + acity->ai.bcost), 
 
1472
        want = kill_desire(benefit, attack, (bcost + acity->ai->bcost), 
1459
1473
                           vuln, victim_count);
1460
 
        if (benefit * a_squared > acity->ai.bcost * vuln) {
 
1474
        if (benefit * a_squared > acity->ai->bcost * vuln) {
1461
1475
          /* If there're enough units to do the job, we don't need this
1462
1476
           * one. */
1463
1477
          /* FIXME: The problem with ai.bcost is that bigger it is, less is
1465
1479
           * cavalries to take over a city, we have four (which is not
1466
1480
           * enough), then we will be severely discouraged to build the
1467
1481
           * fifth one.  Where is logic in this??!?! --GB */
1468
 
          want -= kill_desire(benefit, a_squared, acity->ai.bcost, 
 
1482
          want -= kill_desire(benefit, a_squared, acity->ai->bcost, 
1469
1483
                              vuln, victim_count);
1470
1484
        }
1471
1485
      }
1473
1487
                           : SHIELD_WEIGHTING);
1474
1488
      /* build_cost of ferry */
1475
1489
      needferry = (go_by_boat && !ferryboat
1476
 
                   ? unit_build_shield_cost(boattype) : 0);
 
1490
                   ? utype_build_shield_cost(boattype) : 0);
1477
1491
      /* FIXME: add time to build the ferry? */
1478
1492
      want = military_amortize(pplayer, game_find_city_by_number(punit->homecity),
1479
1493
                               want, MAX(1, move_time),
1494
1508
      }
1495
1509
      /* END STEAM-ENGINES KLUGE */
1496
1510
      
1497
 
      if (punit->id != 0 && ferryboat && is_ground_unit(punit)) {
 
1511
      if (punit->id != 0 && ferryboat && pclass->ai.sea_move == MOVE_NONE) {
1498
1512
        UNIT_LOG(LOG_DEBUG, punit, "in fstk with boat %s@(%d, %d) -> %s@(%d, %d)"
1499
1513
                 " (go_by_boat=%d, move_time=%d, want=%d, best=%d)",
1500
1514
                 unit_rule_name(ferryboat),
1506
1520
      
1507
1521
      if (want > best && ai_fuzzy(pplayer, TRUE)) {
1508
1522
        /* Yes, we like this target */
1509
 
        if (punit->id != 0 && is_ground_unit(punit) 
 
1523
        if (punit->id != 0 && pclass->ai.sea_move == MOVE_NONE
1510
1524
            && !unit_has_type_flag(punit, F_MARINES)
1511
 
            && tile_get_continent(acity->tile) != con) {
 
1525
            && tile_continent(acity->tile) != con) {
1512
1526
          /* a non-virtual ground unit is trying to attack something on 
1513
1527
           * another continent.  Need a beachhead which is adjacent 
1514
1528
           * to the city and an available ocean tile */
1533
1547
     * I am deliberately not adding ferryboat code to the unit_list_iterate. 
1534
1548
     * -- Syela */
1535
1549
    unit_list_iterate(aplayer->units, aunit) {
1536
 
      if (tile_get_city(aunit->tile)) {
 
1550
      if (tile_city(aunit->tile)) {
1537
1551
        /* already dealt with it */
1538
1552
        continue;
1539
1553
      }
1558
1572
        continue;
1559
1573
      }
1560
1574
 
1561
 
      if (is_ground_unit(punit) 
1562
 
          && (tile_get_continent(aunit->tile) != con 
 
1575
      if (pclass->ai.sea_move != MOVE_FULL
 
1576
          && (tile_continent(aunit->tile) != con 
1563
1577
              || WARMAP_COST(aunit->tile) >= maxd)) {
1564
1578
        /* Maybe impossible or too far to walk */
1565
1579
        continue;
1566
1580
      }
1567
1581
 
1568
 
      if (is_sailing_unit(punit)
 
1582
      if (pclass->ai.land_move != MOVE_FULL
1569
1583
          && (!goto_is_sane(punit, aunit->tile, TRUE)
1570
1584
              || WARMAP_SEACOST(aunit->tile) >= maxd)) {
1571
1585
        /* Maybe impossible or too far to sail */
1573
1587
      }
1574
1588
 
1575
1589
      vuln = unit_def_rating_sq(punit, aunit);
1576
 
      benefit = unit_build_shield_cost(unit_type(aunit));
 
1590
      benefit = unit_build_shield_cost(aunit);
1577
1591
 
1578
1592
      move_time = turns_to_enemy_unit(unit_type(punit), move_rate, 
1579
1593
                                      aunit->tile, unit_type(aunit));
1622
1636
 
1623
1637
  CHECK_UNIT(punit);
1624
1638
 
1625
 
  generate_warmap(tile_get_city(punit->tile), punit);
 
1639
  generate_warmap(tile_city(punit->tile), punit);
1626
1640
  players_iterate(aplayer) {
1627
1641
    if (pplayers_allied(pplayer,aplayer)) {
1628
1642
      city_list_iterate(aplayer->cities, pcity) {
1667
1681
  }
1668
1682
 
1669
1683
  if ((pc = dist_nearest_city(pplayer, punit->tile, any_continent, TRUE))) {
1670
 
    if (!is_ocean(tile_get_terrain(punit->tile))) {
 
1684
    if (can_unit_exist_at_tile(punit, punit->tile)) {
1671
1685
      UNIT_LOG(LOG_DEBUG, punit, "Barbarian heading to conquer %s",
1672
1686
               city_name(pc));
1673
1687
      (void) ai_gothere(pplayer, punit, pc->tile);
1949
1963
static void ai_manage_hitpoint_recovery(struct unit *punit)
1950
1964
{
1951
1965
  struct player *pplayer = unit_owner(punit);
1952
 
  struct city *pcity = tile_get_city(punit->tile);
 
1966
  struct city *pcity = tile_city(punit->tile);
1953
1967
  struct city *safe = NULL;
1954
1968
  struct unit_type *punittype = unit_type(punit);
1955
1969
 
2014
2028
  /* "Escorting" aircraft should not do anything. They are activated
2015
2029
   * by their transport or charge.  We do _NOT_ set them to 'done'
2016
2030
   * since they may need be activated once our charge moves. */
2017
 
  if (punit->ai.ai_role == AIUNIT_ESCORT && is_air_unit(punit)) {
 
2031
  if (punit->ai.ai_role == AIUNIT_ESCORT && utype_fuel(unit_type(punit))) {
2018
2032
    return;
2019
2033
  }
2020
2034
 
2111
2125
 
2112
2126
  /* If we are still alive, either sentry or fortify. */
2113
2127
  if ((punit = game_find_unit_by_number(id))) {
 
2128
    struct city *pcity = tile_city(punit->tile);
 
2129
 
2114
2130
    if (unit_list_find(punit->tile->units, punit->ai.ferryboat)) {
2115
 
      handle_unit_activity_request(punit, ACTIVITY_SENTRY);
2116
 
    } else if (punit->tile->city || punit->activity == ACTIVITY_IDLE) {
 
2131
      unit_activity_handling(punit, ACTIVITY_SENTRY);
 
2132
    } else if (pcity || punit->activity == ACTIVITY_IDLE) {
2117
2133
      /* We do not need to fortify in cities - we fortify and sentry
2118
2134
       * according to home defense setup, for easy debugging. */
2119
 
      if (!punit->tile->city || punit->ai.ai_role == AIUNIT_DEFEND_HOME) {
 
2135
      if (!pcity || punit->ai.ai_role == AIUNIT_DEFEND_HOME) {
2120
2136
        if (punit->activity == ACTIVITY_IDLE
2121
2137
            || punit->activity == ACTIVITY_SENTRY) {
2122
 
          handle_unit_activity_request(punit, ACTIVITY_FORTIFYING);
 
2138
          unit_activity_handling(punit, ACTIVITY_FORTIFYING);
2123
2139
        }
2124
2140
      } else {
2125
 
        handle_unit_activity_request(punit, ACTIVITY_SENTRY);
 
2141
        unit_activity_handling(punit, ACTIVITY_SENTRY);
2126
2142
      }
2127
2143
    }
2128
2144
  }
2129
2145
}
2130
2146
 
2131
2147
/**************************************************************************
2132
 
  Barbarian units may disband spontaneously if their age is more then 5,
2133
 
  they are not in cities, and they are far from any enemy units. It is to 
2134
 
  remove barbarians that do not engage into any activity for a long time.
 
2148
  Barbarian units may disband spontaneously if their age is more than
 
2149
  BARBARIAN_MIN_LIFESPAN, they are not in cities, and they are far from
 
2150
  any enemy units. It is to remove barbarians that do not engage into any
 
2151
  activity for a long time.
2135
2152
**************************************************************************/
2136
2153
static bool unit_can_be_retired(struct unit *punit)
2137
2154
{
2138
 
  if (punit->fuel > 0) {        /* fuel abused for barbarian life span */
2139
 
    punit->fuel--;
 
2155
  if (punit->birth_turn + BARBARIAN_MIN_LIFESPAN > game.info.turn) {
2140
2156
    return FALSE;
2141
2157
  }
2142
2158
 
2165
2181
void ai_manage_unit(struct player *pplayer, struct unit *punit)
2166
2182
{
2167
2183
  struct unit *bodyguard = aiguard_guard_of(punit);
 
2184
  bool is_ferry = FALSE;
2168
2185
 
2169
2186
  CHECK_UNIT(punit);
2170
2187
 
2199
2216
    return;
2200
2217
  }
2201
2218
 
 
2219
  if (get_transporter_capacity(punit) > 0) {
 
2220
    unit_class_iterate(pclass) {
 
2221
      /* FIXME: BOTH_MOVING units need ferry only if they use fuel */
 
2222
      if (can_unit_type_transport(unit_type(punit), pclass)
 
2223
          && (pclass->move_type == LAND_MOVING
 
2224
              || (pclass->move_type == BOTH_MOVING
 
2225
                  && !uclass_has_flag(pclass, UCF_MISSILE)))) {
 
2226
        is_ferry = TRUE;
 
2227
        break;
 
2228
      }
 
2229
    } unit_class_iterate_end;
 
2230
  }
 
2231
 
2202
2232
  if ((unit_has_type_flag(punit, F_DIPLOMAT))
2203
2233
      || (unit_has_type_flag(punit, F_SPY))) {
2204
2234
    TIMING_LOG(AIT_DIPLOMAT, TIMER_START);
2221
2251
  } else if (unit_has_type_flag(punit, F_PARATROOPERS)) {
2222
2252
    ai_manage_paratrooper(pplayer, punit);
2223
2253
    return;
2224
 
  } else if (get_transporter_capacity(punit) > 0
2225
 
             && !unit_has_type_flag(punit, F_MISSILE_CARRIER)
2226
 
             && punit->ai.ai_role != AIUNIT_HUNTER) {
 
2254
  } else if (is_ferry && punit->ai.ai_role != AIUNIT_HUNTER) {
2227
2255
    TIMING_LOG(AIT_FERRY, TIMER_START);
2228
2256
    ai_manage_ferryboat(pplayer, punit);
2229
2257
    TIMING_LOG(AIT_FERRY, TIMER_STOP);
2230
2258
    return;
2231
 
  } else if (is_air_unit(punit)
 
2259
  } else if (utype_fuel(unit_type(punit))
2232
2260
             && punit->ai.ai_role != AIUNIT_ESCORT) {
2233
2261
    TIMING_LOG(AIT_AIRUNIT, TIMER_START);
2234
2262
    ai_manage_airunit(pplayer, punit);
2235
2263
    TIMING_LOG(AIT_AIRUNIT, TIMER_STOP);
2236
2264
    return;
2237
 
  } else if (is_heli_unit(punit)) {
 
2265
  } else if (is_losing_hp(punit)) {
 
2266
    /* This unit is losing hitpoints over time */
 
2267
 
2238
2268
    /* TODO: We can try using air-unit code for helicopters, just
2239
2269
     * pretend they have fuel = HP / 3 or something. */
2240
2270
    punit->ai.done = TRUE; /* we did our best, which was ... nothing */
2276
2306
    /* The idea here is that we should never keep more than two
2277
2307
     * units in permanent defense. */
2278
2308
    int total_defense = 0;
2279
 
    int total_attack = pcity->ai.danger;
 
2309
    int total_attack = pcity->ai->danger;
2280
2310
    bool emergency = FALSE;
2281
2311
    int count = 0;
2282
2312
 
2304
2334
        }
2305
2335
        emergency = TRUE;
2306
2336
      } else {
2307
 
        int loglevel = pcity->debug ? LOG_NORMAL : LOG_DEBUG;
 
2337
        int loglevel = pcity->debug ? LOG_TEST : LOG_DEBUG;
2308
2338
 
2309
2339
        total_defense += best_want;
2310
2340
        UNIT_LOG(loglevel, best, "Defending city");
2377
2407
static void ai_manage_barbarian_leader(struct player *pplayer,
2378
2408
                                       struct unit *leader)
2379
2409
{
2380
 
  Continent_id con = tile_get_continent(leader->tile);
 
2410
  Continent_id con = tile_continent(leader->tile);
2381
2411
  int safest = 0;
2382
2412
  struct tile *safest_tile = leader->tile;
2383
2413
  struct unit *closest_unit = NULL;
2385
2415
 
2386
2416
  CHECK_UNIT(leader);
2387
2417
 
2388
 
  if (leader->moves_left == 0 || 
2389
 
      (!is_ocean(tile_get_terrain(leader->tile)) &&
2390
 
       unit_list_size(leader->tile->units) > 1) ) {
2391
 
      handle_unit_activity_request(leader, ACTIVITY_SENTRY);
 
2418
  if (leader->moves_left == 0
 
2419
      || (can_unit_survive_at_tile(leader, leader->tile)
 
2420
          && unit_list_size(leader->tile->units) > 1) ) {
 
2421
      unit_activity_handling(leader, ACTIVITY_SENTRY);
2392
2422
      return;
2393
2423
  }
2394
2424
 
2395
 
  if (leader->transported_by != -1) {
2396
 
    /* Leader is at boat */
2397
 
    struct unit *boat = game_find_unit_by_number(leader->transported_by);
2398
 
 
2399
 
    if (boat->ai.passenger == leader->id) {
2400
 
      /* We are in charge. Of course, since we are the leader...
2401
 
       * But maybe somebody more militaristic should lead our ship to battle! */
2402
 
 
2403
 
      /* First release boat from leaders lead */
2404
 
      aiferry_clear_boat(leader);
2405
 
 
2406
 
      unit_list_iterate(leader->tile->units, warrior) {
2407
 
        if (!unit_has_type_role(warrior, L_BARBARIAN_LEADER)
2408
 
            && get_transporter_capacity(warrior) == 0
2409
 
            && warrior->moves_left > 0) {
2410
 
          /* This seems like a good warrior to lead us in to conquest! */
2411
 
          ai_manage_unit(pplayer, warrior);
2412
 
 
2413
 
          /* If we reached our destination, ferryboat already called
2414
 
           * ai_manage_unit() for leader. So no need to continue here.
2415
 
           * Leader might even be dead.
2416
 
           * If this return is removed, surronding unit_list_iterate()
2417
 
           * has to be replaced with unit_list_iterate_safe()*/
2418
 
          return;
2419
 
        }
2420
 
      } unit_list_iterate_end;
2421
 
    }
2422
 
 
2423
 
    /* If we are not in charge of the boat, continue as if we
2424
 
     * were not in a boat - we may want to leave the ship now. */
 
2425
  if (is_boss_of_boat(leader)) {
 
2426
    /* We are in charge. Of course, since we are the leader...
 
2427
     * But maybe somebody more militaristic should lead our ship to battle! */
 
2428
  
 
2429
    /* First release boat from leaders lead */
 
2430
    aiferry_clear_boat(leader);
 
2431
  
 
2432
    unit_list_iterate(leader->tile->units, warrior) {
 
2433
      if (!unit_has_type_role(warrior, L_BARBARIAN_LEADER)
 
2434
          && get_transporter_capacity(warrior) == 0
 
2435
          && warrior->moves_left > 0) {
 
2436
        /* This seems like a good warrior to lead us in to conquest! */
 
2437
        ai_manage_unit(pplayer, warrior);
 
2438
 
 
2439
        /* If we reached our destination, ferryboat already called
 
2440
         * ai_manage_unit() for leader. So no need to continue here.
 
2441
         * Leader might even be dead.
 
2442
         * If this return is removed, surronding unit_list_iterate()
 
2443
         * has to be replaced with unit_list_iterate_safe()*/
 
2444
        return;
 
2445
      }
 
2446
    } unit_list_iterate_end;
2425
2447
  }
2426
2448
 
 
2449
  /* If we are not in charge of the boat, continue as if we
 
2450
   * were not in a boat - we may want to leave the ship now. */
 
2451
 
2427
2452
  /* the following takes much CPU time and could be avoided */
2428
 
  generate_warmap(tile_get_city(leader->tile), leader);
 
2453
  generate_warmap(tile_city(leader->tile), leader);
2429
2454
 
2430
2455
  /* duck under own units */
2431
2456
  unit_list_iterate(pplayer->units, aunit) {
2432
2457
    if (unit_has_type_role(aunit, L_BARBARIAN_LEADER)
2433
2458
        || !is_ground_unit(aunit)
2434
 
        || tile_get_continent(aunit->tile) != con)
 
2459
        || tile_continent(aunit->tile) != con)
2435
2460
      continue;
2436
2461
 
2437
2462
    if (WARMAP_COST(aunit->tile) < mindist) {
2442
2467
 
2443
2468
  if (closest_unit
2444
2469
      && !same_pos(closest_unit->tile, leader->tile)
2445
 
      && (tile_get_continent(leader->tile)
2446
 
          == tile_get_continent(closest_unit->tile))) {
 
2470
      && (tile_continent(leader->tile)
 
2471
          == tile_continent(closest_unit->tile))) {
2447
2472
    (void) ai_unit_goto(leader, closest_unit->tile);
2448
2473
    return; /* sticks better to own units with this -- jk */
2449
2474
  }
2456
2481
    unit_list_iterate(other_player->units, aunit) {
2457
2482
      if (is_military_unit(aunit)
2458
2483
          && is_ground_unit(aunit)
2459
 
          && tile_get_continent(aunit->tile) == con) {
 
2484
          && tile_continent(aunit->tile) == con) {
2460
2485
        /* questionable assumption: aunit needs as many moves to reach us as we
2461
2486
           need to reach it */
2462
2487
        dist = WARMAP_COST(aunit->tile) - unit_move_rate(aunit);
2474
2499
  } players_iterate_end;
2475
2500
 
2476
2501
  /* Disappearance - 33% chance on coast, when older than barbarian life span */
2477
 
  if (is_ocean_near_tile(leader->tile) && leader->fuel == 0) {
 
2502
  if (is_ocean_near_tile(leader->tile)
 
2503
      && leader->birth_turn + BARBARIAN_MIN_LIFESPAN < game.info.turn) {
2478
2504
    if(myrand(3) == 0) {
2479
2505
      UNIT_LOG(LOG_DEBUG, leader, "barbarian leader disappearing...");
2480
2506
      wipe_unit(leader);
2483
2509
  }
2484
2510
 
2485
2511
  if (!closest_unit) {
2486
 
    handle_unit_activity_request(leader, ACTIVITY_IDLE);
 
2512
    unit_activity_handling(leader, ACTIVITY_IDLE);
2487
2513
    UNIT_LOG(LOG_DEBUG, leader, "Barbarian leader: no enemy.");
2488
2514
    return;
2489
2515
  }
2490
2516
 
2491
 
  generate_warmap(tile_get_city(closest_unit->tile), closest_unit);
 
2517
  generate_warmap(tile_city(closest_unit->tile), closest_unit);
2492
2518
 
2493
2519
  do {
2494
2520
    struct tile *last_tile;
2513
2539
    if (same_pos(leader->tile, safest_tile)) {
2514
2540
      UNIT_LOG(LOG_DEBUG, leader, 
2515
2541
               "Barbarian leader: reached the safest position.");
2516
 
      handle_unit_activity_request(leader, ACTIVITY_IDLE);
 
2542
      unit_activity_handling(leader, ACTIVITY_IDLE);
2517
2543
      return;
2518
2544
    }
2519
2545
 
2544
2570
  int i = 0;
2545
2571
 
2546
2572
  unit_type_iterate(punittype) {
2547
 
    if (!utype_has_flag(punittype, F_NONMIL)
2548
 
        && !utype_has_flag(punittype, F_MISSILE)
 
2573
    if (A_NEVER != punittype->require_advance
 
2574
        && !utype_has_flag(punittype, F_CIVILIAN)
 
2575
        && !uclass_has_flag(utype_class(punittype), UCF_MISSILE)
2549
2576
        && !utype_has_flag(punittype, F_NO_LAND_ATTACK)
2550
 
        && punittype->move_type != AIR_MOVING
 
2577
        && !utype_fuel(punittype)
2551
2578
        && punittype->transport_capacity < 8) {
2552
2579
      simple_ai_types[i] = punittype;
2553
2580
      i++;
2556
2583
 
2557
2584
  simple_ai_types[i] = NULL;
2558
2585
}
 
2586
 
 
2587
/****************************************************************************
 
2588
  Build cached values about unit classes for AI
 
2589
****************************************************************************/
 
2590
void unit_class_ai_init(void)
 
2591
{
 
2592
  bv_special special;
 
2593
  bv_bases bases;
 
2594
 
 
2595
  BV_CLR_ALL(special); /* Can it move even without road */
 
2596
  BV_CLR_ALL(bases);
 
2597
 
 
2598
  unit_class_iterate(pclass) {
 
2599
    bool move_land_enabled  = FALSE; /* Can move at some land terrains */
 
2600
    bool move_land_disabled = FALSE; /* Cannot move at some land terrains */
 
2601
    bool move_sea_enabled   = FALSE; /* Can move at some ocean terrains */
 
2602
    bool move_sea_disabled  = FALSE; /* Cannot move at some ocean terrains */
 
2603
 
 
2604
    terrain_type_iterate(pterrain) {
 
2605
      if (is_native_to_class(pclass, pterrain, special, bases)) {
 
2606
        /* Can move at terrain */
 
2607
        if (is_ocean(pterrain)) {
 
2608
          move_sea_enabled = TRUE;
 
2609
        } else {
 
2610
          move_land_enabled = TRUE;
 
2611
        }
 
2612
      } else {
 
2613
        /* Cannot move at terrain */
 
2614
        if (is_ocean(pterrain)) {
 
2615
          move_sea_disabled = TRUE;
 
2616
        } else {
 
2617
          move_land_disabled = TRUE;
 
2618
        }
 
2619
      }
 
2620
    } terrain_type_iterate_end;
 
2621
 
 
2622
    if (move_land_enabled && !move_land_disabled) {
 
2623
      pclass->ai.land_move = MOVE_FULL;
 
2624
    } else if (move_land_enabled && move_land_disabled) {
 
2625
      pclass->ai.land_move = MOVE_PARTIAL;
 
2626
    } else {
 
2627
      assert(!move_land_enabled);
 
2628
      pclass->ai.land_move = MOVE_NONE;
 
2629
    }
 
2630
 
 
2631
    if (move_sea_enabled && !move_sea_disabled) {
 
2632
      pclass->ai.sea_move = MOVE_FULL;
 
2633
    } else if (move_sea_enabled && move_sea_disabled) {
 
2634
      pclass->ai.sea_move = MOVE_PARTIAL;
 
2635
    } else {
 
2636
      assert(!move_sea_enabled);
 
2637
      pclass->ai.sea_move = MOVE_NONE;
 
2638
    }
 
2639
 
 
2640
  } unit_class_iterate_end;
 
2641
}