"same than" -> "same as".
[freeciv.git] / server / unittools.c
blob5306ff396b6abd6351c5374461e8dd4cb7502286
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 <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
22 /* utility */
23 #include "bitvector.h"
24 #include "fcintl.h"
25 #include "log.h"
26 #include "mem.h"
27 #include "rand.h"
28 #include "shared.h"
29 #include "support.h"
31 /* common */
32 #include "base.h"
33 #include "city.h"
34 #include "combat.h"
35 #include "events.h"
36 #include "game.h"
37 #include "government.h"
38 #include "idex.h"
39 #include "map.h"
40 #include "movement.h"
41 #include "packets.h"
42 #include "player.h"
43 #include "research.h"
44 #include "terrain.h"
45 #include "unit.h"
46 #include "unitlist.h"
47 #include "unittype.h"
49 /* common/scriptcore */
50 #include "luascript_signal.h"
51 #include "luascript_types.h"
53 /* aicore */
54 #include "path_finding.h"
55 #include "pf_tools.h"
57 /* server/scripting */
58 #include "script_server.h"
60 /* server */
61 #include "actiontools.h"
62 #include "aiiface.h"
63 #include "barbarian.h"
64 #include "citytools.h"
65 #include "cityturn.h"
66 #include "diplhand.h"
67 #include "gamehand.h"
68 #include "maphand.h"
69 #include "notify.h"
70 #include "plrhand.h"
71 #include "sanitycheck.h"
72 #include "sernet.h"
73 #include "srv_main.h"
74 #include "techtools.h"
75 #include "unithand.h"
77 /* server/advisors */
78 #include "advgoto.h"
79 #include "autoexplorer.h"
80 #include "autosettlers.h"
82 /* ai */
83 #include "handicaps.h"
85 #include "unittools.h"
88 /* Tools for controlling the client vision of every unit when a unit
89 * moves + script effects. See unit_move(). You can access this data with
90 * punit->server.moving; it may be NULL if the unit is not moving). */
91 struct unit_move_data {
92 int ref_count;
93 struct unit *punit; /* NULL for invalidating. */
94 struct player *powner;
95 bv_player can_see_unit;
96 bv_player can_see_move;
97 struct vision *old_vision;
100 #define SPECLIST_TAG unit_move_data
101 #include "speclist.h"
102 #define unit_move_data_list_iterate(_plist, _pdata) \
103 TYPED_LIST_ITERATE(struct unit_move_data, _plist, _pdata)
104 #define unit_move_data_list_iterate_end LIST_ITERATE_END
105 #define unit_move_data_list_iterate_rev(_plist, _pdata) \
106 TYPED_LIST_ITERATE_REV(struct unit_move_data, _plist, _pdata)
107 #define unit_move_data_list_iterate_rev_end LIST_ITERATE_REV_END
109 /* This data structure lets the auto attack code cache each potential
110 * attacker unit's probability of success against the target unit during
111 * the checks if the unit can do autoattack. It is then reused when the
112 * list of potential attackers is sorted by probability of success. */
113 struct autoattack_prob {
114 int unit_id;
115 struct act_prob prob;
118 #define SPECLIST_TAG autoattack_prob
119 #define SPECLIST_TYPE struct autoattack_prob
120 #include "speclist.h"
122 #define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, \
123 _unit_) \
124 TYPED_LIST_ITERATE(struct autoattack_prob, autoattack_prob_list, _aap_) \
125 struct unit *_unit_ = game_unit_by_number(_aap_->unit_id); \
127 if (_unit_ == NULL) { \
128 continue; \
131 #define autoattack_prob_list_iterate_safe_end LIST_ITERATE_END
133 static void unit_restore_hitpoints(struct unit *punit);
134 static void unit_restore_movepoints(struct player *pplayer, struct unit *punit);
135 static void update_unit_activity(struct unit *punit);
136 static bool try_to_save_unit(struct unit *punit, struct unit_type *pttype,
137 bool helpless, bool teleporting);
138 static void wakeup_neighbor_sentries(struct unit *punit);
139 static void do_upgrade_effects(struct player *pplayer);
141 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
142 static int hp_gain_coord(struct unit *punit);
144 static bool maybe_become_veteran_real(struct unit *punit, bool settler);
146 static void unit_transport_load_tp_status(struct unit *punit,
147 struct unit *ptrans,
148 bool force);
150 static void wipe_unit_full(struct unit *punit, bool transported,
151 enum unit_loss_reason reason,
152 struct player *killer);
154 /**************************************************************************
155 Returns a unit type that matches the role_tech or role roles.
157 If role_tech is given, then we look at all units with this role
158 whose requirements are met by any player, and return a random one. This
159 can be used to give a unit to barbarians taken from the set of most
160 advanced units researched by the 'real' players.
162 If role_tech is not give (-1) or if there are no matching unit types,
163 then we look at 'role' value and return a random matching unit type.
165 It is an error if there are no available units. This function will
166 always return a valid unit.
167 **************************************************************************/
168 struct unit_type *find_a_unit_type(enum unit_role_id role,
169 enum unit_role_id role_tech)
171 struct unit_type *which[U_LAST];
172 int i, num = 0;
174 if (role_tech != -1) {
175 for (i = 0; i < num_role_units(role_tech); i++) {
176 struct unit_type *iunit = get_role_unit(role_tech, i);
177 const int minplayers = 2;
178 int players = 0;
180 /* Note, if there's only one player in the game this check will always
181 * fail. */
182 players_iterate(pplayer) {
183 if (!is_barbarian(pplayer)
184 && can_player_build_unit_direct(pplayer, iunit)) {
185 players++;
187 } players_iterate_end;
188 if (players > minplayers) {
189 which[num++] = iunit;
193 if (num == 0) {
194 for (i = 0; i < num_role_units(role); i++) {
195 which[num++] = get_role_unit(role, i);
199 /* Ruleset code should ensure there is at least one unit for each
200 * possibly-required role, or check before calling this function. */
201 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
202 role, role_tech);
204 return which[fc_rand(num)];
207 /*****************************************************************************
208 Unit has a chance to become veteran. This should not be used for settlers
209 for the work they do.
210 *****************************************************************************/
211 bool maybe_make_veteran(struct unit *punit)
213 return maybe_become_veteran_real(punit, FALSE);
216 /*****************************************************************************
217 After a battle, after diplomatic aggression and after surviving trireme
218 loss chance, this routine is called to decide whether or not the unit
219 should become more experienced.
221 There is a specified chance for it to happen, (+50% if player got SUNTZU)
222 the chances are specified in the units.ruleset file.
224 If 'settler' is TRUE the veteran level is increased due to work done by
225 the unit.
226 *****************************************************************************/
227 static bool maybe_become_veteran_real(struct unit *punit, bool settler)
229 const struct veteran_system *vsystem;
230 const struct veteran_level *vlevel;
231 int chance;
233 fc_assert_ret_val(punit != NULL, FALSE);
235 vsystem = utype_veteran_system(unit_type_get(punit));
236 fc_assert_ret_val(vsystem != NULL, FALSE);
237 fc_assert_ret_val(vsystem->levels > punit->veteran, FALSE);
239 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
240 fc_assert_ret_val(vlevel != NULL, FALSE);
242 if (punit->veteran + 1 >= vsystem->levels
243 || unit_has_type_flag(punit, UTYF_NO_VETERAN)) {
244 return FALSE;
245 } else if (!settler) {
246 int mod = 100 + get_unit_bonus(punit, EFT_VETERAN_COMBAT);
248 /* The modification is tacked on as a multiplier to the base chance.
249 * For example with a base chance of 50% for green units and a modifier
250 * of +50% the end chance is 75%. */
251 chance = vlevel->raise_chance * mod / 100;
252 } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
253 chance = vlevel->work_raise_chance;
254 } else {
255 /* No battle and no work done. */
256 return FALSE;
259 if (fc_rand(100) < chance) {
260 punit->veteran++;
261 return TRUE;
264 return FALSE;
267 /**************************************************************************
268 This is the basic unit versus unit combat routine.
269 1) ALOT of modifiers bonuses etc is added to the 2 units rates.
270 2) the combat loop, which continues until one of the units are dead
271 3) the aftermath, the loser (and potentially the stack which is below it)
272 is wiped, and the winner gets a chance of gaining veteran status
273 **************************************************************************/
274 void unit_versus_unit(struct unit *attacker, struct unit *defender,
275 int *att_hp, int *def_hp)
277 int attackpower = get_total_attack_power(attacker, defender);
278 int defensepower = get_total_defense_power(attacker, defender);
279 int attack_firepower, defense_firepower;
280 struct player *plr1 = unit_owner(attacker);
281 struct player *plr2 = unit_owner(defender);
283 *att_hp = attacker->hp;
284 *def_hp = defender->hp;
285 get_modified_firepower(attacker, defender,
286 &attack_firepower, &defense_firepower);
288 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
289 "defense firepower:%d", attackpower, defensepower,
290 attack_firepower, defense_firepower);
292 plr1->last_war_action = game.info.turn;
293 plr2->last_war_action = game.info.turn;
295 if (attackpower == 0) {
296 *att_hp = 0;
297 } else if (defensepower == 0) {
298 *def_hp = 0;
300 while (*att_hp > 0 && *def_hp > 0) {
301 if (fc_rand(attackpower + defensepower) >= defensepower) {
302 *def_hp -= attack_firepower;
303 } else {
304 *att_hp -= defense_firepower;
307 if (*att_hp < 0) {
308 *att_hp = 0;
310 if (*def_hp < 0) {
311 *def_hp = 0;
315 /**************************************************************************
316 This is the basic unit versus unit classic bombardment routine.
317 1) ALOT of modifiers bonuses etc is added to the 2 units rates.
318 2) Do rate attacks and don't kill the defender, then return.
319 **************************************************************************/
320 void unit_bombs_unit(struct unit *attacker, struct unit *defender,
321 int *att_hp, int *def_hp)
323 int i;
324 int rate = unit_type_get(attacker)->bombard_rate;
326 int attackpower = get_total_attack_power(attacker, defender);
327 int defensepower = get_total_defense_power(attacker, defender);
328 int attack_firepower, defense_firepower;
329 struct player *plr1 = unit_owner(attacker);
330 struct player *plr2 = unit_owner(defender);
332 *att_hp = attacker->hp;
333 *def_hp = defender->hp;
334 get_modified_firepower(attacker, defender,
335 &attack_firepower, &defense_firepower);
337 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
338 "defense firepower:%d", attackpower, defensepower,
339 attack_firepower, defense_firepower);
341 plr1->last_war_action = game.info.turn;
342 plr2->last_war_action = game.info.turn;
344 for (i = 0; i < rate; i++) {
345 if (fc_rand(attackpower + defensepower) >= defensepower) {
346 *def_hp -= attack_firepower;
350 /* Don't kill the target. */
351 if (*def_hp <= 0) {
352 *def_hp = 1;
356 /***************************************************************************
357 Make maybe make either side of combat veteran
358 ****************************************************************************/
359 void combat_veterans(struct unit *attacker, struct unit *defender)
361 if (attacker->hp > 0) {
362 maybe_make_veteran(attacker);
363 } else if (defender->hp > 0) {
364 maybe_make_veteran(defender);
368 /***************************************************************************
369 Do unit auto-upgrades to players with the EFT_UNIT_UPGRADE effect
370 (traditionally from Leonardo's Workshop).
371 ****************************************************************************/
372 static void do_upgrade_effects(struct player *pplayer)
374 int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT);
375 struct unit_list *candidates;
377 if (upgrades <= 0) {
378 return;
380 candidates = unit_list_new();
382 unit_list_iterate(pplayer->units, punit) {
383 /* We have to be careful not to strand units at sea, for example by
384 * upgrading a frigate to an ironclad while it was carrying a unit. */
385 if (UU_OK == unit_upgrade_test(punit, TRUE)) {
386 unit_list_prepend(candidates, punit); /* Potential candidate :) */
388 } unit_list_iterate_end;
390 while (upgrades > 0 && unit_list_size(candidates) > 0) {
391 /* Upgrade one unit. The unit is chosen at random from the list of
392 * available candidates. */
393 int candidate_to_upgrade = fc_rand(unit_list_size(candidates));
394 struct unit *punit = unit_list_get(candidates, candidate_to_upgrade);
395 struct unit_type *type_from = unit_type_get(punit);
396 struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
398 transform_unit(punit, type_to, TRUE);
399 notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
400 _("%s was upgraded for free to %s."),
401 utype_name_translation(type_from),
402 unit_link(punit));
403 unit_list_remove(candidates, punit);
404 upgrades--;
407 unit_list_destroy(candidates);
410 /***************************************************************************
411 1. Do Leonardo's Workshop upgrade if applicable.
413 2. Restore/decrease unit hitpoints.
415 3. Kill dead units.
417 4. Rescue airplanes by returning them to base automatically.
419 5. Decrease fuel of planes in the air.
421 6. Refuel planes that are in bases.
423 7. Kill planes that are out of fuel.
424 ****************************************************************************/
425 void player_restore_units(struct player *pplayer)
427 /* 1) get Leonardo out of the way first: */
428 do_upgrade_effects(pplayer);
430 unit_list_iterate_safe(pplayer->units, punit) {
432 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
433 unit_restore_hitpoints(punit);
435 /* 3) Check that unit has hitpoints */
436 if (punit->hp <= 0) {
437 /* This should usually only happen for heli units, but if any other
438 * units get 0 hp somehow, catch them too. --dwp */
439 /* if 'game.server.killunhomed' is activated unhomed units are slowly
440 * killed; notify player here */
441 if (!punit->homecity && 0 < game.server.killunhomed) {
442 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
443 ftc_server, _("Your %s has run out of hit points "
444 "because it was not supported by a city."),
445 unit_tile_link(punit));
446 } else {
447 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
448 _("Your %s has run out of hit points."),
449 unit_tile_link(punit));
452 wipe_unit(punit, ULR_HP_LOSS, NULL);
453 continue; /* Continue iterating... */
456 /* 4) Rescue planes if needed */
457 if (utype_fuel(unit_type_get(punit))) {
458 /* Shall we emergency return home on the last vapors? */
460 /* I think this is strongly against the spirit of client goto.
461 * The problem is (again) that here we know too much. -- Zamar */
463 if (punit->fuel <= 1
464 && !is_unit_being_refueled(punit)) {
465 struct unit *carrier;
467 carrier = transporter_for_unit(punit);
468 if (carrier) {
469 unit_transport_load_tp_status(punit, carrier, FALSE);
470 } else {
471 bool alive = true;
473 struct pf_map *pfm;
474 struct pf_parameter parameter;
476 pft_fill_unit_parameter(&parameter, punit);
477 parameter.omniscience = !has_handicap(pplayer, H_MAP);
478 pfm = pf_map_new(&parameter);
480 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
481 if (move_cost > punit->moves_left) {
482 /* Too far */
483 break;
486 if (is_airunit_refuel_point(ptile, pplayer, punit)) {
487 struct pf_path *path;
488 int id = punit->id;
490 /* Client orders may be running for this unit - if so
491 * we free them before engaging goto. */
492 free_unit_orders(punit);
494 path = pf_map_path(pfm, ptile);
496 alive = adv_follow_path(punit, path, ptile);
498 if (!alive) {
499 log_error("rescue plane: unit %d died enroute!", id);
500 } else if (!same_pos(unit_tile(punit), ptile)) {
501 /* Enemy units probably blocked our route
502 * FIXME: We should try find alternative route around
503 * the enemy unit instead of just giving up and crashing. */
504 log_debug("rescue plane: unit %d could not move to "
505 "refuel point!", punit->id);
508 if (alive) {
509 /* Clear activity. Unit info will be sent in the end of
510 * the function. */
511 unit_activity_handling(punit, ACTIVITY_IDLE);
512 adv_unit_new_task(punit, AUT_NONE, NULL);
513 punit->goto_tile = NULL;
515 if (!is_unit_being_refueled(punit)) {
516 carrier = transporter_for_unit(punit);
517 if (carrier) {
518 unit_transport_load_tp_status(punit, carrier, FALSE);
522 notify_player(pplayer, unit_tile(punit),
523 E_UNIT_ORDERS, ftc_server,
524 _("Your %s has returned to refuel."),
525 unit_link(punit));
527 pf_path_destroy(path);
528 break;
530 } pf_map_move_costs_iterate_end;
531 pf_map_destroy(pfm);
533 if (!alive) {
534 /* Unit died trying to move to refuel point. */
535 return;
540 /* 5) Update fuel */
541 punit->fuel--;
543 /* 6) Automatically refuel air units in cities, airbases, and
544 * transporters (carriers). */
545 if (is_unit_being_refueled(punit)) {
546 punit->fuel = utype_fuel(unit_type_get(punit));
549 } unit_list_iterate_safe_end;
551 /* 7) Check if there are air units without fuel */
552 unit_list_iterate_safe(pplayer->units, punit) {
553 if (punit->fuel <= 0 && utype_fuel(unit_type_get(punit))) {
554 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
555 _("Your %s has run out of fuel."),
556 unit_tile_link(punit));
557 wipe_unit(punit, ULR_FUEL, NULL);
559 } unit_list_iterate_safe_end;
561 /* Send all updates. */
562 unit_list_iterate(pplayer->units, punit) {
563 send_unit_info(NULL, punit);
564 } unit_list_iterate_end;
567 /****************************************************************************
568 add hitpoints to the unit, hp_gain_coord returns the amount to add
569 united nations will speed up the process by 2 hp's / turn, means helicopters
570 will actually not lose hp's every turn if player have that wonder.
571 Units which have moved don't gain hp, except the United Nations and
572 helicopter effects still occur.
574 If 'game.server.killunhomed' is greater than 0, unhomed units lose
575 'game.server.killunhomed' hitpoints each turn, killing the unit at the end.
576 *****************************************************************************/
577 static void unit_restore_hitpoints(struct unit *punit)
579 bool was_lower;
580 int save_hp;
581 struct unit_class *pclass = unit_class_get(punit);
582 struct city *pcity = tile_city(unit_tile(punit));
584 was_lower = (punit->hp < unit_type_get(punit)->hp);
585 save_hp = punit->hp;
587 if (!punit->moved) {
588 punit->hp += hp_gain_coord(punit);
591 /* Bonus recovery HP (traditionally from the United Nations) */
592 punit->hp += get_unit_bonus(punit, EFT_UNIT_RECOVER);
594 if (!punit->homecity && 0 < game.server.killunhomed
595 && !unit_has_type_flag(punit, UTYF_GAMELOSS)) {
596 /* Hit point loss of units without homecity; at least 1 hp! */
597 /* Gameloss units are immune to this effect. */
598 int hp_loss = MAX(unit_type_get(punit)->hp * game.server.killunhomed / 100,
600 punit->hp = MIN(punit->hp - hp_loss, save_hp - 1);
603 if (!pcity && !tile_has_native_base(unit_tile(punit), unit_type_get(punit))
604 && !unit_transported(punit)) {
605 punit->hp -= unit_type_get(punit)->hp * pclass->hp_loss_pct / 100;
608 if (punit->hp >= unit_type_get(punit)->hp) {
609 punit->hp = unit_type_get(punit)->hp;
610 if (was_lower && punit->activity == ACTIVITY_SENTRY) {
611 set_unit_activity(punit, ACTIVITY_IDLE);
615 if (punit->hp < 0) {
616 punit->hp = 0;
619 punit->moved = FALSE;
620 punit->paradropped = FALSE;
623 /***************************************************************************
624 Move points are trivial, only modifiers to the base value is if it's
625 sea units and the player has certain wonders/techs. Then add veteran
626 bonus, if any.
627 ***************************************************************************/
628 static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
630 punit->moves_left = unit_move_rate(punit);
631 punit->done_moving = FALSE;
634 /****************************************************************************
635 Iterate through all units and update them.
636 ****************************************************************************/
637 void update_unit_activities(struct player *pplayer)
639 unit_list_iterate_safe(pplayer->units, punit) {
640 update_unit_activity(punit);
641 } unit_list_iterate_safe_end;
644 /****************************************************************************
645 Iterate through all units and execute their orders.
646 ****************************************************************************/
647 void execute_unit_orders(struct player *pplayer)
649 unit_list_iterate_safe(pplayer->units, punit) {
650 if (unit_has_orders(punit)) {
651 execute_orders(punit, FALSE);
653 } unit_list_iterate_safe_end;
656 /****************************************************************************
657 Iterate through all units and remember their current activities.
658 ****************************************************************************/
659 void finalize_unit_phase_beginning(struct player *pplayer)
661 /* Remember activities only after all knock-on effects of unit activities
662 * on other units have been resolved */
663 unit_list_iterate(pplayer->units, punit) {
664 punit->changed_from = punit->activity;
665 punit->changed_from_target = punit->activity_target;
666 punit->changed_from_count = punit->activity_count;
667 send_unit_info(NULL, punit);
668 } unit_list_iterate_end;
671 /**************************************************************************
672 returns how many hp's a unit will gain on this square
673 depends on whether or not it's inside city or fortress.
674 barracks will regen landunits completely
675 airports will regen airunits completely
676 ports will regen navalunits completely
677 fortify will add a little extra.
678 ***************************************************************************/
679 static int hp_gain_coord(struct unit *punit)
681 int hp = 0;
682 const int base = unit_type_get(punit)->hp;
684 /* Includes barracks (100%), fortress (25%), etc. */
685 hp += base * get_unit_bonus(punit, EFT_HP_REGEN) / 100;
687 if (tile_city(unit_tile(punit))) {
688 hp = MAX(hp, base / 3);
691 if (!unit_class_get(punit)->hp_loss_pct) {
692 hp += (base + 9) / 10;
695 if (punit->activity == ACTIVITY_FORTIFIED) {
696 hp += (base + 9) / 10;
699 return MAX(hp, 0);
702 /**************************************************************************
703 Calculate the total amount of activity performed by all units on a tile
704 for a given task and target.
705 **************************************************************************/
706 static int total_activity(struct tile *ptile, enum unit_activity act,
707 struct extra_type *tgt)
709 int total = 0;
710 bool tgt_matters = activity_requires_target(act);
712 unit_list_iterate (ptile->units, punit) {
713 if (punit->activity == act
714 && (!tgt_matters || punit->activity_target == tgt)) {
715 total += punit->activity_count;
717 } unit_list_iterate_end;
719 return total;
722 /**************************************************************************
723 Check the total amount of activity performed by all units on a tile
724 for a given task.
725 **************************************************************************/
726 static bool total_activity_done(struct tile *ptile, enum unit_activity act,
727 struct extra_type *tgt)
729 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
732 /**************************************************************************
733 Common notification for all experience levels.
734 **************************************************************************/
735 void notify_unit_experience(struct unit *punit)
737 const struct veteran_system *vsystem;
738 const struct veteran_level *vlevel;
740 if (!punit) {
741 return;
744 vsystem = utype_veteran_system(unit_type_get(punit));
745 fc_assert_ret(vsystem != NULL);
746 fc_assert_ret(vsystem->levels > punit->veteran);
748 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
749 fc_assert_ret(vlevel != NULL);
751 notify_player(unit_owner(punit), unit_tile(punit),
752 E_UNIT_BECAME_VET, ftc_server,
753 /* TRANS: Your <unit> became ... rank of <veteran level>. */
754 _("Your %s became more experienced and achieved the rank "
755 "of %s."),
756 unit_link(punit), name_translation_get(&vlevel->name));
759 /**************************************************************************
760 Convert a single unit to another type.
761 **************************************************************************/
762 static void unit_convert(struct unit *punit)
764 struct unit_type *to_type, *from_type;
766 from_type = unit_type_get(punit);
767 to_type = from_type->converted_to;
769 if (unit_can_convert(punit)) {
770 transform_unit(punit, to_type, TRUE);
771 notify_player(unit_owner(punit), unit_tile(punit),
772 E_UNIT_UPGRADED, ftc_server,
773 _("%s converted to %s."),
774 utype_name_translation(from_type),
775 utype_name_translation(to_type));
776 } else {
777 notify_player(unit_owner(punit), unit_tile(punit),
778 E_UNIT_UPGRADED, ftc_server,
779 _("%s cannot be converted."),
780 utype_name_translation(from_type));
784 /**************************************************************************
785 Cancel all illegal activities done by units at the specified tile.
786 **************************************************************************/
787 void unit_activities_cancel_all_illegal(const struct tile *ptile)
789 unit_list_iterate(ptile->units, punit2) {
790 if (!can_unit_continue_current_activity(punit2)) {
791 if (unit_has_orders(punit2)) {
792 notify_player(unit_owner(punit2), unit_tile(punit2),
793 E_UNIT_ORDERS, ftc_server,
794 _("Orders for %s aborted because activity "
795 "is no longer available."),
796 unit_link(punit2));
797 free_unit_orders(punit2);
800 set_unit_activity(punit2, ACTIVITY_IDLE);
801 send_unit_info(NULL, punit2);
803 } unit_list_iterate_end;
806 /**************************************************************************
807 progress settlers in their current tasks,
808 and units that is pillaging.
809 also move units that is on a goto.
810 restore unit move points (information needed for settler tasks)
811 **************************************************************************/
812 static void update_unit_activity(struct unit *punit)
814 const enum unit_activity tile_changing_actions[] =
815 { ACTIVITY_PILLAGE, ACTIVITY_GEN_ROAD, ACTIVITY_IRRIGATE, ACTIVITY_MINE,
816 ACTIVITY_BASE, ACTIVITY_TRANSFORM, ACTIVITY_POLLUTION,
817 ACTIVITY_FALLOUT, ACTIVITY_LAST };
819 struct player *pplayer = unit_owner(punit);
820 bool unit_activity_done = FALSE;
821 enum unit_activity activity = punit->activity;
822 struct tile *ptile = unit_tile(punit);
823 int i;
825 switch (activity) {
826 case ACTIVITY_IDLE:
827 case ACTIVITY_EXPLORE:
828 case ACTIVITY_FORTIFIED:
829 case ACTIVITY_SENTRY:
830 case ACTIVITY_GOTO:
831 case ACTIVITY_PATROL_UNUSED:
832 case ACTIVITY_UNKNOWN:
833 case ACTIVITY_LAST:
834 /* We don't need the activity_count for the above */
835 break;
837 case ACTIVITY_FORTIFYING:
838 case ACTIVITY_CONVERT:
839 punit->activity_count += get_activity_rate_this_turn(punit);
840 break;
842 case ACTIVITY_POLLUTION:
843 case ACTIVITY_MINE:
844 case ACTIVITY_IRRIGATE:
845 case ACTIVITY_PILLAGE:
846 case ACTIVITY_TRANSFORM:
847 case ACTIVITY_FALLOUT:
848 case ACTIVITY_BASE:
849 case ACTIVITY_GEN_ROAD:
850 punit->activity_count += get_activity_rate_this_turn(punit);
852 /* settler may become veteran when doing something useful */
853 if (maybe_become_veteran_real(punit, TRUE)) {
854 notify_unit_experience(punit);
856 break;
857 case ACTIVITY_OLD_ROAD:
858 case ACTIVITY_OLD_RAILROAD:
859 case ACTIVITY_FORTRESS:
860 case ACTIVITY_AIRBASE:
861 fc_assert(FALSE);
862 break;
865 unit_restore_movepoints(pplayer, punit);
867 switch (activity) {
868 case ACTIVITY_IDLE:
869 case ACTIVITY_FORTIFIED:
870 case ACTIVITY_SENTRY:
871 case ACTIVITY_GOTO:
872 case ACTIVITY_UNKNOWN:
873 case ACTIVITY_FORTIFYING:
874 case ACTIVITY_CONVERT:
875 case ACTIVITY_PATROL_UNUSED:
876 case ACTIVITY_LAST:
877 /* no default, ensure all handled */
878 break;
880 case ACTIVITY_EXPLORE:
881 do_explore(punit);
882 return;
884 case ACTIVITY_PILLAGE:
885 if (total_activity_done(ptile, ACTIVITY_PILLAGE,
886 punit->activity_target)) {
887 struct player *victim = tile_owner(ptile); /* Owner before fortress gets destroyed */
889 destroy_extra(ptile, punit->activity_target);
890 unit_activity_done = TRUE;
892 bounce_units_on_terrain_change(ptile);
894 call_incident(INCIDENT_PILLAGE, unit_owner(punit), victim);
896 /* Change vision if effects have changed. */
897 unit_list_refresh_vision(ptile->units);
899 break;
901 case ACTIVITY_POLLUTION:
902 /* TODO: Remove this fallback target setting when target always correctly
903 * set */
904 if (punit->activity_target == NULL) {
905 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANPOLLUTION,
906 NULL, punit);
908 if (total_activity_done(ptile, ACTIVITY_POLLUTION, punit->activity_target)) {
909 destroy_extra(ptile, punit->activity_target);
910 unit_activity_done = TRUE;
912 break;
914 case ACTIVITY_FALLOUT:
915 /* TODO: Remove this fallback target setting when target always correctly
916 * set */
917 if (punit->activity_target == NULL) {
918 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANFALLOUT,
919 NULL, punit);
921 if (total_activity_done(ptile, ACTIVITY_FALLOUT, punit->activity_target)) {
922 destroy_extra(ptile, punit->activity_target);
923 unit_activity_done = TRUE;
925 break;
927 case ACTIVITY_BASE:
929 if (total_activity(ptile, ACTIVITY_BASE, punit->activity_target)
930 >= tile_activity_time(ACTIVITY_BASE, ptile, punit->activity_target)) {
931 create_extra(ptile, punit->activity_target, unit_owner(punit));
932 unit_activity_done = TRUE;
935 break;
937 case ACTIVITY_GEN_ROAD:
939 if (total_activity(ptile, ACTIVITY_GEN_ROAD, punit->activity_target)
940 >= tile_activity_time(ACTIVITY_GEN_ROAD, ptile, punit->activity_target)) {
941 create_extra(ptile, punit->activity_target, unit_owner(punit));
942 unit_activity_done = TRUE;
945 break;
947 case ACTIVITY_IRRIGATE:
948 case ACTIVITY_MINE:
949 case ACTIVITY_TRANSFORM:
950 if (total_activity_done(ptile, activity, punit->activity_target)) {
951 struct terrain *old = tile_terrain(ptile);
953 /* The function below could change the terrain. Therefore, we have to
954 * check the terrain (which will also do a sanity check for the tile). */
955 tile_apply_activity(ptile, activity, punit->activity_target);
956 check_terrain_change(ptile, old);
957 unit_activity_done = TRUE;
959 break;
961 case ACTIVITY_OLD_ROAD:
962 case ACTIVITY_OLD_RAILROAD:
963 case ACTIVITY_FORTRESS:
964 case ACTIVITY_AIRBASE:
965 fc_assert(FALSE);
966 break;
969 if (unit_activity_done) {
970 update_tile_knowledge(ptile);
971 if (ACTIVITY_IRRIGATE == activity
972 || ACTIVITY_MINE == activity
973 || ACTIVITY_TRANSFORM == activity) {
974 /* FIXME: As we might probably do the activity again, because of the
975 * terrain change cycles, we need to treat these cases separatly.
976 * Probably ACTIVITY_TRANSFORM should be associated to its terrain
977 * target, whereas ACTIVITY_IRRIGATE and ACTIVITY_MINE should only
978 * used for extras. */
979 unit_list_iterate(ptile->units, punit2) {
980 if (punit2->activity == activity) {
981 set_unit_activity(punit2, ACTIVITY_IDLE);
982 send_unit_info(NULL, punit2);
984 } unit_list_iterate_end;
985 } else {
986 unit_list_iterate(ptile->units, punit2) {
987 if (!can_unit_continue_current_activity(punit2)) {
988 set_unit_activity(punit2, ACTIVITY_IDLE);
989 send_unit_info(NULL, punit2);
991 } unit_list_iterate_end;
994 for (i = 0; tile_changing_actions[i] != ACTIVITY_LAST; i++) {
995 if (tile_changing_actions[i] == activity) {
996 /* Some units nearby may not be able to continue their action,
997 * such as building irrigation if we removed the only source
998 * of water from them. */
999 adjc_iterate(ptile, ptile2) {
1000 unit_activities_cancel_all_illegal(ptile2);
1001 } adjc_iterate_end;
1002 break;
1007 if (activity == ACTIVITY_FORTIFYING) {
1008 if (punit->activity_count >= 1) {
1009 set_unit_activity(punit, ACTIVITY_FORTIFIED);
1013 if (activity == ACTIVITY_CONVERT) {
1014 if (punit->activity_count >= unit_type_get(punit)->convert_time * ACTIVITY_FACTOR) {
1015 unit_convert(punit);
1016 set_unit_activity(punit, ACTIVITY_IDLE);
1021 /**************************************************************************
1022 Forget the unit's last activity so that it can't be resumed. This is
1023 used for example when the unit moves or attacks.
1024 **************************************************************************/
1025 void unit_forget_last_activity(struct unit *punit)
1027 punit->changed_from = ACTIVITY_IDLE;
1030 /**************************************************************************
1031 Return TRUE iff activity requires some sort of target to be specified by
1032 the client.
1033 **************************************************************************/
1034 bool unit_activity_needs_target_from_client(enum unit_activity activity)
1036 switch (activity) {
1037 case ACTIVITY_PILLAGE:
1038 /* Can be set server side. */
1039 return FALSE;
1040 default:
1041 return activity_requires_target(activity);
1045 /**************************************************************************
1046 For some activities (currently only pillaging), the precise target can
1047 be assigned by the server rather than explicitly requested by the client.
1048 This function assigns a specific activity+target if the current
1049 settings are open-ended (otherwise leaves them unchanged).
1051 Please update unit_activity_needs_target_from_client() if you add server
1052 side unit activity target setting to more activities.
1053 **************************************************************************/
1054 void unit_assign_specific_activity_target(struct unit *punit,
1055 enum unit_activity *activity,
1056 struct extra_type **target)
1058 if (*activity == ACTIVITY_PILLAGE
1059 && *target == NULL) {
1060 struct tile *ptile = unit_tile(punit);
1061 struct extra_type *tgt;
1063 bv_extras extras = *tile_extras(ptile);
1065 while ((tgt = get_preferred_pillage(extras))) {
1067 BV_CLR(extras, extra_index(tgt));
1069 if (can_unit_do_activity_targeted(punit, *activity, tgt)) {
1070 *target = tgt;
1071 return;
1074 /* Nothing we can pillage here. */
1075 *activity = ACTIVITY_IDLE;
1079 /**************************************************************************
1080 Find place to place partisans. Returns whether such spot was found, and
1081 if it has been found, dst_tile contains that tile.
1082 **************************************************************************/
1083 static bool find_a_good_partisan_spot(struct tile *pcenter,
1084 struct player *powner,
1085 struct unit_type *u_type,
1086 int sq_radius,
1087 struct tile **dst_tile)
1089 int bestvalue = 0;
1091 /* coords of best tile in arg pointers */
1092 circle_iterate(pcenter, sq_radius, ptile) {
1093 int value;
1095 if (!is_native_tile(u_type, ptile)) {
1096 continue;
1099 if (NULL != tile_city(ptile)) {
1100 continue;
1103 if (0 < unit_list_size(ptile->units)) {
1104 continue;
1107 /* City may not have changed hands yet; see place_partisans(). */
1108 value = get_virtual_defense_power(NULL, u_type, powner,
1109 ptile, FALSE, 0);
1110 value *= 10;
1112 if (tile_continent(ptile) != tile_continent(pcenter)) {
1113 value /= 2;
1116 value -= fc_rand(value/3);
1118 if (value > bestvalue) {
1119 *dst_tile = ptile;
1120 bestvalue = value;
1122 } circle_iterate_end;
1124 return bestvalue > 0;
1127 /**************************************************************************
1128 Place partisans for powner around pcenter (normally around a city).
1129 **************************************************************************/
1130 void place_partisans(struct tile *pcenter, struct player *powner,
1131 int count, int sq_radius)
1133 struct tile *ptile = NULL;
1134 struct unit_type *u_type = get_role_unit(L_PARTISAN, 0);
1136 while (count-- > 0
1137 && find_a_good_partisan_spot(pcenter, powner, u_type,
1138 sq_radius, &ptile)) {
1139 struct unit *punit;
1141 punit = create_unit(powner, ptile, u_type, 0, 0, -1);
1142 if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
1143 punit->activity = ACTIVITY_FORTIFIED; /* yes; directly fortified */
1144 send_unit_info(NULL, punit);
1149 /**************************************************************************
1150 Teleport punit to city at cost specified. Returns success. Note that unit
1151 may die if it succesfully moves, i.e., even when return value is TRUE.
1152 (If specified cost is -1, then teleportation costs all movement.)
1153 **************************************************************************/
1154 bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1155 int move_cost, bool verbose)
1157 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1159 if (city_owner(pcity) == unit_owner(punit)){
1160 log_verbose("Teleported %s %s from (%d,%d) to %s",
1161 nation_rule_name(nation_of_unit(punit)),
1162 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1163 if (verbose) {
1164 notify_player(unit_owner(punit), city_tile(pcity),
1165 E_UNIT_RELOCATED, ftc_server,
1166 _("Teleported your %s to %s."),
1167 unit_link(punit),
1168 city_link(pcity));
1171 /* Silently free orders since they won't be applicable anymore. */
1172 free_unit_orders(punit);
1174 if (move_cost == -1) {
1175 move_cost = punit->moves_left;
1177 unit_move(punit, dst_tile, move_cost, NULL, FALSE);
1179 return TRUE;
1181 return FALSE;
1184 /**************************************************************************
1185 Move or remove a unit due to stack conflicts. This function will try to
1186 find a random safe tile within a two tile distance of the unit's current
1187 tile and move the unit there. If no tiles are found, the unit is
1188 disbanded. If 'verbose' is TRUE, a message is sent to the unit owner
1189 regarding what happened.
1190 **************************************************************************/
1191 void bounce_unit(struct unit *punit, bool verbose)
1193 struct player *pplayer;
1194 struct tile *punit_tile;
1195 struct unit_list *pcargo_units;
1196 int count = 0;
1198 /* I assume that there are no topologies that have more than
1199 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1200 const int DIST = 2;
1201 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1203 if (!punit) {
1204 return;
1207 pplayer = unit_owner(punit);
1208 punit_tile = unit_tile(punit);
1210 square_iterate(punit_tile, DIST, ptile) {
1211 if (count >= ARRAY_SIZE(tiles)) {
1212 break;
1215 if (ptile == punit_tile) {
1216 continue;
1219 if (can_unit_survive_at_tile(punit, ptile)
1220 && !is_non_allied_city_tile(ptile, pplayer)
1221 && !is_non_allied_unit_tile(ptile, pplayer)) {
1222 tiles[count++] = ptile;
1224 } square_iterate_end;
1226 if (count > 0) {
1227 struct tile *ptile = tiles[fc_rand(count)];
1229 if (verbose) {
1230 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1231 /* TRANS: A unit is moved to resolve stack conflicts. */
1232 _("Moved your %s."),
1233 unit_link(punit));
1235 unit_move(punit, ptile, 0, NULL, FALSE);
1236 return;
1239 /* Didn't find a place to bounce the unit, going to disband it.
1240 * Try to bounce transported units. */
1241 if (0 < get_transporter_occupancy(punit)) {
1242 pcargo_units = unit_transport_cargo(punit);
1243 unit_list_iterate(pcargo_units, pcargo) {
1244 bounce_unit(pcargo, verbose);
1245 } unit_list_iterate_end;
1248 if (verbose) {
1249 notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1250 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1251 _("Disbanded your %s."),
1252 unit_tile_link(punit));
1254 wipe_unit(punit, ULR_STACK_CONFLICT, NULL);
1258 /**************************************************************************
1259 Throw pplayer's units from non allied cities
1261 If verbose is true, pplayer gets messages about where each units goes.
1262 **************************************************************************/
1263 static void throw_units_from_illegal_cities(struct player *pplayer,
1264 bool verbose)
1266 struct tile *ptile;
1267 struct city *pcity;
1268 struct unit *ptrans;
1269 struct unit_list *pcargo_units;
1271 /* Unload undesired units from transports, if possible. */
1272 unit_list_iterate(pplayer->units, punit) {
1273 ptile = unit_tile(punit);
1274 pcity = tile_city(ptile);
1275 if (NULL != pcity
1276 && !pplayers_allied(city_owner(pcity), pplayer)
1277 && 0 < get_transporter_occupancy(punit)) {
1278 pcargo_units = unit_transport_cargo(punit);
1279 unit_list_iterate(pcargo_units, pcargo) {
1280 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1281 if (can_unit_exist_at_tile(pcargo, ptile)) {
1282 unit_transport_unload_send(pcargo);
1285 } unit_list_iterate_end;
1287 } unit_list_iterate_end;
1289 /* Bounce units except transported ones which will be bounced with their
1290 * transport. */
1291 unit_list_iterate_safe(pplayer->units, punit) {
1292 ptile = unit_tile(punit);
1293 pcity = tile_city(ptile);
1294 if (NULL != pcity
1295 && !pplayers_allied(city_owner(pcity), pplayer)) {
1296 ptrans = unit_transport_get(punit);
1297 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1298 bounce_unit(punit, verbose);
1301 } unit_list_iterate_safe_end;
1303 #ifdef FREECIV_DEBUG
1304 /* Sanity check. */
1305 unit_list_iterate(pplayer->units, punit) {
1306 ptile = unit_tile(punit);
1307 pcity = tile_city(ptile);
1308 fc_assert_msg(NULL == pcity
1309 || pplayers_allied(city_owner(pcity), pplayer),
1310 "Failed to throw %s %d from %s %d (%d, %d)",
1311 unit_rule_name(punit),
1312 punit->id,
1313 city_name_get(pcity),
1314 pcity->id,
1315 TILE_XY(ptile));
1316 } unit_list_iterate_end;
1317 #endif /* FREECIV_DEBUG */
1320 /**************************************************************************
1321 For each pplayer's unit, check if we stack illegally, if so,
1322 bounce both players' units. If on ocean tile, bounce everyone but ships
1323 to avoid drowning. This function assumes that cities are clean.
1325 If verbose is true, the unit owner gets messages about where each
1326 units goes.
1327 **************************************************************************/
1328 static void resolve_stack_conflicts(struct player *pplayer,
1329 struct player *aplayer, bool verbose)
1331 unit_list_iterate_safe(pplayer->units, punit) {
1332 struct tile *ptile = unit_tile(punit);
1334 if (is_non_allied_unit_tile(ptile, pplayer)) {
1335 unit_list_iterate_safe(ptile->units, aunit) {
1336 if (unit_owner(aunit) == pplayer
1337 || unit_owner(aunit) == aplayer
1338 || !can_unit_survive_at_tile(aunit, ptile)) {
1339 bounce_unit(aunit, verbose);
1341 } unit_list_iterate_safe_end;
1343 } unit_list_iterate_safe_end;
1346 /**************************************************************************
1347 When in civil war or an alliance breaks there will potentially be units
1348 from both sides coexisting on the same squares. This routine resolves
1349 this by first bouncing off non-allied units from their cities, then by
1350 bouncing both players' units in now illegal multiowner stacks. To avoid
1351 drowning due to removal of transports, we bounce everyone (including
1352 third parties' units) from ocean tiles.
1354 If verbose is true, the unit owner gets messages about where each
1355 units goes.
1356 **************************************************************************/
1357 void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1358 bool verbose)
1360 throw_units_from_illegal_cities(pplayer, verbose);
1361 throw_units_from_illegal_cities(aplayer, verbose);
1363 resolve_stack_conflicts(pplayer, aplayer, verbose);
1364 resolve_stack_conflicts(aplayer, pplayer, verbose);
1367 /****************************************************************************
1368 Returns the list of the units seen by 'pplayer' potentially seen only
1369 thanks to an alliance with 'aplayer'. The returned pointer is newly
1370 allocated and should be freed by the caller, using unit_list_destroy().
1371 ****************************************************************************/
1372 struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1373 const struct player *aplayer)
1375 struct unit_list *seen_units = unit_list_new();
1377 /* Anybody's units inside ally's cities */
1378 city_list_iterate(aplayer->cities, pcity) {
1379 unit_list_iterate(city_tile(pcity)->units, punit) {
1380 if (can_player_see_unit(pplayer, punit)) {
1381 unit_list_append(seen_units, punit);
1383 } unit_list_iterate_end;
1384 } city_list_iterate_end;
1386 /* Ally's own units inside transports */
1387 unit_list_iterate(aplayer->units, punit) {
1388 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1389 unit_list_append(seen_units, punit);
1391 } unit_list_iterate_end;
1393 /* Make sure the same unit is not added in multiple phases
1394 * (unit within transport in a city) */
1395 unit_list_unique(seen_units);
1397 return seen_units;
1400 /****************************************************************************
1401 When two players cancel an alliance, a lot of units that were visible may
1402 no longer be visible (this includes units in transporters and cities).
1403 Call this function to inform the clients that these units are no longer
1404 visible. Pass the list of seen units returned by get_units_seen_via_ally()
1405 before alliance was broken up.
1406 ****************************************************************************/
1407 void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1408 const struct unit_list *seen_units)
1410 unit_list_iterate(seen_units, punit) {
1411 /* We need to hide units previously seen by the client. */
1412 if (!can_player_see_unit(pplayer, punit)) {
1413 unit_goes_out_of_sight(pplayer, punit);
1415 } unit_list_iterate_end;
1417 city_list_iterate(aplayer->cities, pcity) {
1418 /* The player used to know what units were in these cities. Now that he
1419 * doesn't, he needs to get a new short city packet updating the
1420 * occupied status. */
1421 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1422 send_city_info(pplayer, pcity);
1424 } city_list_iterate_end;
1427 /****************************************************************************
1428 Refresh units visibility of 'aplayer' for 'pplayer' after alliance have
1429 been contracted.
1430 ****************************************************************************/
1431 void give_allied_visibility(struct player *pplayer,
1432 struct player *aplayer)
1434 unit_list_iterate(aplayer->units, punit) {
1435 if (can_player_see_unit(pplayer, punit)) {
1436 send_unit_info(pplayer->connections, punit);
1438 } unit_list_iterate_end;
1441 /**************************************************************************
1442 Is unit being refueled in its current position
1443 **************************************************************************/
1444 bool is_unit_being_refueled(const struct unit *punit)
1446 if (unit_transported(punit) /* Carrier */
1447 || tile_city(unit_tile(punit)) /* City */
1448 || tile_has_refuel_extra(unit_tile(punit),
1449 unit_type_get(punit))) { /* Airbase */
1450 return TRUE;
1452 if (unit_has_type_flag(punit, UTYF_COAST)) {
1453 return is_safe_ocean(unit_tile(punit));
1456 return FALSE;
1459 /**************************************************************************
1460 Can unit refuel on tile. Considers also carrier capacity on tile.
1461 **************************************************************************/
1462 bool is_airunit_refuel_point(const struct tile *ptile,
1463 const struct player *pplayer,
1464 const struct unit *punit)
1466 const struct unit_class *pclass;
1468 if (NULL != is_non_allied_unit_tile(ptile, pplayer)) {
1469 return FALSE;
1472 if (NULL != is_allied_city_tile(ptile, pplayer)) {
1473 return TRUE;
1476 pclass = unit_class_get(punit);
1477 if (NULL != pclass->cache.refuel_bases) {
1478 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1480 extra_type_list_iterate(pclass->cache.refuel_bases, pextra) {
1481 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1482 return TRUE;
1484 } extra_type_list_iterate_end;
1487 return unit_could_load_at(punit, ptile);
1490 /**************************************************************************
1491 Really transforms a single unit to another type.
1493 This function performs no checks. You should perform the appropriate
1494 test first to check that the transformation is legal (test_unit_upgrade()
1495 or test_unit_convert()).
1497 is_free: Does unit owner need to pay upgrade price.
1499 Note that this function is strongly tied to unit.c:test_unit_upgrade().
1500 **************************************************************************/
1501 void transform_unit(struct unit *punit, struct unit_type *to_unit,
1502 bool is_free)
1504 struct player *pplayer = unit_owner(punit);
1505 struct unit_type *old_type = punit->utype;
1506 int old_mr = unit_move_rate(punit);
1507 int old_hp = unit_type_get(punit)->hp;
1509 if (!is_free) {
1510 pplayer->economic.gold -=
1511 unit_upgrade_price(pplayer, unit_type_get(punit), to_unit);
1514 punit->utype = to_unit;
1516 /* New type may not have the same veteran system, and we may want to
1517 * knock some levels off. */
1518 punit->veteran = MIN(punit->veteran,
1519 utype_veteran_system(to_unit)->levels - 1);
1520 if (is_free) {
1521 punit->veteran = MAX(punit->veteran
1522 - game.server.autoupgrade_veteran_loss, 0);
1523 } else {
1524 punit->veteran = MAX(punit->veteran
1525 - game.server.upgrade_veteran_loss, 0);
1528 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1529 * and don't kill the unit. unit_move_rate is used to take into account
1530 * global effects like Magellan's Expedition. */
1531 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1532 punit->moves_left = punit->moves_left * unit_move_rate(punit) / old_mr;
1534 unit_forget_last_activity(punit);
1536 /* update unit upkeep */
1537 city_units_upkeep(game_city_by_number(punit->homecity));
1539 conn_list_do_buffer(pplayer->connections);
1541 unit_refresh_vision(punit);
1543 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1545 send_unit_info(NULL, punit);
1546 conn_list_do_unbuffer(pplayer->connections);
1549 /*************************************************************************
1550 Wrapper of the below
1551 *************************************************************************/
1552 struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1553 struct unit_type *type, int veteran_level,
1554 int homecity_id, int moves_left)
1556 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1557 moves_left, -1, NULL);
1560 /**************************************************************************
1561 Set carried goods for unit.
1562 **************************************************************************/
1563 void unit_get_goods(struct unit *punit)
1565 if (punit->homecity != 0) {
1566 struct city *home = game_city_by_number(punit->homecity);
1568 if (home != NULL && game.info.goods_selection == GSM_LEAVING) {
1569 punit->carrying = goods_from_city_to_unit(home, punit);
1574 /**************************************************************************
1575 Creates a unit, and set it's initial values, and put it into the right
1576 lists.
1577 If moves_left is less than zero, unit will get max moves.
1578 **************************************************************************/
1579 struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1580 struct unit_type *type, int veteran_level,
1581 int homecity_id, int moves_left, int hp_left,
1582 struct unit *ptrans)
1584 struct unit *punit = unit_virtual_create(pplayer, NULL, type, veteran_level);
1585 struct city *pcity;
1587 /* Register unit */
1588 punit->id = identity_number();
1589 idex_register_unit(punit);
1591 fc_assert_ret_val(ptile != NULL, NULL);
1592 unit_tile_set(punit, ptile);
1594 pcity = game_city_by_number(homecity_id);
1595 if (utype_has_flag(type, UTYF_NOHOME)) {
1596 punit->homecity = 0; /* none */
1597 } else {
1598 punit->homecity = homecity_id;
1601 if (hp_left >= 0) {
1602 /* Override default full HP */
1603 punit->hp = hp_left;
1606 if (moves_left >= 0) {
1607 /* Override default full MP */
1608 punit->moves_left = MIN(moves_left, unit_move_rate(punit));
1611 if (ptrans) {
1612 /* Set transporter for unit. */
1613 unit_transport_load_tp_status(punit, ptrans, FALSE);
1614 } else {
1615 fc_assert_ret_val(!ptile || can_unit_exist_at_tile(punit, ptile), NULL);
1618 /* Assume that if moves_left < 0 then the unit is "fresh",
1619 * and not moved; else the unit has had something happen
1620 * to it (eg, bribed) which we treat as equivalent to moved.
1621 * (Otherwise could pass moved arg too...) --dwp */
1622 punit->moved = (moves_left >= 0);
1624 unit_list_prepend(pplayer->units, punit);
1625 unit_list_prepend(ptile->units, punit);
1626 if (pcity && !utype_has_flag(type, UTYF_NOHOME)) {
1627 fc_assert(city_owner(pcity) == pplayer);
1628 unit_list_prepend(pcity->units_supported, punit);
1629 /* Refresh the unit's homecity. */
1630 city_refresh(pcity);
1631 send_city_info(pplayer, pcity);
1634 punit->server.vision = vision_new(pplayer, ptile);
1635 unit_refresh_vision(punit);
1637 send_unit_info(NULL, punit);
1638 maybe_make_contact(ptile, unit_owner(punit));
1639 wakeup_neighbor_sentries(punit);
1641 /* update unit upkeep */
1642 city_units_upkeep(game_city_by_number(homecity_id));
1644 /* The unit may have changed the available tiles in nearby cities. */
1645 city_map_update_tile_now(ptile);
1646 sync_cities();
1648 unit_get_goods(punit);
1650 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1652 return punit;
1655 /**************************************************************************
1656 Set the call back to run when the server removes the unit.
1657 **************************************************************************/
1658 void unit_set_removal_callback(struct unit *punit,
1659 void (*callback)(struct unit *punit))
1661 /* Tried to overwrite another call back. If this assertion is triggered
1662 * in a case where two call back are needed it may be time to support
1663 * more than one unit removal call back at a time. */
1664 fc_assert_ret(punit->server.removal_callback == NULL);
1666 punit->server.removal_callback = callback;
1669 /**************************************************************************
1670 Remove the call back so nothing runs when the server removes the unit.
1671 **************************************************************************/
1672 void unit_unset_removal_callback(struct unit *punit)
1674 punit->server.removal_callback = NULL;
1677 /****************************************************************************
1678 We remove the unit and see if it's disappearance has affected the homecity
1679 and the city it was in.
1680 ****************************************************************************/
1681 static void server_remove_unit_full(struct unit *punit, bool transported,
1682 enum unit_loss_reason reason)
1684 struct packet_unit_remove packet;
1685 struct tile *ptile = unit_tile(punit);
1686 struct city *pcity = tile_city(ptile);
1687 struct city *phomecity = game_city_by_number(punit->homecity);
1688 struct unit *ptrans;
1689 struct player *pplayer = unit_owner(punit);
1691 /* The unit is doomed. */
1692 punit->server.dying = TRUE;
1694 #ifdef FREECIV_DEBUG
1695 unit_list_iterate(ptile->units, pcargo) {
1696 fc_assert(unit_transport_get(pcargo) != punit);
1697 } unit_list_iterate_end;
1698 #endif /* FREECIV_DEBUG */
1700 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1702 /* Save transporter for updating below. */
1703 ptrans = unit_transport_get(punit);
1704 /* Unload unit. */
1705 unit_transport_unload(punit);
1707 /* Since settlers plot in new cities in the minimap before they
1708 are built, so that no two settlers head towards the same city
1709 spot, we need to ensure this reservation is cleared should
1710 the settler disappear on the way. */
1711 adv_unit_new_task(punit, AUT_NONE, NULL);
1713 /* Clear the vision before sending unit remove. Else, we might duplicate
1714 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1715 vision_clear_sight(punit->server.vision);
1716 vision_free(punit->server.vision);
1717 punit->server.vision = NULL;
1719 packet.unit_id = punit->id;
1720 /* Send to onlookers. */
1721 players_iterate(aplayer) {
1722 if (can_player_see_unit_at(aplayer, punit, unit_tile(punit),
1723 transported)) {
1724 lsend_packet_unit_remove(aplayer->connections, &packet);
1726 } players_iterate_end;
1727 /* Send to global observers. */
1728 conn_list_iterate(game.est_connections, pconn) {
1729 if (conn_is_global_observer(pconn)) {
1730 send_packet_unit_remove(pconn, &packet);
1732 } conn_list_iterate_end;
1734 if (punit->server.moving != NULL) {
1735 /* Do not care of this unit for running moves. */
1736 punit->server.moving->punit = NULL;
1739 if (punit->server.removal_callback != NULL) {
1740 /* Run the unit removal call back. */
1741 punit->server.removal_callback(punit);
1744 /* check if this unit had UTYF_GAMELOSS flag */
1745 if (unit_has_type_flag(punit, UTYF_GAMELOSS) && unit_owner(punit)->is_alive) {
1746 notify_conn(game.est_connections, ptile, E_UNIT_LOST_MISC, ftc_server,
1747 _("Unable to defend %s, %s has lost the game."),
1748 unit_link(punit),
1749 player_name(pplayer));
1750 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1751 _("Losing %s meant losing the game! "
1752 "Be more careful next time!"),
1753 unit_link(punit));
1754 player_status_add(unit_owner(punit), PSTATUS_DYING);
1757 script_server_signal_emit("unit_lost", 3,
1758 API_TYPE_UNIT, punit,
1759 API_TYPE_PLAYER, unit_owner(punit),
1760 API_TYPE_STRING, unit_loss_reason_name(reason));
1762 script_server_remove_exported_object(punit);
1763 game_remove_unit(punit);
1764 punit = NULL;
1766 if (NULL != ptrans) {
1767 /* Update the occupy info. */
1768 send_unit_info(NULL, ptrans);
1771 /* This unit may have blocked tiles of adjacent cities. Update them. */
1772 city_map_update_tile_now(ptile);
1773 sync_cities();
1775 if (phomecity) {
1776 city_refresh(phomecity);
1777 send_city_info(city_owner(phomecity), phomecity);
1780 if (pcity && pcity != phomecity) {
1781 city_refresh(pcity);
1782 send_city_info(city_owner(pcity), pcity);
1785 if (pcity && unit_list_size(ptile->units) == 0) {
1786 /* The last unit in the city was killed: update the occupied flag. */
1787 send_city_info(NULL, pcity);
1791 /****************************************************************************
1792 We remove the unit and see if it's disappearance has affected the homecity
1793 and the city it was in.
1794 ****************************************************************************/
1795 static void server_remove_unit(struct unit *punit,
1796 enum unit_loss_reason reason)
1798 server_remove_unit_full(punit, unit_transported(punit), reason);
1801 /**************************************************************************
1802 Handle units destroyed when their transport is destroyed
1803 **************************************************************************/
1804 static void unit_lost_with_transport(const struct player *pplayer,
1805 struct unit *pcargo,
1806 struct unit_type *ptransport,
1807 struct player *killer)
1809 notify_player(pplayer, unit_tile(pcargo), E_UNIT_LOST_MISC, ftc_server,
1810 _("%s lost when %s was lost."),
1811 unit_tile_link(pcargo),
1812 utype_name_translation(ptransport));
1813 /* Unit is not transported any more at this point, but it has jumped
1814 * off the transport and drowns outside. So it must be removed from
1815 * all clients.
1816 * However, we don't know if given client has received ANY updates
1817 * about the swimming unit, and we can't remove it if it's not there
1818 * in the first place -> we send it once here just to be sure it's
1819 * there. */
1820 send_unit_info(NULL, pcargo);
1821 wipe_unit_full(pcargo, FALSE, ULR_TRANSPORT_LOST, killer);
1824 /****************************************************************************
1825 Remove the unit, and passengers if it is a carrying any. Remove the
1826 _minimum_ number, eg there could be another boat on the square.
1827 ****************************************************************************/
1828 static void wipe_unit_full(struct unit *punit, bool transported,
1829 enum unit_loss_reason reason,
1830 struct player *killer)
1832 struct tile *ptile = unit_tile(punit);
1833 struct player *pplayer = unit_owner(punit);
1834 struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1835 struct unit_list *helpless = unit_list_new();
1836 struct unit_list *imperiled = unit_list_new();
1837 struct unit_list *unsaved = unit_list_new();
1838 struct unit *ptrans = unit_transport_get(punit);
1840 /* The unit is doomed. */
1841 punit->server.dying = TRUE;
1843 /* Remove unit itself from its transport */
1844 if (ptrans != NULL) {
1845 unit_transport_unload(punit);
1846 send_unit_info(NULL, ptrans);
1849 /* First pull all units off of the transporter. */
1850 if (get_transporter_occupancy(punit) > 0) {
1851 /* Use iterate_safe as unloaded units will be removed from the list
1852 * while iterating. */
1853 unit_list_iterate_safe(unit_transport_cargo(punit), pcargo) {
1854 bool healthy = FALSE;
1856 if (!can_unit_unload(pcargo, punit)) {
1857 unit_list_prepend(helpless, pcargo);
1858 } else {
1859 if (!can_unit_exist_at_tile(pcargo, ptile)) {
1860 unit_list_prepend(imperiled, pcargo);
1861 } else {
1862 /* These units do not need to be saved. */
1863 healthy = TRUE;
1867 /* Could use unit_transport_unload_send here, but that would
1868 * call send_unit_info for the transporter unnecessarily.
1869 * Note that this means that unit might to get seen briefly
1870 * by clients other than owner's, for example as a result of
1871 * update of homecity common to this cargo and some other
1872 * destroyed unit. */
1873 unit_transport_unload(pcargo);
1874 if (pcargo->activity == ACTIVITY_SENTRY) {
1875 /* Activate sentried units - like planes on a disbanded carrier.
1876 * Note this will activate ground units even if they just change
1877 * transporter. */
1878 set_unit_activity(pcargo, ACTIVITY_IDLE);
1881 /* Unit info for unhealthy units will be sent when they are
1882 * assigned new transport or removed. */
1883 if (healthy) {
1884 send_unit_info(NULL, pcargo);
1886 } unit_list_iterate_safe_end;
1889 /* Now remove the unit. */
1890 server_remove_unit_full(punit, transported, reason);
1892 switch (reason) {
1893 case ULR_KILLED:
1894 case ULR_EXECUTED:
1895 case ULR_SDI:
1896 case ULR_NUKE:
1897 case ULR_BRIBED:
1898 case ULR_CAPTURED:
1899 case ULR_CAUGHT:
1900 case ULR_ELIMINATED:
1901 case ULR_TRANSPORT_LOST:
1902 if (killer != NULL) {
1903 killer->score.units_killed++;
1905 pplayer->score.units_lost++;
1906 break;
1907 case ULR_BARB_UNLEASH:
1908 case ULR_CITY_LOST:
1909 case ULR_STARVED:
1910 case ULR_NONNATIVE_TERR:
1911 case ULR_ARMISTICE:
1912 case ULR_HP_LOSS:
1913 case ULR_FUEL:
1914 case ULR_STACK_CONFLICT:
1915 case ULR_SOLD:
1916 pplayer->score.units_lost++;
1917 break;
1918 case ULR_RETIRED:
1919 case ULR_DISBANDED:
1920 case ULR_USED:
1921 case ULR_EDITOR:
1922 case ULR_PLAYER_DIED:
1923 case ULR_DETONATED:
1924 case ULR_MISSILE:
1925 break;
1928 /* First, sort out helpless cargo. */
1929 if (unit_list_size(helpless) > 0) {
1930 struct unit_list *remaining = unit_list_new();
1932 /* Grant priority to gameloss units and units with the EvacuateFirst
1933 * unit type flag. */
1934 unit_list_iterate_safe(helpless, pcargo) {
1935 if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
1936 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
1937 if (!try_to_save_unit(pcargo, putype_save, TRUE,
1938 unit_has_type_flag(pcargo,
1939 UTYF_EVAC_FIRST))) {
1940 unit_list_prepend(unsaved, pcargo);
1942 } else {
1943 unit_list_prepend(remaining, pcargo);
1945 } unit_list_iterate_safe_end;
1947 /* Handle non-priority units. */
1948 unit_list_iterate_safe(remaining, pcargo) {
1949 if (!try_to_save_unit(pcargo, putype_save, TRUE, FALSE)) {
1950 unit_list_prepend(unsaved, pcargo);
1952 } unit_list_iterate_safe_end;
1954 unit_list_destroy(remaining);
1956 unit_list_destroy(helpless);
1958 /* Then, save any imperiled cargo. */
1959 if (unit_list_size(imperiled) > 0) {
1960 struct unit_list *remaining = unit_list_new();
1962 /* Grant priority to gameloss units and units with the EvacuateFirst
1963 * unit type flag. */
1964 unit_list_iterate_safe(imperiled, pcargo) {
1965 if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
1966 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
1967 if (!try_to_save_unit(pcargo, putype_save, FALSE,
1968 unit_has_type_flag(pcargo,
1969 UTYF_EVAC_FIRST))) {
1970 unit_list_prepend(unsaved, pcargo);
1972 } else {
1973 unit_list_prepend(remaining, pcargo);
1975 } unit_list_iterate_safe_end;
1977 /* Handle non-priority units. */
1978 unit_list_iterate_safe(remaining, pcargo) {
1979 if (!try_to_save_unit(pcargo, putype_save, FALSE, FALSE)) {
1980 unit_list_prepend(unsaved, pcargo);
1982 } unit_list_iterate_safe_end;
1984 unit_list_destroy(remaining);
1986 unit_list_destroy(imperiled);
1988 /* Finally, kill off the unsaved units. */
1989 if (unit_list_size(unsaved) > 0) {
1990 unit_list_iterate_safe(unsaved, dying_unit) {
1991 unit_lost_with_transport(pplayer, dying_unit, putype_save, killer);
1992 } unit_list_iterate_safe_end;
1994 unit_list_destroy(unsaved);
1997 /****************************************************************************
1998 Remove the unit, and passengers if it is a carrying any. Remove the
1999 _minimum_ number, eg there could be another boat on the square.
2000 ****************************************************************************/
2001 void wipe_unit(struct unit *punit, enum unit_loss_reason reason,
2002 struct player *killer)
2004 wipe_unit_full(punit, unit_transported(punit), reason, killer);
2007 /****************************************************************************
2008 Determine if it is possible to save a given unit, and if so, save them.
2009 Note that despite being saved from drowning, teleporting the units to
2010 "safety" may have killed them in the end.
2011 ****************************************************************************/
2012 bool try_to_save_unit(struct unit *punit, struct unit_type *pttype,
2013 bool helpless, bool teleporting)
2015 struct tile *ptile = unit_tile(punit);
2016 struct player *pplayer = unit_owner(punit);
2017 struct unit *ptransport = transporter_for_unit(punit);
2019 /* Helpless units cannot board a transport in their current state. */
2020 if (!helpless
2021 && ptransport != NULL) {
2022 unit_transport_load_tp_status(punit, ptransport, FALSE);
2023 send_unit_info(NULL, punit);
2024 return TRUE;
2025 } else {
2026 /* Only units that cannot find transport are considered for teleport. */
2027 if (teleporting) {
2028 struct city *pcity = find_closest_city(ptile, NULL, unit_owner(punit),
2029 FALSE, FALSE, FALSE, TRUE, FALSE,
2030 utype_class(pttype));
2031 if (pcity != NULL) {
2032 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2034 sz_strlcpy(tplink, unit_link(punit));
2036 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2037 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2038 _("%s escaped the destruction of %s, and fled to %s."),
2039 tplink,
2040 utype_name_translation(pttype),
2041 city_link(pcity));
2042 return TRUE;
2047 /* The unit could not use transport on the tile, and could not teleport. */
2048 return FALSE;
2051 /****************************************************************************
2052 We don't really change owner of the unit, but create completely new
2053 unit as its copy. The new pointer to 'punit' is returned.
2054 ****************************************************************************/
2055 struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2056 int homecity, enum unit_loss_reason reason)
2058 struct unit *gained_unit;
2060 fc_assert(!utype_player_already_has_this_unique(pplayer,
2061 unit_type_get(punit)));
2063 /* Convert the unit to your cause. Fog is lifted in the create algorithm. */
2064 gained_unit = create_unit_full(pplayer, unit_tile(punit),
2065 unit_type_get(punit), punit->veteran,
2066 homecity, punit->moves_left,
2067 punit->hp, NULL);
2069 /* Owner changes, nationality not. */
2070 gained_unit->nationality = punit->nationality;
2072 /* Copy some more unit fields */
2073 gained_unit->fuel = punit->fuel;
2074 gained_unit->paradropped = punit->paradropped;
2075 gained_unit->server.birth_turn = punit->server.birth_turn;
2077 send_unit_info(NULL, gained_unit);
2079 /* update unit upkeep in the homecity of the victim */
2080 if (punit->homecity > 0) {
2081 /* update unit upkeep */
2082 city_units_upkeep(game_city_by_number(punit->homecity));
2084 /* update unit upkeep in the new homecity */
2085 if (homecity > 0) {
2086 city_units_upkeep(game_city_by_number(homecity));
2089 /* Be sure to wipe the converted unit! */
2090 wipe_unit(punit, reason, NULL);
2092 return gained_unit; /* Returns the replacement. */
2095 /**************************************************************************
2096 Called when one unit kills another in combat (this function is only
2097 called in one place). It handles all side effects including
2098 notifications and killstack.
2099 **************************************************************************/
2100 void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2102 char pkiller_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK];
2103 struct player *pvictim = unit_owner(punit);
2104 struct player *pvictor = unit_owner(pkiller);
2105 int ransom, unitcount = 0;
2106 bool escaped;
2108 sz_strlcpy(pkiller_link, unit_link(pkiller));
2109 sz_strlcpy(punit_link, unit_tile_link(punit));
2111 /* The unit is doomed. */
2112 punit->server.dying = TRUE;
2114 if ((game.info.gameloss_style & GAMELOSS_STYLE_LOOT)
2115 && unit_has_type_flag(punit, UTYF_GAMELOSS)) {
2116 ransom = fc_rand(1 + pvictim->economic.gold);
2117 int n;
2119 /* give map */
2120 give_distorted_map(pvictim, pvictor, 1, 1, TRUE);
2122 log_debug("victim has money: %d", pvictim->economic.gold);
2123 pvictor->economic.gold += ransom;
2124 pvictim->economic.gold -= ransom;
2126 n = 1 + fc_rand(3);
2128 while (n > 0) {
2129 Tech_type_id ttid = steal_a_tech(pvictor, pvictim, A_UNSET);
2131 if (ttid == A_NONE) {
2132 log_debug("Worthless enemy doesn't have more techs to steal.");
2133 break;
2134 } else {
2135 log_debug("Pressed tech %s from captured enemy",
2136 research_advance_rule_name(research_get(pvictor), ttid));
2137 if (!fc_rand(3)) {
2138 break; /* out of luck */
2140 n--;
2144 { /* try to submit some cities */
2145 int vcsize = city_list_size(pvictim->cities);
2146 int evcsize = vcsize;
2147 int conqsize = evcsize;
2149 if (evcsize < 3) {
2150 evcsize = 0;
2151 } else {
2152 evcsize -=3;
2154 /* about a quarter on average with high numbers less probable */
2155 conqsize = fc_rand(fc_rand(evcsize));
2157 log_debug("conqsize=%d", conqsize);
2159 if (conqsize > 0) {
2160 bool palace = game.server.savepalace;
2161 bool submit = FALSE;
2163 game.server.savepalace = FALSE; /* moving it around is dumb */
2165 city_list_iterate_safe(pvictim->cities, pcity) {
2166 /* kindly ask the citizens to submit */
2167 if (fc_rand(vcsize) < conqsize) {
2168 submit = TRUE;
2170 vcsize--;
2171 if (submit) {
2172 conqsize--;
2173 /* Transfer city to the victorious player
2174 * kill all its units outside of a radius of 7,
2175 * give verbose messages of every unit transferred,
2176 * and raze buildings according to raze chance
2177 * (also removes palace) */
2178 (void) transfer_city(pvictor, pcity, 7, TRUE, TRUE, TRUE,
2179 !is_barbarian(pvictor));
2180 submit = FALSE;
2182 if (conqsize <= 0) {
2183 break;
2185 } city_list_iterate_safe_end;
2186 game.server.savepalace = palace;
2191 /* barbarian leader ransom hack */
2192 if (is_barbarian(pvictim) && unit_has_type_role(punit, L_BARBARIAN_LEADER)
2193 && (unit_list_size(unit_tile(punit)->units) == 1)
2194 && uclass_has_flag(unit_class_get(pkiller), UCF_COLLECT_RANSOM)) {
2195 /* Occupying units can collect ransom if leader is alone in the tile */
2196 ransom = (pvictim->economic.gold >= game.server.ransom_gold)
2197 ? game.server.ransom_gold : pvictim->economic.gold;
2198 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2199 PL_("Barbarian leader captured; %d gold ransom paid.",
2200 "Barbarian leader captured; %d gold ransom paid.",
2201 ransom),
2202 ransom);
2203 pvictor->economic.gold += ransom;
2204 pvictim->economic.gold -= ransom;
2205 send_player_info_c(pvictor, NULL); /* let me see my new gold :-) */
2206 unitcount = 1;
2209 if (unitcount == 0) {
2210 unit_list_iterate(unit_tile(punit)->units, vunit) {
2211 if (pplayers_at_war(pvictor, unit_owner(vunit))) {
2212 unitcount++;
2214 } unit_list_iterate_end;
2217 if (!is_stack_vulnerable(unit_tile(punit)) || unitcount == 1) {
2218 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2219 /* TRANS: "... Cannon ... the Polish Destroyer." */
2220 _("Your attacking %s succeeded against the %s %s!"),
2221 pkiller_link,
2222 nation_adjective_for_player(pvictim),
2223 punit_link);
2224 if (vet) {
2225 notify_unit_experience(pkiller);
2227 notify_player(pvictim, unit_tile(punit), E_UNIT_LOST_DEF, ftc_server,
2228 /* TRANS: "Cannon ... the Polish Destroyer." */
2229 _("%s lost to an attack by the %s %s."),
2230 punit_link,
2231 nation_adjective_for_player(pvictor),
2232 pkiller_link);
2234 wipe_unit(punit, ULR_KILLED, pvictor);
2235 } else { /* unitcount > 1 */
2236 int i;
2237 int num_killed[player_slot_count()];
2238 int num_escaped[player_slot_count()];
2239 struct unit *other_killed[player_slot_count()];
2240 struct tile *ptile = unit_tile(punit);
2242 fc_assert(unitcount > 1);
2244 /* initialize */
2245 for (i = 0; i < player_slot_count(); i++) {
2246 num_killed[i] = 0;
2247 other_killed[i] = NULL;
2248 num_escaped[i] = 0;
2251 /* count killed units */
2252 unit_list_iterate(ptile->units, vunit) {
2253 struct player *vplayer = unit_owner(vunit);
2255 if (pplayers_at_war(pvictor, vplayer)
2256 && is_unit_reachable_at(vunit, pkiller, ptile)) {
2257 escaped = FALSE;
2259 if (unit_has_type_flag(vunit, UTYF_CANESCAPE)
2260 && !unit_has_type_flag(pkiller, UTYF_CANKILLESCAPING)
2261 && vunit->hp > 0
2262 && vunit->moves_left > pkiller->moves_left
2263 && fc_rand(2)) {
2264 int curr_def_bonus;
2265 int def_bonus = 0;
2266 struct tile *dsttile = NULL;
2267 int move_cost;
2269 fc_assert(vunit->hp > 0);
2271 adjc_iterate(ptile, ptile2) {
2272 if (can_exist_at_tile(vunit->utype, ptile2)
2273 && NULL == tile_city(ptile2)) {
2274 move_cost = map_move_cost_unit(vunit, ptile2);
2275 if (pkiller->moves_left <= vunit->moves_left - move_cost
2276 && (is_allied_unit_tile(ptile2, pvictim)
2277 || unit_list_size(ptile2->units)) == 0) {
2278 curr_def_bonus = tile_extras_defense_bonus(ptile2,
2279 vunit->utype);
2280 if (def_bonus <= curr_def_bonus) {
2281 def_bonus = curr_def_bonus;
2282 dsttile = ptile2;
2286 } adjc_iterate_end;
2288 if (dsttile != NULL) {
2289 move_cost = map_move_cost_unit(vunit, dsttile);
2290 unit_move(vunit, dsttile, move_cost, NULL, FALSE);
2291 num_escaped[player_index(vplayer)]++;
2292 escaped = TRUE;
2293 unitcount--;
2297 if (!escaped) {
2298 num_killed[player_index(vplayer)]++;
2300 if (vunit != punit) {
2301 other_killed[player_index(vplayer)] = vunit;
2302 other_killed[player_index(pvictor)] = vunit;
2306 } unit_list_iterate_end;
2308 /* Inform the destroyer: lots of different cases here! */
2309 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2310 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2311 PL_("Your attacking %s succeeded against the %s %s "
2312 "(and %d other unit)!",
2313 "Your attacking %s succeeded against the %s %s "
2314 "(and %d other units)!", unitcount - 1),
2315 pkiller_link,
2316 nation_adjective_for_player(pvictim),
2317 punit_link,
2318 unitcount - 1);
2319 if (vet) {
2320 notify_unit_experience(pkiller);
2323 /* inform the owners: this only tells about owned units that were killed.
2324 * there may have been 20 units who died but if only 2 belonged to the
2325 * particular player they'll only learn about those.
2327 * Also if a large number of units die you don't find out what type
2328 * they all are. */
2329 for (i = 0; i < player_slot_count(); i++) {
2330 if (num_killed[i] == 1) {
2331 if (i == player_index(pvictim)) {
2332 fc_assert(other_killed[i] == NULL);
2333 notify_player(player_by_number(i), ptile,
2334 E_UNIT_LOST_DEF, ftc_server,
2335 /* TRANS: "Cannon ... the Polish Destroyer." */
2336 _("%s lost to an attack by the %s %s."),
2337 punit_link,
2338 nation_adjective_for_player(pvictor),
2339 pkiller_link);
2340 } else {
2341 fc_assert(other_killed[i] != punit);
2342 notify_player(player_by_number(i), ptile,
2343 E_UNIT_LOST_DEF, ftc_server,
2344 /* TRANS: "Cannon lost when the Polish Destroyer
2345 * attacked the German Musketeers." */
2346 _("%s lost when the %s %s attacked the %s %s."),
2347 unit_link(other_killed[i]),
2348 nation_adjective_for_player(pvictor),
2349 pkiller_link,
2350 nation_adjective_for_player(pvictim),
2351 punit_link);
2353 } else if (num_killed[i] > 1) {
2354 if (i == player_index(pvictim)) {
2355 int others = num_killed[i] - 1;
2357 if (others == 1) {
2358 notify_player(player_by_number(i), ptile,
2359 E_UNIT_LOST_DEF, ftc_server,
2360 /* TRANS: "Musketeers (and Cannon) lost to an
2361 * attack from the Polish Destroyer." */
2362 _("%s (and %s) lost to an attack from the %s %s."),
2363 punit_link,
2364 unit_link(other_killed[i]),
2365 nation_adjective_for_player(pvictor),
2366 pkiller_link);
2367 } else {
2368 notify_player(player_by_number(i), ptile,
2369 E_UNIT_LOST_DEF, ftc_server,
2370 /* TRANS: "Musketeers and 3 other units lost to
2371 * an attack from the Polish Destroyer."
2372 * (only happens with at least 2 other units) */
2373 PL_("%s and %d other unit lost to an attack "
2374 "from the %s %s.",
2375 "%s and %d other units lost to an attack "
2376 "from the %s %s.", others),
2377 punit_link,
2378 others,
2379 nation_adjective_for_player(pvictor),
2380 pkiller_link);
2382 } else {
2383 notify_player(player_by_number(i), ptile,
2384 E_UNIT_LOST_DEF, ftc_server,
2385 /* TRANS: "2 units lost when the Polish Destroyer
2386 * attacked the German Musketeers."
2387 * (only happens with at least 2 other units) */
2388 PL_("%d unit lost when the %s %s attacked the %s %s.",
2389 "%d units lost when the %s %s attacked the %s %s.",
2390 num_killed[i]),
2391 num_killed[i],
2392 nation_adjective_for_player(pvictor),
2393 pkiller_link,
2394 nation_adjective_for_player(pvictim),
2395 punit_link);
2400 /* Inform the owner of the units that escaped. */
2401 for (i = 0; i < player_slot_count(); ++i) {
2402 if (0 < num_escaped[i]) {
2403 notify_player(player_by_number(i), unit_tile(punit),
2404 E_UNIT_ESCAPED, ftc_server,
2405 PL_("%d unit escaped from attack by %s %s",
2406 "%d units escaped from attack by %s %s",
2407 num_escaped[i]),
2408 num_escaped[i],
2409 pkiller_link,
2410 nation_adjective_for_player(pkiller->nationality)
2415 /* remove the units - note the logic of which units actually die
2416 * must be mimiced exactly in at least one place up above. */
2417 punit = NULL; /* wiped during following iteration so unsafe to use */
2419 unit_list_iterate_safe(ptile->units, punit2) {
2420 if (pplayers_at_war(pvictor, unit_owner(punit2))
2421 && is_unit_reachable_at(punit2, pkiller, ptile)) {
2422 wipe_unit(punit2, ULR_KILLED, pvictor);
2424 } unit_list_iterate_safe_end;
2428 /**************************************************************************
2429 Package a unit_info packet. This packet contains basically all
2430 information about a unit.
2431 **************************************************************************/
2432 void package_unit(struct unit *punit, struct packet_unit_info *packet)
2434 packet->id = punit->id;
2435 packet->owner = player_number(unit_owner(punit));
2436 packet->nationality = player_number(unit_nationality(punit));
2437 packet->tile = tile_index(unit_tile(punit));
2438 packet->facing = punit->facing;
2439 packet->homecity = punit->homecity;
2440 output_type_iterate(o) {
2441 packet->upkeep[o] = punit->upkeep[o];
2442 } output_type_iterate_end;
2443 packet->veteran = punit->veteran;
2444 packet->type = utype_number(unit_type_get(punit));
2445 packet->movesleft = punit->moves_left;
2446 packet->hp = punit->hp;
2447 packet->activity = punit->activity;
2448 packet->activity_count = punit->activity_count;
2450 if (punit->activity_target != NULL) {
2451 packet->activity_tgt = extra_index(punit->activity_target);
2452 } else {
2453 packet->activity_tgt = EXTRA_NONE;
2456 packet->changed_from = punit->changed_from;
2457 packet->changed_from_count = punit->changed_from_count;
2459 if (punit->changed_from_target != NULL) {
2460 packet->changed_from_tgt = extra_index(punit->changed_from_target);
2461 } else {
2462 packet->changed_from_tgt = EXTRA_NONE;
2465 packet->ai = punit->ai_controlled;
2466 packet->fuel = punit->fuel;
2467 packet->goto_tile = (NULL != punit->goto_tile
2468 ? tile_index(punit->goto_tile) : -1);
2469 packet->paradropped = punit->paradropped;
2470 packet->done_moving = punit->done_moving;
2471 if (!unit_transported(punit)) {
2472 packet->transported = FALSE;
2473 packet->transported_by = 0;
2474 } else {
2475 packet->transported = TRUE;
2476 packet->transported_by = unit_transport_get(punit)->id;
2478 if (punit->carrying != NULL) {
2479 packet->carrying = goods_index(punit->carrying);
2480 } else {
2481 packet->carrying = -1;
2483 packet->occupied = (get_transporter_occupancy(punit) > 0);
2484 packet->battlegroup = punit->battlegroup;
2485 packet->has_orders = punit->has_orders;
2486 if (punit->has_orders) {
2487 int i;
2489 packet->orders_length = punit->orders.length;
2490 packet->orders_index = punit->orders.index;
2491 packet->orders_repeat = punit->orders.repeat;
2492 packet->orders_vigilant = punit->orders.vigilant;
2493 for (i = 0; i < punit->orders.length; i++) {
2494 packet->orders[i] = punit->orders.list[i].order;
2495 packet->orders_dirs[i] = punit->orders.list[i].dir;
2496 packet->orders_activities[i] = punit->orders.list[i].activity;
2497 packet->orders_targets[i] = punit->orders.list[i].target;
2498 packet->orders_actions[i] = punit->orders.list[i].action;
2500 } else {
2501 packet->orders_length = packet->orders_index = 0;
2502 packet->orders_repeat = packet->orders_vigilant = FALSE;
2503 /* No need to initialize array. */
2506 packet->action_decision_want = punit->action_decision_want;
2507 packet->action_decision_tile = (punit->action_decision_tile
2508 ? tile_index(punit->action_decision_tile)
2509 : IDENTITY_NUMBER_ZERO);
2512 /**************************************************************************
2513 Package a short_unit_info packet. This contains a limited amount of
2514 information about the unit, and is sent to players who shouldn't know
2515 everything (like the unit's owner's enemies).
2516 **************************************************************************/
2517 void package_short_unit(struct unit *punit,
2518 struct packet_unit_short_info *packet,
2519 enum unit_info_use packet_use, int info_city_id)
2521 packet->packet_use = packet_use;
2522 packet->info_city_id = info_city_id;
2524 packet->id = punit->id;
2525 packet->owner = player_number(unit_owner(punit));
2526 packet->tile = tile_index(unit_tile(punit));
2527 packet->facing = punit->facing;
2528 packet->veteran = punit->veteran;
2529 packet->type = utype_number(unit_type_get(punit));
2530 packet->hp = punit->hp;
2531 packet->occupied = (get_transporter_occupancy(punit) > 0);
2532 if (punit->activity == ACTIVITY_EXPLORE
2533 || punit->activity == ACTIVITY_GOTO) {
2534 packet->activity = ACTIVITY_IDLE;
2535 } else {
2536 packet->activity = punit->activity;
2539 if (punit->activity_target == NULL) {
2540 packet->activity_tgt = EXTRA_NONE;
2541 } else {
2542 packet->activity_tgt = extra_index(punit->activity_target);
2545 /* Transported_by information is sent to the client even for units that
2546 * aren't fully known. Note that for non-allied players, any transported
2547 * unit can't be seen at all. For allied players we have to know if
2548 * transporters have room in them so that we can load units properly. */
2549 if (!unit_transported(punit)) {
2550 packet->transported = FALSE;
2551 packet->transported_by = 0;
2552 } else {
2553 packet->transported = TRUE;
2554 packet->transported_by = unit_transport_get(punit)->id;
2558 /**************************************************************************
2559 Handle situation where unit goes out of player sight.
2560 **************************************************************************/
2561 void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2563 dlsend_packet_unit_remove(pplayer->connections, punit->id);
2564 if (punit->server.moving != NULL) {
2565 /* Update status of 'pplayer' vision for 'punit'. */
2566 BV_CLR(punit->server.moving->can_see_unit, player_index(pplayer));
2570 /****************************************************************************
2571 send the unit to the players who need the info.
2572 dest = NULL means all connections (game.est_connections)
2573 ****************************************************************************/
2574 void send_unit_info(struct conn_list *dest, struct unit *punit)
2576 const struct player *powner;
2577 struct packet_unit_info info;
2578 struct packet_unit_short_info sinfo;
2579 struct unit_move_data *pdata;
2581 if (dest == NULL) {
2582 dest = game.est_connections;
2585 CHECK_UNIT(punit);
2587 powner = unit_owner(punit);
2588 package_unit(punit, &info);
2589 package_short_unit(punit, &sinfo, UNIT_INFO_IDENTITY, 0);
2590 pdata = punit->server.moving;
2592 conn_list_iterate(dest, pconn) {
2593 struct player *pplayer = conn_get_player(pconn);
2595 /* Be careful to consider all cases where pplayer is NULL... */
2596 if (pplayer == NULL) {
2597 if (pconn->observer) {
2598 send_packet_unit_info(pconn, &info);
2600 } else if (pplayer == powner) {
2601 send_packet_unit_info(pconn, &info);
2602 if (pdata != NULL) {
2603 BV_SET(pdata->can_see_unit, player_index(pplayer));
2605 } else if (can_player_see_unit(pplayer, punit)) {
2606 send_packet_unit_short_info(pconn, &sinfo, FALSE);
2607 if (pdata != NULL) {
2608 BV_SET(pdata->can_see_unit, player_index(pplayer));
2611 } conn_list_iterate_end;
2614 /**************************************************************************
2615 For each specified connections, send information about all the units
2616 known to that player/conn.
2617 **************************************************************************/
2618 void send_all_known_units(struct conn_list *dest)
2620 conn_list_do_buffer(dest);
2621 conn_list_iterate(dest, pconn) {
2622 struct player *pplayer = pconn->playing;
2624 if (NULL == pplayer && !pconn->observer) {
2625 continue;
2628 players_iterate(unitowner) {
2629 unit_list_iterate(unitowner->units, punit) {
2630 send_unit_info(dest, punit);
2631 } unit_list_iterate_end;
2632 } players_iterate_end;
2634 conn_list_iterate_end;
2635 conn_list_do_unbuffer(dest);
2636 flush_packets();
2639 /**************************************************************************
2640 Nuke a square: 1) remove all units on the square, and 2) halve the
2641 size of the city on the square.
2643 If it isn't a city square or an ocean square then with 50% chance add
2644 some fallout, then notify the client about the changes.
2645 **************************************************************************/
2646 static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
2648 struct city *pcity = NULL;
2650 unit_list_iterate_safe(ptile->units, punit) {
2651 notify_player(unit_owner(punit), ptile, E_UNIT_LOST_MISC, ftc_server,
2652 _("Your %s was nuked by %s."),
2653 unit_tile_link(punit),
2654 pplayer == unit_owner(punit)
2655 ? _("yourself")
2656 : nation_plural_for_player(pplayer));
2657 if (unit_owner(punit) != pplayer) {
2658 notify_player(pplayer, ptile, E_UNIT_WIN, ftc_server,
2659 _("The %s %s was nuked."),
2660 nation_adjective_for_player(unit_owner(punit)),
2661 unit_tile_link(punit));
2663 wipe_unit(punit, ULR_NUKE, pplayer);
2664 } unit_list_iterate_safe_end;
2666 pcity = tile_city(ptile);
2668 if (pcity) {
2669 notify_player(city_owner(pcity), ptile, E_CITY_NUKED, ftc_server,
2670 _("%s was nuked by %s."),
2671 city_link(pcity),
2672 pplayer == city_owner(pcity)
2673 ? _("yourself")
2674 : nation_plural_for_player(pplayer));
2676 if (city_owner(pcity) != pplayer) {
2677 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2678 _("You nuked %s."),
2679 city_link(pcity));
2682 city_reduce_size(pcity, city_size_get(pcity) / 2, pplayer, "nuke");
2685 if (fc_rand(2) == 1) {
2686 struct extra_type *pextra;
2688 pextra = rand_extra_for_tile(ptile, EC_FALLOUT);
2689 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2690 tile_add_extra(ptile, pextra);
2691 update_tile_knowledge(ptile);
2696 /**************************************************************************
2697 Nuke all the squares in a 3x3 square around the center of the explosion
2698 pplayer is the player that caused the explosion.
2699 **************************************************************************/
2700 void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
2702 square_iterate(ptile, 1, ptile1) {
2703 do_nuke_tile(pplayer, ptile1);
2704 } square_iterate_end;
2706 notify_conn(NULL, ptile, E_NUKE, ftc_server,
2707 _("The %s detonated a nuke!"),
2708 nation_plural_for_player(pplayer));
2711 /**************************************************************************
2712 go by airline, if both cities have an airport and neither has been used this
2713 turn the unit will be transported by it and have its moves set to 0
2714 **************************************************************************/
2715 bool do_airline(struct unit *punit, struct city *pdest_city)
2717 struct city *psrc_city = tile_city(unit_tile(punit));
2719 notify_player(unit_owner(punit), city_tile(pdest_city),
2720 E_UNIT_RELOCATED, ftc_server,
2721 _("%s transported successfully."),
2722 unit_link(punit));
2724 unit_move(punit, pdest_city->tile, punit->moves_left, NULL,
2725 /* Can only airlift to allied and domestic cities */
2726 FALSE);
2728 /* Update airlift fields. */
2729 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
2730 psrc_city->airlift--;
2731 send_city_info(city_owner(psrc_city), psrc_city);
2733 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
2734 pdest_city->airlift--;
2735 send_city_info(city_owner(pdest_city), pdest_city);
2738 return TRUE;
2741 /**************************************************************************
2742 Autoexplore with unit.
2743 **************************************************************************/
2744 void do_explore(struct unit *punit)
2746 switch (manage_auto_explorer(punit)) {
2747 case MR_DEATH:
2748 /* don't use punit! */
2749 return;
2750 case MR_NOT_ALLOWED:
2751 /* Needed for something else */
2752 return;
2753 case MR_OK:
2754 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2755 * but don't count on this. See PR#39792.
2757 if (punit->activity == ACTIVITY_EXPLORE) {
2758 break;
2760 /* fallthru */
2761 default:
2762 unit_activity_handling(punit, ACTIVITY_IDLE);
2764 /* FIXME: When the manage_auto_explorer() call changes the activity from
2765 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2766 * alone. We reset it here. See PR#12931. */
2767 punit->ai_controlled = FALSE;
2768 break;
2771 send_unit_info(NULL, punit); /* probably duplicate */
2774 /**************************************************************************
2775 Returns whether the drop was made or not. Note that it also returns 1
2776 in the case where the drop was succesful, but the unit was killed by
2777 barbarians in a hut.
2778 **************************************************************************/
2779 bool do_paradrop(struct unit *punit, struct tile *ptile)
2781 struct player *pplayer = unit_owner(punit);
2783 if (map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
2784 if (!can_unit_exist_at_tile(punit, ptile)
2785 && (!game.info.paradrop_to_transport
2786 || !unit_could_load_at(punit, ptile))) {
2787 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2788 _("This unit cannot paradrop into %s."),
2789 terrain_name_translation(tile_terrain(ptile)));
2790 return FALSE;
2793 if (NULL != is_non_attack_city_tile(ptile, pplayer)) {
2794 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2795 _("Cannot attack unless you declare war first."));
2796 return FALSE;
2799 unit_list_iterate(ptile->units, pother) {
2800 if (can_player_see_unit(pplayer, pother)
2801 && pplayers_non_attack(pplayer, unit_owner(pother))) {
2802 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2803 _("Cannot attack unless you declare war first."));
2804 return FALSE;
2806 } unit_list_iterate_end;
2808 if (is_military_unit(punit)
2809 && !player_can_invade_tile(pplayer, ptile)) {
2810 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2811 _("Cannot invade unless you break peace with "
2812 "%s first."),
2813 player_name(tile_owner(ptile)));
2814 return FALSE;
2816 } else {
2817 /* Only take in account values from player map. */
2818 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
2820 if (NULL == plrtile->site
2821 && !is_native_to_class(unit_class_get(punit), plrtile->terrain,
2822 &(plrtile->extras))) {
2823 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2824 _("This unit cannot paradrop into %s."),
2825 terrain_name_translation(plrtile->terrain));
2826 return FALSE;
2829 if (NULL != plrtile->site
2830 && plrtile->owner != NULL
2831 && pplayers_non_attack(pplayer, plrtile->owner)) {
2832 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2833 _("Cannot attack unless you declare war first."));
2834 return FALSE;
2837 if (is_military_unit(punit)
2838 && NULL != plrtile->owner
2839 && players_non_invade(pplayer, plrtile->owner)) {
2840 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2841 _("Cannot invade unless you break peace with "
2842 "%s first."),
2843 player_name(plrtile->owner));
2844 return FALSE;
2847 /* Safe terrain, really? Not transformed since player last saw it. */
2848 if (!can_unit_exist_at_tile(punit, ptile)
2849 && (!game.info.paradrop_to_transport
2850 || !unit_could_load_at(punit, ptile))) {
2851 map_show_circle(pplayer, ptile, unit_type_get(punit)->vision_radius_sq);
2852 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
2853 _("Your %s paradropped into the %s and was lost."),
2854 unit_tile_link(punit),
2855 terrain_name_translation(tile_terrain(ptile)));
2856 pplayer->score.units_lost++;
2857 server_remove_unit(punit, ULR_NONNATIVE_TERR);
2858 return TRUE;
2862 if (is_non_attack_city_tile(ptile, pplayer)
2863 || is_non_allied_unit_tile(ptile, pplayer)) {
2864 map_show_circle(pplayer, ptile, unit_type_get(punit)->vision_radius_sq);
2865 maybe_make_contact(ptile, pplayer);
2866 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
2867 _("Your %s was killed by enemy units at the "
2868 "paradrop destination."),
2869 unit_tile_link(punit));
2870 /* TODO: Should defender score.units_killed get increased too?
2871 * What if there's units of several allied players? Should the
2872 * city owner or owner of the first/random unit get the kill? */
2873 pplayer->score.units_lost++;
2874 server_remove_unit(punit, ULR_KILLED);
2875 return TRUE;
2878 /* All ok */
2879 punit->paradropped = TRUE;
2880 if (unit_move(punit, ptile, unit_type_get(punit)->paratroopers_mr_sub,
2881 NULL,
2882 /* A paradrop into a non allied city results in a city
2883 * occupation. */
2884 /* FIXME: move the following actor requirements to the
2885 * ruleset. One alternative is to split "Paradrop Unit".
2886 * Another is to use different enablers. */
2887 (pplayer->ai_common.barbarian_type != ANIMAL_BARBARIAN
2888 && uclass_has_flag(unit_class_get(punit),
2889 UCF_CAN_OCCUPY_CITY)
2890 && !unit_has_type_flag(punit, UTYF_CIVILIAN)
2891 && is_non_allied_city_tile(ptile, pplayer)))) {
2892 /* Ensure we finished on valid state. */
2893 fc_assert(can_unit_exist_at_tile(punit, unit_tile(punit))
2894 || unit_transported(punit));
2896 return TRUE;
2899 /**************************************************************************
2900 Give 25 Gold or kill the unit. For H_LIMITEDHUTS
2901 Return TRUE if unit is alive, and FALSE if it was killed
2902 **************************************************************************/
2903 static bool hut_get_limited(struct unit *punit)
2905 bool ok = TRUE;
2906 int hut_chance = fc_rand(12);
2907 struct player *pplayer = unit_owner(punit);
2908 /* 1 in 12 to get barbarians */
2909 if (hut_chance != 0) {
2910 int cred = 25;
2911 notify_player(pplayer, unit_tile(punit), E_HUT_GOLD, ftc_server,
2912 PL_("You found %d gold.",
2913 "You found %d gold.", cred), cred);
2914 pplayer->economic.gold += cred;
2915 } else if (city_exists_within_max_city_map(unit_tile(punit), TRUE)
2916 || unit_has_type_flag(punit, UTYF_GAMELOSS)) {
2917 notify_player(pplayer, unit_tile(punit),
2918 E_HUT_BARB_CITY_NEAR, ftc_server,
2919 _("An abandoned village is here."));
2920 } else {
2921 notify_player(pplayer, unit_tile(punit), E_HUT_BARB_KILLED, ftc_server,
2922 _("Your %s has been killed by barbarians!"),
2923 unit_tile_link(punit));
2924 wipe_unit(punit, ULR_BARB_UNLEASH, NULL);
2925 ok = FALSE;
2927 return ok;
2930 /**************************************************************************
2931 Due to the effects in the scripted hut behavior can not be predicted,
2932 unit_enter_hut returns nothing.
2933 **************************************************************************/
2934 static void unit_enter_hut(struct unit *punit)
2936 struct player *pplayer = unit_owner(punit);
2937 enum hut_behavior behavior = unit_class_get(punit)->hut_behavior;
2938 struct tile *ptile = unit_tile(punit);
2940 /* FIXME: Should we still run "hut_enter" script when
2941 * hut_behavior is HUT_NOTHING or HUT_FRIGHTEN? */
2942 if (behavior == HUT_NOTHING) {
2943 return;
2946 extra_type_by_category_iterate(ECAT_BONUS, pextra) {
2947 if (tile_has_extra(ptile, pextra)) {
2948 pplayer->server.huts++;
2950 destroy_extra(ptile, pextra);
2951 update_tile_knowledge(unit_tile(punit));
2953 if (behavior == HUT_FRIGHTEN) {
2954 notify_player(pplayer, unit_tile(punit), E_HUT_BARB, ftc_server,
2955 _("Your overflight frightens the tribe;"
2956 " they scatter in terror."));
2957 return;
2960 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
2961 if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
2962 (void) hut_get_limited(punit);
2963 return;
2966 /* FIXME: Should have parameter for hut extra type */
2967 script_server_signal_emit("hut_enter", 1,
2968 API_TYPE_UNIT, punit);
2970 } extra_type_by_category_iterate_end;
2972 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
2973 return;
2976 /****************************************************************************
2977 Put the unit onto the transporter, and tell everyone.
2978 ****************************************************************************/
2979 void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
2981 fc_assert_ret(punit != NULL);
2982 fc_assert_ret(ptrans != NULL);
2984 unit_transport_load(punit, ptrans, FALSE);
2986 send_unit_info(NULL, punit);
2987 send_unit_info(NULL, ptrans);
2990 /****************************************************************************
2991 Load unit to transport, send transport's loaded status to everyone.
2992 ****************************************************************************/
2993 static void unit_transport_load_tp_status(struct unit *punit,
2994 struct unit *ptrans,
2995 bool force)
2997 bool had_cargo;
2999 fc_assert_ret(punit != NULL);
3000 fc_assert_ret(ptrans != NULL);
3002 had_cargo = get_transporter_occupancy(ptrans) > 0;
3004 unit_transport_load(punit, ptrans, force);
3006 if (!had_cargo) {
3007 /* Transport's loaded status changed */
3008 send_unit_info(NULL, ptrans);
3012 /****************************************************************************
3013 Pull the unit off of the transporter, and tell everyone.
3014 ****************************************************************************/
3015 void unit_transport_unload_send(struct unit *punit)
3017 struct unit *ptrans;
3019 fc_assert_ret(punit);
3021 ptrans = unit_transport_get(punit);
3023 fc_assert_ret(ptrans);
3025 unit_transport_unload(punit);
3027 send_unit_info(NULL, punit);
3028 send_unit_info(NULL, ptrans);
3031 /*****************************************************************
3032 Used when unit_survive_autoattack()'s autoattack_prob_list
3033 autoattack frees its items.
3034 *****************************************************************/
3035 static void autoattack_prob_free(struct autoattack_prob *prob)
3037 free(prob);
3040 /**************************************************************************
3041 This function is passed to autoattack_prob_list_sort() to sort a list of
3042 units and action probabilities according to their win chance against the
3043 autoattack target, modified by transportation relationships.
3045 The reason for making sure that a cargo unit is ahead of its
3046 transporter(s) is to leave transports out of combat if at all possible.
3047 (The transport could be destroyed during combat.)
3048 **************************************************************************/
3049 static int compare_units(const struct autoattack_prob *const *p1,
3050 const struct autoattack_prob *const *q1)
3052 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3053 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3055 /* Sort by transport depth first. This makes sure that no transport
3056 * attacks before its cargo does -- cargo sorts earlier in the list. */
3058 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3060 /* Walk the transport stacks in parallel, so as to bail out as soon as
3061 * one of them is empty (avoid walking deep stacks more often than
3062 * necessary). */
3063 while (p1trans && q1trans) {
3064 p1trans = unit_transport_get(p1trans);
3065 q1trans = unit_transport_get(q1trans);
3067 if (!p1trans && q1trans) {
3068 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3069 * earlier in the list (p1 > q1). */
3070 return 1;
3071 } else if (p1trans && !q1trans) {
3072 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3073 return -1;
3075 /* else same depth, so move on to checking win chance: */
3078 /* Put the units with the highest probability of success first. The up
3079 * side of this is that units with bonuses against the victim attacks
3080 * before other units. The downside is that strong units can be led
3081 * away by sacrificial units. */
3082 return (-1
3083 /* Assume the worst. */
3084 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3087 /*****************************************************************
3088 Check if unit survives enemy autoattacks. We assume that any
3089 unit that is adjacent to us can see us.
3090 *****************************************************************/
3091 static bool unit_survive_autoattack(struct unit *punit)
3093 struct autoattack_prob_list *autoattack;
3094 int moves = punit->moves_left;
3095 int sanity1 = punit->id;
3097 if (!game.server.autoattack) {
3098 return TRUE;
3101 autoattack = autoattack_prob_list_new_full(autoattack_prob_free);
3103 /* Kludge to prevent attack power from dropping to zero during calc */
3104 punit->moves_left = MAX(punit->moves_left, 1);
3106 adjc_iterate(unit_tile(punit), ptile) {
3107 /* First add all eligible units to a autoattack list */
3108 unit_list_iterate(ptile->units, penemy) {
3109 struct autoattack_prob *probability = fc_malloc(sizeof(*probability));
3110 struct tile *tgt_tile = unit_tile(punit);
3112 fc_assert_action(tgt_tile, continue);
3114 probability->prob =
3115 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ,
3116 penemy, unit_owner(punit), NULL,
3117 tgt_tile, tile_city(tgt_tile),
3118 punit);
3120 if (action_prob_possible(probability->prob)) {
3121 probability->unit_id = penemy->id;
3122 autoattack_prob_list_prepend(autoattack, probability);
3124 } unit_list_iterate_end;
3125 } adjc_iterate_end;
3127 /* Sort the potential attackers from highest to lowest success
3128 * probability. */
3129 if (autoattack_prob_list_size(autoattack) >= 2) {
3130 autoattack_prob_list_sort(autoattack, &compare_units);
3133 autoattack_prob_list_iterate_safe(autoattack, peprob, penemy) {
3134 int sanity2 = penemy->id;
3135 struct tile *ptile = unit_tile(penemy);
3136 struct unit *enemy_defender = get_defender(punit, ptile);
3137 double punitwin, penemywin;
3138 double threshold = 0.25;
3139 struct tile *tgt_tile = unit_tile(punit);
3141 fc_assert(tgt_tile);
3143 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3144 /* Don't leave city defenseless */
3145 threshold = 0.90;
3148 if (NULL != enemy_defender) {
3149 punitwin = unit_win_chance(punit, enemy_defender);
3150 } else {
3151 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3152 punitwin = 1.0;
3155 /* Previous attacks may have changed the odds. Recalculate. */
3156 peprob->prob =
3157 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ,
3158 penemy, unit_owner(punit), NULL,
3159 tgt_tile, tile_city(tgt_tile),
3160 punit);
3162 if (!action_prob_possible(peprob->prob)) {
3163 /* No longer legal. */
3164 continue;
3167 /* Assume the worst. */
3168 penemywin = action_prob_to_0_to_1_pessimist(peprob->prob);
3170 if ((penemywin > 1.0 - punitwin
3171 || unit_has_type_flag(punit, UTYF_PROVOKING))
3172 && penemywin > threshold) {
3174 #ifdef REALLY_DEBUG_THIS
3175 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3176 unit_rule_name(penemy), unit_rule_name(punit),
3177 TILE_XY(unit_tile(punit)), penemywin,
3178 1.0 - punitwin, threshold);
3179 #endif
3181 unit_activity_handling(penemy, ACTIVITY_IDLE);
3182 action_auto_perf_unit_do(AAPC_UNIT_MOVED_ADJ,
3183 penemy, unit_owner(punit), NULL,
3184 tgt_tile, tile_city(tgt_tile), punit);
3185 } else {
3186 #ifdef REALLY_DEBUG_THIS
3187 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3188 unit_rule_name(penemy), unit_rule_name(punit),
3189 TILE_XY(unit_tile(punit)), penemywin,
3190 1.0 - punitwin, threshold);
3191 #endif
3192 continue;
3195 if (game_unit_by_number(sanity2)) {
3196 send_unit_info(NULL, penemy);
3198 if (game_unit_by_number(sanity1)) {
3199 send_unit_info(NULL, punit);
3200 } else {
3201 autoattack_prob_list_destroy(autoattack);
3202 return FALSE; /* moving unit dead */
3204 } autoattack_prob_list_iterate_safe_end;
3206 autoattack_prob_list_destroy(autoattack);
3207 if (game_unit_by_number(sanity1)) {
3208 /* We could have lost movement in combat */
3209 punit->moves_left = MIN(punit->moves_left, moves);
3210 send_unit_info(NULL, punit);
3211 return TRUE;
3212 } else {
3213 return FALSE;
3217 /****************************************************************************
3218 Cancel orders for the unit.
3219 ****************************************************************************/
3220 static void cancel_orders(struct unit *punit, char *dbg_msg)
3222 free_unit_orders(punit);
3223 send_unit_info(NULL, punit);
3224 log_debug("%s", dbg_msg);
3227 /*****************************************************************
3228 Will wake up any neighboring enemy sentry units or patrolling
3229 units.
3230 *****************************************************************/
3231 static void wakeup_neighbor_sentries(struct unit *punit)
3233 bool alone_in_city;
3235 if (NULL != tile_city(unit_tile(punit))) {
3236 int count = 0;
3238 unit_list_iterate(unit_tile(punit)->units, aunit) {
3239 /* Consider only units not transported. */
3240 if (!unit_transported(aunit)) {
3241 count++;
3243 } unit_list_iterate_end;
3245 alone_in_city = (1 == count);
3246 } else {
3247 alone_in_city = FALSE;
3250 /* There may be sentried units with a sightrange > 3, but we don't
3251 wake them up if the punit is farther away than 3. */
3252 square_iterate(unit_tile(punit), 3, ptile) {
3253 unit_list_iterate(ptile->units, penemy) {
3254 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3255 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3257 if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
3258 && penemy->activity == ACTIVITY_SENTRY
3259 && radius_sq >= distance_sq
3260 /* If the unit moved on a city, and the unit is alone, consider
3261 * it is visible. */
3262 && (alone_in_city
3263 || can_player_see_unit(unit_owner(penemy), punit))
3264 /* on board transport; don't awaken */
3265 && can_unit_exist_at_tile(penemy, unit_tile(penemy))) {
3266 set_unit_activity(penemy, ACTIVITY_IDLE);
3267 send_unit_info(NULL, penemy);
3269 } unit_list_iterate_end;
3270 } square_iterate_end;
3272 /* Wakeup patrolling units we bump into.
3273 We do not wakeup units further away than 3 squares... */
3274 square_iterate(unit_tile(punit), 3, ptile) {
3275 unit_list_iterate(ptile->units, ppatrol) {
3276 if (punit != ppatrol
3277 && unit_has_orders(ppatrol)
3278 && ppatrol->orders.vigilant) {
3279 if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
3280 cancel_orders(ppatrol, " stopping because of nearby enemy");
3281 notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
3282 E_UNIT_ORDERS, ftc_server,
3283 _("Orders for %s aborted after enemy movement was "
3284 "spotted."),
3285 unit_link(ppatrol));
3288 } unit_list_iterate_end;
3289 } square_iterate_end;
3292 /**************************************************************************
3293 Does: 1) updates the unit's homecity and the city it enters/leaves (the
3294 city's happiness varies). This also takes into account when the
3295 unit enters/leaves a fortress.
3296 2) updates adjacent cities' unavailable tiles.
3298 FIXME: Sometimes it is not necessary to send cities because the goverment
3299 doesn't care whether a unit is away or not.
3300 **************************************************************************/
3301 static bool unit_move_consequences(struct unit *punit,
3302 struct tile *src_tile,
3303 struct tile *dst_tile,
3304 bool passenger,
3305 bool conquer_city_allowed)
3307 struct city *fromcity = tile_city(src_tile);
3308 struct city *tocity = tile_city(dst_tile);
3309 struct city *homecity_start_pos = NULL;
3310 struct city *homecity_end_pos = NULL;
3311 int homecity_id_start_pos = punit->homecity;
3312 int homecity_id_end_pos = punit->homecity;
3313 struct player *pplayer_start_pos = unit_owner(punit);
3314 struct player *pplayer_end_pos = pplayer_start_pos;
3315 struct unit_type *type_start_pos = unit_type_get(punit);
3316 struct unit_type *type_end_pos = type_start_pos;
3317 bool refresh_homecity_start_pos = FALSE;
3318 bool refresh_homecity_end_pos = FALSE;
3319 int saved_id = punit->id;
3320 bool alive = TRUE;
3322 if (tocity && conquer_city_allowed) {
3323 if (!passenger) {
3324 /* The unit that does the move may conquer. */
3325 unit_conquer_city(punit, tocity);
3328 /* Run for passengers too. A passenger may have been killed when its
3329 * transport conquered a city. (unit_conquer_city() can cause Lua code
3330 * to run) */
3332 alive = unit_is_alive(saved_id);
3333 if (alive) {
3334 /* In case script has changed something about unit */
3335 pplayer_end_pos = unit_owner(punit);
3336 type_end_pos = unit_type_get(punit);
3337 homecity_id_end_pos = punit->homecity;
3341 if (homecity_id_start_pos != 0) {
3342 homecity_start_pos = game_city_by_number(homecity_id_start_pos);
3344 if (homecity_id_start_pos != homecity_id_end_pos) {
3345 homecity_end_pos = game_city_by_number(homecity_id_end_pos);
3346 } else {
3347 homecity_end_pos = homecity_start_pos;
3350 /* We only do refreshes for non-AI players to now make sure the AI turns
3351 doesn't take too long. Perhaps we should make a special refresh_city
3352 functions that only refreshed happines. */
3354 /* might have changed owners or may be destroyed */
3355 tocity = tile_city(dst_tile);
3357 if (tocity) { /* entering a city */
3358 if (tocity->owner == pplayer_end_pos) {
3359 if (tocity != homecity_end_pos && is_human(pplayer_end_pos)) {
3360 city_refresh(tocity);
3361 send_city_info(pplayer_end_pos, tocity);
3364 if (homecity_start_pos) {
3365 refresh_homecity_start_pos = TRUE;
3369 if (fromcity) { /* leaving a city */
3370 if (homecity_start_pos) {
3371 refresh_homecity_start_pos = TRUE;
3373 if (fromcity != homecity_start_pos
3374 && fromcity->owner == pplayer_start_pos
3375 && is_human(pplayer_start_pos)) {
3376 city_refresh(fromcity);
3377 send_city_info(pplayer_start_pos, fromcity);
3381 /* entering/leaving a fortress or friendly territory */
3382 if (homecity_start_pos || homecity_end_pos) {
3383 if ((game.info.happyborders != HB_DISABLED && tile_owner(src_tile) != tile_owner(dst_tile))
3384 || (tile_has_base_flag_for_unit(dst_tile,
3385 type_end_pos,
3386 BF_NOT_AGGRESSIVE)
3387 && is_friendly_city_near(pplayer_end_pos, dst_tile))
3388 || (tile_has_base_flag_for_unit(src_tile,
3389 type_start_pos,
3390 BF_NOT_AGGRESSIVE)
3391 && is_friendly_city_near(pplayer_start_pos, src_tile))) {
3392 refresh_homecity_start_pos = TRUE;
3393 refresh_homecity_end_pos = TRUE;
3397 if (refresh_homecity_start_pos && is_human(pplayer_start_pos)) {
3398 city_refresh(homecity_start_pos);
3399 send_city_info(pplayer_start_pos, homecity_start_pos);
3401 if (refresh_homecity_end_pos
3402 && (!refresh_homecity_start_pos
3403 || homecity_start_pos != homecity_end_pos)
3404 && is_human(pplayer_end_pos)) {
3405 city_refresh(homecity_end_pos);
3406 send_city_info(pplayer_end_pos, homecity_end_pos);
3409 city_map_update_tile_now(dst_tile);
3410 sync_cities();
3412 return alive;
3415 /**************************************************************************
3416 Check if the units activity is legal for a move , and reset it if it isn't.
3417 **************************************************************************/
3418 static void check_unit_activity(struct unit *punit)
3420 switch (punit->activity) {
3421 case ACTIVITY_IDLE:
3422 case ACTIVITY_SENTRY:
3423 case ACTIVITY_EXPLORE:
3424 case ACTIVITY_GOTO:
3425 break;
3426 case ACTIVITY_POLLUTION:
3427 case ACTIVITY_MINE:
3428 case ACTIVITY_IRRIGATE:
3429 case ACTIVITY_FORTIFIED:
3430 case ACTIVITY_FORTRESS:
3431 case ACTIVITY_PILLAGE:
3432 case ACTIVITY_TRANSFORM:
3433 case ACTIVITY_UNKNOWN:
3434 case ACTIVITY_AIRBASE:
3435 case ACTIVITY_FORTIFYING:
3436 case ACTIVITY_FALLOUT:
3437 case ACTIVITY_PATROL_UNUSED:
3438 case ACTIVITY_BASE:
3439 case ACTIVITY_GEN_ROAD:
3440 case ACTIVITY_CONVERT:
3441 case ACTIVITY_OLD_ROAD:
3442 case ACTIVITY_OLD_RAILROAD:
3443 case ACTIVITY_LAST:
3444 set_unit_activity(punit, ACTIVITY_IDLE);
3445 break;
3449 /****************************************************************************
3450 Create a new unit move data, or use previous one if available.
3451 ****************************************************************************/
3452 static struct unit_move_data *unit_move_data(struct unit *punit,
3453 struct tile *psrctile,
3454 struct tile *pdesttile)
3456 struct unit_move_data *pdata;
3457 struct player *powner = unit_owner(punit);
3458 const v_radius_t radius_sq =
3459 V_RADIUS(get_unit_vision_at(punit, pdesttile, V_MAIN),
3460 get_unit_vision_at(punit, pdesttile, V_INVIS));
3461 struct vision *new_vision;
3462 bool success;
3464 if (punit->server.moving) {
3465 /* Recursive moving (probably due to a script). */
3466 pdata = punit->server.moving;
3467 pdata->ref_count++;
3468 fc_assert_msg(pdata->punit == punit,
3469 "Unit number %d (%p) was going to die, but "
3470 "server attempts to move it.",
3471 punit->id, punit);
3472 fc_assert_msg(pdata->old_vision == NULL,
3473 "Unit number %d (%p) has done an incomplete move.",
3474 punit->id, punit);
3475 } else {
3476 pdata = fc_malloc(sizeof(*pdata));
3477 pdata->ref_count = 1;
3478 pdata->punit = punit;
3479 punit->server.moving = pdata;
3480 BV_CLR_ALL(pdata->can_see_unit);
3482 pdata->powner = powner;
3483 BV_CLR_ALL(pdata->can_see_move);
3484 pdata->old_vision = punit->server.vision;
3486 /* Remove unit from the source tile. */
3487 fc_assert(unit_tile(punit) == psrctile);
3488 success = unit_list_remove(psrctile->units, punit);
3489 fc_assert(success == TRUE);
3491 /* Set new tile. */
3492 unit_tile_set(punit, pdesttile);
3493 unit_list_prepend(pdesttile->units, punit);
3495 if (unit_transported(punit)) {
3496 /* Silently free orders since they won't be applicable anymore. */
3497 free_unit_orders(punit);
3500 /* Check unit activity. */
3501 check_unit_activity(punit);
3502 unit_did_action(punit);
3503 unit_forget_last_activity(punit);
3505 /* We first unfog the destination, then send the move,
3506 * and then fog the old territory. This means that the player
3507 * gets a chance to see the newly explored territory while the
3508 * client moves the unit, and both areas are visible during the
3509 * move */
3511 /* Enhance vision if unit steps into a fortress */
3512 new_vision = vision_new(powner, pdesttile);
3513 punit->server.vision = new_vision;
3514 vision_change_sight(new_vision, radius_sq);
3515 ASSERT_VISION(new_vision);
3517 return pdata;
3520 /****************************************************************************
3521 Decrease the reference counter and destroy if needed.
3522 ****************************************************************************/
3523 static void unit_move_data_unref(struct unit_move_data *pdata)
3525 fc_assert_ret(pdata != NULL);
3526 fc_assert_ret(pdata->ref_count > 0);
3527 fc_assert_msg(pdata->old_vision == NULL,
3528 "Unit number %d (%p) has done an incomplete move.",
3529 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3531 pdata->ref_count--;
3532 if (pdata->ref_count == 0) {
3533 if (pdata->punit != NULL) {
3534 fc_assert(pdata->punit->server.moving == pdata);
3535 pdata->punit->server.moving = NULL;
3537 free(pdata);
3541 /*****************************************************************************
3542 Moves a unit. No checks whatsoever! This is meant as a practical
3543 function for other functions, like do_airline, which do the checking
3544 themselves.
3546 If you move a unit you should always use this function, as it also sets
3547 the transport status of the unit correctly. Note that the source tile (the
3548 current tile of the unit) and pdesttile need not be adjacent.
3550 Returns TRUE iff unit still alive.
3551 *****************************************************************************/
3552 bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3553 struct unit *embark_to, bool conquer_city_allowed)
3555 struct player *pplayer;
3556 struct tile *psrctile;
3557 struct city *pcity;
3558 struct unit *ptransporter;
3559 struct packet_unit_info src_info, dest_info;
3560 struct packet_unit_short_info src_sinfo, dest_sinfo;
3561 struct unit_move_data_list *plist =
3562 unit_move_data_list_new_full(unit_move_data_unref);
3563 struct unit_move_data *pdata;
3564 int saved_id;
3565 bool unit_lives;
3566 bool adj;
3567 enum direction8 facing;
3568 struct player *bowner;
3570 /* Some checks. */
3571 fc_assert_ret_val(punit != NULL, FALSE);
3572 fc_assert_ret_val(pdesttile != NULL, FALSE);
3574 pplayer = unit_owner(punit);
3575 saved_id = punit->id;
3576 psrctile = unit_tile(punit);
3577 adj = base_get_direction_for_step(psrctile, pdesttile, &facing);
3579 conn_list_do_buffer(game.est_connections);
3581 /* Unload the unit if on a transport. */
3582 ptransporter = unit_transport_get(punit);
3583 if (ptransporter != NULL) {
3584 /* Unload unit _before_ setting the new tile! */
3585 unit_transport_unload(punit);
3586 /* Send updated information to anyone watching that transporter
3587 * was unloading cargo. */
3588 send_unit_info(NULL, ptransporter);
3591 /* Wakup units next to us before we move. */
3592 wakeup_neighbor_sentries(punit);
3594 /* Make info packets at 'psrctile'. */
3595 if (adj) {
3596 /* If tiles are adjacent, we will show the move to users able
3597 * to see it. */
3598 package_unit(punit, &src_info);
3599 package_short_unit(punit, &src_sinfo, UNIT_INFO_IDENTITY, 0);
3602 /* Make new data for 'punit'. */
3603 pdata = unit_move_data(punit, psrctile, pdesttile);
3604 unit_move_data_list_prepend(plist, pdata);
3606 /* Set unit orientation */
3607 if (adj) {
3608 /* Only change orientation when moving to adjacent tile */
3609 punit->facing = facing;
3612 /* Move magic. */
3613 punit->moved = TRUE;
3614 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3615 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3616 /* The next order may not require any remaining move fragments. */
3617 punit->done_moving = TRUE;
3620 /* No longer relevant. */
3621 punit->action_decision_tile = NULL;
3622 punit->action_decision_want = ACT_DEC_NOTHING;
3624 if (!adj
3625 && action_tgt_city(punit, pdesttile, FALSE)) {
3626 /* The unit can perform an action to the city at the destination tile.
3627 * A long distance move (like an airlift) doesn't ask what action to
3628 * perform before moving. Ask now. */
3630 punit->action_decision_want = ACT_DEC_PASSIVE;
3631 punit->action_decision_tile = pdesttile;
3634 /* Claim ownership of fortress? */
3635 bowner = extra_owner(pdesttile);
3636 if ((bowner == NULL || pplayers_at_war(bowner, pplayer))
3637 && tile_has_claimable_base(pdesttile, unit_type_get(punit))) {
3638 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3639 * Even if original unit cannot claim other kind of bases, the
3640 * first claimed base will have influence over other bases,
3641 * or something like that. */
3642 tile_claim_bases(pdesttile, pplayer);
3645 /* Move all contained units. */
3646 unit_cargo_iterate(punit, pcargo) {
3647 pdata = unit_move_data(pcargo, psrctile, pdesttile);
3648 unit_move_data_list_append(plist, pdata);
3649 } unit_cargo_iterate_end;
3651 /* Get data for 'punit'. */
3652 pdata = unit_move_data_list_front(plist);
3654 /* Determine the players able to see the move(s), now that the player
3655 * vision has been increased. */
3656 if (adj) {
3657 /* Main unit for adjacent move: the move is visible for every player
3658 * able to see on the matching unit layer. */
3659 enum vision_layer vlayer = is_hiding_unit(punit) ? V_INVIS : V_MAIN;
3661 players_iterate(oplayer) {
3662 if (map_is_known_and_seen(psrctile, oplayer, vlayer)
3663 || map_is_known_and_seen(pdesttile, oplayer, vlayer)) {
3664 BV_SET(pdata->can_see_unit, player_index(oplayer));
3665 BV_SET(pdata->can_see_move, player_index(oplayer));
3667 } players_iterate_end;
3669 unit_move_data_list_iterate(plist, pmove_data) {
3670 if (adj && pmove_data == pdata) {
3671 /* If positions are adjacent, we have already handled 'punit'. See
3672 * above. */
3673 continue;
3676 players_iterate(oplayer) {
3677 if ((adj
3678 && can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
3679 pmove_data != pdata))
3680 || can_player_see_unit_at(oplayer, pmove_data->punit, pdesttile,
3681 pmove_data != pdata)) {
3682 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3683 BV_SET(pmove_data->can_see_move, player_index(oplayer));
3685 if (can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
3686 pmove_data != pdata)) {
3687 /* The unit was seen with its source tile even if it was
3688 * teleported. */
3689 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3691 } players_iterate_end;
3692 } unit_move_data_list_iterate_end;
3694 /* Check timeout settings. */
3695 if (current_turn_timeout() != 0 && game.server.timeoutaddenemymove > 0) {
3696 bool new_information_for_enemy = FALSE;
3698 phase_players_iterate(penemy) {
3699 /* Increase the timeout if an enemy unit moves and the
3700 * timeoutaddenemymove setting is in use. */
3701 if (penemy->is_connected
3702 && pplayer != penemy
3703 && pplayers_at_war(pplayer, penemy)
3704 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
3705 new_information_for_enemy = TRUE;
3706 break;
3708 } phase_players_iterate_end;
3710 if (new_information_for_enemy) {
3711 increase_timeout_because_unit_moved();
3715 /* Notifications of the move to the clients. */
3716 if (adj) {
3717 /* Special case: 'punit' is moving to adjacent position. Then we show
3718 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
3720 /* Make info packets at 'pdesttile'. */
3721 package_unit(punit, &dest_info);
3722 package_short_unit(punit, &dest_sinfo, UNIT_INFO_IDENTITY, 0);
3724 conn_list_iterate(game.est_connections, pconn) {
3725 struct player *aplayer = conn_get_player(pconn);
3727 if (aplayer == NULL) {
3728 if (pconn->observer) {
3729 /* Global observers see all... */
3730 send_packet_unit_info(pconn, &src_info);
3731 send_packet_unit_info(pconn, &dest_info);
3733 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
3734 if (aplayer == pplayer) {
3735 send_packet_unit_info(pconn, &src_info);
3736 send_packet_unit_info(pconn, &dest_info);
3737 } else {
3738 send_packet_unit_short_info(pconn, &src_sinfo, FALSE);
3739 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
3742 } conn_list_iterate_end;
3745 /* Other moves. */
3746 unit_move_data_list_iterate(plist, pmove_data) {
3747 if (adj && pmove_data == pdata) {
3748 /* If positions are adjacent, we have already shown 'punit' move.
3749 * See above. */
3750 continue;
3753 /* Make info packets at 'pdesttile'. */
3754 package_unit(pmove_data->punit, &dest_info);
3755 package_short_unit(pmove_data->punit, &dest_sinfo,
3756 UNIT_INFO_IDENTITY, 0);
3758 conn_list_iterate(game.est_connections, pconn) {
3759 struct player *aplayer = conn_get_player(pconn);
3761 if (aplayer == NULL) {
3762 if (pconn->observer) {
3763 /* Global observers see all... */
3764 send_packet_unit_info(pconn, &dest_info);
3766 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
3767 if (aplayer == pmove_data->powner) {
3768 send_packet_unit_info(pconn, &dest_info);
3769 } else {
3770 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
3773 } conn_list_iterate_end;
3774 } unit_move_data_list_iterate_end;
3776 /* Clear old vision. */
3777 unit_move_data_list_iterate(plist, pmove_data) {
3778 vision_clear_sight(pmove_data->old_vision);
3779 vision_free(pmove_data->old_vision);
3780 pmove_data->old_vision = NULL;
3781 } unit_move_data_list_iterate_end;
3783 /* Move consequences. */
3784 unit_move_data_list_iterate(plist, pmove_data) {
3785 struct unit *aunit = pmove_data->punit;
3787 if (aunit != NULL
3788 && unit_owner(aunit) == pmove_data->powner
3789 && unit_tile(aunit) == pdesttile) {
3790 (void) unit_move_consequences(aunit, psrctile, pdesttile,
3791 pdata != pmove_data,
3792 conquer_city_allowed);
3794 } unit_move_data_list_iterate_end;
3796 unit_lives = (pdata->punit == punit);
3798 /* Wakeup units and make contact. */
3799 if (unit_lives) {
3800 wakeup_neighbor_sentries(punit);
3802 maybe_make_contact(pdesttile, pplayer);
3804 if (unit_lives) {
3805 /* Special checks for ground units in the ocean. */
3806 if (embark_to || !can_unit_survive_at_tile(punit, pdesttile)) {
3807 if (embark_to != NULL) {
3808 ptransporter = embark_to;
3809 } else {
3810 ptransporter = transporter_for_unit(punit);
3812 if (ptransporter) {
3813 unit_transport_load_tp_status(punit, ptransporter, FALSE);
3815 /* Set activity to sentry if boarding a ship. */
3816 if (is_human(pplayer)
3817 && !unit_has_orders(punit)
3818 && !punit->ai_controlled
3819 && !can_unit_exist_at_tile(punit, pdesttile)) {
3820 set_unit_activity(punit, ACTIVITY_SENTRY);
3823 send_unit_info(NULL, punit);
3828 /* Remove units going out of sight. */
3829 unit_move_data_list_iterate_rev(plist, pmove_data) {
3830 struct unit *aunit = pmove_data->punit;
3832 if (aunit == NULL) {
3833 continue; /* Died! */
3836 players_iterate(aplayer) {
3837 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
3838 && !can_player_see_unit(aplayer, aunit)) {
3839 unit_goes_out_of_sight(aplayer, aunit);
3841 } players_iterate_end;
3842 } unit_move_data_list_iterate_rev_end;
3844 /* Inform the owner's client about actor unit arrival. Can, depending on
3845 * the client settings, cause the client to start the process that makes
3846 * the action selection dialog pop up. */
3847 if ((pcity = tile_city(pdesttile))) {
3848 /* Arrival in a city counts. */
3850 unit_move_data_list_iterate(plist, pmove_data) {
3851 struct unit *ptrans;
3852 bool ok;
3853 struct unit *act_unit;
3854 struct player *act_player;
3856 act_unit = pmove_data->punit;
3857 act_player = unit_owner(act_unit);
3859 if (act_unit == NULL
3860 || !unit_is_alive(act_unit->id)) {
3861 /* The unit died before reaching this point. */
3862 continue;
3865 if (unit_tile(act_unit) != pdesttile) {
3866 /* The unit didn't arrive at the destination tile. */
3867 continue;
3870 if (!is_human(act_player)) {
3871 /* Only humans need reminders. */
3872 continue;
3875 if (!unit_transported(act_unit)) {
3876 /* Don't show the action selection dialog again. Non transported
3877 * units are handled before they move to the tile. */
3878 continue;
3881 /* Open action dialog only if 'act_unit' and all its transporters
3882 * (recursively) don't have orders. */
3883 if (unit_has_orders(act_unit)) {
3884 /* The unit it self has orders. */
3885 continue;
3888 for (ptrans = unit_transport_get(act_unit);;
3889 ptrans = unit_transport_get(ptrans)) {
3890 if (NULL == ptrans) {
3891 /* No (recursive) transport has orders. */
3892 ok = TRUE;
3893 break;
3894 } else if (unit_has_orders(ptrans)) {
3895 /* A unit transporting the unit has orders */
3896 ok = FALSE;
3897 break;
3901 if (!ok) {
3902 /* A unit transporting act_unit has orders. */
3903 continue;
3906 if (action_tgt_city(act_unit, pdesttile, FALSE)) {
3907 /* There is a valid target. */
3909 act_unit->action_decision_want = ACT_DEC_PASSIVE;
3910 act_unit->action_decision_tile = pdesttile;
3912 /* Let the client know that this unit wants the player to decide
3913 * what to do. */
3914 send_unit_info(player_reply_dest(act_player), act_unit);
3916 } unit_move_data_list_iterate_end;
3919 unit_move_data_list_destroy(plist);
3921 /* Check cities at source and destination. */
3922 if ((pcity = tile_city(psrctile))) {
3923 refresh_dumb_city(pcity);
3925 if ((pcity = tile_city(pdesttile))) {
3926 refresh_dumb_city(pcity);
3929 if (unit_lives) {
3930 /* Let the scripts run ... */
3931 script_server_signal_emit("unit_moved", 3,
3932 API_TYPE_UNIT, punit,
3933 API_TYPE_TILE, psrctile,
3934 API_TYPE_TILE, pdesttile);
3935 unit_lives = unit_is_alive(saved_id);
3938 if (unit_lives) {
3939 /* Autoattack. */
3940 unit_lives = unit_survive_autoattack(punit);
3943 if (unit_lives) {
3944 /* Is there a hut? */
3945 if (tile_has_cause_extra(pdesttile, EC_HUT)) {
3946 unit_enter_hut(punit);
3947 unit_lives = unit_is_alive(saved_id);
3951 conn_list_do_unbuffer(game.est_connections);
3953 return unit_lives;
3956 /**************************************************************************
3957 Maybe cancel the goto if there is an enemy in the way
3958 **************************************************************************/
3959 static bool maybe_cancel_goto_due_to_enemy(struct unit *punit,
3960 struct tile *ptile)
3962 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
3963 || is_non_allied_city_tile(ptile, unit_owner(punit)));
3966 /**************************************************************************
3967 Maybe cancel the patrol as there is an enemy near.
3969 If you modify the wakeup range you should change it in
3970 wakeup_neighbor_sentries() too.
3971 **************************************************************************/
3972 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
3974 bool cancel = FALSE;
3975 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
3976 struct player *pplayer = unit_owner(punit);
3978 circle_iterate(unit_tile(punit), radius_sq, ptile) {
3979 struct unit *penemy = is_non_allied_unit_tile(ptile, pplayer);
3981 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
3983 if ((penemy && can_player_see_unit(pplayer, penemy))
3984 || (pdcity && !pplayers_allied(pplayer, vision_site_owner(pdcity))
3985 && pdcity->occupied)) {
3986 cancel = TRUE;
3987 break;
3989 } circle_iterate_end;
3991 return cancel;
3994 /**************************************************************************
3995 Returns TRUE iff it is reasonable to assume that the player is wathing
3996 the unit.
3998 Since the player is watching the unit there is no need to inform him
3999 about things he could see happening. Remember that it still may
4000 be necessary to explain why something happened.
4001 **************************************************************************/
4002 static inline bool player_is_watching(struct unit *punit, const bool fresh)
4004 /* The player just sent the orders to the unit. The unit has moves left.
4005 * It is therefore safe to assume that the player already is paying
4006 * attention to the unit. */
4007 return fresh && punit->moves_left > 0;
4010 /****************************************************************************
4011 Executes a unit's orders stored in punit->orders. The unit is put on idle
4012 if an action fails or if "patrol" is set and an enemy unit is encountered.
4014 The return value will be TRUE if the unit lives, FALSE otherwise. (This
4015 function used to return a goto_result enumeration, declared in gotohand.h.
4016 But this enumeration was never checked by the caller and just lead to
4017 confusion. All the caller really needs to know is if the unit lived or
4018 died; everything else is handled internally within execute_orders.)
4020 If the orders are repeating the loop starts over at the beginning once it
4021 completes. To avoid infinite loops on railroad we stop for this
4022 turn when the unit is back where it started, even if it have moves left.
4024 A unit will attack under orders only on its final action.
4026 The fresh parameter is true if the order execution happens because the
4027 orders just were received.
4028 ****************************************************************************/
4029 bool execute_orders(struct unit *punit, const bool fresh)
4031 struct tile *dst_tile;
4032 struct city *tgt_city;
4033 struct unit *tgt_unit;
4034 struct act_prob prob;
4035 int tgt_id;
4036 bool performed;
4037 const char *name;
4038 bool res, last_order;
4039 int unitid = punit->id;
4040 struct player *pplayer = unit_owner(punit);
4041 int moves_made = 0;
4042 enum unit_activity activity;
4044 fc_assert_ret_val(unit_has_orders(punit), TRUE);
4046 if (punit->activity != ACTIVITY_IDLE) {
4047 /* Unit's in the middle of an activity; wait for it to finish. */
4048 punit->done_moving = TRUE;
4049 return TRUE;
4052 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4054 /* Any time the orders are canceled we should give the player a message. */
4056 while (TRUE) {
4057 struct unit_order order;
4059 if (punit->done_moving) {
4060 log_debug(" stopping because we're done this turn");
4061 return TRUE;
4064 if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
4065 /* "Patrol" orders are stopped if an enemy is near. */
4066 cancel_orders(punit, " stopping because of nearby enemy");
4067 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4068 _("Orders for %s aborted as there are units nearby."),
4069 unit_link(punit));
4070 return TRUE;
4073 if (moves_made == punit->orders.length) {
4074 /* For repeating orders, don't repeat more than once per turn. */
4075 log_debug(" stopping because we ran a round");
4076 punit->done_moving = TRUE;
4077 send_unit_info(NULL, punit);
4078 return TRUE;
4080 moves_made++;
4082 order = punit->orders.list[punit->orders.index];
4084 switch (order.order) {
4085 case ORDER_MOVE:
4086 case ORDER_ACTION_MOVE:
4087 case ORDER_FULL_MP:
4088 if (0 == punit->moves_left) {
4089 log_debug(" stopping because of no more move points");
4090 return TRUE;
4092 break;
4093 case ORDER_PERFORM_ACTION:
4094 if (action_mp_full_makes_legal(punit, order.action)) {
4095 log_debug(" stopping. Not enough move points this turn");
4096 return TRUE;
4098 break;
4099 case ORDER_ACTIVITY:
4100 case ORDER_LAST:
4101 /* Those actions don't require moves left. */
4102 break;
4105 last_order = (!punit->orders.repeat
4106 && punit->orders.index + 1 == punit->orders.length);
4108 if (last_order) {
4109 /* Clear the orders before we engage in the move. That way any
4110 * has_orders checks will yield FALSE and this will be treated as
4111 * a normal move. This is important: for instance a caravan goto
4112 * will popup the caravan dialog on the last move only. */
4113 free_unit_orders(punit);
4116 /* Advance the orders one step forward. This is needed because any
4117 * updates sent to the client as a result of the action should include
4118 * the new index value. Note that we have to send_unit_info somewhere
4119 * after this point so that the client is properly updated. */
4120 punit->orders.index++;
4122 switch (order.order) {
4123 case ORDER_FULL_MP:
4124 if (punit->moves_left < unit_move_rate(punit)) {
4125 /* If the unit doesn't have full MP then it just waits until the
4126 * next turn. We assume that the next turn it will have full MP
4127 * (there's no check for that). */
4128 punit->done_moving = TRUE;
4129 log_debug(" waiting this turn");
4130 send_unit_info(NULL, punit);
4132 break;
4133 case ORDER_ACTIVITY:
4134 activity = order.activity;
4136 struct extra_type *pextra = (order.target == EXTRA_NONE ?
4137 NULL :
4138 extra_by_number(order.target));
4140 if (pextra == NULL && activity_requires_target(order.activity)) {
4141 /* Try to find a target extra before giving up this order or, if
4142 * serious enough, all orders. */
4144 enum unit_activity new_activity = order.activity;
4146 unit_assign_specific_activity_target(punit,
4147 &new_activity, &pextra);
4149 if (new_activity != order.activity) {
4150 /* At the time this code was written the only possible activity
4151 * change from unit_assign_specific_activity_target() was from
4152 * ACTIVITY_PILLAGE to ACTIVITY_IDLE. That would only happen
4153 * when a target extra couldn't be found. -- Sveinung */
4154 fc_assert_msg((order.activity == ACTIVITY_PILLAGE
4155 && new_activity == ACTIVITY_IDLE),
4156 "Skipping an order when canceling all orders may"
4157 " have been the correct thing to do.");
4159 /* Already removed, let's continue. */
4160 break;
4163 /* Should have given up or, if supported, changed the order's
4164 * activity to the activity suggested by
4165 * unit_activity_handling_targeted() before this line was
4166 * reached.
4167 * Remember that unit_activity_handling_targeted() has the power
4168 * to change the order's target extra directly. */
4169 fc_assert_msg(new_activity == order.activity,
4170 "Activity not updated. Target may have changed.");
4172 /* Should have found a target or given up before reaching this
4173 * line. */
4174 fc_assert_msg((pextra != NULL
4175 || !activity_requires_target(order.activity)),
4176 "Activity requires a target. No target found.");
4179 if (can_unit_do_activity_targeted(punit, activity, pextra)) {
4180 punit->done_moving = TRUE;
4181 set_unit_activity_targeted(punit, activity, pextra);
4182 send_unit_info(NULL, punit);
4183 break;
4184 } else {
4185 if ((activity == ACTIVITY_BASE
4186 || activity == ACTIVITY_GEN_ROAD
4187 || activity == ACTIVITY_IRRIGATE
4188 || activity == ACTIVITY_MINE)
4189 && tile_has_extra(unit_tile(punit), pextra)) {
4190 break; /* Already built, let's continue. */
4191 } else if ((activity == ACTIVITY_POLLUTION
4192 || activity == ACTIVITY_FALLOUT
4193 || activity == ACTIVITY_PILLAGE)
4194 && !tile_has_extra(unit_tile(punit), pextra)) {
4195 break; /* Already removed, let's continue. */
4200 cancel_orders(punit, " orders canceled because of failed activity");
4201 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4202 _("Orders for %s aborted since they "
4203 "give an invalid activity."),
4204 unit_link(punit));
4205 return TRUE;
4206 case ORDER_MOVE:
4207 case ORDER_ACTION_MOVE:
4208 /* Move unit */
4209 if (!(dst_tile = mapstep(unit_tile(punit), order.dir))) {
4210 cancel_orders(punit, " move order sent us to invalid location");
4211 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4212 _("Orders for %s aborted since they "
4213 "give an invalid location."),
4214 unit_link(punit));
4215 return TRUE;
4218 if (order.order != ORDER_ACTION_MOVE
4219 && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
4220 /* Plain move required: no attack, trade route etc. */
4221 cancel_orders(punit, " orders canceled because of enemy");
4222 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4223 _("Orders for %s aborted as there "
4224 "are units in the way."),
4225 unit_link(punit));
4226 return TRUE;
4229 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4230 res = unit_move_handling(punit, dst_tile, FALSE,
4231 order.order != ORDER_ACTION_MOVE, NULL);
4232 if (!player_unit_by_number(pplayer, unitid)) {
4233 log_debug(" unit died while moving.");
4234 /* A player notification should already have been sent. */
4235 return FALSE;
4238 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4239 /* Movement succeeded but unit didn't move. */
4240 log_debug(" orders resulted in combat.");
4241 send_unit_info(NULL, punit);
4242 return TRUE;
4245 if (!res) {
4246 fc_assert(0 <= punit->moves_left);
4248 /* Movement failed (ZOC, etc.) */
4249 cancel_orders(punit, " attempt to move failed.");
4251 if (!player_is_watching(punit, fresh)
4252 /* The final move "failed" because the unit needs to ask the
4253 * player what action it should take.
4255 * The action decision request notifies the player. Its
4256 * location at the unit's last order makes it clear to the
4257 * player who the decision is for. ("The Spy I sent to Berlin
4258 * has arrived.")
4260 * A notification message is therefore redundant. */
4261 && !(last_order
4262 && punit->action_decision_want == ACT_DEC_ACTIVE
4263 && punit->action_decision_tile == dst_tile)) {
4264 /* The player may have missed this. No one else will announce it
4265 * in a satisfying manner. Inform the player. */
4266 notify_player(pplayer, unit_tile(punit),
4267 E_UNIT_ORDERS, ftc_server,
4268 _("Orders for %s aborted because of failed move."),
4269 unit_link(punit));
4272 return TRUE;
4274 break;
4275 case ORDER_PERFORM_ACTION:
4276 log_debug(" orders: doing action %d", order.action);
4278 if (!direction8_is_valid(order.dir)) {
4279 /* The target of the action is on the actor's tile. */
4280 dst_tile = unit_tile(punit);
4281 } else {
4282 /* The target of the action is on a tile next to the actor. */
4283 dst_tile = mapstep(unit_tile(punit), order.dir);
4286 if (dst_tile == NULL) {
4287 /* Could be at the edge of the map while trying to target a tile
4288 * outside of it. */
4290 cancel_orders(punit, " target location doesn't exist");
4291 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4292 order.action, dst_tile, NULL, NULL);
4294 return TRUE;
4297 /* Get the target city from the target tile. */
4298 tgt_city = tile_city(dst_tile);
4300 if (tgt_city == NULL
4301 && action_id_get_target_kind(order.action) == ATK_CITY) {
4302 /* This action targets a city but no city target was found. */
4304 cancel_orders(punit, " perform action vs city with no city");
4305 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4306 order.action, dst_tile, tgt_city, NULL);
4308 return TRUE;
4311 /* Get a target unit at the target tile. */
4312 tgt_unit = action_tgt_unit(punit, dst_tile, TRUE);
4314 if (tgt_unit == NULL
4315 && action_id_get_target_kind(order.action) == ATK_UNIT) {
4316 /* This action targets a unit but no target unit was found. */
4318 cancel_orders(punit, " perform action vs unit with no unit");
4319 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4320 order.action, dst_tile, tgt_city, tgt_unit);
4322 return TRUE;
4325 /* No target selected. */
4326 tgt_id = -1;
4328 /* Assume impossible until told otherwise. */
4329 prob = ACTPROB_IMPOSSIBLE;
4331 switch (action_id_get_target_kind(order.action)) {
4332 case ATK_UNITS:
4333 prob = action_prob_vs_units(punit, order.action,
4334 dst_tile);
4335 tgt_id = dst_tile->index;
4336 break;
4337 case ATK_TILE:
4338 prob = action_prob_vs_tile(punit, order.action,
4339 dst_tile);
4340 tgt_id = dst_tile->index;
4341 break;
4342 case ATK_CITY:
4343 prob = action_prob_vs_city(punit, order.action,
4344 tgt_city);
4345 tgt_id = tgt_city->id;
4346 break;
4347 case ATK_UNIT:
4348 prob = action_prob_vs_unit(punit, order.action,
4349 tgt_unit);
4351 tgt_id = tgt_unit->id;
4352 break;
4353 case ATK_SELF:
4354 prob = action_prob_self(punit, order.action);
4356 tgt_id = unitid;
4357 break;
4358 case ATK_COUNT:
4359 log_error("Invalid action target kind");
4361 /* The check below will abort and cancel the orders because prob
4362 * was initialized to impossible above this switch statement. */
4364 break;
4367 if (!action_prob_possible(prob)) {
4368 /* The player has enough information to know that this action is
4369 * against the rules. Don't risk any punishment by trying to
4370 * perform it. */
4372 cancel_orders(punit, " illegal action");
4373 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4374 _("%s could not do %s to %s."),
4375 unit_link(punit),
4376 action_id_name_translation(order.action),
4377 tile_link(dst_tile));
4379 /* Try to explain what rule made it illegal. */
4380 illegal_action_msg(unit_owner(punit), E_BAD_COMMAND, punit,
4381 order.action, dst_tile, tgt_city, tgt_unit);
4383 return TRUE;
4386 if (action_id_has_result(order.action, ACTION_FOUND_CITY)) {
4387 /* This action needs a name. */
4388 name = city_name_suggestion(pplayer, unit_tile(punit));
4389 } else {
4390 /* This action doesn't need a name. */
4391 name = "";
4394 performed = unit_perform_action(pplayer,
4395 unitid,
4396 tgt_id,
4397 order.target,
4398 name,
4399 order.action,
4400 ACT_REQ_PLAYER);
4402 if (!player_unit_by_number(pplayer, unitid)) {
4403 /* The unit "died" while performing the action. */
4404 return FALSE;
4407 if (!performed) {
4408 /* The action wasn't performed as ordered. */
4410 cancel_orders(punit, " failed action");
4411 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4412 _("Orders for %s aborted because "
4413 "doing %s to %s failed."),
4414 unit_link(punit),
4415 action_id_name_translation(order.action),
4416 tile_link(dst_tile));
4418 return TRUE;
4421 break;
4422 case ORDER_LAST:
4423 cancel_orders(punit, " client sent invalid order!");
4424 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4425 _("Your %s has invalid orders."),
4426 unit_link(punit));
4427 return TRUE;
4430 if (last_order) {
4431 fc_assert(punit->has_orders == FALSE);
4432 log_debug(" stopping because orders are complete");
4433 return TRUE;
4436 if (punit->orders.index == punit->orders.length) {
4437 fc_assert(punit->orders.repeat);
4438 /* Start over. */
4439 log_debug(" repeating orders.");
4440 punit->orders.index = 0;
4442 } /* end while */
4445 /****************************************************************************
4446 Return the vision the unit will have at the given tile. The base vision
4447 range may be modified by effects.
4449 Note that vision MUST be independent of transported_by for this to work
4450 properly.
4451 ****************************************************************************/
4452 int get_unit_vision_at(struct unit *punit, struct tile *ptile,
4453 enum vision_layer vlayer)
4455 const int base = (unit_type_get(punit)->vision_radius_sq
4456 + get_unittype_bonus(unit_owner(punit), ptile,
4457 unit_type_get(punit),
4458 EFT_UNIT_VISION_RADIUS_SQ));
4459 switch (vlayer) {
4460 case V_MAIN:
4461 return base;
4462 case V_INVIS:
4463 return MIN(base, 2);
4464 case V_COUNT:
4465 break;
4468 log_error("Unsupported vision layer variant: %d.", vlayer);
4469 return 0;
4472 /****************************************************************************
4473 Refresh the unit's vision.
4475 This function has very small overhead and can be called any time effects
4476 may have changed the vision range of the city.
4477 ****************************************************************************/
4478 void unit_refresh_vision(struct unit *punit)
4480 struct vision *uvision = punit->server.vision;
4481 const v_radius_t radius_sq =
4482 V_RADIUS(get_unit_vision_at(punit, unit_tile(punit), V_MAIN),
4483 get_unit_vision_at(punit, unit_tile(punit), V_INVIS));
4485 vision_change_sight(uvision, radius_sq);
4486 ASSERT_VISION(uvision);
4489 /****************************************************************************
4490 Refresh the vision of all units in the list - see unit_refresh_vision.
4491 ****************************************************************************/
4492 void unit_list_refresh_vision(struct unit_list *punitlist)
4494 unit_list_iterate(punitlist, punit) {
4495 unit_refresh_vision(punit);
4496 } unit_list_iterate_end;
4499 /****************************************************************************
4500 Used to implement the game rule controlled by the unitwaittime setting.
4501 Notifies the unit owner if the unit is unable to act.
4502 ****************************************************************************/
4503 bool unit_can_do_action_now(const struct unit *punit)
4505 time_t dt;
4507 if (!punit) {
4508 return FALSE;
4511 if (game.server.unitwaittime <= 0) {
4512 return TRUE;
4515 if (punit->server.action_turn != game.info.turn - 1) {
4516 return TRUE;
4519 dt = time(NULL) - punit->server.action_timestamp;
4520 if (dt < game.server.unitwaittime) {
4521 char buf[64];
4522 format_time_duration(game.server.unitwaittime - dt, buf, sizeof(buf));
4523 notify_player(unit_owner(punit), unit_tile(punit), E_BAD_COMMAND,
4524 ftc_server, _("Your unit may not act for another %s "
4525 "this turn. See /help unitwaittime."), buf);
4526 return FALSE;
4529 return TRUE;
4532 /****************************************************************************
4533 Mark a unit as having done something at the current time. This is used
4534 in conjunction with unit_can_do_action_now() and the unitwaittime setting.
4535 ****************************************************************************/
4536 void unit_did_action(struct unit *punit)
4538 if (!punit) {
4539 return;
4542 punit->server.action_timestamp = time(NULL);
4543 punit->server.action_turn = game.info.turn;
4546 /**************************************************************************
4547 Units (usually barbarian units) may disband spontaneously if they are
4548 far from any enemy units or cities. It is to remove barbarians that do
4549 not engage into any activity for a long time.
4550 **************************************************************************/
4551 bool unit_can_be_retired(struct unit *punit)
4553 /* check if there is enemy nearby */
4554 square_iterate(unit_tile(punit), 3, ptile) {
4555 if (is_enemy_city_tile(ptile, unit_owner(punit))
4556 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4557 return FALSE;
4560 square_iterate_end;
4562 return TRUE;