Fix division by zero when unit activity rate is zero
[freeciv.git] / server / unittools.c
blobcfe9f4c91e67b09d3cf3a6dd2b85677c721a3746
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 "aiiface.h"
62 #include "barbarian.h"
63 #include "citytools.h"
64 #include "cityturn.h"
65 #include "diplhand.h"
66 #include "gamehand.h"
67 #include "maphand.h"
68 #include "notify.h"
69 #include "plrhand.h"
70 #include "sanitycheck.h"
71 #include "sernet.h"
72 #include "srv_main.h"
73 #include "techtools.h"
74 #include "unithand.h"
76 /* server/advisors */
77 #include "advgoto.h"
78 #include "autoexplorer.h"
79 #include "autosettlers.h"
81 /* ai */
82 #include "handicaps.h"
84 #include "unittools.h"
87 /* Tools for controlling the client vision of every unit when a unit
88 * moves + script effects. See unit_move(). You can access this data with
89 * punit->server.moving; it may be NULL if the unit is not moving). */
90 struct unit_move_data {
91 int ref_count;
92 struct unit *punit; /* NULL for invalidating. */
93 struct player *powner;
94 bv_player can_see_unit;
95 bv_player can_see_move;
96 struct vision *old_vision;
99 #define SPECLIST_TAG unit_move_data
100 #include "speclist.h"
101 #define unit_move_data_list_iterate(_plist, _pdata) \
102 TYPED_LIST_ITERATE(struct unit_move_data, _plist, _pdata)
103 #define unit_move_data_list_iterate_end LIST_ITERATE_END
104 #define unit_move_data_list_iterate_rev(_plist, _pdata) \
105 TYPED_LIST_ITERATE_REV(struct unit_move_data, _plist, _pdata)
106 #define unit_move_data_list_iterate_rev_end LIST_ITERATE_REV_END
108 /* We need this global variable for our sort algorithm */
109 static struct tile *autoattack_target;
111 static void unit_restore_hitpoints(struct unit *punit);
112 static void unit_restore_movepoints(struct player *pplayer, struct unit *punit);
113 static void update_unit_activity(struct unit *punit);
114 static bool try_to_save_unit(struct unit *punit, struct unit_type *pttype,
115 bool helpless, bool teleporting);
116 static void wakeup_neighbor_sentries(struct unit *punit);
117 static void do_upgrade_effects(struct player *pplayer);
119 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
120 static int hp_gain_coord(struct unit *punit);
122 static bool maybe_become_veteran_real(struct unit *punit, bool settler);
124 static void unit_transport_load_tp_status(struct unit *punit,
125 struct unit *ptrans,
126 bool force);
128 static void wipe_unit_full(struct unit *punit, bool transported,
129 enum unit_loss_reason reason,
130 struct player *killer);
132 /**************************************************************************
133 Returns a unit type that matches the role_tech or role roles.
135 If role_tech is given, then we look at all units with this role
136 whose requirements are met by any player, and return a random one. This
137 can be used to give a unit to barbarians taken from the set of most
138 advanced units researched by the 'real' players.
140 If role_tech is not give (-1) or if there are no matching unit types,
141 then we look at 'role' value and return a random matching unit type.
143 It is an error if there are no available units. This function will
144 always return a valid unit.
145 **************************************************************************/
146 struct unit_type *find_a_unit_type(enum unit_role_id role,
147 enum unit_role_id role_tech)
149 struct unit_type *which[U_LAST];
150 int i, num=0;
152 if (role_tech != -1) {
153 for(i=0; i<num_role_units(role_tech); i++) {
154 struct unit_type *iunit = get_role_unit(role_tech, i);
155 const int minplayers = 2;
156 int players = 0;
158 /* Note, if there's only one player in the game this check will always
159 * fail. */
160 players_iterate(pplayer) {
161 if (!is_barbarian(pplayer)
162 && can_player_build_unit_direct(pplayer, iunit)) {
163 players++;
165 } players_iterate_end;
166 if (players > minplayers) {
167 which[num++] = iunit;
171 if(num==0) {
172 for(i=0; i<num_role_units(role); i++) {
173 which[num++] = get_role_unit(role, i);
177 /* Ruleset code should ensure there is at least one unit for each
178 * possibly-required role, or check before calling this function. */
179 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
180 role, role_tech);
182 return which[fc_rand(num)];
185 /*****************************************************************************
186 Unit has a chance to become veteran. This should not be used for settlers
187 for the work they do.
188 *****************************************************************************/
189 bool maybe_make_veteran(struct unit *punit)
191 return maybe_become_veteran_real(punit, FALSE);
194 /*****************************************************************************
195 After a battle, after diplomatic aggression and after surviving trireme
196 loss chance, this routine is called to decide whether or not the unit
197 should become more experienced.
199 There is a specified chance for it to happen, (+50% if player got SUNTZU)
200 the chances are specified in the units.ruleset file.
202 If 'settler' is TRUE the veteran level is increased due to work done by
203 the unit.
204 *****************************************************************************/
205 static bool maybe_become_veteran_real(struct unit *punit, bool settler)
207 const struct veteran_system *vsystem;
208 const struct veteran_level *vlevel;
209 int chance;
211 fc_assert_ret_val(punit != NULL, FALSE);
213 vsystem = utype_veteran_system(unit_type_get(punit));
214 fc_assert_ret_val(vsystem != NULL, FALSE);
215 fc_assert_ret_val(vsystem->levels > punit->veteran, FALSE);
217 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
218 fc_assert_ret_val(vlevel != NULL, FALSE);
220 if (punit->veteran + 1 >= vsystem->levels
221 || unit_has_type_flag(punit, UTYF_NO_VETERAN)) {
222 return FALSE;
223 } else if (!settler) {
224 int mod = 100 + get_unit_bonus(punit, EFT_VETERAN_COMBAT);
226 /* The modification is tacked on as a multiplier to the base chance.
227 * For example with a base chance of 50% for green units and a modifier
228 * of +50% the end chance is 75%. */
229 chance = vlevel->raise_chance * mod / 100;
230 } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
231 chance = vlevel->work_raise_chance;
232 } else {
233 /* No battle and no work done. */
234 return FALSE;
237 if (fc_rand(100) < chance) {
238 punit->veteran++;
239 return TRUE;
242 return FALSE;
245 /**************************************************************************
246 This is the basic unit versus unit combat routine.
247 1) ALOT of modifiers bonuses etc is added to the 2 units rates.
248 2) If the attack is a bombardment, do rate attacks and don't kill the
249 defender, then return.
250 3) the combat loop, which continues until one of the units are dead
251 4) the aftermath, the loser (and potentially the stack which is below it)
252 is wiped, and the winner gets a chance of gaining veteran status
253 **************************************************************************/
254 void unit_versus_unit(struct unit *attacker, struct unit *defender,
255 bool bombard, int *att_hp, int *def_hp)
257 int attackpower = get_total_attack_power(attacker, defender);
258 int defensepower = get_total_defense_power(attacker, defender);
259 int attack_firepower, defense_firepower;
260 struct player *plr1 = unit_owner(attacker);
261 struct player *plr2 = unit_owner(defender);
263 *att_hp = attacker->hp;
264 *def_hp = defender->hp;
265 get_modified_firepower(attacker, defender,
266 &attack_firepower, &defense_firepower);
268 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
269 "defense firepower:%d", attackpower, defensepower,
270 attack_firepower, defense_firepower);
272 plr1->last_war_action = game.info.turn;
273 plr2->last_war_action = game.info.turn;
275 if (bombard) {
276 int i;
277 int rate = unit_type_get(attacker)->bombard_rate;
279 for (i = 0; i < rate; i++) {
280 if (fc_rand(attackpower+defensepower) >= defensepower) {
281 *def_hp -= attack_firepower;
285 /* Don't kill the target. */
286 if (*def_hp <= 0) {
287 *def_hp = 1;
289 return;
292 if (attackpower == 0) {
293 *att_hp = 0;
294 } else if (defensepower == 0) {
295 *def_hp = 0;
297 while (*att_hp > 0 && *def_hp > 0) {
298 if (fc_rand(attackpower + defensepower) >= defensepower) {
299 *def_hp -= attack_firepower;
300 } else {
301 *att_hp -= defense_firepower;
304 if (*att_hp < 0) {
305 *att_hp = 0;
307 if (*def_hp < 0) {
308 *def_hp = 0;
312 /***************************************************************************
313 Make maybe make either side of combat veteran
314 ****************************************************************************/
315 void combat_veterans(struct unit *attacker, struct unit *defender)
317 if (attacker->hp > 0) {
318 maybe_make_veteran(attacker);
319 } else if (defender->hp > 0) {
320 maybe_make_veteran(defender);
324 /***************************************************************************
325 Do unit auto-upgrades to players with the EFT_UNIT_UPGRADE effect
326 (traditionally from Leonardo's Workshop).
327 ****************************************************************************/
328 static void do_upgrade_effects(struct player *pplayer)
330 int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT);
331 struct unit_list *candidates;
333 if (upgrades <= 0) {
334 return;
336 candidates = unit_list_new();
338 unit_list_iterate(pplayer->units, punit) {
339 /* We have to be careful not to strand units at sea, for example by
340 * upgrading a frigate to an ironclad while it was carrying a unit. */
341 if (UU_OK == unit_upgrade_test(punit, TRUE)) {
342 unit_list_prepend(candidates, punit); /* Potential candidate :) */
344 } unit_list_iterate_end;
346 while (upgrades > 0 && unit_list_size(candidates) > 0) {
347 /* Upgrade one unit. The unit is chosen at random from the list of
348 * available candidates. */
349 int candidate_to_upgrade = fc_rand(unit_list_size(candidates));
350 struct unit *punit = unit_list_get(candidates, candidate_to_upgrade);
351 struct unit_type *type_from = unit_type_get(punit);
352 struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
354 transform_unit(punit, type_to, TRUE);
355 notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
356 _("%s was upgraded for free to %s."),
357 utype_name_translation(type_from),
358 unit_link(punit));
359 unit_list_remove(candidates, punit);
360 upgrades--;
363 unit_list_destroy(candidates);
366 /***************************************************************************
367 1. Do Leonardo's Workshop upgrade if applicable.
369 2. Restore/decrease unit hitpoints.
371 3. Kill dead units.
373 4. Rescue airplanes by returning them to base automatically.
375 5. Decrease fuel of planes in the air.
377 6. Refuel planes that are in bases.
379 7. Kill planes that are out of fuel.
380 ****************************************************************************/
381 void player_restore_units(struct player *pplayer)
383 /* 1) get Leonardo out of the way first: */
384 do_upgrade_effects(pplayer);
386 unit_list_iterate_safe(pplayer->units, punit) {
388 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
389 unit_restore_hitpoints(punit);
391 /* 3) Check that unit has hitpoints */
392 if (punit->hp <= 0) {
393 /* This should usually only happen for heli units, but if any other
394 * units get 0 hp somehow, catch them too. --dwp */
395 /* if 'game.server.killunhomed' is activated unhomed units are slowly
396 * killed; notify player here */
397 if (!punit->homecity && 0 < game.server.killunhomed) {
398 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
399 ftc_server, _("Your %s has run out of hit points "
400 "because it was not supported by a city."),
401 unit_tile_link(punit));
402 } else {
403 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
404 _("Your %s has run out of hit points."),
405 unit_tile_link(punit));
408 wipe_unit(punit, ULR_HP_LOSS, NULL);
409 continue; /* Continue iterating... */
412 /* 4) Rescue planes if needed */
413 if (utype_fuel(unit_type_get(punit))) {
414 /* Shall we emergency return home on the last vapors? */
416 /* I think this is strongly against the spirit of client goto.
417 * The problem is (again) that here we know too much. -- Zamar */
419 if (punit->fuel <= 1
420 && !is_unit_being_refueled(punit)) {
421 struct unit *carrier;
423 carrier = transporter_for_unit(punit);
424 if (carrier) {
425 unit_transport_load_tp_status(punit, carrier, FALSE);
426 } else {
427 bool alive = true;
429 struct pf_map *pfm;
430 struct pf_parameter parameter;
432 pft_fill_unit_parameter(&parameter, punit);
433 parameter.omniscience = !has_handicap(pplayer, H_MAP);
434 pfm = pf_map_new(&parameter);
436 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
437 if (move_cost > punit->moves_left) {
438 /* Too far */
439 break;
442 if (is_airunit_refuel_point(ptile, pplayer, punit)) {
443 struct pf_path *path;
444 int id = punit->id;
446 /* Client orders may be running for this unit - if so
447 * we free them before engaging goto. */
448 free_unit_orders(punit);
450 path = pf_map_path(pfm, ptile);
452 alive = adv_follow_path(punit, path, ptile);
454 if (!alive) {
455 log_error("rescue plane: unit %d died enroute!", id);
456 } else if (!same_pos(unit_tile(punit), ptile)) {
457 /* Enemy units probably blocked our route
458 * FIXME: We should try find alternative route around
459 * the enemy unit instead of just giving up and crashing. */
460 log_debug("rescue plane: unit %d could not move to "
461 "refuel point!", punit->id);
464 if (alive) {
465 /* Clear activity. Unit info will be sent in the end of
466 * the function. */
467 unit_activity_handling(punit, ACTIVITY_IDLE);
468 adv_unit_new_task(punit, AUT_NONE, NULL);
469 punit->goto_tile = NULL;
471 if (!is_unit_being_refueled(punit)) {
472 carrier = transporter_for_unit(punit);
473 if (carrier) {
474 unit_transport_load_tp_status(punit, carrier, FALSE);
478 notify_player(pplayer, unit_tile(punit),
479 E_UNIT_ORDERS, ftc_server,
480 _("Your %s has returned to refuel."),
481 unit_link(punit));
483 pf_path_destroy(path);
484 break;
486 } pf_map_move_costs_iterate_end;
487 pf_map_destroy(pfm);
489 if (!alive) {
490 /* Unit died trying to move to refuel point. */
491 return;
496 /* 5) Update fuel */
497 punit->fuel--;
499 /* 6) Automatically refuel air units in cities, airbases, and
500 * transporters (carriers). */
501 if (is_unit_being_refueled(punit)) {
502 punit->fuel = utype_fuel(unit_type_get(punit));
505 } unit_list_iterate_safe_end;
507 /* 7) Check if there are air units without fuel */
508 unit_list_iterate_safe(pplayer->units, punit) {
509 if (punit->fuel <= 0 && utype_fuel(unit_type_get(punit))) {
510 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
511 _("Your %s has run out of fuel."),
512 unit_tile_link(punit));
513 wipe_unit(punit, ULR_FUEL, NULL);
515 } unit_list_iterate_safe_end;
517 /* Send all updates. */
518 unit_list_iterate(pplayer->units, punit) {
519 send_unit_info(NULL, punit);
520 } unit_list_iterate_end;
523 /****************************************************************************
524 add hitpoints to the unit, hp_gain_coord returns the amount to add
525 united nations will speed up the process by 2 hp's / turn, means helicopters
526 will actually not lose hp's every turn if player have that wonder.
527 Units which have moved don't gain hp, except the United Nations and
528 helicopter effects still occur.
530 If 'game.server.killunhomed' is greater than 0, unhomed units lose
531 'game.server.killunhomed' hitpoints each turn, killing the unit at the end.
532 *****************************************************************************/
533 static void unit_restore_hitpoints(struct unit *punit)
535 bool was_lower;
536 int save_hp;
537 struct unit_class *pclass = unit_class_get(punit);
538 struct city *pcity = tile_city(unit_tile(punit));
540 was_lower = (punit->hp < unit_type_get(punit)->hp);
541 save_hp = punit->hp;
543 if (!punit->moved) {
544 punit->hp += hp_gain_coord(punit);
547 /* Bonus recovery HP (traditionally from the United Nations) */
548 punit->hp += get_unit_bonus(punit, EFT_UNIT_RECOVER);
550 if (!punit->homecity && 0 < game.server.killunhomed
551 && !unit_has_type_flag(punit, UTYF_GAMELOSS)) {
552 /* Hit point loss of units without homecity; at least 1 hp! */
553 /* Gameloss units are immune to this effect. */
554 int hp_loss = MAX(unit_type_get(punit)->hp * game.server.killunhomed / 100,
556 punit->hp = MIN(punit->hp - hp_loss, save_hp - 1);
559 if (!pcity && !tile_has_native_base(unit_tile(punit), unit_type_get(punit))
560 && !unit_transported(punit)) {
561 punit->hp -= unit_type_get(punit)->hp * pclass->hp_loss_pct / 100;
564 if (punit->hp >= unit_type_get(punit)->hp) {
565 punit->hp = unit_type_get(punit)->hp;
566 if (was_lower && punit->activity == ACTIVITY_SENTRY) {
567 set_unit_activity(punit, ACTIVITY_IDLE);
571 if (punit->hp < 0) {
572 punit->hp = 0;
575 punit->moved = FALSE;
576 punit->paradropped = FALSE;
579 /***************************************************************************
580 Move points are trivial, only modifiers to the base value is if it's
581 sea units and the player has certain wonders/techs. Then add veteran
582 bonus, if any.
583 ***************************************************************************/
584 static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
586 punit->moves_left = unit_move_rate(punit);
587 punit->done_moving = FALSE;
590 /****************************************************************************
591 Iterate through all units and update them.
592 ****************************************************************************/
593 void update_unit_activities(struct player *pplayer)
595 unit_list_iterate_safe(pplayer->units, punit) {
596 update_unit_activity(punit);
597 } unit_list_iterate_safe_end;
600 /****************************************************************************
601 Iterate through all units and execute their orders.
602 ****************************************************************************/
603 void execute_unit_orders(struct player *pplayer)
605 unit_list_iterate_safe(pplayer->units, punit) {
606 if (unit_has_orders(punit)) {
607 execute_orders(punit, FALSE);
609 } unit_list_iterate_safe_end;
612 /****************************************************************************
613 Iterate through all units and remember their current activities.
614 ****************************************************************************/
615 void finalize_unit_phase_beginning(struct player *pplayer)
617 /* Remember activities only after all knock-on effects of unit activities
618 * on other units have been resolved */
619 unit_list_iterate(pplayer->units, punit) {
620 punit->changed_from = punit->activity;
621 punit->changed_from_target = punit->activity_target;
622 punit->changed_from_count = punit->activity_count;
623 send_unit_info(NULL, punit);
624 } unit_list_iterate_end;
627 /**************************************************************************
628 returns how many hp's a unit will gain on this square
629 depends on whether or not it's inside city or fortress.
630 barracks will regen landunits completely
631 airports will regen airunits completely
632 ports will regen navalunits completely
633 fortify will add a little extra.
634 ***************************************************************************/
635 static int hp_gain_coord(struct unit *punit)
637 int hp = 0;
638 const int base = unit_type_get(punit)->hp;
640 /* Includes barracks (100%), fortress (25%), etc. */
641 hp += base * get_unit_bonus(punit, EFT_HP_REGEN) / 100;
643 if (tile_city(unit_tile(punit))) {
644 hp = MAX(hp, base / 3);
647 if (!unit_class_get(punit)->hp_loss_pct) {
648 hp += (base + 9) / 10;
651 if (punit->activity == ACTIVITY_FORTIFIED) {
652 hp += (base + 9) / 10;
655 return MAX(hp, 0);
658 /**************************************************************************
659 Calculate the total amount of activity performed by all units on a tile
660 for a given task and target.
661 **************************************************************************/
662 static int total_activity(struct tile *ptile, enum unit_activity act,
663 struct extra_type *tgt)
665 int total = 0;
666 bool tgt_matters = activity_requires_target(act);
668 unit_list_iterate (ptile->units, punit) {
669 if (punit->activity == act
670 && (!tgt_matters || punit->activity_target == tgt)) {
671 total += punit->activity_count;
673 } unit_list_iterate_end;
675 return total;
678 /**************************************************************************
679 Check the total amount of activity performed by all units on a tile
680 for a given task.
681 **************************************************************************/
682 static bool total_activity_done(struct tile *ptile, enum unit_activity act,
683 struct extra_type *tgt)
685 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
688 /**************************************************************************
689 Common notification for all experience levels.
690 **************************************************************************/
691 void notify_unit_experience(struct unit *punit)
693 const struct veteran_system *vsystem;
694 const struct veteran_level *vlevel;
696 if (!punit) {
697 return;
700 vsystem = utype_veteran_system(unit_type_get(punit));
701 fc_assert_ret(vsystem != NULL);
702 fc_assert_ret(vsystem->levels > punit->veteran);
704 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
705 fc_assert_ret(vlevel != NULL);
707 notify_player(unit_owner(punit), unit_tile(punit),
708 E_UNIT_BECAME_VET, ftc_server,
709 /* TRANS: Your <unit> became ... rank of <veteran level>. */
710 _("Your %s became more experienced and achieved the rank "
711 "of %s."),
712 unit_link(punit), name_translation_get(&vlevel->name));
715 /**************************************************************************
716 Convert a single unit to another type.
717 **************************************************************************/
718 static void unit_convert(struct unit *punit)
720 struct unit_type *to_type, *from_type;
722 from_type = unit_type_get(punit);
723 to_type = from_type->converted_to;
725 if (unit_can_convert(punit)) {
726 transform_unit(punit, to_type, TRUE);
727 notify_player(unit_owner(punit), unit_tile(punit),
728 E_UNIT_UPGRADED, ftc_server,
729 _("%s converted to %s."),
730 utype_name_translation(from_type),
731 utype_name_translation(to_type));
732 } else {
733 notify_player(unit_owner(punit), unit_tile(punit),
734 E_UNIT_UPGRADED, ftc_server,
735 _("%s cannot be converted."),
736 utype_name_translation(from_type));
740 /**************************************************************************
741 progress settlers in their current tasks,
742 and units that is pillaging.
743 also move units that is on a goto.
744 restore unit move points (information needed for settler tasks)
745 **************************************************************************/
746 static void update_unit_activity(struct unit *punit)
748 const enum unit_activity tile_changing_actions[] =
749 { ACTIVITY_PILLAGE, ACTIVITY_GEN_ROAD, ACTIVITY_IRRIGATE, ACTIVITY_MINE,
750 ACTIVITY_BASE, ACTIVITY_TRANSFORM, ACTIVITY_POLLUTION,
751 ACTIVITY_FALLOUT, ACTIVITY_LAST };
753 struct player *pplayer = unit_owner(punit);
754 bool unit_activity_done = FALSE;
755 enum unit_activity activity = punit->activity;
756 struct tile *ptile = unit_tile(punit);
757 int i;
759 switch (activity) {
760 case ACTIVITY_IDLE:
761 case ACTIVITY_EXPLORE:
762 case ACTIVITY_FORTIFIED:
763 case ACTIVITY_SENTRY:
764 case ACTIVITY_GOTO:
765 case ACTIVITY_PATROL_UNUSED:
766 case ACTIVITY_UNKNOWN:
767 case ACTIVITY_LAST:
768 /* We don't need the activity_count for the above */
769 break;
771 case ACTIVITY_FORTIFYING:
772 case ACTIVITY_CONVERT:
773 punit->activity_count += get_activity_rate_this_turn(punit);
774 break;
776 case ACTIVITY_POLLUTION:
777 case ACTIVITY_MINE:
778 case ACTIVITY_IRRIGATE:
779 case ACTIVITY_PILLAGE:
780 case ACTIVITY_TRANSFORM:
781 case ACTIVITY_FALLOUT:
782 case ACTIVITY_BASE:
783 case ACTIVITY_GEN_ROAD:
784 punit->activity_count += get_activity_rate_this_turn(punit);
786 /* settler may become veteran when doing something useful */
787 if (maybe_become_veteran_real(punit, TRUE)) {
788 notify_unit_experience(punit);
790 break;
791 case ACTIVITY_OLD_ROAD:
792 case ACTIVITY_OLD_RAILROAD:
793 case ACTIVITY_FORTRESS:
794 case ACTIVITY_AIRBASE:
795 fc_assert(FALSE);
796 break;
799 unit_restore_movepoints(pplayer, punit);
801 switch (activity) {
802 case ACTIVITY_IDLE:
803 case ACTIVITY_FORTIFIED:
804 case ACTIVITY_SENTRY:
805 case ACTIVITY_GOTO:
806 case ACTIVITY_UNKNOWN:
807 case ACTIVITY_FORTIFYING:
808 case ACTIVITY_CONVERT:
809 case ACTIVITY_PATROL_UNUSED:
810 case ACTIVITY_LAST:
811 /* no default, ensure all handled */
812 break;
814 case ACTIVITY_EXPLORE:
815 do_explore(punit);
816 return;
818 case ACTIVITY_PILLAGE:
819 if (total_activity_done(ptile, ACTIVITY_PILLAGE,
820 punit->activity_target)) {
821 struct player *victim = tile_owner(ptile); /* Owner before fortress gets destroyed */
823 destroy_extra(ptile, punit->activity_target);
824 unit_activity_done = TRUE;
826 bounce_units_on_terrain_change(ptile);
828 call_incident(INCIDENT_PILLAGE, unit_owner(punit), victim);
830 /* Change vision if effects have changed. */
831 unit_list_refresh_vision(ptile->units);
833 break;
835 case ACTIVITY_POLLUTION:
836 /* TODO: Remove this fallback target setting when target always correctly
837 * set */
838 if (punit->activity_target == NULL) {
839 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANPOLLUTION,
840 NULL, punit);
842 if (total_activity_done(ptile, ACTIVITY_POLLUTION, punit->activity_target)) {
843 destroy_extra(ptile, punit->activity_target);
844 unit_activity_done = TRUE;
846 break;
848 case ACTIVITY_FALLOUT:
849 /* TODO: Remove this fallback target setting when target always correctly
850 * set */
851 if (punit->activity_target == NULL) {
852 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANFALLOUT,
853 NULL, punit);
855 if (total_activity_done(ptile, ACTIVITY_FALLOUT, punit->activity_target)) {
856 destroy_extra(ptile, punit->activity_target);
857 unit_activity_done = TRUE;
859 break;
861 case ACTIVITY_BASE:
863 if (total_activity(ptile, ACTIVITY_BASE, punit->activity_target)
864 >= tile_activity_time(ACTIVITY_BASE, ptile, punit->activity_target)) {
865 create_extra(ptile, punit->activity_target, unit_owner(punit));
866 unit_activity_done = TRUE;
869 break;
871 case ACTIVITY_GEN_ROAD:
873 if (total_activity(ptile, ACTIVITY_GEN_ROAD, punit->activity_target)
874 >= tile_activity_time(ACTIVITY_GEN_ROAD, ptile, punit->activity_target)) {
875 create_extra(ptile, punit->activity_target, unit_owner(punit));
876 unit_activity_done = TRUE;
879 break;
881 case ACTIVITY_IRRIGATE:
882 case ACTIVITY_MINE:
883 case ACTIVITY_TRANSFORM:
884 if (total_activity_done(ptile, activity, punit->activity_target)) {
885 struct terrain *old = tile_terrain(ptile);
887 /* The function below could change the terrain. Therefore, we have to
888 * check the terrain (which will also do a sanity check for the tile). */
889 tile_apply_activity(ptile, activity, punit->activity_target);
890 check_terrain_change(ptile, old);
891 unit_activity_done = TRUE;
893 break;
895 case ACTIVITY_OLD_ROAD:
896 case ACTIVITY_OLD_RAILROAD:
897 case ACTIVITY_FORTRESS:
898 case ACTIVITY_AIRBASE:
899 fc_assert(FALSE);
900 break;
903 if (unit_activity_done) {
904 update_tile_knowledge(ptile);
905 if (ACTIVITY_IRRIGATE == activity
906 || ACTIVITY_MINE == activity
907 || ACTIVITY_TRANSFORM == activity) {
908 /* FIXME: As we might probably do the activity again, because of the
909 * terrain change cycles, we need to treat these cases separatly.
910 * Probably ACTIVITY_TRANSFORM should be associated to its terrain
911 * target, whereas ACTIVITY_IRRIGATE and ACTIVITY_MINE should only
912 * used for extras. */
913 unit_list_iterate(ptile->units, punit2) {
914 if (punit2->activity == activity) {
915 set_unit_activity(punit2, ACTIVITY_IDLE);
916 send_unit_info(NULL, punit2);
918 } unit_list_iterate_end;
919 } else {
920 unit_list_iterate(ptile->units, punit2) {
921 if (!can_unit_continue_current_activity(punit2)) {
922 set_unit_activity(punit2, ACTIVITY_IDLE);
923 send_unit_info(NULL, punit2);
925 } unit_list_iterate_end;
928 for (i = 0; tile_changing_actions[i] != ACTIVITY_LAST; i++) {
929 if (tile_changing_actions[i] == activity) {
930 /* Some units nearby may not be able to continue their action,
931 * such as building irrigation if we removed the only source
932 * of water from them. */
933 adjc_iterate(ptile, ptile2) {
934 unit_list_iterate(ptile2->units, punit2) {
935 if (!can_unit_continue_current_activity(punit2)) {
936 if (unit_has_orders(punit2)) {
937 notify_player(unit_owner(punit2), unit_tile(punit2),
938 E_UNIT_ORDERS, ftc_server,
939 _("Orders for %s aborted because activity "
940 "is no longer available."),
941 unit_link(punit2));
942 free_unit_orders(punit2);
944 set_unit_activity(punit2, ACTIVITY_IDLE);
945 send_unit_info(NULL, punit2);
947 } unit_list_iterate_end;
948 } adjc_iterate_end;
949 break;
954 if (activity == ACTIVITY_FORTIFYING) {
955 if (punit->activity_count >= 1) {
956 set_unit_activity(punit, ACTIVITY_FORTIFIED);
960 if (activity == ACTIVITY_CONVERT) {
961 if (punit->activity_count >= unit_type_get(punit)->convert_time * ACTIVITY_FACTOR) {
962 unit_convert(punit);
963 set_unit_activity(punit, ACTIVITY_IDLE);
968 /**************************************************************************
969 Forget the unit's last activity so that it can't be resumed. This is
970 used for example when the unit moves or attacks.
971 **************************************************************************/
972 void unit_forget_last_activity(struct unit *punit)
974 punit->changed_from = ACTIVITY_IDLE;
977 /**************************************************************************
978 Return TRUE iff activity requires some sort of target to be specified by
979 the client.
980 **************************************************************************/
981 bool unit_activity_needs_target_from_client(enum unit_activity activity)
983 switch (activity) {
984 case ACTIVITY_PILLAGE:
985 /* Can be set server side. */
986 return FALSE;
987 default:
988 return activity_requires_target(activity);
992 /**************************************************************************
993 For some activities (currently only pillaging), the precise target can
994 be assigned by the server rather than explicitly requested by the client.
995 This function assigns a specific activity+target if the current
996 settings are open-ended (otherwise leaves them unchanged).
998 Please update unit_activity_needs_target_from_client() if you add server
999 side unit activity target setting to more activities.
1000 **************************************************************************/
1001 void unit_assign_specific_activity_target(struct unit *punit,
1002 enum unit_activity *activity,
1003 struct extra_type **target)
1005 if (*activity == ACTIVITY_PILLAGE
1006 && *target == NULL) {
1007 struct tile *ptile = unit_tile(punit);
1008 struct extra_type *tgt;
1010 bv_extras extras = *tile_extras(ptile);
1012 while ((tgt = get_preferred_pillage(extras))) {
1014 BV_CLR(extras, extra_index(tgt));
1016 if (can_unit_do_activity_targeted(punit, *activity, tgt)) {
1017 *target = tgt;
1018 return;
1021 /* Nothing we can pillage here. */
1022 *activity = ACTIVITY_IDLE;
1026 /**************************************************************************
1027 Find place to place partisans. Returns whether such spot was found, and
1028 if it has been found, dst_tile contains that tile.
1029 **************************************************************************/
1030 static bool find_a_good_partisan_spot(struct tile *pcenter,
1031 struct player *powner,
1032 struct unit_type *u_type,
1033 int sq_radius,
1034 struct tile **dst_tile)
1036 int bestvalue = 0;
1038 /* coords of best tile in arg pointers */
1039 circle_iterate(pcenter, sq_radius, ptile) {
1040 int value;
1042 if (!is_native_tile(u_type, ptile)) {
1043 continue;
1046 if (NULL != tile_city(ptile)) {
1047 continue;
1050 if (0 < unit_list_size(ptile->units)) {
1051 continue;
1054 /* City may not have changed hands yet; see place_partisans(). */
1055 value = get_virtual_defense_power(NULL, u_type, powner,
1056 ptile, FALSE, 0);
1057 value *= 10;
1059 if (tile_continent(ptile) != tile_continent(pcenter)) {
1060 value /= 2;
1063 value -= fc_rand(value/3);
1065 if (value > bestvalue) {
1066 *dst_tile = ptile;
1067 bestvalue = value;
1069 } circle_iterate_end;
1071 return bestvalue > 0;
1074 /**************************************************************************
1075 Place partisans for powner around pcenter (normally around a city).
1076 **************************************************************************/
1077 void place_partisans(struct tile *pcenter, struct player *powner,
1078 int count, int sq_radius)
1080 struct tile *ptile = NULL;
1081 struct unit_type *u_type = get_role_unit(L_PARTISAN, 0);
1083 while (count-- > 0
1084 && find_a_good_partisan_spot(pcenter, powner, u_type,
1085 sq_radius, &ptile)) {
1086 struct unit *punit;
1088 punit = create_unit(powner, ptile, u_type, 0, 0, -1);
1089 if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
1090 punit->activity = ACTIVITY_FORTIFIED; /* yes; directly fortified */
1091 send_unit_info(NULL, punit);
1096 /**************************************************************************
1097 Teleport punit to city at cost specified. Returns success. Note that unit
1098 may die if it succesfully moves, i.e., even when return value is TRUE.
1099 (If specified cost is -1, then teleportation costs all movement.)
1100 **************************************************************************/
1101 bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1102 int move_cost, bool verbose)
1104 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1106 if (city_owner(pcity) == unit_owner(punit)){
1107 log_verbose("Teleported %s %s from (%d,%d) to %s",
1108 nation_rule_name(nation_of_unit(punit)),
1109 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1110 if (verbose) {
1111 notify_player(unit_owner(punit), city_tile(pcity),
1112 E_UNIT_RELOCATED, ftc_server,
1113 _("Teleported your %s to %s."),
1114 unit_link(punit),
1115 city_link(pcity));
1118 /* Silently free orders since they won't be applicable anymore. */
1119 free_unit_orders(punit);
1121 if (move_cost == -1) {
1122 move_cost = punit->moves_left;
1124 unit_move(punit, dst_tile, move_cost, NULL);
1126 return TRUE;
1128 return FALSE;
1131 /**************************************************************************
1132 Move or remove a unit due to stack conflicts. This function will try to
1133 find a random safe tile within a two tile distance of the unit's current
1134 tile and move the unit there. If no tiles are found, the unit is
1135 disbanded. If 'verbose' is TRUE, a message is sent to the unit owner
1136 regarding what happened.
1137 **************************************************************************/
1138 void bounce_unit(struct unit *punit, bool verbose)
1140 struct player *pplayer;
1141 struct tile *punit_tile;
1142 struct unit_list *pcargo_units;
1143 int count = 0;
1145 /* I assume that there are no topologies that have more than
1146 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1147 const int DIST = 2;
1148 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1150 if (!punit) {
1151 return;
1154 pplayer = unit_owner(punit);
1155 punit_tile = unit_tile(punit);
1157 square_iterate(punit_tile, DIST, ptile) {
1158 if (count >= ARRAY_SIZE(tiles)) {
1159 break;
1162 if (ptile == punit_tile) {
1163 continue;
1166 if (can_unit_survive_at_tile(punit, ptile)
1167 && !is_non_allied_city_tile(ptile, pplayer)
1168 && !is_non_allied_unit_tile(ptile, pplayer)) {
1169 tiles[count++] = ptile;
1171 } square_iterate_end;
1173 if (count > 0) {
1174 struct tile *ptile = tiles[fc_rand(count)];
1176 if (verbose) {
1177 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1178 /* TRANS: A unit is moved to resolve stack conflicts. */
1179 _("Moved your %s."),
1180 unit_link(punit));
1182 unit_move(punit, ptile, 0, NULL);
1183 return;
1186 /* Didn't find a place to bounce the unit, going to disband it.
1187 * Try to bounce transported units. */
1188 if (0 < get_transporter_occupancy(punit)) {
1189 pcargo_units = unit_transport_cargo(punit);
1190 unit_list_iterate(pcargo_units, pcargo) {
1191 bounce_unit(pcargo, verbose);
1192 } unit_list_iterate_end;
1195 if (verbose) {
1196 notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1197 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1198 _("Disbanded your %s."),
1199 unit_tile_link(punit));
1201 wipe_unit(punit, ULR_STACK_CONFLICT, NULL);
1205 /**************************************************************************
1206 Throw pplayer's units from non allied cities
1208 If verbose is true, pplayer gets messages about where each units goes.
1209 **************************************************************************/
1210 static void throw_units_from_illegal_cities(struct player *pplayer,
1211 bool verbose)
1213 struct tile *ptile;
1214 struct city *pcity;
1215 struct unit *ptrans;
1216 struct unit_list *pcargo_units;
1218 /* Unload undesired units from transports, if possible. */
1219 unit_list_iterate(pplayer->units, punit) {
1220 ptile = unit_tile(punit);
1221 pcity = tile_city(ptile);
1222 if (NULL != pcity
1223 && !pplayers_allied(city_owner(pcity), pplayer)
1224 && 0 < get_transporter_occupancy(punit)) {
1225 pcargo_units = unit_transport_cargo(punit);
1226 unit_list_iterate(pcargo_units, pcargo) {
1227 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1228 if (can_unit_exist_at_tile(pcargo, ptile)) {
1229 unit_transport_unload_send(pcargo);
1232 } unit_list_iterate_end;
1234 } unit_list_iterate_end;
1236 /* Bounce units except transported ones which will be bounced with their
1237 * transport. */
1238 unit_list_iterate_safe(pplayer->units, punit) {
1239 ptile = unit_tile(punit);
1240 pcity = tile_city(ptile);
1241 if (NULL != pcity
1242 && !pplayers_allied(city_owner(pcity), pplayer)) {
1243 ptrans = unit_transport_get(punit);
1244 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1245 bounce_unit(punit, verbose);
1248 } unit_list_iterate_safe_end;
1250 #ifdef FREECIV_DEBUG
1251 /* Sanity check. */
1252 unit_list_iterate(pplayer->units, punit) {
1253 ptile = unit_tile(punit);
1254 pcity = tile_city(ptile);
1255 fc_assert_msg(NULL == pcity
1256 || pplayers_allied(city_owner(pcity), pplayer),
1257 "Failed to throw %s %d from %s %d (%d, %d)",
1258 unit_rule_name(punit),
1259 punit->id,
1260 city_name_get(pcity),
1261 pcity->id,
1262 TILE_XY(ptile));
1263 } unit_list_iterate_end;
1264 #endif /* FREECIV_DEBUG */
1267 /**************************************************************************
1268 For each pplayer's unit, check if we stack illegally, if so,
1269 bounce both players' units. If on ocean tile, bounce everyone but ships
1270 to avoid drowning. This function assumes that cities are clean.
1272 If verbose is true, the unit owner gets messages about where each
1273 units goes.
1274 **************************************************************************/
1275 static void resolve_stack_conflicts(struct player *pplayer,
1276 struct player *aplayer, bool verbose)
1278 unit_list_iterate_safe(pplayer->units, punit) {
1279 struct tile *ptile = unit_tile(punit);
1281 if (is_non_allied_unit_tile(ptile, pplayer)) {
1282 unit_list_iterate_safe(ptile->units, aunit) {
1283 if (unit_owner(aunit) == pplayer
1284 || unit_owner(aunit) == aplayer
1285 || !can_unit_survive_at_tile(aunit, ptile)) {
1286 bounce_unit(aunit, verbose);
1288 } unit_list_iterate_safe_end;
1290 } unit_list_iterate_safe_end;
1293 /**************************************************************************
1294 When in civil war or an alliance breaks there will potentially be units
1295 from both sides coexisting on the same squares. This routine resolves
1296 this by first bouncing off non-allied units from their cities, then by
1297 bouncing both players' units in now illegal multiowner stacks. To avoid
1298 drowning due to removal of transports, we bounce everyone (including
1299 third parties' units) from ocean tiles.
1301 If verbose is true, the unit owner gets messages about where each
1302 units goes.
1303 **************************************************************************/
1304 void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1305 bool verbose)
1307 throw_units_from_illegal_cities(pplayer, verbose);
1308 throw_units_from_illegal_cities(aplayer, verbose);
1310 resolve_stack_conflicts(pplayer, aplayer, verbose);
1311 resolve_stack_conflicts(aplayer, pplayer, verbose);
1314 /****************************************************************************
1315 Returns the list of the units seen by 'pplayer' potentially seen only
1316 thanks to an alliance with 'aplayer'. The returned pointer is newly
1317 allocated and should be freed by the caller, using unit_list_destroy().
1318 ****************************************************************************/
1319 struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1320 const struct player *aplayer)
1322 struct unit_list *seen_units = unit_list_new();
1324 /* Anybody's units inside ally's cities */
1325 city_list_iterate(aplayer->cities, pcity) {
1326 unit_list_iterate(city_tile(pcity)->units, punit) {
1327 if (can_player_see_unit(pplayer, punit)) {
1328 unit_list_append(seen_units, punit);
1330 } unit_list_iterate_end;
1331 } city_list_iterate_end;
1333 /* Ally's own units inside transports */
1334 unit_list_iterate(aplayer->units, punit) {
1335 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1336 unit_list_append(seen_units, punit);
1338 } unit_list_iterate_end;
1340 /* Make sure the same unit is not added in multiple phases
1341 * (unit within transport in a city) */
1342 unit_list_unique(seen_units);
1344 return seen_units;
1347 /****************************************************************************
1348 When two players cancel an alliance, a lot of units that were visible may
1349 no longer be visible (this includes units in transporters and cities).
1350 Call this function to inform the clients that these units are no longer
1351 visible. Pass the list of seen units returned by get_units_seen_via_ally()
1352 before alliance was broken up.
1353 ****************************************************************************/
1354 void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1355 const struct unit_list *seen_units)
1357 unit_list_iterate(seen_units, punit) {
1358 /* We need to hide units previously seen by the client. */
1359 if (!can_player_see_unit(pplayer, punit)) {
1360 unit_goes_out_of_sight(pplayer, punit);
1362 } unit_list_iterate_end;
1364 city_list_iterate(aplayer->cities, pcity) {
1365 /* The player used to know what units were in these cities. Now that he
1366 * doesn't, he needs to get a new short city packet updating the
1367 * occupied status. */
1368 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1369 send_city_info(pplayer, pcity);
1371 } city_list_iterate_end;
1374 /****************************************************************************
1375 Refresh units visibility of 'aplayer' for 'pplayer' after alliance have
1376 been contracted.
1377 ****************************************************************************/
1378 void give_allied_visibility(struct player *pplayer,
1379 struct player *aplayer)
1381 unit_list_iterate(aplayer->units, punit) {
1382 if (can_player_see_unit(pplayer, punit)) {
1383 send_unit_info(pplayer->connections, punit);
1385 } unit_list_iterate_end;
1388 /**************************************************************************
1389 Is unit being refueled in its current position
1390 **************************************************************************/
1391 bool is_unit_being_refueled(const struct unit *punit)
1393 return (unit_transported(punit) /* Carrier */
1394 || tile_city(unit_tile(punit)) /* City */
1395 || tile_has_refuel_extra(unit_tile(punit),
1396 unit_type_get(punit))); /* Airbase */
1399 /**************************************************************************
1400 Can unit refuel on tile. Considers also carrier capacity on tile.
1401 **************************************************************************/
1402 bool is_airunit_refuel_point(const struct tile *ptile,
1403 const struct player *pplayer,
1404 const struct unit *punit)
1406 const struct unit_class *pclass;
1408 if (NULL != is_non_allied_unit_tile(ptile, pplayer)) {
1409 return FALSE;
1412 if (NULL != is_allied_city_tile(ptile, pplayer)) {
1413 return TRUE;
1416 pclass = unit_class_get(punit);
1417 if (NULL != pclass->cache.refuel_bases) {
1418 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1420 extra_type_list_iterate(pclass->cache.refuel_bases, pextra) {
1421 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1422 return TRUE;
1424 } extra_type_list_iterate_end;
1427 return unit_could_load_at(punit, ptile);
1430 /**************************************************************************
1431 Really transforms a single unit to another type.
1433 This function performs no checks. You should perform the appropriate
1434 test first to check that the transformation is legal (test_unit_upgrade()
1435 or test_unit_convert()).
1437 is_free: Does unit owner need to pay upgrade price.
1439 Note that this function is strongly tied to unit.c:test_unit_upgrade().
1440 **************************************************************************/
1441 void transform_unit(struct unit *punit, struct unit_type *to_unit,
1442 bool is_free)
1444 struct player *pplayer = unit_owner(punit);
1445 struct unit_type *old_type = punit->utype;
1446 int old_mr = unit_move_rate(punit);
1447 int old_hp = unit_type_get(punit)->hp;
1449 if (!is_free) {
1450 pplayer->economic.gold -=
1451 unit_upgrade_price(pplayer, unit_type_get(punit), to_unit);
1454 punit->utype = to_unit;
1456 /* New type may not have the same veteran system, and we may want to
1457 * knock some levels off. */
1458 punit->veteran = MIN(punit->veteran,
1459 utype_veteran_system(to_unit)->levels - 1);
1460 if (is_free) {
1461 punit->veteran = MAX(punit->veteran
1462 - game.server.autoupgrade_veteran_loss, 0);
1463 } else {
1464 punit->veteran = MAX(punit->veteran
1465 - game.server.upgrade_veteran_loss, 0);
1468 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1469 * and don't kill the unit. unit_move_rate is used to take into account
1470 * global effects like Magellan's Expedition. */
1471 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1472 punit->moves_left = punit->moves_left * unit_move_rate(punit) / old_mr;
1474 unit_forget_last_activity(punit);
1476 /* update unit upkeep */
1477 city_units_upkeep(game_city_by_number(punit->homecity));
1479 conn_list_do_buffer(pplayer->connections);
1481 unit_refresh_vision(punit);
1483 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1485 send_unit_info(NULL, punit);
1486 conn_list_do_unbuffer(pplayer->connections);
1489 /*************************************************************************
1490 Wrapper of the below
1491 *************************************************************************/
1492 struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1493 struct unit_type *type, int veteran_level,
1494 int homecity_id, int moves_left)
1496 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1497 moves_left, -1, NULL);
1500 /**************************************************************************
1501 Creates a unit, and set it's initial values, and put it into the right
1502 lists.
1503 If moves_left is less than zero, unit will get max moves.
1504 **************************************************************************/
1505 struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1506 struct unit_type *type, int veteran_level,
1507 int homecity_id, int moves_left, int hp_left,
1508 struct unit *ptrans)
1510 struct unit *punit = unit_virtual_create(pplayer, NULL, type, veteran_level);
1511 struct city *pcity;
1513 /* Register unit */
1514 punit->id = identity_number();
1515 idex_register_unit(punit);
1517 fc_assert_ret_val(ptile != NULL, NULL);
1518 unit_tile_set(punit, ptile);
1520 pcity = game_city_by_number(homecity_id);
1521 if (utype_has_flag(type, UTYF_NOHOME)) {
1522 punit->homecity = 0; /* none */
1523 } else {
1524 punit->homecity = homecity_id;
1527 if (hp_left >= 0) {
1528 /* Override default full HP */
1529 punit->hp = hp_left;
1532 if (moves_left >= 0) {
1533 /* Override default full MP */
1534 punit->moves_left = MIN(moves_left, unit_move_rate(punit));
1537 if (ptrans) {
1538 /* Set transporter for unit. */
1539 unit_transport_load_tp_status(punit, ptrans, FALSE);
1540 } else {
1541 fc_assert_ret_val(!ptile || can_unit_exist_at_tile(punit, ptile), NULL);
1544 /* Assume that if moves_left < 0 then the unit is "fresh",
1545 * and not moved; else the unit has had something happen
1546 * to it (eg, bribed) which we treat as equivalent to moved.
1547 * (Otherwise could pass moved arg too...) --dwp */
1548 punit->moved = (moves_left >= 0);
1550 unit_list_prepend(pplayer->units, punit);
1551 unit_list_prepend(ptile->units, punit);
1552 if (pcity && !utype_has_flag(type, UTYF_NOHOME)) {
1553 fc_assert(city_owner(pcity) == pplayer);
1554 unit_list_prepend(pcity->units_supported, punit);
1555 /* Refresh the unit's homecity. */
1556 city_refresh(pcity);
1557 send_city_info(pplayer, pcity);
1560 punit->server.vision = vision_new(pplayer, ptile);
1561 unit_refresh_vision(punit);
1563 send_unit_info(NULL, punit);
1564 maybe_make_contact(ptile, unit_owner(punit));
1565 wakeup_neighbor_sentries(punit);
1567 /* update unit upkeep */
1568 city_units_upkeep(game_city_by_number(homecity_id));
1570 /* The unit may have changed the available tiles in nearby cities. */
1571 city_map_update_tile_now(ptile);
1572 sync_cities();
1574 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1576 return punit;
1579 /****************************************************************************
1580 We remove the unit and see if it's disappearance has affected the homecity
1581 and the city it was in.
1582 ****************************************************************************/
1583 static void server_remove_unit_full(struct unit *punit, bool transported,
1584 enum unit_loss_reason reason)
1586 struct packet_unit_remove packet;
1587 struct tile *ptile = unit_tile(punit);
1588 struct city *pcity = tile_city(ptile);
1589 struct city *phomecity = game_city_by_number(punit->homecity);
1590 struct unit *ptrans;
1591 struct player *pplayer = unit_owner(punit);
1593 /* The unit is doomed. */
1594 punit->server.dying = TRUE;
1596 #ifdef DEBUG
1597 unit_list_iterate(ptile->units, pcargo) {
1598 fc_assert(unit_transport_get(pcargo) != punit);
1599 } unit_list_iterate_end;
1600 #endif
1602 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1604 /* Save transporter for updating below. */
1605 ptrans = unit_transport_get(punit);
1606 /* Unload unit. */
1607 unit_transport_unload(punit);
1609 /* Since settlers plot in new cities in the minimap before they
1610 are built, so that no two settlers head towards the same city
1611 spot, we need to ensure this reservation is cleared should
1612 the settler disappear on the way. */
1613 adv_unit_new_task(punit, AUT_NONE, NULL);
1615 /* Clear the vision before sending unit remove. Else, we might duplicate
1616 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1617 vision_clear_sight(punit->server.vision);
1618 vision_free(punit->server.vision);
1619 punit->server.vision = NULL;
1621 packet.unit_id = punit->id;
1622 /* Send to onlookers. */
1623 players_iterate(aplayer) {
1624 if (can_player_see_unit_at(aplayer, punit, unit_tile(punit),
1625 transported)) {
1626 lsend_packet_unit_remove(aplayer->connections, &packet);
1628 } players_iterate_end;
1629 /* Send to global observers. */
1630 conn_list_iterate(game.est_connections, pconn) {
1631 if (conn_is_global_observer(pconn)) {
1632 send_packet_unit_remove(pconn, &packet);
1634 } conn_list_iterate_end;
1636 if (punit->server.moving != NULL) {
1637 /* Do not care of this unit for running moves. */
1638 punit->server.moving->punit = NULL;
1641 /* check if this unit had UTYF_GAMELOSS flag */
1642 if (unit_has_type_flag(punit, UTYF_GAMELOSS) && unit_owner(punit)->is_alive) {
1643 notify_conn(game.est_connections, ptile, E_UNIT_LOST_MISC, ftc_server,
1644 _("Unable to defend %s, %s has lost the game."),
1645 unit_link(punit),
1646 player_name(pplayer));
1647 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1648 _("Losing %s meant losing the game! "
1649 "Be more careful next time!"),
1650 unit_link(punit));
1651 player_status_add(unit_owner(punit), PSTATUS_DYING);
1654 script_server_signal_emit("unit_lost", 3,
1655 API_TYPE_UNIT, punit,
1656 API_TYPE_PLAYER, unit_owner(punit),
1657 API_TYPE_STRING, unit_loss_reason_name(reason));
1659 script_server_remove_exported_object(punit);
1660 game_remove_unit(punit);
1661 punit = NULL;
1663 if (NULL != ptrans) {
1664 /* Update the occupy info. */
1665 send_unit_info(NULL, ptrans);
1668 /* This unit may have blocked tiles of adjacent cities. Update them. */
1669 city_map_update_tile_now(ptile);
1670 sync_cities();
1672 if (phomecity) {
1673 city_refresh(phomecity);
1674 send_city_info(city_owner(phomecity), phomecity);
1677 if (pcity && pcity != phomecity) {
1678 city_refresh(pcity);
1679 send_city_info(city_owner(pcity), pcity);
1682 if (pcity && unit_list_size(ptile->units) == 0) {
1683 /* The last unit in the city was killed: update the occupied flag. */
1684 send_city_info(NULL, pcity);
1688 /****************************************************************************
1689 We remove the unit and see if it's disappearance has affected the homecity
1690 and the city it was in.
1691 ****************************************************************************/
1692 static void server_remove_unit(struct unit *punit,
1693 enum unit_loss_reason reason)
1695 server_remove_unit_full(punit, unit_transported(punit), reason);
1698 /**************************************************************************
1699 Handle units destroyed when their transport is destroyed
1700 **************************************************************************/
1701 static void unit_lost_with_transport(const struct player *pplayer,
1702 struct unit *pcargo,
1703 struct unit_type *ptransport,
1704 struct player *killer)
1706 notify_player(pplayer, unit_tile(pcargo), E_UNIT_LOST_MISC, ftc_server,
1707 _("%s lost when %s was lost."),
1708 unit_tile_link(pcargo),
1709 utype_name_translation(ptransport));
1710 /* Unit is not transported any more at this point, but it has jumped
1711 * off the transport and drowns outside. So it must be removed from
1712 * all clients.
1713 * However, we don't know if given client has received ANY updates
1714 * about the swimming unit, and we can't remove it if it's not there
1715 * in the first place -> we send it once here just to be sure it's
1716 * there. */
1717 send_unit_info(NULL, pcargo);
1718 wipe_unit_full(pcargo, FALSE, ULR_TRANSPORT_LOST, killer);
1721 /****************************************************************************
1722 Remove the unit, and passengers if it is a carrying any. Remove the
1723 _minimum_ number, eg there could be another boat on the square.
1724 ****************************************************************************/
1725 static void wipe_unit_full(struct unit *punit, bool transported,
1726 enum unit_loss_reason reason,
1727 struct player *killer)
1729 struct tile *ptile = unit_tile(punit);
1730 struct player *pplayer = unit_owner(punit);
1731 struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1732 struct unit_list *helpless = unit_list_new();
1733 struct unit_list *imperiled = unit_list_new();
1734 struct unit_list *unsaved = unit_list_new();
1735 struct unit *ptrans = unit_transport_get(punit);
1737 /* The unit is doomed. */
1738 punit->server.dying = TRUE;
1740 /* Remove unit itself from its transport */
1741 if (ptrans != NULL) {
1742 unit_transport_unload(punit);
1743 send_unit_info(NULL, ptrans);
1746 /* First pull all units off of the transporter. */
1747 if (get_transporter_occupancy(punit) > 0) {
1748 /* Use iterate_safe as unloaded units will be removed from the list
1749 * while iterating. */
1750 unit_list_iterate_safe(unit_transport_cargo(punit), pcargo) {
1751 bool healthy = FALSE;
1753 if (!can_unit_unload(pcargo, punit)) {
1754 unit_list_prepend(helpless, pcargo);
1755 } else {
1756 if (!can_unit_exist_at_tile(pcargo, ptile)) {
1757 unit_list_prepend(imperiled, pcargo);
1758 } else {
1759 /* These units do not need to be saved. */
1760 healthy = TRUE;
1764 /* Could use unit_transport_unload_send here, but that would
1765 * call send_unit_info for the transporter unnecessarily.
1766 * Note that this means that unit might to get seen briefly
1767 * by clients other than owner's, for example as a result of
1768 * update of homecity common to this cargo and some other
1769 * destroyed unit. */
1770 unit_transport_unload(pcargo);
1771 if (pcargo->activity == ACTIVITY_SENTRY) {
1772 /* Activate sentried units - like planes on a disbanded carrier.
1773 * Note this will activate ground units even if they just change
1774 * transporter. */
1775 set_unit_activity(pcargo, ACTIVITY_IDLE);
1778 /* Unit info for unhealthy units will be sent when they are
1779 * assigned new transport or removed. */
1780 if (healthy) {
1781 send_unit_info(NULL, pcargo);
1783 } unit_list_iterate_safe_end;
1786 /* Now remove the unit. */
1787 server_remove_unit_full(punit, transported, reason);
1789 switch (reason) {
1790 case ULR_KILLED:
1791 case ULR_EXECUTED:
1792 case ULR_SDI:
1793 case ULR_NUKE:
1794 case ULR_BRIBED:
1795 case ULR_CAPTURED:
1796 case ULR_CAUGHT:
1797 case ULR_ELIMINATED:
1798 case ULR_TRANSPORT_LOST:
1799 if (killer != NULL) {
1800 killer->score.units_killed++;
1802 pplayer->score.units_lost++;
1803 break;
1804 case ULR_BARB_UNLEASH:
1805 case ULR_CITY_LOST:
1806 case ULR_STARVED:
1807 case ULR_NONNATIVE_TERR:
1808 case ULR_ARMISTICE:
1809 case ULR_HP_LOSS:
1810 case ULR_FUEL:
1811 case ULR_STACK_CONFLICT:
1812 case ULR_SOLD:
1813 pplayer->score.units_lost++;
1814 break;
1815 case ULR_RETIRED:
1816 case ULR_DISBANDED:
1817 case ULR_USED:
1818 case ULR_EDITOR:
1819 case ULR_PLAYER_DIED:
1820 case ULR_DETONATED:
1821 case ULR_MISSILE:
1822 break;
1825 /* First, sort out helpless cargo. */
1826 if (unit_list_size(helpless) > 0) {
1827 struct unit_list *remaining = unit_list_new();
1829 /* Grant priority to undisbandable and gameloss units. */
1830 unit_list_iterate_safe(helpless, pcargo) {
1831 if (unit_has_type_flag(pcargo, UTYF_UNDISBANDABLE)
1832 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
1833 if (!try_to_save_unit(pcargo, putype_save, TRUE,
1834 unit_has_type_flag(pcargo,
1835 UTYF_UNDISBANDABLE))) {
1836 unit_list_prepend(unsaved, pcargo);
1838 } else {
1839 unit_list_prepend(remaining, pcargo);
1841 } unit_list_iterate_safe_end;
1843 /* Handle non-priority units. */
1844 unit_list_iterate_safe(remaining, pcargo) {
1845 if (!try_to_save_unit(pcargo, putype_save, TRUE, FALSE)) {
1846 unit_list_prepend(unsaved, pcargo);
1848 } unit_list_iterate_safe_end;
1850 unit_list_destroy(remaining);
1852 unit_list_destroy(helpless);
1854 /* Then, save any imperiled cargo. */
1855 if (unit_list_size(imperiled) > 0) {
1856 struct unit_list *remaining = unit_list_new();
1858 /* Grant priority to undisbandable and gameloss units. */
1859 unit_list_iterate_safe(imperiled, pcargo) {
1860 if (unit_has_type_flag(pcargo, UTYF_UNDISBANDABLE)
1861 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
1862 if (!try_to_save_unit(pcargo, putype_save, FALSE,
1863 unit_has_type_flag(pcargo,
1864 UTYF_UNDISBANDABLE))) {
1865 unit_list_prepend(unsaved, pcargo);
1867 } else {
1868 unit_list_prepend(remaining, pcargo);
1870 } unit_list_iterate_safe_end;
1872 /* Handle non-priority units. */
1873 unit_list_iterate_safe(remaining, pcargo) {
1874 if (!try_to_save_unit(pcargo, putype_save, FALSE, FALSE)) {
1875 unit_list_prepend(unsaved, pcargo);
1877 } unit_list_iterate_safe_end;
1879 unit_list_destroy(remaining);
1881 unit_list_destroy(imperiled);
1883 /* Finally, kill off the unsaved units. */
1884 if (unit_list_size(unsaved) > 0) {
1885 unit_list_iterate_safe(unsaved, dying_unit) {
1886 unit_lost_with_transport(pplayer, dying_unit, putype_save, killer);
1887 } unit_list_iterate_safe_end;
1889 unit_list_destroy(unsaved);
1892 /****************************************************************************
1893 Remove the unit, and passengers if it is a carrying any. Remove the
1894 _minimum_ number, eg there could be another boat on the square.
1895 ****************************************************************************/
1896 void wipe_unit(struct unit *punit, enum unit_loss_reason reason,
1897 struct player *killer)
1899 wipe_unit_full(punit, unit_transported(punit), reason, killer);
1902 /****************************************************************************
1903 Determine if it is possible to save a given unit, and if so, save them.
1904 Note that despite being saved from drowning, teleporting the units to
1905 "safety" may have killed them in the end.
1906 ****************************************************************************/
1907 bool try_to_save_unit(struct unit *punit, struct unit_type *pttype,
1908 bool helpless, bool teleporting)
1910 struct tile *ptile = unit_tile(punit);
1911 struct player *pplayer = unit_owner(punit);
1912 struct unit *ptransport = transporter_for_unit(punit);
1914 /* Helpless units cannot board a transport in their current state. */
1915 if (!helpless
1916 && ptransport != NULL) {
1917 unit_transport_load_tp_status(punit, ptransport, FALSE);
1918 send_unit_info(NULL, punit);
1919 return TRUE;
1920 } else {
1921 /* Only units that cannot find transport are considered for teleport. */
1922 if (teleporting) {
1923 struct city *pcity = find_closest_city(ptile, NULL, unit_owner(punit),
1924 FALSE, FALSE, FALSE, TRUE, FALSE,
1925 utype_class(pttype));
1926 if (pcity != NULL) {
1927 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
1929 sz_strlcpy(tplink, unit_link(punit));
1931 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
1932 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1933 _("%s escaped the destruction of %s, and fled to %s."),
1934 tplink,
1935 utype_name_translation(pttype),
1936 city_link(pcity));
1937 return TRUE;
1942 /* The unit could not use transport on the tile, and could not teleport. */
1943 return FALSE;
1946 /****************************************************************************
1947 We don't really change owner of the unit, but create completely new
1948 unit as its copy. The new pointer to 'punit' is returned.
1949 ****************************************************************************/
1950 struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
1951 int homecity, enum unit_loss_reason reason)
1953 struct unit *gained_unit;
1955 fc_assert(!utype_player_already_has_this_unique(pplayer,
1956 unit_type_get(punit)));
1958 /* Convert the unit to your cause. Fog is lifted in the create algorithm. */
1959 gained_unit = create_unit_full(pplayer, unit_tile(punit),
1960 unit_type_get(punit), punit->veteran,
1961 homecity, punit->moves_left,
1962 punit->hp, NULL);
1964 /* Owner changes, nationality not. */
1965 gained_unit->nationality = punit->nationality;
1967 /* Copy some more unit fields */
1968 gained_unit->fuel = punit->fuel;
1969 gained_unit->paradropped = punit->paradropped;
1970 gained_unit->server.birth_turn = punit->server.birth_turn;
1972 send_unit_info(NULL, gained_unit);
1974 /* update unit upkeep in the homecity of the victim */
1975 if (punit->homecity > 0) {
1976 /* update unit upkeep */
1977 city_units_upkeep(game_city_by_number(punit->homecity));
1979 /* update unit upkeep in the new homecity */
1980 if (homecity > 0) {
1981 city_units_upkeep(game_city_by_number(homecity));
1984 /* Be sure to wipe the converted unit! */
1985 wipe_unit(punit, reason, NULL);
1987 return gained_unit; /* Returns the replacement. */
1990 /**************************************************************************
1991 Called when one unit kills another in combat (this function is only
1992 called in one place). It handles all side effects including
1993 notifications and killstack.
1994 **************************************************************************/
1995 void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
1997 char pkiller_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK];
1998 struct player *pvictim = unit_owner(punit);
1999 struct player *pvictor = unit_owner(pkiller);
2000 int ransom, unitcount = 0;
2002 sz_strlcpy(pkiller_link, unit_link(pkiller));
2003 sz_strlcpy(punit_link, unit_tile_link(punit));
2005 /* The unit is doomed. */
2006 punit->server.dying = TRUE;
2008 if ((game.info.gameloss_style & GAMELOSS_STYLE_LOOT)
2009 && unit_has_type_flag(punit, UTYF_GAMELOSS)) {
2010 ransom = fc_rand(1 + pvictim->economic.gold);
2011 int n;
2013 /* give map */
2014 give_distorted_map(pvictim, pvictor, 1, 1, TRUE);
2016 log_debug("victim has money: %d", pvictim->economic.gold);
2017 pvictor->economic.gold += ransom;
2018 pvictim->economic.gold -= ransom;
2020 n = 1 + fc_rand(3);
2022 while (n > 0) {
2023 Tech_type_id ttid = steal_a_tech(pvictor, pvictim, A_UNSET);
2025 if (ttid == A_NONE) {
2026 log_debug("Worthless enemy doesn't have more techs to steal.");
2027 break;
2028 } else {
2029 log_debug("Pressed tech %s from captured enemy",
2030 research_advance_rule_name(research_get(pvictor), ttid));
2031 if (!fc_rand(3)) {
2032 break; /* out of luck */
2034 n--;
2038 { /* try to submit some cities */
2039 int vcsize = city_list_size(pvictim->cities);
2040 int evcsize = vcsize;
2041 int conqsize = evcsize;
2043 if (evcsize < 3) {
2044 evcsize = 0;
2045 } else {
2046 evcsize -=3;
2048 /* about a quarter on average with high numbers less probable */
2049 conqsize = fc_rand(fc_rand(evcsize));
2051 log_debug("conqsize=%d", conqsize);
2053 if (conqsize > 0) {
2054 bool palace = game.server.savepalace;
2055 bool submit = FALSE;
2057 game.server.savepalace = FALSE; /* moving it around is dumb */
2059 city_list_iterate_safe(pvictim->cities, pcity) {
2060 /* kindly ask the citizens to submit */
2061 if (fc_rand(vcsize) < conqsize) {
2062 submit = TRUE;
2064 vcsize--;
2065 if (submit) {
2066 conqsize--;
2067 /* Transfer city to the victorious player
2068 * kill all its units outside of a radius of 7,
2069 * give verbose messages of every unit transferred,
2070 * and raze buildings according to raze chance
2071 * (also removes palace) */
2072 (void) transfer_city(pvictor, pcity, 7, TRUE, TRUE, TRUE,
2073 !is_barbarian(pvictor));
2074 submit = FALSE;
2076 if (conqsize <= 0) {
2077 break;
2079 } city_list_iterate_safe_end;
2080 game.server.savepalace = palace;
2085 /* barbarian leader ransom hack */
2086 if( is_barbarian(pvictim) && unit_has_type_role(punit, L_BARBARIAN_LEADER)
2087 && (unit_list_size(unit_tile(punit)->units) == 1)
2088 && uclass_has_flag(unit_class_get(pkiller), UCF_COLLECT_RANSOM)) {
2089 /* Occupying units can collect ransom if leader is alone in the tile */
2090 ransom = (pvictim->economic.gold >= game.server.ransom_gold)
2091 ? game.server.ransom_gold : pvictim->economic.gold;
2092 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2093 PL_("Barbarian leader captured; %d gold ransom paid.",
2094 "Barbarian leader captured; %d gold ransom paid.",
2095 ransom),
2096 ransom);
2097 pvictor->economic.gold += ransom;
2098 pvictim->economic.gold -= ransom;
2099 send_player_info_c(pvictor, NULL); /* let me see my new gold :-) */
2100 unitcount = 1;
2103 if (unitcount == 0) {
2104 unit_list_iterate(unit_tile(punit)->units, vunit) {
2105 if (pplayers_at_war(pvictor, unit_owner(vunit))) {
2106 unitcount++;
2108 } unit_list_iterate_end;
2111 if (!is_stack_vulnerable(unit_tile(punit)) || unitcount == 1) {
2112 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2113 /* TRANS: "... Cannon ... the Polish Destroyer." */
2114 _("Your attacking %s succeeded against the %s %s!"),
2115 pkiller_link,
2116 nation_adjective_for_player(pvictim),
2117 punit_link);
2118 if (vet) {
2119 notify_unit_experience(pkiller);
2121 notify_player(pvictim, unit_tile(punit), E_UNIT_LOST_DEF, ftc_server,
2122 /* TRANS: "Cannon ... the Polish Destroyer." */
2123 _("%s lost to an attack by the %s %s."),
2124 punit_link,
2125 nation_adjective_for_player(pvictor),
2126 pkiller_link);
2128 wipe_unit(punit, ULR_KILLED, pvictor);
2129 } else { /* unitcount > 1 */
2130 int i;
2131 int num_killed[player_slot_count()];
2132 struct unit *other_killed[player_slot_count()];
2133 struct tile *ptile = unit_tile(punit);
2135 fc_assert(unitcount > 1);
2137 /* initialize */
2138 for (i = 0; i < player_slot_count(); i++) {
2139 num_killed[i] = 0;
2140 other_killed[i] = NULL;
2143 /* count killed units */
2144 unit_list_iterate(ptile->units, vunit) {
2145 struct player *vplayer = unit_owner(vunit);
2146 if (pplayers_at_war(pvictor, vplayer)
2147 && is_unit_reachable_at(vunit, pkiller, ptile)) {
2148 num_killed[player_index(vplayer)]++;
2149 if (vunit != punit) {
2150 other_killed[player_index(vplayer)] = vunit;
2151 other_killed[player_index(pvictor)] = vunit;
2154 } unit_list_iterate_end;
2156 /* Inform the destroyer: lots of different cases here! */
2157 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2158 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2159 PL_("Your attacking %s succeeded against the %s %s "
2160 "(and %d other unit)!",
2161 "Your attacking %s succeeded against the %s %s "
2162 "(and %d other units)!", unitcount - 1),
2163 pkiller_link,
2164 nation_adjective_for_player(pvictim),
2165 punit_link,
2166 unitcount - 1);
2167 if (vet) {
2168 notify_unit_experience(pkiller);
2171 /* inform the owners: this only tells about owned units that were killed.
2172 * there may have been 20 units who died but if only 2 belonged to the
2173 * particular player they'll only learn about those.
2175 * Also if a large number of units die you don't find out what type
2176 * they all are. */
2177 for (i = 0; i < player_slot_count(); i++) {
2178 if (num_killed[i] == 1) {
2179 if (i == player_index(pvictim)) {
2180 fc_assert(other_killed[i] == NULL);
2181 notify_player(player_by_number(i), ptile,
2182 E_UNIT_LOST_DEF, ftc_server,
2183 /* TRANS: "Cannon ... the Polish Destroyer." */
2184 _("%s lost to an attack by the %s %s."),
2185 punit_link,
2186 nation_adjective_for_player(pvictor),
2187 pkiller_link);
2188 } else {
2189 fc_assert(other_killed[i] != punit);
2190 notify_player(player_by_number(i), ptile,
2191 E_UNIT_LOST_DEF, ftc_server,
2192 /* TRANS: "Cannon lost when the Polish Destroyer
2193 * attacked the German Musketeers." */
2194 _("%s lost when the %s %s attacked the %s %s."),
2195 unit_link(other_killed[i]),
2196 nation_adjective_for_player(pvictor),
2197 pkiller_link,
2198 nation_adjective_for_player(pvictim),
2199 punit_link);
2201 } else if (num_killed[i] > 1) {
2202 if (i == player_index(pvictim)) {
2203 int others = num_killed[i] - 1;
2205 if (others == 1) {
2206 notify_player(player_by_number(i), ptile,
2207 E_UNIT_LOST_DEF, ftc_server,
2208 /* TRANS: "Musketeers (and Cannon) lost to an
2209 * attack from the Polish Destroyer." */
2210 _("%s (and %s) lost to an attack from the %s %s."),
2211 punit_link,
2212 unit_link(other_killed[i]),
2213 nation_adjective_for_player(pvictor),
2214 pkiller_link);
2215 } else {
2216 notify_player(player_by_number(i), ptile,
2217 E_UNIT_LOST_DEF, ftc_server,
2218 /* TRANS: "Musketeers and 3 other units lost to
2219 * an attack from the Polish Destroyer."
2220 * (only happens with at least 2 other units) */
2221 PL_("%s and %d other unit lost to an attack "
2222 "from the %s %s.",
2223 "%s and %d other units lost to an attack "
2224 "from the %s %s.", others),
2225 punit_link,
2226 others,
2227 nation_adjective_for_player(pvictor),
2228 pkiller_link);
2230 } else {
2231 notify_player(player_by_number(i), ptile,
2232 E_UNIT_LOST_DEF, ftc_server,
2233 /* TRANS: "2 units lost when the Polish Destroyer
2234 * attacked the German Musketeers."
2235 * (only happens with at least 2 other units) */
2236 PL_("%d unit lost when the %s %s attacked the %s %s.",
2237 "%d units lost when the %s %s attacked the %s %s.",
2238 num_killed[i]),
2239 num_killed[i],
2240 nation_adjective_for_player(pvictor),
2241 pkiller_link,
2242 nation_adjective_for_player(pvictim),
2243 punit_link);
2248 /* remove the units - note the logic of which units actually die
2249 * must be mimiced exactly in at least one place up above. */
2250 punit = NULL; /* wiped during following iteration so unsafe to use */
2252 unit_list_iterate_safe(ptile->units, punit2) {
2253 if (pplayers_at_war(pvictor, unit_owner(punit2))
2254 && is_unit_reachable_at(punit2, pkiller, ptile)) {
2255 wipe_unit(punit2, ULR_KILLED, pvictor);
2257 } unit_list_iterate_safe_end;
2261 /**************************************************************************
2262 Package a unit_info packet. This packet contains basically all
2263 information about a unit.
2264 **************************************************************************/
2265 void package_unit(struct unit *punit, struct packet_unit_info *packet)
2267 packet->id = punit->id;
2268 packet->owner = player_number(unit_owner(punit));
2269 packet->nationality = player_number(unit_nationality(punit));
2270 packet->tile = tile_index(unit_tile(punit));
2271 packet->facing = punit->facing;
2272 packet->homecity = punit->homecity;
2273 output_type_iterate(o) {
2274 packet->upkeep[o] = punit->upkeep[o];
2275 } output_type_iterate_end;
2276 packet->veteran = punit->veteran;
2277 packet->type = utype_number(unit_type_get(punit));
2278 packet->movesleft = punit->moves_left;
2279 packet->hp = punit->hp;
2280 packet->activity = punit->activity;
2281 packet->activity_count = punit->activity_count;
2283 if (punit->activity_target != NULL) {
2284 packet->activity_tgt = extra_index(punit->activity_target);
2285 } else {
2286 packet->activity_tgt = EXTRA_NONE;
2289 packet->changed_from = punit->changed_from;
2290 packet->changed_from_count = punit->changed_from_count;
2292 if (punit->changed_from_target != NULL) {
2293 packet->changed_from_tgt = extra_index(punit->changed_from_target);
2294 } else {
2295 packet->changed_from_tgt = EXTRA_NONE;
2298 packet->ai = punit->ai_controlled;
2299 packet->fuel = punit->fuel;
2300 packet->goto_tile = (NULL != punit->goto_tile
2301 ? tile_index(punit->goto_tile) : -1);
2302 packet->paradropped = punit->paradropped;
2303 packet->done_moving = punit->done_moving;
2304 if (!unit_transported(punit)) {
2305 packet->transported = FALSE;
2306 packet->transported_by = 0;
2307 } else {
2308 packet->transported = TRUE;
2309 packet->transported_by = unit_transport_get(punit)->id;
2311 packet->occupied = (get_transporter_occupancy(punit) > 0);
2312 packet->battlegroup = punit->battlegroup;
2313 packet->has_orders = punit->has_orders;
2314 if (punit->has_orders) {
2315 int i;
2317 packet->orders_length = punit->orders.length;
2318 packet->orders_index = punit->orders.index;
2319 packet->orders_repeat = punit->orders.repeat;
2320 packet->orders_vigilant = punit->orders.vigilant;
2321 for (i = 0; i < punit->orders.length; i++) {
2322 packet->orders[i] = punit->orders.list[i].order;
2323 packet->orders_dirs[i] = punit->orders.list[i].dir;
2324 packet->orders_activities[i] = punit->orders.list[i].activity;
2325 packet->orders_targets[i] = punit->orders.list[i].target;
2327 } else {
2328 packet->orders_length = packet->orders_index = 0;
2329 packet->orders_repeat = packet->orders_vigilant = FALSE;
2330 /* No need to initialize array. */
2333 packet->action_decision_want = punit->action_decision_want;
2334 packet->action_decision_tile = (punit->action_decision_tile
2335 ? tile_index(punit->action_decision_tile)
2336 : IDENTITY_NUMBER_ZERO);
2339 /**************************************************************************
2340 Package a short_unit_info packet. This contains a limited amount of
2341 information about the unit, and is sent to players who shouldn't know
2342 everything (like the unit's owner's enemies).
2343 **************************************************************************/
2344 void package_short_unit(struct unit *punit,
2345 struct packet_unit_short_info *packet,
2346 enum unit_info_use packet_use, int info_city_id)
2348 packet->packet_use = packet_use;
2349 packet->info_city_id = info_city_id;
2351 packet->id = punit->id;
2352 packet->owner = player_number(unit_owner(punit));
2353 packet->tile = tile_index(unit_tile(punit));
2354 packet->facing = punit->facing;
2355 packet->veteran = punit->veteran;
2356 packet->type = utype_number(unit_type_get(punit));
2357 packet->hp = punit->hp;
2358 packet->occupied = (get_transporter_occupancy(punit) > 0);
2359 if (punit->activity == ACTIVITY_EXPLORE
2360 || punit->activity == ACTIVITY_GOTO) {
2361 packet->activity = ACTIVITY_IDLE;
2362 } else {
2363 packet->activity = punit->activity;
2366 if (punit->activity_target == NULL) {
2367 packet->activity_tgt = EXTRA_NONE;
2368 } else {
2369 packet->activity_tgt = extra_index(punit->activity_target);
2372 /* Transported_by information is sent to the client even for units that
2373 * aren't fully known. Note that for non-allied players, any transported
2374 * unit can't be seen at all. For allied players we have to know if
2375 * transporters have room in them so that we can load units properly. */
2376 if (!unit_transported(punit)) {
2377 packet->transported = FALSE;
2378 packet->transported_by = 0;
2379 } else {
2380 packet->transported = TRUE;
2381 packet->transported_by = unit_transport_get(punit)->id;
2385 /**************************************************************************
2386 Handle situation where unit goes out of player sight.
2387 **************************************************************************/
2388 void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2390 dlsend_packet_unit_remove(pplayer->connections, punit->id);
2391 if (punit->server.moving != NULL) {
2392 /* Update status of 'pplayer' vision for 'punit'. */
2393 BV_CLR(punit->server.moving->can_see_unit, player_index(pplayer));
2397 /****************************************************************************
2398 send the unit to the players who need the info.
2399 dest = NULL means all connections (game.est_connections)
2400 ****************************************************************************/
2401 void send_unit_info(struct conn_list *dest, struct unit *punit)
2403 const struct player *powner;
2404 struct packet_unit_info info;
2405 struct packet_unit_short_info sinfo;
2406 struct unit_move_data *pdata;
2408 if (dest == NULL) {
2409 dest = game.est_connections;
2412 CHECK_UNIT(punit);
2414 powner = unit_owner(punit);
2415 package_unit(punit, &info);
2416 package_short_unit(punit, &sinfo, UNIT_INFO_IDENTITY, 0);
2417 pdata = punit->server.moving;
2419 conn_list_iterate(dest, pconn) {
2420 struct player *pplayer = conn_get_player(pconn);
2422 /* Be careful to consider all cases where pplayer is NULL... */
2423 if (pplayer == NULL) {
2424 if (pconn->observer) {
2425 send_packet_unit_info(pconn, &info);
2427 } else if (pplayer == powner) {
2428 send_packet_unit_info(pconn, &info);
2429 if (pdata != NULL) {
2430 BV_SET(pdata->can_see_unit, player_index(pplayer));
2432 } else if (can_player_see_unit(pplayer, punit)) {
2433 send_packet_unit_short_info(pconn, &sinfo, FALSE);
2434 if (pdata != NULL) {
2435 BV_SET(pdata->can_see_unit, player_index(pplayer));
2438 } conn_list_iterate_end;
2441 /**************************************************************************
2442 For each specified connections, send information about all the units
2443 known to that player/conn.
2444 **************************************************************************/
2445 void send_all_known_units(struct conn_list *dest)
2447 conn_list_do_buffer(dest);
2448 conn_list_iterate(dest, pconn) {
2449 struct player *pplayer = pconn->playing;
2451 if (NULL == pplayer && !pconn->observer) {
2452 continue;
2455 players_iterate(unitowner) {
2456 unit_list_iterate(unitowner->units, punit) {
2457 send_unit_info(dest, punit);
2458 } unit_list_iterate_end;
2459 } players_iterate_end;
2461 conn_list_iterate_end;
2462 conn_list_do_unbuffer(dest);
2463 flush_packets();
2466 /**************************************************************************
2467 Nuke a square: 1) remove all units on the square, and 2) halve the
2468 size of the city on the square.
2470 If it isn't a city square or an ocean square then with 50% chance add
2471 some fallout, then notify the client about the changes.
2472 **************************************************************************/
2473 static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
2475 struct city *pcity = NULL;
2477 unit_list_iterate_safe(ptile->units, punit) {
2478 notify_player(unit_owner(punit), ptile, E_UNIT_LOST_MISC, ftc_server,
2479 _("Your %s was nuked by %s."),
2480 unit_tile_link(punit),
2481 pplayer == unit_owner(punit)
2482 ? _("yourself")
2483 : nation_plural_for_player(pplayer));
2484 if (unit_owner(punit) != pplayer) {
2485 notify_player(pplayer, ptile, E_UNIT_WIN, ftc_server,
2486 _("The %s %s was nuked."),
2487 nation_adjective_for_player(unit_owner(punit)),
2488 unit_tile_link(punit));
2490 wipe_unit(punit, ULR_NUKE, pplayer);
2491 } unit_list_iterate_safe_end;
2493 pcity = tile_city(ptile);
2495 if (pcity) {
2496 notify_player(city_owner(pcity), ptile, E_CITY_NUKED, ftc_server,
2497 _("%s was nuked by %s."),
2498 city_link(pcity),
2499 pplayer == city_owner(pcity)
2500 ? _("yourself")
2501 : nation_plural_for_player(pplayer));
2503 if (city_owner(pcity) != pplayer) {
2504 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2505 _("You nuked %s."),
2506 city_link(pcity));
2509 city_reduce_size(pcity, city_size_get(pcity) / 2, pplayer, "nuke");
2512 if (fc_rand(2) == 1) {
2513 struct extra_type *pextra;
2515 pextra = rand_extra_for_tile(ptile, EC_FALLOUT);
2516 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2517 tile_add_extra(ptile, pextra);
2518 update_tile_knowledge(ptile);
2523 /**************************************************************************
2524 Nuke all the squares in a 3x3 square around the center of the explosion
2525 pplayer is the player that caused the explosion.
2526 **************************************************************************/
2527 void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
2529 struct player *victim = tile_owner(ptile);
2531 call_incident(INCIDENT_NUCLEAR, pplayer, victim);
2533 if (pplayer == victim) {
2534 players_iterate(oplayer) {
2535 if (victim != oplayer) {
2536 call_incident(INCIDENT_NUCLEAR_SELF, pplayer, oplayer);
2538 } players_iterate_end;
2539 } else {
2540 players_iterate(oplayer) {
2541 if (victim != oplayer) {
2542 call_incident(INCIDENT_NUCLEAR_NOT_TARGET, pplayer, oplayer);
2544 } players_iterate_end;
2547 square_iterate(ptile, 1, ptile1) {
2548 do_nuke_tile(pplayer, ptile1);
2549 } square_iterate_end;
2551 notify_conn(NULL, ptile, E_NUKE, ftc_server,
2552 _("The %s detonated a nuke!"),
2553 nation_plural_for_player(pplayer));
2556 /**************************************************************************
2557 go by airline, if both cities have an airport and neither has been used this
2558 turn the unit will be transported by it and have its moves set to 0
2559 **************************************************************************/
2560 bool do_airline(struct unit *punit, struct city *pdest_city)
2562 struct city *psrc_city = tile_city(unit_tile(punit));
2565 enum unit_airlift_result result =
2566 test_unit_can_airlift_to(NULL, punit, pdest_city);
2567 if (!is_successful_airlift_result(result)) {
2568 switch (result) {
2569 /* These two can happen through no fault of the client (for allied
2570 * airlifts), so we give useful messages. */
2571 case AR_SRC_NO_FLIGHTS:
2572 notify_player(unit_owner(punit), unit_tile(punit),
2573 E_UNIT_RELOCATED, ftc_server,
2574 /* TRANS: Airlift failure message.
2575 * "Paris has no capacity to transport Warriors." */
2576 _("%s has no capacity to transport %s."),
2577 city_link(psrc_city), unit_link(punit));
2578 break;
2579 case AR_DST_NO_FLIGHTS:
2580 notify_player(unit_owner(punit), unit_tile(punit),
2581 E_UNIT_RELOCATED, ftc_server,
2582 /* TRANS: Airlift failure message.
2583 * "Paris has no capacity to transport Warriors." */
2584 _("%s has no capacity to transport %s."),
2585 city_link(pdest_city), unit_link(punit));
2586 break;
2587 default:
2588 /* The client should have been able to foresee all the other
2589 * causes of failure, so it's not worth having specific messages for
2590 * all of them. */
2591 notify_player(unit_owner(punit), unit_tile(punit),
2592 E_UNIT_RELOCATED, ftc_server,
2593 /* TRANS: Airlift failure message.
2594 * "Warriors cannot be transported to Paris." */
2595 _("%s cannot be transported to %s."),
2596 unit_link(punit), city_link(pdest_city));
2597 break;
2599 return FALSE;
2603 notify_player(unit_owner(punit), city_tile(pdest_city),
2604 E_UNIT_RELOCATED, ftc_server,
2605 _("%s transported successfully."),
2606 unit_link(punit));
2608 unit_move(punit, pdest_city->tile, punit->moves_left, NULL);
2610 /* Update airlift fields. */
2611 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
2612 psrc_city->airlift--;
2613 send_city_info(city_owner(psrc_city), psrc_city);
2615 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
2616 pdest_city->airlift--;
2617 send_city_info(city_owner(pdest_city), pdest_city);
2620 return TRUE;
2623 /**************************************************************************
2624 Autoexplore with unit.
2625 **************************************************************************/
2626 void do_explore(struct unit *punit)
2628 switch (manage_auto_explorer(punit)) {
2629 case MR_DEATH:
2630 /* don't use punit! */
2631 return;
2632 case MR_NOT_ALLOWED:
2633 /* Needed for something else */
2634 return;
2635 case MR_OK:
2636 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2637 * but don't count on this. See PR#39792.
2639 if (punit->activity == ACTIVITY_EXPLORE) {
2640 break;
2642 /* fallthru */
2643 default:
2644 unit_activity_handling(punit, ACTIVITY_IDLE);
2646 /* FIXME: When the manage_auto_explorer() call changes the activity from
2647 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2648 * alone. We reset it here. See PR#12931. */
2649 punit->ai_controlled = FALSE;
2650 break;
2653 send_unit_info(NULL, punit); /* probably duplicate */
2656 /**************************************************************************
2657 Returns whether the drop was made or not. Note that it also returns 1
2658 in the case where the drop was succesful, but the unit was killed by
2659 barbarians in a hut.
2660 **************************************************************************/
2661 bool do_paradrop(struct unit *punit, struct tile *ptile)
2663 struct player *pplayer = unit_owner(punit);
2664 int range, distance;
2666 if (!unit_has_type_flag(punit, UTYF_PARATROOPERS)) {
2667 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2668 _("This unit type can not be paradropped."));
2669 return FALSE;
2672 if (!can_unit_paradrop(punit)) {
2673 return FALSE;
2676 if (get_transporter_occupancy(punit) > 0) {
2677 notify_player(pplayer, unit_tile(punit), E_BAD_COMMAND, ftc_server,
2678 _("You cannot paradrop a unit that is "
2679 "transporting other units."));
2680 return FALSE;
2683 if (!map_is_known(ptile, pplayer)) {
2684 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2685 _("The destination location is not known."));
2686 return FALSE;
2689 range = unit_type_get(punit)->paratroopers_range;
2690 distance = real_map_distance(unit_tile(punit), ptile);
2691 if (distance > range) {
2692 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2693 _("The distance to the target (%i) "
2694 "is greater than the unit's range (%i)."),
2695 distance, range);
2696 return FALSE;
2697 } else if (distance < 1) {
2698 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2699 _("Already here."));
2700 return FALSE;
2703 if (map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
2704 if (!can_unit_exist_at_tile(punit, ptile)
2705 && (!game.info.paradrop_to_transport
2706 || !unit_could_load_at(punit, ptile))) {
2707 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2708 _("This unit cannot paradrop into %s."),
2709 terrain_name_translation(tile_terrain(ptile)));
2710 return FALSE;
2713 if (NULL != is_non_attack_city_tile(ptile, pplayer)) {
2714 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2715 _("Cannot attack unless you declare war first."));
2716 return FALSE;
2719 unit_list_iterate(ptile->units, pother) {
2720 if (can_player_see_unit(pplayer, pother)
2721 && pplayers_non_attack(pplayer, unit_owner(pother))) {
2722 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2723 _("Cannot attack unless you declare war first."));
2724 return FALSE;
2726 } unit_list_iterate_end;
2728 if (is_military_unit(punit)
2729 && !player_can_invade_tile(pplayer, ptile)) {
2730 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2731 _("Cannot invade unless you break peace with "
2732 "%s first."),
2733 player_name(tile_owner(ptile)));
2734 return FALSE;
2736 } else {
2737 /* Only take in account values from player map. */
2738 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
2740 if (NULL == plrtile->site
2741 && !is_native_to_class(unit_class_get(punit), plrtile->terrain,
2742 &(plrtile->extras))) {
2743 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2744 _("This unit cannot paradrop into %s."),
2745 terrain_name_translation(plrtile->terrain));
2746 return FALSE;
2749 if (NULL != plrtile->site
2750 && plrtile->owner != NULL
2751 && pplayers_non_attack(pplayer, plrtile->owner)) {
2752 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2753 _("Cannot attack unless you declare war first."));
2754 return FALSE;
2757 if (is_military_unit(punit)
2758 && NULL != plrtile->owner
2759 && players_non_invade(pplayer, plrtile->owner)) {
2760 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
2761 _("Cannot invade unless you break peace with "
2762 "%s first."),
2763 player_name(plrtile->owner));
2764 return FALSE;
2767 /* Safe terrain, really? Not transformed since player last saw it. */
2768 if (!can_unit_exist_at_tile(punit, ptile)
2769 && (!game.info.paradrop_to_transport
2770 || !unit_could_load_at(punit, ptile))) {
2771 map_show_circle(pplayer, ptile, unit_type_get(punit)->vision_radius_sq);
2772 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
2773 _("Your %s paradropped into the %s and was lost."),
2774 unit_tile_link(punit),
2775 terrain_name_translation(tile_terrain(ptile)));
2776 pplayer->score.units_lost++;
2777 server_remove_unit(punit, ULR_NONNATIVE_TERR);
2778 return TRUE;
2782 if (is_non_attack_city_tile(ptile, pplayer)
2783 || is_non_allied_unit_tile(ptile, pplayer)) {
2784 map_show_circle(pplayer, ptile, unit_type_get(punit)->vision_radius_sq);
2785 maybe_make_contact(ptile, pplayer);
2786 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
2787 _("Your %s was killed by enemy units at the "
2788 "paradrop destination."),
2789 unit_tile_link(punit));
2790 /* TODO: Should defender score.units_killed get increased too?
2791 * What if there's units of several allied players? Should the
2792 * city owner or owner of the first/random unit get the kill? */
2793 pplayer->score.units_lost++;
2794 server_remove_unit(punit, ULR_KILLED);
2795 return TRUE;
2798 /* All ok */
2799 punit->paradropped = TRUE;
2800 if (unit_move(punit, ptile, unit_type_get(punit)->paratroopers_mr_sub, NULL)) {
2801 /* Ensure we finished on valid state. */
2802 fc_assert(can_unit_exist_at_tile(punit, unit_tile(punit))
2803 || unit_transported(punit));
2805 return TRUE;
2808 /**************************************************************************
2809 Give 25 Gold or kill the unit. For H_LIMITEDHUTS
2810 Return TRUE if unit is alive, and FALSE if it was killed
2811 **************************************************************************/
2812 static bool hut_get_limited(struct unit *punit)
2814 bool ok = TRUE;
2815 int hut_chance = fc_rand(12);
2816 struct player *pplayer = unit_owner(punit);
2817 /* 1 in 12 to get barbarians */
2818 if (hut_chance != 0) {
2819 int cred = 25;
2820 notify_player(pplayer, unit_tile(punit), E_HUT_GOLD, ftc_server,
2821 PL_("You found %d gold.",
2822 "You found %d gold.", cred), cred);
2823 pplayer->economic.gold += cred;
2824 } else if (city_exists_within_max_city_map(unit_tile(punit), TRUE)
2825 || unit_has_type_flag(punit, UTYF_GAMELOSS)) {
2826 notify_player(pplayer, unit_tile(punit),
2827 E_HUT_BARB_CITY_NEAR, ftc_server,
2828 _("An abandoned village is here."));
2829 } else {
2830 notify_player(pplayer, unit_tile(punit), E_HUT_BARB_KILLED, ftc_server,
2831 _("Your %s has been killed by barbarians!"),
2832 unit_tile_link(punit));
2833 wipe_unit(punit, ULR_BARB_UNLEASH, NULL);
2834 ok = FALSE;
2836 return ok;
2839 /**************************************************************************
2840 Due to the effects in the scripted hut behavior can not be predicted,
2841 unit_enter_hut returns nothing.
2842 **************************************************************************/
2843 static void unit_enter_hut(struct unit *punit)
2845 struct player *pplayer = unit_owner(punit);
2846 enum hut_behavior behavior = unit_class_get(punit)->hut_behavior;
2847 struct tile *ptile = unit_tile(punit);
2849 /* FIXME: Should we still run "hut_enter" script when
2850 * hut_behavior is HUT_NOTHING or HUT_FRIGHTEN? */
2851 if (behavior == HUT_NOTHING) {
2852 return;
2855 extra_type_by_category_iterate(ECAT_BONUS, pextra) {
2856 if (tile_has_extra(ptile, pextra)) {
2857 pplayer->server.huts++;
2859 destroy_extra(ptile, pextra);
2860 update_tile_knowledge(unit_tile(punit));
2862 if (behavior == HUT_FRIGHTEN) {
2863 notify_player(pplayer, unit_tile(punit), E_HUT_BARB, ftc_server,
2864 _("Your overflight frightens the tribe;"
2865 " they scatter in terror."));
2866 return;
2869 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
2870 if (pplayer->ai_controlled && has_handicap(pplayer, H_LIMITEDHUTS)) {
2871 (void) hut_get_limited(punit);
2872 return;
2875 /* FIXME: Should have parameter for hut extra type */
2876 script_server_signal_emit("hut_enter", 1,
2877 API_TYPE_UNIT, punit);
2879 } extra_type_by_category_iterate_end;
2881 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
2882 return;
2885 /****************************************************************************
2886 Put the unit onto the transporter, and tell everyone.
2887 ****************************************************************************/
2888 void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
2890 fc_assert_ret(punit != NULL);
2891 fc_assert_ret(ptrans != NULL);
2893 unit_transport_load(punit, ptrans, FALSE);
2895 send_unit_info(NULL, punit);
2896 send_unit_info(NULL, ptrans);
2899 /****************************************************************************
2900 Load unit to transport, send transport's loaded status to everyone.
2901 ****************************************************************************/
2902 static void unit_transport_load_tp_status(struct unit *punit,
2903 struct unit *ptrans,
2904 bool force)
2906 bool had_cargo;
2908 fc_assert_ret(punit != NULL);
2909 fc_assert_ret(ptrans != NULL);
2911 had_cargo = get_transporter_occupancy(ptrans) > 0;
2913 unit_transport_load(punit, ptrans, force);
2915 if (!had_cargo) {
2916 /* Transport's loaded status changed */
2917 send_unit_info(NULL, ptrans);
2921 /****************************************************************************
2922 Pull the unit off of the transporter, and tell everyone.
2923 ****************************************************************************/
2924 void unit_transport_unload_send(struct unit *punit)
2926 struct unit *ptrans;
2928 fc_assert_ret(punit);
2930 ptrans = unit_transport_get(punit);
2932 fc_assert_ret(ptrans);
2934 unit_transport_unload(punit);
2936 send_unit_info(NULL, punit);
2937 send_unit_info(NULL, ptrans);
2940 /**************************************************************************
2941 This function is passed to unit_list_sort() to sort a list of units
2942 according to their win chance against autoattack_target, modified by
2943 transportation relationships.
2945 The reason for making sure that a cargo unit is ahead of its
2946 transporter(s) is to leave transports out of combat if at all possible.
2947 (The transport could be destroyed during combat.)
2948 **************************************************************************/
2949 static int compare_units(const struct unit *const *p1,
2950 const struct unit *const *q1)
2952 struct unit *p1def = get_defender(*p1, autoattack_target);
2953 struct unit *q1def = get_defender(*q1, autoattack_target);
2954 int p1uwc = unit_win_chance(*p1, p1def);
2955 int q1uwc = unit_win_chance(*q1, q1def);
2957 /* Sort by transport depth first. This makes sure that no transport
2958 * attacks before its cargo does -- cargo sorts earlier in the list. */
2960 const struct unit *p1trans = *p1, *q1trans = *q1;
2962 /* Walk the transport stacks in parallel, so as to bail out as soon as
2963 * one of them is empty (avoid walking deep stacks more often than
2964 * necessary). */
2965 while (p1trans && q1trans) {
2966 p1trans = unit_transport_get(p1trans);
2967 q1trans = unit_transport_get(q1trans);
2969 if (!p1trans && q1trans) {
2970 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
2971 * earlier in the list (p1 > q1). */
2972 return 1;
2973 } else if (p1trans && !q1trans) {
2974 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
2975 return -1;
2977 /* else same depth, so move on to checking win chance: */
2980 /* Put the units with the highest probability of success first. The up
2981 * side of this is that units with bonuses against the victim attacks
2982 * before other units. The downside is that strong units can be lead
2983 * away by sacrificial units. */
2984 if (p1uwc < q1uwc) {
2985 return +1; /* q is better */
2986 } else if (p1uwc == q1uwc) {
2987 return 0;
2988 } else {
2989 return -1; /* p is better */
2993 /*****************************************************************
2994 Can this unit be used in autoattack
2995 *****************************************************************/
2996 static bool is_suitable_autoattack_unit(struct unit *punit)
2998 if (unit_has_type_flag(punit, UTYF_NUCLEAR)) {
2999 /* Not a good idea to nuke our own area */
3000 return FALSE;
3003 return TRUE;
3006 /*****************************************************************
3007 Check if unit survives enemy autoattacks. We assume that any
3008 unit that is adjacent to us can see us.
3009 *****************************************************************/
3010 static bool unit_survive_autoattack(struct unit *punit)
3012 struct unit_list *autoattack;
3013 int moves = punit->moves_left;
3014 int sanity1 = punit->id;
3016 if (!game.server.autoattack) {
3017 return TRUE;
3020 autoattack = unit_list_new();
3022 /* Kludge to prevent attack power from dropping to zero during calc */
3023 punit->moves_left = MAX(punit->moves_left, 1);
3025 adjc_iterate(unit_tile(punit), ptile) {
3026 /* First add all eligible units to a unit list */
3027 unit_list_iterate(ptile->units, penemy) {
3028 struct player *enemyplayer = unit_owner(penemy);
3029 enum diplstate_type ds =
3030 player_diplstate_get(unit_owner(punit), enemyplayer)->type;
3032 if (penemy->moves_left > 0
3033 && ds == DS_WAR
3034 && is_suitable_autoattack_unit(penemy)
3035 && (unit_attack_unit_at_tile_result(penemy, punit, unit_tile(punit))
3036 == ATT_OK)) {
3037 unit_list_prepend(autoattack, penemy);
3039 } unit_list_iterate_end;
3040 } adjc_iterate_end;
3042 /* Sort the potential attackers from highest to lowest success
3043 * probability. */
3044 autoattack_target = unit_tile(punit); /* global variable */
3045 if (unit_list_size(autoattack) >= 2) {
3046 unit_list_sort(autoattack, &compare_units);
3049 unit_list_iterate_safe(autoattack, penemy) {
3050 int sanity2 = penemy->id;
3051 struct tile *ptile = unit_tile(penemy);
3052 struct unit *enemy_defender = get_defender(punit, ptile);
3053 struct unit *punit_defender = get_defender(penemy, unit_tile(punit));
3054 double punitwin, penemywin;
3055 double threshold = 0.25;
3057 fc_assert_action(NULL != punit_defender, continue);
3059 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3060 /* Don't leave city defenseless */
3061 threshold = 0.90;
3064 if (NULL != enemy_defender) {
3065 punitwin = unit_win_chance(punit, enemy_defender);
3066 } else {
3067 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3068 punitwin = 1.0;
3070 penemywin = unit_win_chance(penemy, punit_defender);
3072 if ((penemywin > 1.0 - punitwin
3073 || utype_acts_hostile(unit_type_get(punit))
3074 || get_transporter_capacity(punit) > 0)
3075 && penemywin > threshold) {
3076 #ifdef REALLY_DEBUG_THIS
3077 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3078 unit_rule_name(penemy), unit_rule_name(punit),
3079 TILE_XY(unit_tile(punit)), penemywin,
3080 1.0 - punitwin, threshold);
3081 #endif
3083 unit_activity_handling(penemy, ACTIVITY_IDLE);
3084 /* Attack */
3085 (void) unit_move_handling(penemy, unit_tile(punit),
3086 FALSE, TRUE, NULL);
3087 } else {
3088 #ifdef REALLY_DEBUG_THIS
3089 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3090 unit_rule_name(penemy), unit_rule_name(punit),
3091 TILE_XY(unit_tile(punit)), penemywin,
3092 1.0 - punitwin, threshold);
3093 #endif
3094 continue;
3097 if (game_unit_by_number(sanity2)) {
3098 send_unit_info(NULL, penemy);
3100 if (game_unit_by_number(sanity1)) {
3101 send_unit_info(NULL, punit);
3102 } else {
3103 unit_list_destroy(autoattack);
3104 return FALSE; /* moving unit dead */
3106 } unit_list_iterate_safe_end;
3108 unit_list_destroy(autoattack);
3109 if (game_unit_by_number(sanity1)) {
3110 /* We could have lost movement in combat */
3111 punit->moves_left = MIN(punit->moves_left, moves);
3112 send_unit_info(NULL, punit);
3113 return TRUE;
3114 } else {
3115 return FALSE;
3119 /****************************************************************************
3120 Cancel orders for the unit.
3121 ****************************************************************************/
3122 static void cancel_orders(struct unit *punit, char *dbg_msg)
3124 free_unit_orders(punit);
3125 send_unit_info(NULL, punit);
3126 log_debug("%s", dbg_msg);
3129 /*****************************************************************
3130 Will wake up any neighboring enemy sentry units or patrolling
3131 units.
3132 *****************************************************************/
3133 static void wakeup_neighbor_sentries(struct unit *punit)
3135 bool alone_in_city;
3137 if (NULL != tile_city(unit_tile(punit))) {
3138 int count = 0;
3140 unit_list_iterate(unit_tile(punit)->units, aunit) {
3141 /* Consider only units not transported. */
3142 if (!unit_transported(aunit)) {
3143 count++;
3145 } unit_list_iterate_end;
3147 alone_in_city = (1 == count);
3148 } else {
3149 alone_in_city = FALSE;
3152 /* There may be sentried units with a sightrange > 3, but we don't
3153 wake them up if the punit is farther away than 3. */
3154 square_iterate(unit_tile(punit), 3, ptile) {
3155 unit_list_iterate(ptile->units, penemy) {
3156 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3157 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3159 if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
3160 && penemy->activity == ACTIVITY_SENTRY
3161 && radius_sq >= distance_sq
3162 /* If the unit moved on a city, and the unit is alone, consider
3163 * it is visible. */
3164 && (alone_in_city
3165 || can_player_see_unit(unit_owner(penemy), punit))
3166 /* on board transport; don't awaken */
3167 && can_unit_exist_at_tile(penemy, unit_tile(penemy))) {
3168 set_unit_activity(penemy, ACTIVITY_IDLE);
3169 send_unit_info(NULL, penemy);
3171 } unit_list_iterate_end;
3172 } square_iterate_end;
3174 /* Wakeup patrolling units we bump into.
3175 We do not wakeup units further away than 3 squares... */
3176 square_iterate(unit_tile(punit), 3, ptile) {
3177 unit_list_iterate(ptile->units, ppatrol) {
3178 if (punit != ppatrol
3179 && unit_has_orders(ppatrol)
3180 && ppatrol->orders.vigilant) {
3181 if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
3182 cancel_orders(ppatrol, " stopping because of nearby enemy");
3183 notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
3184 E_UNIT_ORDERS, ftc_server,
3185 _("Orders for %s aborted after enemy movement was "
3186 "spotted."),
3187 unit_link(ppatrol));
3190 } unit_list_iterate_end;
3191 } square_iterate_end;
3194 /**************************************************************************
3195 Does: 1) updates the unit's homecity and the city it enters/leaves (the
3196 city's happiness varies). This also takes into account when the
3197 unit enters/leaves a fortress.
3198 2) updates adjacent cities' unavailable tiles.
3200 FIXME: Sometimes it is not necessary to send cities because the goverment
3201 doesn't care whether a unit is away or not.
3202 **************************************************************************/
3203 static bool unit_move_consequences(struct unit *punit,
3204 struct tile *src_tile,
3205 struct tile *dst_tile,
3206 bool passenger)
3208 struct city *fromcity = tile_city(src_tile);
3209 struct city *tocity = tile_city(dst_tile);
3210 struct city *homecity_start_pos = NULL;
3211 struct city *homecity_end_pos = NULL;
3212 int homecity_id_start_pos = punit->homecity;
3213 int homecity_id_end_pos = punit->homecity;
3214 struct player *pplayer_start_pos = unit_owner(punit);
3215 struct player *pplayer_end_pos = pplayer_start_pos;
3216 struct unit_type *type_start_pos = unit_type_get(punit);
3217 struct unit_type *type_end_pos = type_start_pos;
3218 bool refresh_homecity_start_pos = FALSE;
3219 bool refresh_homecity_end_pos = FALSE;
3220 int saved_id = punit->id;
3221 bool alive = TRUE;
3223 if (tocity) {
3224 unit_enter_city(punit, tocity, passenger);
3226 alive = unit_is_alive(saved_id);
3227 if (alive) {
3228 /* In case script has changed something about unit */
3229 pplayer_end_pos = unit_owner(punit);
3230 type_end_pos = unit_type_get(punit);
3231 homecity_id_end_pos = punit->homecity;
3235 if (homecity_id_start_pos != 0) {
3236 homecity_start_pos = game_city_by_number(homecity_id_start_pos);
3238 if (homecity_id_start_pos != homecity_id_end_pos) {
3239 homecity_end_pos = game_city_by_number(homecity_id_end_pos);
3240 } else {
3241 homecity_end_pos = homecity_start_pos;
3244 /* We only do refreshes for non-AI players to now make sure the AI turns
3245 doesn't take too long. Perhaps we should make a special refresh_city
3246 functions that only refreshed happines. */
3248 /* might have changed owners or may be destroyed */
3249 tocity = tile_city(dst_tile);
3251 if (tocity) { /* entering a city */
3252 if (tocity->owner == pplayer_end_pos) {
3253 if (tocity != homecity_end_pos && !pplayer_end_pos->ai_controlled) {
3254 city_refresh(tocity);
3255 send_city_info(pplayer_end_pos, tocity);
3258 if (homecity_start_pos) {
3259 refresh_homecity_start_pos = TRUE;
3263 if (fromcity) { /* leaving a city */
3264 if (homecity_start_pos) {
3265 refresh_homecity_start_pos = TRUE;
3267 if (fromcity != homecity_start_pos
3268 && fromcity->owner == pplayer_start_pos
3269 && !pplayer_start_pos->ai_controlled) {
3270 city_refresh(fromcity);
3271 send_city_info(pplayer_start_pos, fromcity);
3275 /* entering/leaving a fortress or friendly territory */
3276 if (homecity_start_pos || homecity_end_pos) {
3277 if ((game.info.happyborders != HB_DISABLED && tile_owner(src_tile) != tile_owner(dst_tile))
3278 || (tile_has_base_flag_for_unit(dst_tile,
3279 type_end_pos,
3280 BF_NOT_AGGRESSIVE)
3281 && is_friendly_city_near(pplayer_end_pos, dst_tile))
3282 || (tile_has_base_flag_for_unit(src_tile,
3283 type_start_pos,
3284 BF_NOT_AGGRESSIVE)
3285 && is_friendly_city_near(pplayer_start_pos, src_tile))) {
3286 refresh_homecity_start_pos = TRUE;
3287 refresh_homecity_end_pos = TRUE;
3291 if (refresh_homecity_start_pos && !pplayer_start_pos->ai_controlled) {
3292 city_refresh(homecity_start_pos);
3293 send_city_info(pplayer_start_pos, homecity_start_pos);
3295 if (refresh_homecity_end_pos
3296 && (!refresh_homecity_start_pos
3297 || homecity_start_pos != homecity_end_pos)
3298 && !pplayer_end_pos->ai_controlled) {
3299 city_refresh(homecity_end_pos);
3300 send_city_info(pplayer_end_pos, homecity_end_pos);
3303 city_map_update_tile_now(dst_tile);
3304 sync_cities();
3306 return alive;
3309 /**************************************************************************
3310 Check if the units activity is legal for a move , and reset it if it isn't.
3311 **************************************************************************/
3312 static void check_unit_activity(struct unit *punit)
3314 switch (punit->activity) {
3315 case ACTIVITY_IDLE:
3316 case ACTIVITY_SENTRY:
3317 case ACTIVITY_EXPLORE:
3318 case ACTIVITY_GOTO:
3319 break;
3320 case ACTIVITY_POLLUTION:
3321 case ACTIVITY_MINE:
3322 case ACTIVITY_IRRIGATE:
3323 case ACTIVITY_FORTIFIED:
3324 case ACTIVITY_FORTRESS:
3325 case ACTIVITY_PILLAGE:
3326 case ACTIVITY_TRANSFORM:
3327 case ACTIVITY_UNKNOWN:
3328 case ACTIVITY_AIRBASE:
3329 case ACTIVITY_FORTIFYING:
3330 case ACTIVITY_FALLOUT:
3331 case ACTIVITY_PATROL_UNUSED:
3332 case ACTIVITY_BASE:
3333 case ACTIVITY_GEN_ROAD:
3334 case ACTIVITY_CONVERT:
3335 case ACTIVITY_OLD_ROAD:
3336 case ACTIVITY_OLD_RAILROAD:
3337 case ACTIVITY_LAST:
3338 set_unit_activity(punit, ACTIVITY_IDLE);
3339 break;
3343 /****************************************************************************
3344 Create a new unit move data, or use previous one if available.
3345 ****************************************************************************/
3346 static struct unit_move_data *unit_move_data(struct unit *punit,
3347 struct tile *psrctile,
3348 struct tile *pdesttile)
3350 struct unit_move_data *pdata;
3351 struct player *powner = unit_owner(punit);
3352 const v_radius_t radius_sq =
3353 V_RADIUS(get_unit_vision_at(punit, pdesttile, V_MAIN),
3354 get_unit_vision_at(punit, pdesttile, V_INVIS));
3355 struct vision *new_vision;
3356 bool success;
3358 if (punit->server.moving) {
3359 /* Recursive moving (probably due to a script). */
3360 pdata = punit->server.moving;
3361 pdata->ref_count++;
3362 fc_assert_msg(pdata->punit == punit,
3363 "Unit number %d (%p) was going to die, but "
3364 "server attempts to move it.",
3365 punit->id, punit);
3366 fc_assert_msg(pdata->old_vision == NULL,
3367 "Unit number %d (%p) has done an incomplete move.",
3368 punit->id, punit);
3369 } else {
3370 pdata = fc_malloc(sizeof(*pdata));
3371 pdata->ref_count = 1;
3372 pdata->punit = punit;
3373 punit->server.moving = pdata;
3374 BV_CLR_ALL(pdata->can_see_unit);
3376 pdata->powner = powner;
3377 BV_CLR_ALL(pdata->can_see_move);
3378 pdata->old_vision = punit->server.vision;
3380 /* Remove unit from the source tile. */
3381 fc_assert(unit_tile(punit) == psrctile);
3382 success = unit_list_remove(psrctile->units, punit);
3383 fc_assert(success == TRUE);
3385 /* Set new tile. */
3386 unit_tile_set(punit, pdesttile);
3387 unit_list_prepend(pdesttile->units, punit);
3389 if (unit_transported(punit)) {
3390 /* Silently free orders since they won't be applicable anymore. */
3391 free_unit_orders(punit);
3394 /* Check unit activity. */
3395 check_unit_activity(punit);
3396 unit_did_action(punit);
3397 unit_forget_last_activity(punit);
3399 /* We first unfog the destination, then send the move,
3400 * and then fog the old territory. This means that the player
3401 * gets a chance to see the newly explored territory while the
3402 * client moves the unit, and both areas are visible during the
3403 * move */
3405 /* Enhance vision if unit steps into a fortress */
3406 new_vision = vision_new(powner, pdesttile);
3407 punit->server.vision = new_vision;
3408 vision_change_sight(new_vision, radius_sq);
3409 ASSERT_VISION(new_vision);
3411 return pdata;
3414 /****************************************************************************
3415 Decrease the reference counter and destroy if needed.
3416 ****************************************************************************/
3417 static void unit_move_data_unref(struct unit_move_data *pdata)
3419 fc_assert_ret(pdata != NULL);
3420 fc_assert_ret(pdata->ref_count > 0);
3421 fc_assert_msg(pdata->old_vision == NULL,
3422 "Unit number %d (%p) has done an incomplete move.",
3423 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3425 pdata->ref_count--;
3426 if (pdata->ref_count == 0) {
3427 if (pdata->punit != NULL) {
3428 fc_assert(pdata->punit->server.moving == pdata);
3429 pdata->punit->server.moving = NULL;
3431 free(pdata);
3435 /*****************************************************************************
3436 Moves a unit. No checks whatsoever! This is meant as a practical
3437 function for other functions, like do_airline, which do the checking
3438 themselves.
3440 If you move a unit you should always use this function, as it also sets
3441 the transport status of the unit correctly. Note that the source tile (the
3442 current tile of the unit) and pdesttile need not be adjacent.
3444 Returns TRUE iff unit still alive.
3445 *****************************************************************************/
3446 bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3447 struct unit *embark_to)
3449 struct player *pplayer;
3450 struct tile *psrctile;
3451 struct city *pcity;
3452 struct unit *ptransporter;
3453 struct packet_unit_info src_info, dest_info;
3454 struct packet_unit_short_info src_sinfo, dest_sinfo;
3455 struct unit_move_data_list *plist =
3456 unit_move_data_list_new_full(unit_move_data_unref);
3457 struct unit_move_data *pdata;
3458 int saved_id;
3459 bool unit_lives;
3460 bool adj;
3461 enum direction8 facing;
3462 struct player *bowner;
3464 /* Some checks. */
3465 fc_assert_ret_val(punit != NULL, FALSE);
3466 fc_assert_ret_val(pdesttile != NULL, FALSE);
3468 pplayer = unit_owner(punit);
3469 saved_id = punit->id;
3470 psrctile = unit_tile(punit);
3471 adj = base_get_direction_for_step(psrctile, pdesttile, &facing);
3473 conn_list_do_buffer(game.est_connections);
3475 /* Unload the unit if on a transport. */
3476 ptransporter = unit_transport_get(punit);
3477 if (ptransporter != NULL) {
3478 /* Unload unit _before_ setting the new tile! */
3479 unit_transport_unload(punit);
3480 /* Send updated information to anyone watching that transporter
3481 * was unloading cargo. */
3482 send_unit_info(NULL, ptransporter);
3485 /* Wakup units next to us before we move. */
3486 wakeup_neighbor_sentries(punit);
3488 /* Make info packets at 'psrctile'. */
3489 if (adj) {
3490 /* If tiles are adjacent, we will show the move to users able
3491 * to see it. */
3492 package_unit(punit, &src_info);
3493 package_short_unit(punit, &src_sinfo, UNIT_INFO_IDENTITY, 0);
3496 /* Make new data for 'punit'. */
3497 pdata = unit_move_data(punit, psrctile, pdesttile);
3498 unit_move_data_list_prepend(plist, pdata);
3500 /* Set unit orientation */
3501 if (adj) {
3502 /* Only change orientation when moving to adjacent tile */
3503 punit->facing = facing;
3506 /* Move magic. */
3507 punit->moved = TRUE;
3508 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3509 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3510 /* The next order may not require any remaining move fragments. */
3511 punit->done_moving = TRUE;
3514 /* No longer relevant. */
3515 punit->action_decision_tile = NULL;
3516 punit->action_decision_want = ACT_DEC_NOTHING;
3518 if (!adj
3519 && action_tgt_city(punit, pdesttile)) {
3520 /* The unit can perform an action to the city at the destination tile.
3521 * A long distance move (like an airlift) doesn't ask what action to
3522 * perform before moving. Ask now. */
3524 punit->action_decision_want = ACT_DEC_PASSIVE;
3525 punit->action_decision_tile = pdesttile;
3528 /* Claim ownership of fortress? */
3529 bowner = extra_owner(pdesttile);
3530 if ((bowner == NULL || pplayers_at_war(bowner, pplayer))
3531 && tile_has_claimable_base(pdesttile, unit_type_get(punit))) {
3532 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3533 * Even if original unit cannot claim other kind of bases, the
3534 * first claimed base will have influence over other bases,
3535 * or something like that. */
3536 tile_claim_bases(pdesttile, pplayer);
3539 /* Move all contained units. */
3540 unit_cargo_iterate(punit, pcargo) {
3541 pdata = unit_move_data(pcargo, psrctile, pdesttile);
3542 unit_move_data_list_append(plist, pdata);
3543 } unit_cargo_iterate_end;
3545 /* Get data for 'punit'. */
3546 pdata = unit_move_data_list_front(plist);
3548 /* Determine the players able to see the move(s), now that the player
3549 * vision has been increased. */
3550 if (adj) {
3551 /* Main unit for adjacent move: the move is visible for every player
3552 * able to see on the matching unit layer. */
3553 enum vision_layer vlayer = is_hiding_unit(punit) ? V_INVIS : V_MAIN;
3555 players_iterate(oplayer) {
3556 if (map_is_known_and_seen(psrctile, oplayer, vlayer)
3557 || map_is_known_and_seen(pdesttile, oplayer, vlayer)) {
3558 BV_SET(pdata->can_see_unit, player_index(oplayer));
3559 BV_SET(pdata->can_see_move, player_index(oplayer));
3561 } players_iterate_end;
3563 unit_move_data_list_iterate(plist, pmove_data) {
3564 if (adj && pmove_data == pdata) {
3565 /* If positions are adjacent, we have already handled 'punit'. See
3566 * above. */
3567 continue;
3570 players_iterate(oplayer) {
3571 if ((adj
3572 && can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
3573 pmove_data != pdata))
3574 || can_player_see_unit_at(oplayer, pmove_data->punit, pdesttile,
3575 pmove_data != pdata)) {
3576 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3577 BV_SET(pmove_data->can_see_move, player_index(oplayer));
3579 if (can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
3580 pmove_data != pdata)) {
3581 /* The unit was seen with its source tile even if it was
3582 * teleported. */
3583 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3585 } players_iterate_end;
3586 } unit_move_data_list_iterate_end;
3588 /* Check timeout settings. */
3589 if (current_turn_timeout() != 0 && game.server.timeoutaddenemymove > 0) {
3590 bool new_information_for_enemy = FALSE;
3592 phase_players_iterate(penemy) {
3593 /* Increase the timeout if an enemy unit moves and the
3594 * timeoutaddenemymove setting is in use. */
3595 if (penemy->is_connected
3596 && pplayer != penemy
3597 && pplayers_at_war(pplayer, penemy)
3598 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
3599 new_information_for_enemy = TRUE;
3600 break;
3602 } phase_players_iterate_end;
3604 if (new_information_for_enemy) {
3605 increase_timeout_because_unit_moved();
3609 /* Notifications of the move to the clients. */
3610 if (adj) {
3611 /* Special case: 'punit' is moving to adjacent position. Then we show
3612 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
3614 /* Make info packets at 'pdesttile'. */
3615 package_unit(punit, &dest_info);
3616 package_short_unit(punit, &dest_sinfo, UNIT_INFO_IDENTITY, 0);
3618 conn_list_iterate(game.est_connections, pconn) {
3619 struct player *aplayer = conn_get_player(pconn);
3621 if (aplayer == NULL) {
3622 if (pconn->observer) {
3623 /* Global observers see all... */
3624 send_packet_unit_info(pconn, &src_info);
3625 send_packet_unit_info(pconn, &dest_info);
3627 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
3628 if (aplayer == pplayer) {
3629 send_packet_unit_info(pconn, &src_info);
3630 send_packet_unit_info(pconn, &dest_info);
3631 } else {
3632 send_packet_unit_short_info(pconn, &src_sinfo, FALSE);
3633 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
3636 } conn_list_iterate_end;
3639 /* Other moves. */
3640 unit_move_data_list_iterate(plist, pmove_data) {
3641 if (adj && pmove_data == pdata) {
3642 /* If positions are adjacent, we have already shown 'punit' move.
3643 * See above. */
3644 continue;
3647 /* Make info packets at 'pdesttile'. */
3648 package_unit(pmove_data->punit, &dest_info);
3649 package_short_unit(pmove_data->punit, &dest_sinfo,
3650 UNIT_INFO_IDENTITY, 0);
3652 conn_list_iterate(game.est_connections, pconn) {
3653 struct player *aplayer = conn_get_player(pconn);
3655 if (aplayer == NULL) {
3656 if (pconn->observer) {
3657 /* Global observers see all... */
3658 send_packet_unit_info(pconn, &dest_info);
3660 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
3661 if (aplayer == pmove_data->powner) {
3662 send_packet_unit_info(pconn, &dest_info);
3663 } else {
3664 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
3667 } conn_list_iterate_end;
3668 } unit_move_data_list_iterate_end;
3670 /* Clear old vision. */
3671 unit_move_data_list_iterate(plist, pmove_data) {
3672 vision_clear_sight(pmove_data->old_vision);
3673 vision_free(pmove_data->old_vision);
3674 pmove_data->old_vision = NULL;
3675 } unit_move_data_list_iterate_end;
3677 /* Move consequences. */
3678 unit_move_data_list_iterate(plist, pmove_data) {
3679 struct unit *aunit = pmove_data->punit;
3681 if (aunit != NULL
3682 && unit_owner(aunit) == pmove_data->powner
3683 && unit_tile(aunit) == pdesttile) {
3684 (void) unit_move_consequences(aunit, psrctile, pdesttile,
3685 pdata != pmove_data);
3687 } unit_move_data_list_iterate_end;
3689 unit_lives = (pdata->punit == punit);
3691 /* Wakeup units and make contact. */
3692 if (unit_lives) {
3693 wakeup_neighbor_sentries(punit);
3695 maybe_make_contact(pdesttile, pplayer);
3697 if (unit_lives) {
3698 /* Special checks for ground units in the ocean. */
3699 if (embark_to || !can_unit_survive_at_tile(punit, pdesttile)) {
3700 if (embark_to != NULL) {
3701 ptransporter = embark_to;
3702 } else {
3703 ptransporter = transporter_for_unit(punit);
3705 if (ptransporter) {
3706 unit_transport_load_tp_status(punit, ptransporter, FALSE);
3708 /* Set activity to sentry if boarding a ship. */
3709 if (!pplayer->ai_controlled
3710 && !unit_has_orders(punit)
3711 && !punit->ai_controlled
3712 && !can_unit_exist_at_tile(punit, pdesttile)) {
3713 set_unit_activity(punit, ACTIVITY_SENTRY);
3716 send_unit_info(NULL, punit);
3721 /* Remove units going out of sight. */
3722 unit_move_data_list_iterate_rev(plist, pmove_data) {
3723 struct unit *aunit = pmove_data->punit;
3725 if (aunit == NULL) {
3726 continue; /* Died! */
3729 players_iterate(aplayer) {
3730 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
3731 && !can_player_see_unit(aplayer, aunit)) {
3732 unit_goes_out_of_sight(aplayer, aunit);
3734 } players_iterate_end;
3735 } unit_move_data_list_iterate_rev_end;
3737 /* Inform the owner's client about actor unit arrival. Can, depending on
3738 * the client settings, cause the client to start the process that makes
3739 * the action selection dialog pop up. */
3740 if ((pcity = tile_city(pdesttile))) {
3741 /* Arrival in a city counts. */
3743 unit_move_data_list_iterate(plist, pmove_data) {
3744 struct unit *ptrans;
3745 bool ok;
3746 struct unit *act_unit;
3747 struct player *act_player;
3749 act_unit = pmove_data->punit;
3750 act_player = unit_owner(act_unit);
3752 if (act_unit == NULL
3753 || !unit_is_alive(act_unit->id)) {
3754 /* The unit died before reaching this point. */
3755 continue;
3758 if (unit_tile(act_unit) != pdesttile) {
3759 /* The unit didn't arrive at the destination tile. */
3760 continue;
3763 if (act_player->ai_controlled) {
3764 /* The AI doesn't need reminders. */
3765 continue;
3768 if (!unit_transported(act_unit)) {
3769 /* Don't show the action selection dialog again. Non transported
3770 * units are handled before they move to the tile. */
3771 continue;
3774 /* Open action dialog only if 'act_unit' and all its transporters
3775 * (recursively) don't have orders. */
3776 if (unit_has_orders(act_unit)) {
3777 /* The unit it self has orders. */
3778 continue;
3781 for (ptrans = unit_transport_get(act_unit);;
3782 ptrans = unit_transport_get(ptrans)) {
3783 if (NULL == ptrans) {
3784 /* No (recursive) transport has orders. */
3785 ok = TRUE;
3786 break;
3787 } else if (unit_has_orders(ptrans)) {
3788 /* A unit transporting the unit has orders */
3789 ok = FALSE;
3790 break;
3794 if (!ok) {
3795 /* A unit transporting act_unit has orders. */
3796 continue;
3799 if (action_tgt_city(act_unit, pdesttile)) {
3800 /* There is a valid target. */
3802 act_unit->action_decision_want = ACT_DEC_PASSIVE;
3803 act_unit->action_decision_tile = pdesttile;
3805 /* Let the client know that this unit wants the player to decide
3806 * what to do. */
3807 send_unit_info(player_reply_dest(act_player), act_unit);
3809 } unit_move_data_list_iterate_end;
3812 unit_move_data_list_destroy(plist);
3814 /* Check cities at source and destination. */
3815 if ((pcity = tile_city(psrctile))) {
3816 refresh_dumb_city(pcity);
3818 if ((pcity = tile_city(pdesttile))) {
3819 refresh_dumb_city(pcity);
3822 if (unit_lives) {
3823 /* Let the scripts run ... */
3824 script_server_signal_emit("unit_moved", 3,
3825 API_TYPE_UNIT, punit,
3826 API_TYPE_TILE, psrctile,
3827 API_TYPE_TILE, pdesttile);
3828 unit_lives = unit_is_alive(saved_id);
3831 if (unit_lives) {
3832 /* Autoattack. */
3833 unit_lives = unit_survive_autoattack(punit);
3836 if (unit_lives) {
3837 /* Is there a hut? */
3838 if (tile_has_cause_extra(pdesttile, EC_HUT)) {
3839 unit_enter_hut(punit);
3840 unit_lives = unit_is_alive(saved_id);
3844 conn_list_do_unbuffer(game.est_connections);
3846 return unit_lives;
3849 /**************************************************************************
3850 Maybe cancel the goto if there is an enemy in the way
3851 **************************************************************************/
3852 static bool maybe_cancel_goto_due_to_enemy(struct unit *punit,
3853 struct tile *ptile)
3855 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
3856 || is_non_allied_city_tile(ptile, unit_owner(punit)));
3859 /**************************************************************************
3860 Maybe cancel the patrol as there is an enemy near.
3862 If you modify the wakeup range you should change it in
3863 wakeup_neighbor_sentries() too.
3864 **************************************************************************/
3865 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
3867 bool cancel = FALSE;
3868 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
3869 struct player *pplayer = unit_owner(punit);
3871 circle_iterate(unit_tile(punit), radius_sq, ptile) {
3872 struct unit *penemy = is_non_allied_unit_tile(ptile, pplayer);
3874 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
3876 if ((penemy && can_player_see_unit(pplayer, penemy))
3877 || (pdcity && !pplayers_allied(pplayer, vision_site_owner(pdcity))
3878 && pdcity->occupied)) {
3879 cancel = TRUE;
3880 break;
3882 } circle_iterate_end;
3884 return cancel;
3887 /**************************************************************************
3888 Returns the action id corresponding to the specified order id.
3889 **************************************************************************/
3890 static int order_to_action(struct unit *punit, enum unit_orders order)
3892 switch (order) {
3893 case ORDER_BUILD_WONDER:
3894 return ACTION_HELP_WONDER;
3895 case ORDER_TRADE_ROUTE:
3896 return ACTION_TRADE_ROUTE;
3897 case ORDER_MOVE:
3898 case ORDER_ACTION_MOVE:
3899 case ORDER_FULL_MP:
3900 case ORDER_BUILD_CITY:
3901 case ORDER_ACTIVITY:
3902 case ORDER_DISBAND:
3903 case ORDER_HOMECITY:
3904 case ORDER_LAST:
3905 /* Not action enabler controlled. */
3906 break;
3909 fc_assert_msg(FALSE, "No action to map order to.");
3910 return ACTION_COUNT;
3913 /**************************************************************************
3914 Returns TRUE iff it is reasonable to assume that the player is wathing
3915 the unit.
3917 Since the player is watching the unit there is no need to inform him
3918 about things he could see happening. Remember that it still may
3919 be necessary to explain why something happened.
3920 **************************************************************************/
3921 static inline bool player_is_watching(struct unit *punit, const bool fresh)
3923 /* The player just sent the orders to the unit. The unit has moves left.
3924 * It is therefore safe to assume that the player already is paying
3925 * attention to the unit. */
3926 return fresh && punit->moves_left > 0;
3929 /****************************************************************************
3930 Executes a unit's orders stored in punit->orders. The unit is put on idle
3931 if an action fails or if "patrol" is set and an enemy unit is encountered.
3933 The return value will be TRUE if the unit lives, FALSE otherwise. (This
3934 function used to return a goto_result enumeration, declared in gotohand.h.
3935 But this enumeration was never checked by the caller and just lead to
3936 confusion. All the caller really needs to know is if the unit lived or
3937 died; everything else is handled internally within execute_orders.)
3939 If the orders are repeating the loop starts over at the beginning once it
3940 completes. To avoid infinite loops on railroad we stop for this
3941 turn when the unit is back where it started, even if it have moves left.
3943 A unit will attack under orders only on its final action.
3945 The fresh parameter is true if the order execution happens because the
3946 orders just were received.
3947 ****************************************************************************/
3948 bool execute_orders(struct unit *punit, const bool fresh)
3950 struct tile *dst_tile;
3951 bool res, last_order;
3952 int unitid = punit->id;
3953 struct player *pplayer = unit_owner(punit);
3954 int moves_made = 0;
3955 enum unit_activity activity;
3957 fc_assert_ret_val(unit_has_orders(punit), TRUE);
3959 if (punit->activity != ACTIVITY_IDLE) {
3960 /* Unit's in the middle of an activity; wait for it to finish. */
3961 punit->done_moving = TRUE;
3962 return TRUE;
3965 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
3967 /* Any time the orders are canceled we should give the player a message. */
3969 while (TRUE) {
3970 struct unit_order order;
3972 if (punit->done_moving) {
3973 log_debug(" stopping because we're done this turn");
3974 return TRUE;
3977 if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
3978 /* "Patrol" orders are stopped if an enemy is near. */
3979 cancel_orders(punit, " stopping because of nearby enemy");
3980 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
3981 _("Orders for %s aborted as there are units nearby."),
3982 unit_link(punit));
3983 return TRUE;
3986 if (moves_made == punit->orders.length) {
3987 /* For repeating orders, don't repeat more than once per turn. */
3988 log_debug(" stopping because we ran a round");
3989 punit->done_moving = TRUE;
3990 send_unit_info(NULL, punit);
3991 return TRUE;
3993 moves_made++;
3995 order = punit->orders.list[punit->orders.index];
3997 switch (order.order) {
3998 case ORDER_MOVE:
3999 case ORDER_ACTION_MOVE:
4000 case ORDER_FULL_MP:
4001 case ORDER_BUILD_CITY:
4002 if (0 == punit->moves_left) {
4003 log_debug(" stopping because of no more move points");
4004 return TRUE;
4006 break;
4007 case ORDER_BUILD_WONDER:
4008 case ORDER_TRADE_ROUTE:
4009 if (action_mp_full_makes_legal(punit, order_to_action(punit, order.order))) {
4010 log_debug(" stopping. Not enough move points this turn");
4011 return TRUE;
4013 break;
4014 case ORDER_ACTIVITY:
4015 case ORDER_DISBAND:
4016 case ORDER_HOMECITY:
4017 case ORDER_LAST:
4018 /* Those actions don't require moves left. */
4019 break;
4022 last_order = (!punit->orders.repeat
4023 && punit->orders.index + 1 == punit->orders.length);
4025 if (last_order) {
4026 /* Clear the orders before we engage in the move. That way any
4027 * has_orders checks will yield FALSE and this will be treated as
4028 * a normal move. This is important: for instance a caravan goto
4029 * will popup the caravan dialog on the last move only. */
4030 free_unit_orders(punit);
4033 /* Advance the orders one step forward. This is needed because any
4034 * updates sent to the client as a result of the action should include
4035 * the new index value. Note that we have to send_unit_info somewhere
4036 * after this point so that the client is properly updated. */
4037 punit->orders.index++;
4039 switch (order.order) {
4040 case ORDER_FULL_MP:
4041 if (punit->moves_left < unit_move_rate(punit)) {
4042 /* If the unit doesn't have full MP then it just waits until the
4043 * next turn. We assume that the next turn it will have full MP
4044 * (there's no check for that). */
4045 punit->done_moving = TRUE;
4046 log_debug(" waiting this turn");
4047 send_unit_info(NULL, punit);
4049 break;
4050 case ORDER_BUILD_CITY:
4051 unit_build_city(pplayer, punit,
4052 city_name_suggestion(pplayer, unit_tile(punit)));
4053 log_debug(" building city");
4054 if (player_unit_by_number(pplayer, unitid)) {
4055 /* Build failed. */
4056 cancel_orders(punit, " orders canceled; failed to build city");
4057 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4058 _("Orders for %s aborted because building "
4059 "of city failed."),
4060 unit_link(punit));
4061 return TRUE;
4062 } else {
4063 /* Build succeeded => unit "died" */
4064 return FALSE;
4066 case ORDER_ACTIVITY:
4067 activity = order.activity;
4069 struct extra_type *pextra = (order.target == EXTRA_NONE ?
4070 NULL :
4071 extra_by_number(order.target));
4073 if (pextra == NULL && activity_requires_target(order.activity)) {
4074 /* Try to find a target extra before giving up this order or, if
4075 * serious enough, all orders. */
4077 enum unit_activity new_activity = order.activity;
4079 unit_assign_specific_activity_target(punit,
4080 &new_activity, &pextra);
4082 if (new_activity != order.activity) {
4083 /* At the time this code was written the only possible activity
4084 * change from unit_assign_specific_activity_target() was from
4085 * ACTIVITY_PILLAGE to ACTIVITY_IDLE. That would only happen
4086 * when a target extra couldn't be found. -- Sveinung */
4087 fc_assert_msg((order.activity == ACTIVITY_PILLAGE
4088 && new_activity == ACTIVITY_IDLE),
4089 "Skipping an order when canceling all orders may"
4090 " have been the correct thing to do.");
4092 /* Already removed, let's continue. */
4093 break;
4096 /* Should have given up or, if supported, changed the order's
4097 * activity to the activity suggested by
4098 * unit_activity_handling_targeted() before this line was
4099 * reached.
4100 * Remember that unit_activity_handling_targeted() has the power
4101 * to change the order's target extra directly. */
4102 fc_assert_msg(new_activity == order.activity,
4103 "Activity not updated. Target may have changed.");
4105 /* Should have found a target or given up before reaching this
4106 * line. */
4107 fc_assert_msg((pextra != NULL
4108 || !activity_requires_target(order.activity)),
4109 "Activity requires a target. No target found.");
4112 if (can_unit_do_activity_targeted(punit, activity, pextra)) {
4113 punit->done_moving = TRUE;
4114 set_unit_activity_targeted(punit, activity, pextra);
4115 send_unit_info(NULL, punit);
4116 break;
4117 } else {
4118 if ((activity == ACTIVITY_BASE
4119 || activity == ACTIVITY_GEN_ROAD
4120 || activity == ACTIVITY_IRRIGATE
4121 || activity == ACTIVITY_MINE)
4122 && tile_has_extra(unit_tile(punit), pextra)) {
4123 break; /* Already built, let's continue. */
4124 } else if ((activity == ACTIVITY_POLLUTION
4125 || activity == ACTIVITY_FALLOUT
4126 || activity == ACTIVITY_PILLAGE)
4127 && !tile_has_extra(unit_tile(punit), pextra)) {
4128 break; /* Already removed, let's continue. */
4133 cancel_orders(punit, " orders canceled because of failed activity");
4134 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4135 _("Orders for %s aborted since they "
4136 "give an invalid activity."),
4137 unit_link(punit));
4138 return TRUE;
4139 case ORDER_MOVE:
4140 case ORDER_ACTION_MOVE:
4141 /* Move unit */
4142 if (!(dst_tile = mapstep(unit_tile(punit), order.dir))) {
4143 cancel_orders(punit, " move order sent us to invalid location");
4144 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4145 _("Orders for %s aborted since they "
4146 "give an invalid location."),
4147 unit_link(punit));
4148 return TRUE;
4151 if (order.order != ORDER_ACTION_MOVE
4152 && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
4153 /* Plain move required: no attack, trade route etc. */
4154 cancel_orders(punit, " orders canceled because of enemy");
4155 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4156 _("Orders for %s aborted as there "
4157 "are units in the way."),
4158 unit_link(punit));
4159 return TRUE;
4162 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4163 res = unit_move_handling(punit, dst_tile, FALSE,
4164 order.order != ORDER_ACTION_MOVE, NULL);
4165 if (!player_unit_by_number(pplayer, unitid)) {
4166 log_debug(" unit died while moving.");
4167 /* A player notification should already have been sent. */
4168 return FALSE;
4171 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4172 /* Movement succeeded but unit didn't move. */
4173 log_debug(" orders resulted in combat.");
4174 send_unit_info(NULL, punit);
4175 return TRUE;
4178 if (!res) {
4179 fc_assert(0 <= punit->moves_left);
4181 /* Movement failed (ZOC, etc.) */
4182 cancel_orders(punit, " attempt to move failed.");
4184 if (!player_is_watching(punit, fresh)
4185 /* The final move "failed" because the unit needs to ask the
4186 * player what action it should take.
4188 * The action decision request notifies the player. Its
4189 * location at the unit's last order makes it clear to the
4190 * player who the decision is for. ("The Spy I sent to Berlin
4191 * has arrived.")
4193 * A notification message is therefore redundant. */
4194 && !(last_order
4195 && punit->action_decision_want == ACT_DEC_ACTIVE
4196 && punit->action_decision_tile == dst_tile)) {
4197 /* The player may have missed this. No one else will announce it
4198 * in a satisfying manner. Inform the player. */
4199 notify_player(pplayer, unit_tile(punit),
4200 E_UNIT_ORDERS, ftc_server,
4201 _("Orders for %s aborted because of failed move."),
4202 unit_link(punit));
4205 return TRUE;
4207 break;
4208 case ORDER_DISBAND:
4209 log_debug(" orders: disbanding");
4210 handle_unit_disband(pplayer, unitid);
4211 return FALSE;
4212 case ORDER_HOMECITY:
4213 log_debug(" orders: changing homecity");
4214 if (tile_city(unit_tile(punit))) {
4215 handle_unit_change_homecity(pplayer, unitid,
4216 tile_city(unit_tile(punit))->id);
4217 } else {
4218 cancel_orders(punit, " no homecity");
4219 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4220 _("Attempt to change homecity for %s failed."),
4221 unit_link(punit));
4222 return TRUE;
4224 break;
4225 case ORDER_TRADE_ROUTE:
4226 log_debug(" orders: establishing trade route.");
4227 dst_tile = unit_tile(punit);
4229 fc_assert_ret_val_msg(dst_tile, FALSE, "No tile for ordered unit");
4231 if (tile_city(dst_tile) == NULL) {
4232 cancel_orders(punit, " trade route order with no city");
4233 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4234 _("Orders for %s aborted since they "
4235 "give a location without a city."),
4236 unit_link(punit));
4237 return TRUE;
4240 handle_unit_do_action(pplayer,
4241 unitid, tile_city(dst_tile)->id,
4242 0, ACTION_TRADE_ROUTE);
4243 if (player_unit_by_number(pplayer, unitid)) {
4244 cancel_orders(punit, " no trade route city");
4245 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4246 _("Attempt to establish trade route for %s failed."),
4247 unit_link(punit));
4248 return TRUE;
4249 } else {
4250 return FALSE;
4252 case ORDER_BUILD_WONDER:
4253 log_debug(" orders: building wonder");
4254 dst_tile = unit_tile(punit);
4256 fc_assert_ret_val_msg(dst_tile, FALSE, "No tile for ordered unit");
4258 if (tile_city(dst_tile) == NULL) {
4259 cancel_orders(punit, " build wonder order with no city");
4260 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4261 _("Orders for %s aborted since they "
4262 "give a location without a city."),
4263 unit_link(punit));
4264 return TRUE;
4267 handle_unit_do_action(pplayer,
4268 unitid,
4269 tile_city(dst_tile)->id,
4270 0, ACTION_HELP_WONDER);
4271 if (player_unit_by_number(pplayer, unitid)) {
4272 cancel_orders(punit, " no wonder city");
4273 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4274 _("Attempt to build wonder for %s failed."),
4275 unit_link(punit));
4276 return TRUE;
4277 } else {
4278 return FALSE;
4280 case ORDER_LAST:
4281 cancel_orders(punit, " client sent invalid order!");
4282 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4283 _("Your %s has invalid orders."),
4284 unit_link(punit));
4285 return TRUE;
4288 if (last_order) {
4289 fc_assert(punit->has_orders == FALSE);
4290 log_debug(" stopping because orders are complete");
4291 return TRUE;
4294 if (punit->orders.index == punit->orders.length) {
4295 fc_assert(punit->orders.repeat);
4296 /* Start over. */
4297 log_debug(" repeating orders.");
4298 punit->orders.index = 0;
4300 } /* end while */
4303 /****************************************************************************
4304 Return the vision the unit will have at the given tile. The base vision
4305 range may be modified by effects.
4307 Note that vision MUST be independent of transported_by for this to work
4308 properly.
4309 ****************************************************************************/
4310 int get_unit_vision_at(struct unit *punit, struct tile *ptile,
4311 enum vision_layer vlayer)
4313 const int base = (unit_type_get(punit)->vision_radius_sq
4314 + get_unittype_bonus(unit_owner(punit), ptile,
4315 unit_type_get(punit),
4316 EFT_UNIT_VISION_RADIUS_SQ));
4317 switch (vlayer) {
4318 case V_MAIN:
4319 return base;
4320 case V_INVIS:
4321 return MIN(base, 2);
4322 case V_COUNT:
4323 break;
4326 log_error("Unsupported vision layer variant: %d.", vlayer);
4327 return 0;
4330 /****************************************************************************
4331 Refresh the unit's vision.
4333 This function has very small overhead and can be called any time effects
4334 may have changed the vision range of the city.
4335 ****************************************************************************/
4336 void unit_refresh_vision(struct unit *punit)
4338 struct vision *uvision = punit->server.vision;
4339 const v_radius_t radius_sq =
4340 V_RADIUS(get_unit_vision_at(punit, unit_tile(punit), V_MAIN),
4341 get_unit_vision_at(punit, unit_tile(punit), V_INVIS));
4343 vision_change_sight(uvision, radius_sq);
4344 ASSERT_VISION(uvision);
4347 /****************************************************************************
4348 Refresh the vision of all units in the list - see unit_refresh_vision.
4349 ****************************************************************************/
4350 void unit_list_refresh_vision(struct unit_list *punitlist)
4352 unit_list_iterate(punitlist, punit) {
4353 unit_refresh_vision(punit);
4354 } unit_list_iterate_end;
4357 /****************************************************************************
4358 Used to implement the game rule controlled by the unitwaittime setting.
4359 Notifies the unit owner if the unit is unable to act.
4360 ****************************************************************************/
4361 bool unit_can_do_action_now(const struct unit *punit)
4363 time_t dt;
4365 if (!punit) {
4366 return FALSE;
4369 if (game.server.unitwaittime <= 0) {
4370 return TRUE;
4373 if (punit->server.action_turn != game.info.turn - 1) {
4374 return TRUE;
4377 dt = time(NULL) - punit->server.action_timestamp;
4378 if (dt < game.server.unitwaittime) {
4379 char buf[64];
4380 format_time_duration(game.server.unitwaittime - dt, buf, sizeof(buf));
4381 notify_player(unit_owner(punit), unit_tile(punit), E_BAD_COMMAND,
4382 ftc_server, _("Your unit may not act for another %s "
4383 "this turn. See /help unitwaittime."), buf);
4384 return FALSE;
4387 return TRUE;
4390 /****************************************************************************
4391 Mark a unit as having done something at the current time. This is used
4392 in conjunction with unit_can_do_action_now() and the unitwaittime setting.
4393 ****************************************************************************/
4394 void unit_did_action(struct unit *punit)
4396 if (!punit) {
4397 return;
4400 punit->server.action_timestamp = time(NULL);
4401 punit->server.action_turn = game.info.turn;
4404 /**************************************************************************
4405 Units (usually barbarian units) may disband spontaneously if they are
4406 far from any enemy units or cities. It is to remove barbarians that do
4407 not engage into any activity for a long time.
4408 **************************************************************************/
4409 bool unit_can_be_retired(struct unit *punit)
4411 /* check if there is enemy nearby */
4412 square_iterate(unit_tile(punit), 3, ptile) {
4413 if (is_enemy_city_tile(ptile, unit_owner(punit))
4414 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4415 return FALSE;
4418 square_iterate_end;
4420 return TRUE;