115
112
transported = NULL;
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;
122
119
} city_list_iterate_end;
123
120
if (!most_needed) {
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;
130
127
} city_list_iterate_end;
136
133
unit_list_iterate(pplayer->units, punit) {
137
134
struct tile *ptile = (punit->tile);
135
struct city *pcity = tile_city(ptile);
139
if (ptile->city && ptile->city->ai.urgency == 0
140
&& ptile->city->ai.danger - DEFENCE_POWER(punit) < comparison
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;
149
148
} unit_list_iterate_end;
266
265
int move_rate = unit_move_rate(punit);
266
struct unit_class *pclass = unit_class(punit);
268
switch (unit_type(punit)->move_type) {
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 */
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;
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 */
279
move_time = WARMAP_COST(ptile) / move_rate;
283
move_time = WARMAP_SEACOST(ptile) / move_rate;
288
move_time = real_map_distance(punit->tile, ptile)
289
* SINGLE_MOVE / move_rate;
293
die("ai/aiunit.c:unit_move_turns: illegal move type %d",
294
unit_type(punit)->move_type);
280
if (uclass_move_type(pclass) == SEA_MOVING) {
281
move_time = WARMAP_SEACOST(ptile) / move_rate;
283
move_time = WARMAP_COST(ptile) / move_rate;
297
286
return move_time;
619
608
* enemy units because we are looking for trouble!
620
609
* Hence no call ai_avoid_risks()
623
tgt_map = pf_create_map(¶meter);
624
while (pf_next(tgt_map)) {
625
struct pf_position pos;
612
tgt_map = pf_map_new(¶meter);
613
pf_map_iterate_move_costs(tgt_map, iter_tile, move_cost, FALSE) {
627
615
bool move_needed;
630
pf_next_get_position(tgt_map, &pos);
632
if (pos.total_MC > punit->moves_left) {
618
if (move_cost > punit->moves_left) {
633
619
/* This is too far */
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 */
643
want = ai_rampage_want(punit, pos.tile);
629
want = ai_rampage_want(punit, iter_tile);
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)
648
634
/* Select the relevant threshold */
649
635
thresh = (move_needed ? thresh_move : thresh_adj);
888
874
} unit_list_iterate_end;
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);
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) {
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
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! */
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));
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! */
981
970
ai_unit_new_role(punit, AIUNIT_NONE, NULL); /* Nope! */
1078
1067
int speed, bool go_by_boat,
1079
1068
struct unit *boat, const struct unit_type *boattype)
1081
switch (our_type->move_type) {
1084
int boatspeed = boattype->move_rate;
1085
int move_time = (WARMAP_SEACOST(acity->tile)) / boatspeed;
1087
if (utype_has_flag(boattype, F_TRIREME) && move_time > 2) {
1088
/* FIXME: Should also check for LIGHTHOUSE */
1089
/* Return something prohibitive */
1093
/* Time to get to the boat */
1094
move_time += (WARMAP_COST(boat->tile) + speed - 1) / speed;
1097
if (!utype_has_flag(our_type, F_MARINES)) {
1098
/* Time to get off the boat (Marines do it from the vessel) */
1104
/* We are walking */
1105
return (WARMAP_COST(acity->tile) + speed - 1) / speed;
1070
struct unit_class *pclass = utype_class(our_type);
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;
1076
if (utype_has_flag(boattype, F_TRIREME) && move_time > 2) {
1077
/* Return something prohibitive */
1081
/* Time to get to the boat */
1082
move_time += (WARMAP_COST(boat->tile) + speed - 1) / speed;
1085
if (!utype_has_flag(our_type, F_MARINES)) {
1086
/* Time to get off the boat (Marines do it from the vessel) */
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;
1111
freelog(LOG_ERROR, "ERROR: Unsupported move_type in time_to_enemy_city");
1112
/* Return something prohibitive */
1099
return (WARMAP_COST(acity->tile) + speed - 1) / speed;
1118
1102
/************************************************************************
1125
1109
int speed, struct tile *ptile,
1126
1110
const struct unit_type *enemy_type)
1112
struct unit_class *pclass = utype_class(our_type);
1130
switch (our_type->move_type) {
1115
if (pclass->ai.land_move != MOVE_NONE) {
1132
1116
dist = WARMAP_COST(ptile);
1135
1118
dist = WARMAP_SEACOST(ptile);
1138
/* Compiler warning */
1140
freelog(LOG_ERROR, "ERROR: Unsupported unit_type in time_to_enemy_city");
1141
/* Return something prohibitive */
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).
1166
1141
If dest == TRUE then a valid goto is presumed.
1167
1142
**************************************************************************/
1183
1158
square_iterate(ptile, radius, tile1) {
1184
struct city *pcity = tile_get_city(tile1);
1159
struct city *pcity = tile_city(tile1);
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;
1166
if (unit_has_type_flag(punit, F_ONEATTACK)) {
1169
attacks = unit_type(punit)->move_rate;
1171
pcity->ai->invasion.attack += attacks;
1172
if (which == INVASION_OCCUPY) {
1173
pcity->ai->invasion.occupy++;
1192
1176
} square_iterate_end;
1238
1221
* never learning steam engine, even though ironclads would be very
1239
1222
* useful. -- Syela */
1224
struct unit_class *pclass = unit_class(punit);
1242
1226
/*** Very preliminary checks */
1243
1227
*dest_tile = punit->tile;
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
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);
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);
1309
invasion_funct(aunit, FALSE, 2, 1);
1295
invasion_funct(aunit, FALSE, 2, INVASION_OCCUPY);
1311
1297
} unit_list_iterate_end;
1312
1298
/* end horrible initialization subroutine */
1333
1319
maxd = MIN(6, move_rate) * THRESHOLD + 1;
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));
1338
1324
/* most flexible but costs milliseconds */
1339
generate_warmap(tile_get_city(*dest_tile), punit);
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);
1327
if (pclass->ai.sea_move == MOVE_NONE) {
1328
/* We need boat to move over sea */
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);
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 */
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
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);
1351
1353
boattype = best_role_unit_for_player(pplayer, L_FERRYBOAT);
1352
1354
if (boattype == NULL) {
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));
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. */
1422
1426
if (v > vuln) {
1423
1427
/* They can build a better defender! */
1425
benefit = unit_build_shield_cost(def_type);
1429
benefit = utype_build_shield_cost(def_type);
1430
if (COULD_OCCUPY(punit) || TEST_BIT(acity->ai.invasion, 0)) {
1431
/* There are units able to occupy the city! */
1434
reserves = acity->ai->invasion.attack -
1435
unit_list_size(acity->tile->units);
1437
if (reserves >= 0) {
1438
/* We have enough units to kill all the units in the city */
1440
&& (COULD_OCCUPY(punit) || acity->ai->invasion.occupy > 0)) {
1441
/* There are units able to occupy the city after all defenders
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 */
1439
1451
/* AI was not sending enough reinforcements to totally wipe out a city
1449
1461
} else if (move_time > THRESHOLD) {
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;
1456
int a_squared = acity->ai.attack * acity->ai.attack;
1470
int a_squared = acity->ai->attack * acity->ai->attack;
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
1463
1477
/* FIXME: The problem with ai.bcost is that bigger it is, less is
1495
1509
/* END STEAM-ENGINES KLUGE */
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),
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 */
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 */
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 */
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);
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);
2125
handle_unit_activity_request(punit, ACTIVITY_SENTRY);
2141
unit_activity_handling(punit, ACTIVITY_SENTRY);
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)
2138
if (punit->fuel > 0) { /* fuel abused for barbarian life span */
2155
if (punit->birth_turn + BARBARIAN_MIN_LIFESPAN > game.info.turn) {
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)))) {
2229
} unit_class_iterate_end;
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);
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);
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);
2237
} else if (is_heli_unit(punit)) {
2265
} else if (is_losing_hp(punit)) {
2266
/* This unit is losing hitpoints over time */
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 */
2386
2416
CHECK_UNIT(leader);
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);
2395
if (leader->transported_by != -1) {
2396
/* Leader is at boat */
2397
struct unit *boat = game_find_unit_by_number(leader->transported_by);
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! */
2403
/* First release boat from leaders lead */
2404
aiferry_clear_boat(leader);
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);
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()*/
2420
} unit_list_iterate_end;
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! */
2429
/* First release boat from leaders lead */
2430
aiferry_clear_boat(leader);
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);
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()*/
2446
} unit_list_iterate_end;
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. */
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);
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)
2437
2462
if (WARMAP_COST(aunit->tile) < mindist) {
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;
2557
2584
simple_ai_types[i] = NULL;
2587
/****************************************************************************
2588
Build cached values about unit classes for AI
2589
****************************************************************************/
2590
void unit_class_ai_init(void)
2595
BV_CLR_ALL(special); /* Can it move even without road */
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 */
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;
2610
move_land_enabled = TRUE;
2613
/* Cannot move at terrain */
2614
if (is_ocean(pterrain)) {
2615
move_sea_disabled = TRUE;
2617
move_land_disabled = TRUE;
2620
} terrain_type_iterate_end;
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;
2627
assert(!move_land_enabled);
2628
pclass->ai.land_move = MOVE_NONE;
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;
2636
assert(!move_sea_enabled);
2637
pclass->ai.sea_move = MOVE_NONE;
2640
} unit_class_iterate_end;