Replaced deprecated gtk_menu_popup() calls with modern constructs in gtk3.22-client
[freeciv.git] / server / unittools.c
blob0ae7fcad251d00a706fc7dd7a4b6981761653159
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 it
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. */
2959 if (unit_transport_depth(*p1) != unit_transport_depth(*q1)) {
2960 /* The units have a different number of recursive transporters. */
2961 return unit_transport_depth(*q1) - unit_transport_depth(*p1);
2964 /* Put the units with the highest probability of success first. The up
2965 * side of this is that units with bonuses against the victim attacks
2966 * before other units. The downside is that strong units can be lead
2967 * away by sacrificial units. */
2968 if (p1uwc < q1uwc) {
2969 return +1; /* q is better */
2970 } else if (p1uwc == q1uwc) {
2971 return 0;
2972 } else {
2973 return -1; /* p is better */
2977 /*****************************************************************
2978 Can this unit be used in autoattack
2979 *****************************************************************/
2980 static bool is_suitable_autoattack_unit(struct unit *punit)
2982 if (unit_has_type_flag(punit, UTYF_NUCLEAR)) {
2983 /* Not a good idea to nuke our own area */
2984 return FALSE;
2987 return TRUE;
2990 /*****************************************************************
2991 Check if unit survives enemy autoattacks. We assume that any
2992 unit that is adjacent to us can see us.
2993 *****************************************************************/
2994 static bool unit_survive_autoattack(struct unit *punit)
2996 struct unit_list *autoattack;
2997 int moves = punit->moves_left;
2998 int sanity1 = punit->id;
3000 if (!game.server.autoattack) {
3001 return TRUE;
3004 autoattack = unit_list_new();
3006 /* Kludge to prevent attack power from dropping to zero during calc */
3007 punit->moves_left = MAX(punit->moves_left, 1);
3009 adjc_iterate(unit_tile(punit), ptile) {
3010 /* First add all eligible units to a unit list */
3011 unit_list_iterate(ptile->units, penemy) {
3012 struct player *enemyplayer = unit_owner(penemy);
3013 enum diplstate_type ds =
3014 player_diplstate_get(unit_owner(punit), enemyplayer)->type;
3016 if (penemy->moves_left > 0
3017 && ds == DS_WAR
3018 && is_suitable_autoattack_unit(penemy)
3019 && (unit_attack_unit_at_tile_result(penemy, punit, unit_tile(punit))
3020 == ATT_OK)) {
3021 unit_list_prepend(autoattack, penemy);
3023 } unit_list_iterate_end;
3024 } adjc_iterate_end;
3026 /* Sort the potential attackers from highest to lowest success
3027 * probability. */
3028 autoattack_target = unit_tile(punit); /* global variable */
3029 if (unit_list_size(autoattack) >= 2) {
3030 unit_list_sort(autoattack, &compare_units);
3033 unit_list_iterate_safe(autoattack, penemy) {
3034 int sanity2 = penemy->id;
3035 struct tile *ptile = unit_tile(penemy);
3036 struct unit *enemy_defender = get_defender(punit, ptile);
3037 struct unit *punit_defender = get_defender(penemy, unit_tile(punit));
3038 double punitwin, penemywin;
3039 double threshold = 0.25;
3041 fc_assert_action(NULL != punit_defender, continue);
3043 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3044 /* Don't leave city defenseless */
3045 threshold = 0.90;
3048 if (NULL != enemy_defender) {
3049 punitwin = unit_win_chance(punit, enemy_defender);
3050 } else {
3051 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3052 punitwin = 1.0;
3054 penemywin = unit_win_chance(penemy, punit_defender);
3056 if ((penemywin > 1.0 - punitwin
3057 || utype_acts_hostile(unit_type_get(punit))
3058 || get_transporter_capacity(punit) > 0)
3059 && penemywin > threshold) {
3060 #ifdef REALLY_DEBUG_THIS
3061 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3062 unit_rule_name(penemy), unit_rule_name(punit),
3063 TILE_XY(unit_tile(punit)), penemywin,
3064 1.0 - punitwin, threshold);
3065 #endif
3067 unit_activity_handling(penemy, ACTIVITY_IDLE);
3068 /* Attack */
3069 (void) unit_move_handling(penemy, unit_tile(punit),
3070 FALSE, TRUE, NULL);
3071 } else {
3072 #ifdef REALLY_DEBUG_THIS
3073 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3074 unit_rule_name(penemy), unit_rule_name(punit),
3075 TILE_XY(unit_tile(punit)), penemywin,
3076 1.0 - punitwin, threshold);
3077 #endif
3078 continue;
3081 if (game_unit_by_number(sanity2)) {
3082 send_unit_info(NULL, penemy);
3084 if (game_unit_by_number(sanity1)) {
3085 send_unit_info(NULL, punit);
3086 } else {
3087 unit_list_destroy(autoattack);
3088 return FALSE; /* moving unit dead */
3090 } unit_list_iterate_safe_end;
3092 unit_list_destroy(autoattack);
3093 if (game_unit_by_number(sanity1)) {
3094 /* We could have lost movement in combat */
3095 punit->moves_left = MIN(punit->moves_left, moves);
3096 send_unit_info(NULL, punit);
3097 return TRUE;
3098 } else {
3099 return FALSE;
3103 /****************************************************************************
3104 Cancel orders for the unit.
3105 ****************************************************************************/
3106 static void cancel_orders(struct unit *punit, char *dbg_msg)
3108 free_unit_orders(punit);
3109 send_unit_info(NULL, punit);
3110 log_debug("%s", dbg_msg);
3113 /*****************************************************************
3114 Will wake up any neighboring enemy sentry units or patrolling
3115 units.
3116 *****************************************************************/
3117 static void wakeup_neighbor_sentries(struct unit *punit)
3119 bool alone_in_city;
3121 if (NULL != tile_city(unit_tile(punit))) {
3122 int count = 0;
3124 unit_list_iterate(unit_tile(punit)->units, aunit) {
3125 /* Consider only units not transported. */
3126 if (!unit_transported(aunit)) {
3127 count++;
3129 } unit_list_iterate_end;
3131 alone_in_city = (1 == count);
3132 } else {
3133 alone_in_city = FALSE;
3136 /* There may be sentried units with a sightrange > 3, but we don't
3137 wake them up if the punit is farther away than 3. */
3138 square_iterate(unit_tile(punit), 3, ptile) {
3139 unit_list_iterate(ptile->units, penemy) {
3140 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3141 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3143 if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
3144 && penemy->activity == ACTIVITY_SENTRY
3145 && radius_sq >= distance_sq
3146 /* If the unit moved on a city, and the unit is alone, consider
3147 * it is visible. */
3148 && (alone_in_city
3149 || can_player_see_unit(unit_owner(penemy), punit))
3150 /* on board transport; don't awaken */
3151 && can_unit_exist_at_tile(penemy, unit_tile(penemy))) {
3152 set_unit_activity(penemy, ACTIVITY_IDLE);
3153 send_unit_info(NULL, penemy);
3155 } unit_list_iterate_end;
3156 } square_iterate_end;
3158 /* Wakeup patrolling units we bump into.
3159 We do not wakeup units further away than 3 squares... */
3160 square_iterate(unit_tile(punit), 3, ptile) {
3161 unit_list_iterate(ptile->units, ppatrol) {
3162 if (punit != ppatrol
3163 && unit_has_orders(ppatrol)
3164 && ppatrol->orders.vigilant) {
3165 if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
3166 cancel_orders(ppatrol, " stopping because of nearby enemy");
3167 notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
3168 E_UNIT_ORDERS, ftc_server,
3169 _("Orders for %s aborted after enemy movement was "
3170 "spotted."),
3171 unit_link(ppatrol));
3174 } unit_list_iterate_end;
3175 } square_iterate_end;
3178 /**************************************************************************
3179 Does: 1) updates the unit's homecity and the city it enters/leaves (the
3180 city's happiness varies). This also takes into account when the
3181 unit enters/leaves a fortress.
3182 2) updates adjacent cities' unavailable tiles.
3184 FIXME: Sometimes it is not necessary to send cities because the goverment
3185 doesn't care whether a unit is away or not.
3186 **************************************************************************/
3187 static bool unit_move_consequences(struct unit *punit,
3188 struct tile *src_tile,
3189 struct tile *dst_tile,
3190 bool passenger)
3192 struct city *fromcity = tile_city(src_tile);
3193 struct city *tocity = tile_city(dst_tile);
3194 struct city *homecity_start_pos = NULL;
3195 struct city *homecity_end_pos = NULL;
3196 int homecity_id_start_pos = punit->homecity;
3197 int homecity_id_end_pos = punit->homecity;
3198 struct player *pplayer_start_pos = unit_owner(punit);
3199 struct player *pplayer_end_pos = pplayer_start_pos;
3200 struct unit_type *type_start_pos = unit_type_get(punit);
3201 struct unit_type *type_end_pos = type_start_pos;
3202 bool refresh_homecity_start_pos = FALSE;
3203 bool refresh_homecity_end_pos = FALSE;
3204 int saved_id = punit->id;
3205 bool alive = TRUE;
3207 if (tocity) {
3208 unit_enter_city(punit, tocity, passenger);
3210 alive = unit_is_alive(saved_id);
3211 if (alive) {
3212 /* In case script has changed something about unit */
3213 pplayer_end_pos = unit_owner(punit);
3214 type_end_pos = unit_type_get(punit);
3215 homecity_id_end_pos = punit->homecity;
3219 if (homecity_id_start_pos != 0) {
3220 homecity_start_pos = game_city_by_number(homecity_id_start_pos);
3222 if (homecity_id_start_pos != homecity_id_end_pos) {
3223 homecity_end_pos = game_city_by_number(homecity_id_end_pos);
3224 } else {
3225 homecity_end_pos = homecity_start_pos;
3228 /* We only do refreshes for non-AI players to now make sure the AI turns
3229 doesn't take too long. Perhaps we should make a special refresh_city
3230 functions that only refreshed happines. */
3232 /* might have changed owners or may be destroyed */
3233 tocity = tile_city(dst_tile);
3235 if (tocity) { /* entering a city */
3236 if (tocity->owner == pplayer_end_pos) {
3237 if (tocity != homecity_end_pos && !pplayer_end_pos->ai_controlled) {
3238 city_refresh(tocity);
3239 send_city_info(pplayer_end_pos, tocity);
3242 if (homecity_start_pos) {
3243 refresh_homecity_start_pos = TRUE;
3247 if (fromcity) { /* leaving a city */
3248 if (homecity_start_pos) {
3249 refresh_homecity_start_pos = TRUE;
3251 if (fromcity != homecity_start_pos
3252 && fromcity->owner == pplayer_start_pos
3253 && !pplayer_start_pos->ai_controlled) {
3254 city_refresh(fromcity);
3255 send_city_info(pplayer_start_pos, fromcity);
3259 /* entering/leaving a fortress or friendly territory */
3260 if (homecity_start_pos || homecity_end_pos) {
3261 if ((game.info.happyborders != HB_DISABLED && tile_owner(src_tile) != tile_owner(dst_tile))
3262 || (tile_has_base_flag_for_unit(dst_tile,
3263 type_end_pos,
3264 BF_NOT_AGGRESSIVE)
3265 && is_friendly_city_near(pplayer_end_pos, dst_tile))
3266 || (tile_has_base_flag_for_unit(src_tile,
3267 type_start_pos,
3268 BF_NOT_AGGRESSIVE)
3269 && is_friendly_city_near(pplayer_start_pos, src_tile))) {
3270 refresh_homecity_start_pos = TRUE;
3271 refresh_homecity_end_pos = TRUE;
3275 if (refresh_homecity_start_pos && !pplayer_start_pos->ai_controlled) {
3276 city_refresh(homecity_start_pos);
3277 send_city_info(pplayer_start_pos, homecity_start_pos);
3279 if (refresh_homecity_end_pos
3280 && (!refresh_homecity_start_pos
3281 || homecity_start_pos != homecity_end_pos)
3282 && !pplayer_end_pos->ai_controlled) {
3283 city_refresh(homecity_end_pos);
3284 send_city_info(pplayer_end_pos, homecity_end_pos);
3287 city_map_update_tile_now(dst_tile);
3288 sync_cities();
3290 return alive;
3293 /**************************************************************************
3294 Check if the units activity is legal for a move , and reset it if it isn't.
3295 **************************************************************************/
3296 static void check_unit_activity(struct unit *punit)
3298 switch (punit->activity) {
3299 case ACTIVITY_IDLE:
3300 case ACTIVITY_SENTRY:
3301 case ACTIVITY_EXPLORE:
3302 case ACTIVITY_GOTO:
3303 break;
3304 case ACTIVITY_POLLUTION:
3305 case ACTIVITY_MINE:
3306 case ACTIVITY_IRRIGATE:
3307 case ACTIVITY_FORTIFIED:
3308 case ACTIVITY_FORTRESS:
3309 case ACTIVITY_PILLAGE:
3310 case ACTIVITY_TRANSFORM:
3311 case ACTIVITY_UNKNOWN:
3312 case ACTIVITY_AIRBASE:
3313 case ACTIVITY_FORTIFYING:
3314 case ACTIVITY_FALLOUT:
3315 case ACTIVITY_PATROL_UNUSED:
3316 case ACTIVITY_BASE:
3317 case ACTIVITY_GEN_ROAD:
3318 case ACTIVITY_CONVERT:
3319 case ACTIVITY_OLD_ROAD:
3320 case ACTIVITY_OLD_RAILROAD:
3321 case ACTIVITY_LAST:
3322 set_unit_activity(punit, ACTIVITY_IDLE);
3323 break;
3327 /****************************************************************************
3328 Create a new unit move data, or use previous one if available.
3329 ****************************************************************************/
3330 static struct unit_move_data *unit_move_data(struct unit *punit,
3331 struct tile *psrctile,
3332 struct tile *pdesttile)
3334 struct unit_move_data *pdata;
3335 struct player *powner = unit_owner(punit);
3336 const v_radius_t radius_sq =
3337 V_RADIUS(get_unit_vision_at(punit, pdesttile, V_MAIN),
3338 get_unit_vision_at(punit, pdesttile, V_INVIS));
3339 struct vision *new_vision;
3340 bool success;
3342 if (punit->server.moving) {
3343 /* Recursive moving (probably due to a script). */
3344 pdata = punit->server.moving;
3345 pdata->ref_count++;
3346 fc_assert_msg(pdata->punit == punit,
3347 "Unit number %d (%p) was going to die, but "
3348 "server attempts to move it.",
3349 punit->id, punit);
3350 fc_assert_msg(pdata->old_vision == NULL,
3351 "Unit number %d (%p) has done an incomplete move.",
3352 punit->id, punit);
3353 } else {
3354 pdata = fc_malloc(sizeof(*pdata));
3355 pdata->ref_count = 1;
3356 pdata->punit = punit;
3357 punit->server.moving = pdata;
3358 BV_CLR_ALL(pdata->can_see_unit);
3360 pdata->powner = powner;
3361 BV_CLR_ALL(pdata->can_see_move);
3362 pdata->old_vision = punit->server.vision;
3364 /* Remove unit from the source tile. */
3365 fc_assert(unit_tile(punit) == psrctile);
3366 success = unit_list_remove(psrctile->units, punit);
3367 fc_assert(success == TRUE);
3369 /* Set new tile. */
3370 unit_tile_set(punit, pdesttile);
3371 unit_list_prepend(pdesttile->units, punit);
3373 if (unit_transported(punit)) {
3374 /* Silently free orders since they won't be applicable anymore. */
3375 free_unit_orders(punit);
3378 /* Check unit activity. */
3379 check_unit_activity(punit);
3380 unit_did_action(punit);
3381 unit_forget_last_activity(punit);
3383 /* We first unfog the destination, then send the move,
3384 * and then fog the old territory. This means that the player
3385 * gets a chance to see the newly explored territory while the
3386 * client moves the unit, and both areas are visible during the
3387 * move */
3389 /* Enhance vision if unit steps into a fortress */
3390 new_vision = vision_new(powner, pdesttile);
3391 punit->server.vision = new_vision;
3392 vision_change_sight(new_vision, radius_sq);
3393 ASSERT_VISION(new_vision);
3395 return pdata;
3398 /****************************************************************************
3399 Decrease the reference counter and destroy if needed.
3400 ****************************************************************************/
3401 static void unit_move_data_unref(struct unit_move_data *pdata)
3403 fc_assert_ret(pdata != NULL);
3404 fc_assert_ret(pdata->ref_count > 0);
3405 fc_assert_msg(pdata->old_vision == NULL,
3406 "Unit number %d (%p) has done an incomplete move.",
3407 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3409 pdata->ref_count--;
3410 if (pdata->ref_count == 0) {
3411 if (pdata->punit != NULL) {
3412 fc_assert(pdata->punit->server.moving == pdata);
3413 pdata->punit->server.moving = NULL;
3415 free(pdata);
3419 /*****************************************************************************
3420 Moves a unit. No checks whatsoever! This is meant as a practical
3421 function for other functions, like do_airline, which do the checking
3422 themselves.
3424 If you move a unit you should always use this function, as it also sets
3425 the transport status of the unit correctly. Note that the source tile (the
3426 current tile of the unit) and pdesttile need not be adjacent.
3428 Returns TRUE iff unit still alive.
3429 *****************************************************************************/
3430 bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3431 struct unit *embark_to)
3433 struct player *pplayer;
3434 struct tile *psrctile;
3435 struct city *pcity;
3436 struct unit *ptransporter;
3437 struct packet_unit_info src_info, dest_info;
3438 struct packet_unit_short_info src_sinfo, dest_sinfo;
3439 struct unit_move_data_list *plist =
3440 unit_move_data_list_new_full(unit_move_data_unref);
3441 struct unit_move_data *pdata;
3442 int saved_id;
3443 bool unit_lives;
3444 bool adj;
3445 enum direction8 facing;
3446 struct player *bowner;
3448 /* Some checks. */
3449 fc_assert_ret_val(punit != NULL, FALSE);
3450 fc_assert_ret_val(pdesttile != NULL, FALSE);
3452 pplayer = unit_owner(punit);
3453 saved_id = punit->id;
3454 psrctile = unit_tile(punit);
3455 adj = base_get_direction_for_step(psrctile, pdesttile, &facing);
3457 conn_list_do_buffer(game.est_connections);
3459 /* Unload the unit if on a transport. */
3460 ptransporter = unit_transport_get(punit);
3461 if (ptransporter != NULL) {
3462 /* Unload unit _before_ setting the new tile! */
3463 unit_transport_unload(punit);
3464 /* Send updated information to anyone watching that transporter
3465 * was unloading cargo. */
3466 send_unit_info(NULL, ptransporter);
3469 /* Wakup units next to us before we move. */
3470 wakeup_neighbor_sentries(punit);
3472 /* Make info packets at 'psrctile'. */
3473 if (adj) {
3474 /* If tiles are adjacent, we will show the move to users able
3475 * to see it. */
3476 package_unit(punit, &src_info);
3477 package_short_unit(punit, &src_sinfo, UNIT_INFO_IDENTITY, 0);
3480 /* Make new data for 'punit'. */
3481 pdata = unit_move_data(punit, psrctile, pdesttile);
3482 unit_move_data_list_prepend(plist, pdata);
3484 /* Set unit orientation */
3485 if (adj) {
3486 /* Only change orientation when moving to adjacent tile */
3487 punit->facing = facing;
3490 /* Move magic. */
3491 punit->moved = TRUE;
3492 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3493 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3494 /* The next order may not require any remaining move fragments. */
3495 punit->done_moving = TRUE;
3498 /* No longer relevant. */
3499 punit->action_decision_tile = NULL;
3500 punit->action_decision_want = ACT_DEC_NOTHING;
3502 if (!adj
3503 && action_tgt_city(punit, pdesttile)) {
3504 /* The unit can perform an action to the city at the destination tile.
3505 * A long distance move (like an airlift) doesn't ask what action to
3506 * perform before moving. Ask now. */
3508 punit->action_decision_want = ACT_DEC_PASSIVE;
3509 punit->action_decision_tile = pdesttile;
3512 /* Claim ownership of fortress? */
3513 bowner = extra_owner(pdesttile);
3514 if ((bowner == NULL || pplayers_at_war(bowner, pplayer))
3515 && tile_has_claimable_base(pdesttile, unit_type_get(punit))) {
3516 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3517 * Even if original unit cannot claim other kind of bases, the
3518 * first claimed base will have influence over other bases,
3519 * or something like that. */
3520 tile_claim_bases(pdesttile, pplayer);
3523 /* Move all contained units. */
3524 unit_cargo_iterate(punit, pcargo) {
3525 pdata = unit_move_data(pcargo, psrctile, pdesttile);
3526 unit_move_data_list_append(plist, pdata);
3527 } unit_cargo_iterate_end;
3529 /* Get data for 'punit'. */
3530 pdata = unit_move_data_list_front(plist);
3532 /* Determine the players able to see the move(s), now that the player
3533 * vision has been increased. */
3534 if (adj) {
3535 /* Main unit for adjacent move: the move is visible for every player
3536 * able to see on the matching unit layer. */
3537 enum vision_layer vlayer = is_hiding_unit(punit) ? V_INVIS : V_MAIN;
3539 players_iterate(oplayer) {
3540 if (map_is_known_and_seen(psrctile, oplayer, vlayer)
3541 || map_is_known_and_seen(pdesttile, oplayer, vlayer)) {
3542 BV_SET(pdata->can_see_unit, player_index(oplayer));
3543 BV_SET(pdata->can_see_move, player_index(oplayer));
3545 } players_iterate_end;
3547 unit_move_data_list_iterate(plist, pmove_data) {
3548 if (adj && pmove_data == pdata) {
3549 /* If positions are adjacent, we have already handled 'punit'. See
3550 * above. */
3551 continue;
3554 players_iterate(oplayer) {
3555 if ((adj
3556 && can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
3557 pmove_data != pdata))
3558 || can_player_see_unit_at(oplayer, pmove_data->punit, pdesttile,
3559 pmove_data != pdata)) {
3560 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3561 BV_SET(pmove_data->can_see_move, player_index(oplayer));
3563 if (can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
3564 pmove_data != pdata)) {
3565 /* The unit was seen with its source tile even if it was
3566 * teleported. */
3567 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3569 } players_iterate_end;
3570 } unit_move_data_list_iterate_end;
3572 /* Check timeout settings. */
3573 if (current_turn_timeout() != 0 && game.server.timeoutaddenemymove > 0) {
3574 bool new_information_for_enemy = FALSE;
3576 phase_players_iterate(penemy) {
3577 /* Increase the timeout if an enemy unit moves and the
3578 * timeoutaddenemymove setting is in use. */
3579 if (penemy->is_connected
3580 && pplayer != penemy
3581 && pplayers_at_war(pplayer, penemy)
3582 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
3583 new_information_for_enemy = TRUE;
3584 break;
3586 } phase_players_iterate_end;
3588 if (new_information_for_enemy) {
3589 increase_timeout_because_unit_moved();
3593 /* Notifications of the move to the clients. */
3594 if (adj) {
3595 /* Special case: 'punit' is moving to adjacent position. Then we show
3596 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
3598 /* Make info packets at 'pdesttile'. */
3599 package_unit(punit, &dest_info);
3600 package_short_unit(punit, &dest_sinfo, UNIT_INFO_IDENTITY, 0);
3602 conn_list_iterate(game.est_connections, pconn) {
3603 struct player *aplayer = conn_get_player(pconn);
3605 if (aplayer == NULL) {
3606 if (pconn->observer) {
3607 /* Global observers see all... */
3608 send_packet_unit_info(pconn, &src_info);
3609 send_packet_unit_info(pconn, &dest_info);
3611 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
3612 if (aplayer == pplayer) {
3613 send_packet_unit_info(pconn, &src_info);
3614 send_packet_unit_info(pconn, &dest_info);
3615 } else {
3616 send_packet_unit_short_info(pconn, &src_sinfo, FALSE);
3617 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
3620 } conn_list_iterate_end;
3623 /* Other moves. */
3624 unit_move_data_list_iterate(plist, pmove_data) {
3625 if (adj && pmove_data == pdata) {
3626 /* If positions are adjacent, we have already shown 'punit' move.
3627 * See above. */
3628 continue;
3631 /* Make info packets at 'pdesttile'. */
3632 package_unit(pmove_data->punit, &dest_info);
3633 package_short_unit(pmove_data->punit, &dest_sinfo,
3634 UNIT_INFO_IDENTITY, 0);
3636 conn_list_iterate(game.est_connections, pconn) {
3637 struct player *aplayer = conn_get_player(pconn);
3639 if (aplayer == NULL) {
3640 if (pconn->observer) {
3641 /* Global observers see all... */
3642 send_packet_unit_info(pconn, &dest_info);
3644 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
3645 if (aplayer == pmove_data->powner) {
3646 send_packet_unit_info(pconn, &dest_info);
3647 } else {
3648 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
3651 } conn_list_iterate_end;
3652 } unit_move_data_list_iterate_end;
3654 /* Clear old vision. */
3655 unit_move_data_list_iterate(plist, pmove_data) {
3656 vision_clear_sight(pmove_data->old_vision);
3657 vision_free(pmove_data->old_vision);
3658 pmove_data->old_vision = NULL;
3659 } unit_move_data_list_iterate_end;
3661 /* Move consequences. */
3662 unit_move_data_list_iterate(plist, pmove_data) {
3663 struct unit *aunit = pmove_data->punit;
3665 if (aunit != NULL
3666 && unit_owner(aunit) == pmove_data->powner
3667 && unit_tile(aunit) == pdesttile) {
3668 (void) unit_move_consequences(aunit, psrctile, pdesttile,
3669 pdata != pmove_data);
3671 } unit_move_data_list_iterate_end;
3673 unit_lives = (pdata->punit == punit);
3675 /* Wakeup units and make contact. */
3676 if (unit_lives) {
3677 wakeup_neighbor_sentries(punit);
3679 maybe_make_contact(pdesttile, pplayer);
3681 if (unit_lives) {
3682 /* Special checks for ground units in the ocean. */
3683 if (embark_to || !can_unit_survive_at_tile(punit, pdesttile)) {
3684 if (embark_to != NULL) {
3685 ptransporter = embark_to;
3686 } else {
3687 ptransporter = transporter_for_unit(punit);
3689 if (ptransporter) {
3690 unit_transport_load_tp_status(punit, ptransporter, FALSE);
3692 /* Set activity to sentry if boarding a ship. */
3693 if (!pplayer->ai_controlled
3694 && !unit_has_orders(punit)
3695 && !punit->ai_controlled
3696 && !can_unit_exist_at_tile(punit, pdesttile)) {
3697 set_unit_activity(punit, ACTIVITY_SENTRY);
3700 send_unit_info(NULL, punit);
3705 /* Remove units going out of sight. */
3706 unit_move_data_list_iterate_rev(plist, pmove_data) {
3707 struct unit *aunit = pmove_data->punit;
3709 if (aunit == NULL) {
3710 continue; /* Died! */
3713 players_iterate(aplayer) {
3714 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
3715 && !can_player_see_unit(aplayer, aunit)) {
3716 unit_goes_out_of_sight(aplayer, aunit);
3718 } players_iterate_end;
3719 } unit_move_data_list_iterate_rev_end;
3721 /* Inform the owner's client about actor unit arrival. Can, depending on
3722 * the client settings, cause the client to start the process that makes
3723 * the action selection dialog pop up. */
3724 if ((pcity = tile_city(pdesttile))) {
3725 /* Arrival in a city counts. */
3727 unit_move_data_list_iterate(plist, pmove_data) {
3728 struct unit *ptrans;
3729 bool ok;
3730 struct unit *act_unit;
3731 struct player *act_player;
3733 act_unit = pmove_data->punit;
3734 act_player = unit_owner(act_unit);
3736 if (act_unit == NULL
3737 || !unit_is_alive(act_unit->id)) {
3738 /* The unit died before reaching this point. */
3739 continue;
3742 if (unit_tile(act_unit) != pdesttile) {
3743 /* The unit didn't arrive at the destination tile. */
3744 continue;
3747 if (act_player->ai_controlled) {
3748 /* The AI doesn't need reminders. */
3749 continue;
3752 if (!unit_transported(act_unit)) {
3753 /* Don't show the action selection dialog again. Non transported
3754 * units are handled before they move to the tile. */
3755 continue;
3758 /* Open action dialog only if 'act_unit' and all its transporters
3759 * (recursively) don't have orders. */
3760 if (unit_has_orders(act_unit)) {
3761 /* The unit it self has orders. */
3762 continue;
3765 for (ptrans = unit_transport_get(act_unit);;
3766 ptrans = unit_transport_get(ptrans)) {
3767 if (NULL == ptrans) {
3768 /* No (recursive) transport has orders. */
3769 ok = TRUE;
3770 break;
3771 } else if (unit_has_orders(ptrans)) {
3772 /* A unit transporting the unit has orders */
3773 ok = FALSE;
3774 break;
3778 if (!ok) {
3779 /* A unit transporting act_unit has orders. */
3780 continue;
3783 if (action_tgt_city(act_unit, pdesttile)) {
3784 /* There is a valid target. */
3786 act_unit->action_decision_want = ACT_DEC_PASSIVE;
3787 act_unit->action_decision_tile = pdesttile;
3789 /* Let the client know that this unit wants the player to decide
3790 * what to do. */
3791 send_unit_info(player_reply_dest(act_player), act_unit);
3793 } unit_move_data_list_iterate_end;
3796 unit_move_data_list_destroy(plist);
3798 /* Check cities at source and destination. */
3799 if ((pcity = tile_city(psrctile))) {
3800 refresh_dumb_city(pcity);
3802 if ((pcity = tile_city(pdesttile))) {
3803 refresh_dumb_city(pcity);
3806 if (unit_lives) {
3807 /* Let the scripts run ... */
3808 script_server_signal_emit("unit_moved", 3,
3809 API_TYPE_UNIT, punit,
3810 API_TYPE_TILE, psrctile,
3811 API_TYPE_TILE, pdesttile);
3812 unit_lives = unit_is_alive(saved_id);
3815 if (unit_lives) {
3816 /* Autoattack. */
3817 unit_lives = unit_survive_autoattack(punit);
3820 if (unit_lives) {
3821 /* Is there a hut? */
3822 if (tile_has_cause_extra(pdesttile, EC_HUT)) {
3823 unit_enter_hut(punit);
3824 unit_lives = unit_is_alive(saved_id);
3828 conn_list_do_unbuffer(game.est_connections);
3830 return unit_lives;
3833 /**************************************************************************
3834 Maybe cancel the goto if there is an enemy in the way
3835 **************************************************************************/
3836 static bool maybe_cancel_goto_due_to_enemy(struct unit *punit,
3837 struct tile *ptile)
3839 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
3840 || is_non_allied_city_tile(ptile, unit_owner(punit)));
3843 /**************************************************************************
3844 Maybe cancel the patrol as there is an enemy near.
3846 If you modify the wakeup range you should change it in
3847 wakeup_neighbor_sentries() too.
3848 **************************************************************************/
3849 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
3851 bool cancel = FALSE;
3852 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
3853 struct player *pplayer = unit_owner(punit);
3855 circle_iterate(unit_tile(punit), radius_sq, ptile) {
3856 struct unit *penemy = is_non_allied_unit_tile(ptile, pplayer);
3858 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
3860 if ((penemy && can_player_see_unit(pplayer, penemy))
3861 || (pdcity && !pplayers_allied(pplayer, vision_site_owner(pdcity))
3862 && pdcity->occupied)) {
3863 cancel = TRUE;
3864 break;
3866 } circle_iterate_end;
3868 return cancel;
3871 /**************************************************************************
3872 Returns the action id corresponding to the specified order id.
3873 **************************************************************************/
3874 static int order_to_action(struct unit *punit, enum unit_orders order)
3876 switch (order) {
3877 case ORDER_BUILD_WONDER:
3878 return ACTION_HELP_WONDER;
3879 case ORDER_TRADE_ROUTE:
3880 return ACTION_TRADE_ROUTE;
3881 case ORDER_MOVE:
3882 case ORDER_ACTION_MOVE:
3883 case ORDER_FULL_MP:
3884 case ORDER_BUILD_CITY:
3885 case ORDER_ACTIVITY:
3886 case ORDER_DISBAND:
3887 case ORDER_HOMECITY:
3888 case ORDER_LAST:
3889 /* Not action enabler controlled. */
3890 break;
3893 fc_assert_msg(FALSE, "No action to map order to.");
3894 return ACTION_COUNT;
3897 /**************************************************************************
3898 Returns TRUE iff it is reasonable to assume that the player is wathing
3899 the unit.
3901 Since the player is watching the unit there is no need to inform him
3902 about things he could see happening. Remember that it still may
3903 be necessary to explain why something happened.
3904 **************************************************************************/
3905 static inline bool player_is_watching(struct unit *punit, const bool fresh)
3907 /* The player just sent the orders to the unit. The unit has moves left.
3908 * It is therefore safe to assume that the player already is paying
3909 * attention to the unit. */
3910 return fresh && punit->moves_left > 0;
3913 /****************************************************************************
3914 Executes a unit's orders stored in punit->orders. The unit is put on idle
3915 if an action fails or if "patrol" is set and an enemy unit is encountered.
3917 The return value will be TRUE if the unit lives, FALSE otherwise. (This
3918 function used to return a goto_result enumeration, declared in gotohand.h.
3919 But this enumeration was never checked by the caller and just lead to
3920 confusion. All the caller really needs to know is if the unit lived or
3921 died; everything else is handled internally within execute_orders.)
3923 If the orders are repeating the loop starts over at the beginning once it
3924 completes. To avoid infinite loops on railroad we stop for this
3925 turn when the unit is back where it started, even if it have moves left.
3927 A unit will attack under orders only on its final action.
3929 The fresh parameter is true if the order execution happens because the
3930 orders just were received.
3931 ****************************************************************************/
3932 bool execute_orders(struct unit *punit, const bool fresh)
3934 struct tile *dst_tile;
3935 bool res, last_order;
3936 int unitid = punit->id;
3937 struct player *pplayer = unit_owner(punit);
3938 int moves_made = 0;
3939 enum unit_activity activity;
3941 fc_assert_ret_val(unit_has_orders(punit), TRUE);
3943 if (punit->activity != ACTIVITY_IDLE) {
3944 /* Unit's in the middle of an activity; wait for it to finish. */
3945 punit->done_moving = TRUE;
3946 return TRUE;
3949 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
3951 /* Any time the orders are canceled we should give the player a message. */
3953 while (TRUE) {
3954 struct unit_order order;
3956 if (punit->done_moving) {
3957 log_debug(" stopping because we're done this turn");
3958 return TRUE;
3961 if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
3962 /* "Patrol" orders are stopped if an enemy is near. */
3963 cancel_orders(punit, " stopping because of nearby enemy");
3964 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
3965 _("Orders for %s aborted as there are units nearby."),
3966 unit_link(punit));
3967 return TRUE;
3970 if (moves_made == punit->orders.length) {
3971 /* For repeating orders, don't repeat more than once per turn. */
3972 log_debug(" stopping because we ran a round");
3973 punit->done_moving = TRUE;
3974 send_unit_info(NULL, punit);
3975 return TRUE;
3977 moves_made++;
3979 order = punit->orders.list[punit->orders.index];
3981 switch (order.order) {
3982 case ORDER_MOVE:
3983 case ORDER_ACTION_MOVE:
3984 case ORDER_FULL_MP:
3985 case ORDER_BUILD_CITY:
3986 if (0 == punit->moves_left) {
3987 log_debug(" stopping because of no more move points");
3988 return TRUE;
3990 break;
3991 case ORDER_BUILD_WONDER:
3992 case ORDER_TRADE_ROUTE:
3993 if (action_mp_full_makes_legal(punit, order_to_action(punit, order.order))) {
3994 log_debug(" stopping. Not enough move points this turn");
3995 return TRUE;
3997 break;
3998 case ORDER_ACTIVITY:
3999 case ORDER_DISBAND:
4000 case ORDER_HOMECITY:
4001 case ORDER_LAST:
4002 /* Those actions don't require moves left. */
4003 break;
4006 last_order = (!punit->orders.repeat
4007 && punit->orders.index + 1 == punit->orders.length);
4009 if (last_order) {
4010 /* Clear the orders before we engage in the move. That way any
4011 * has_orders checks will yield FALSE and this will be treated as
4012 * a normal move. This is important: for instance a caravan goto
4013 * will popup the caravan dialog on the last move only. */
4014 free_unit_orders(punit);
4017 /* Advance the orders one step forward. This is needed because any
4018 * updates sent to the client as a result of the action should include
4019 * the new index value. Note that we have to send_unit_info somewhere
4020 * after this point so that the client is properly updated. */
4021 punit->orders.index++;
4023 switch (order.order) {
4024 case ORDER_FULL_MP:
4025 if (punit->moves_left < unit_move_rate(punit)) {
4026 /* If the unit doesn't have full MP then it just waits until the
4027 * next turn. We assume that the next turn it will have full MP
4028 * (there's no check for that). */
4029 punit->done_moving = TRUE;
4030 log_debug(" waiting this turn");
4031 send_unit_info(NULL, punit);
4033 break;
4034 case ORDER_BUILD_CITY:
4035 unit_build_city(pplayer, punit,
4036 city_name_suggestion(pplayer, unit_tile(punit)));
4037 log_debug(" building city");
4038 if (player_unit_by_number(pplayer, unitid)) {
4039 /* Build failed. */
4040 cancel_orders(punit, " orders canceled; failed to build city");
4041 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4042 _("Orders for %s aborted because building "
4043 "of city failed."),
4044 unit_link(punit));
4045 return TRUE;
4046 } else {
4047 /* Build succeeded => unit "died" */
4048 return FALSE;
4050 case ORDER_ACTIVITY:
4051 activity = order.activity;
4053 struct extra_type *pextra = (order.target == EXTRA_NONE ?
4054 NULL :
4055 extra_by_number(order.target));
4057 if (pextra == NULL && activity_requires_target(order.activity)) {
4058 /* Try to find a target extra before giving up this order or, if
4059 * serious enough, all orders. */
4061 enum unit_activity new_activity = order.activity;
4063 unit_assign_specific_activity_target(punit,
4064 &new_activity, &pextra);
4066 if (new_activity != order.activity) {
4067 /* At the time this code was written the only possible activity
4068 * change from unit_assign_specific_activity_target() was from
4069 * ACTIVITY_PILLAGE to ACTIVITY_IDLE. That would only happen
4070 * when a target extra couldn't be found. -- Sveinung */
4071 fc_assert_msg((order.activity == ACTIVITY_PILLAGE
4072 && new_activity == ACTIVITY_IDLE),
4073 "Skipping an order when canceling all orders may"
4074 " have been the correct thing to do.");
4076 /* Already removed, let's continue. */
4077 break;
4080 /* Should have given up or, if supported, changed the order's
4081 * activity to the activity suggested by
4082 * unit_activity_handling_targeted() before this line was
4083 * reached.
4084 * Remember that unit_activity_handling_targeted() has the power
4085 * to change the order's target extra directly. */
4086 fc_assert_msg(new_activity == order.activity,
4087 "Activity not updated. Target may have changed.");
4089 /* Should have found a target or given up before reaching this
4090 * line. */
4091 fc_assert_msg((pextra != NULL
4092 || !activity_requires_target(order.activity)),
4093 "Activity requires a target. No target found.");
4096 if (can_unit_do_activity_targeted(punit, activity, pextra)) {
4097 punit->done_moving = TRUE;
4098 set_unit_activity_targeted(punit, activity, pextra);
4099 send_unit_info(NULL, punit);
4100 break;
4101 } else {
4102 if ((activity == ACTIVITY_BASE
4103 || activity == ACTIVITY_GEN_ROAD
4104 || activity == ACTIVITY_IRRIGATE
4105 || activity == ACTIVITY_MINE)
4106 && tile_has_extra(unit_tile(punit), pextra)) {
4107 break; /* Already built, let's continue. */
4108 } else if ((activity == ACTIVITY_POLLUTION
4109 || activity == ACTIVITY_FALLOUT
4110 || activity == ACTIVITY_PILLAGE)
4111 && !tile_has_extra(unit_tile(punit), pextra)) {
4112 break; /* Already removed, let's continue. */
4117 cancel_orders(punit, " orders canceled because of failed activity");
4118 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4119 _("Orders for %s aborted since they "
4120 "give an invalid activity."),
4121 unit_link(punit));
4122 return TRUE;
4123 case ORDER_MOVE:
4124 case ORDER_ACTION_MOVE:
4125 /* Move unit */
4126 if (!(dst_tile = mapstep(unit_tile(punit), order.dir))) {
4127 cancel_orders(punit, " move order sent us to invalid location");
4128 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4129 _("Orders for %s aborted since they "
4130 "give an invalid location."),
4131 unit_link(punit));
4132 return TRUE;
4135 if (order.order != ORDER_ACTION_MOVE
4136 && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
4137 /* Plain move required: no attack, trade route etc. */
4138 cancel_orders(punit, " orders canceled because of enemy");
4139 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4140 _("Orders for %s aborted as there "
4141 "are units in the way."),
4142 unit_link(punit));
4143 return TRUE;
4146 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4147 res = unit_move_handling(punit, dst_tile, FALSE,
4148 order.order != ORDER_ACTION_MOVE, NULL);
4149 if (!player_unit_by_number(pplayer, unitid)) {
4150 log_debug(" unit died while moving.");
4151 /* A player notification should already have been sent. */
4152 return FALSE;
4155 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4156 /* Movement succeeded but unit didn't move. */
4157 log_debug(" orders resulted in combat.");
4158 send_unit_info(NULL, punit);
4159 return TRUE;
4162 if (!res) {
4163 fc_assert(0 <= punit->moves_left);
4165 /* Movement failed (ZOC, etc.) */
4166 cancel_orders(punit, " attempt to move failed.");
4168 if (!player_is_watching(punit, fresh)
4169 /* The final move "failed" because the unit needs to ask the
4170 * player what action it should take.
4172 * The action decision request notifies the player. Its
4173 * location at the unit's last order makes it clear to the
4174 * player who the decision is for. ("The Spy I sent to Berlin
4175 * has arrived.")
4177 * A notification message is therefore redundant. */
4178 && !(last_order
4179 && punit->action_decision_want == ACT_DEC_ACTIVE
4180 && punit->action_decision_tile == dst_tile)) {
4181 /* The player may have missed this. No one else will announce it
4182 * in a satisfying manner. Inform the player. */
4183 notify_player(pplayer, unit_tile(punit),
4184 E_UNIT_ORDERS, ftc_server,
4185 _("Orders for %s aborted because of failed move."),
4186 unit_link(punit));
4189 return TRUE;
4191 break;
4192 case ORDER_DISBAND:
4193 log_debug(" orders: disbanding");
4194 handle_unit_disband(pplayer, unitid);
4195 return FALSE;
4196 case ORDER_HOMECITY:
4197 log_debug(" orders: changing homecity");
4198 if (tile_city(unit_tile(punit))) {
4199 handle_unit_change_homecity(pplayer, unitid,
4200 tile_city(unit_tile(punit))->id);
4201 } else {
4202 cancel_orders(punit, " no homecity");
4203 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4204 _("Attempt to change homecity for %s failed."),
4205 unit_link(punit));
4206 return TRUE;
4208 break;
4209 case ORDER_TRADE_ROUTE:
4210 log_debug(" orders: establishing trade route.");
4211 dst_tile = unit_tile(punit);
4213 fc_assert_ret_val_msg(dst_tile, FALSE, "No tile for ordered unit");
4215 if (tile_city(dst_tile) == NULL) {
4216 cancel_orders(punit, " trade route order with no city");
4217 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4218 _("Orders for %s aborted since they "
4219 "give a location without a city."),
4220 unit_link(punit));
4221 return TRUE;
4224 handle_unit_do_action(pplayer,
4225 unitid, tile_city(dst_tile)->id,
4226 0, ACTION_TRADE_ROUTE);
4227 if (player_unit_by_number(pplayer, unitid)) {
4228 cancel_orders(punit, " no trade route city");
4229 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4230 _("Attempt to establish trade route for %s failed."),
4231 unit_link(punit));
4232 return TRUE;
4233 } else {
4234 return FALSE;
4236 case ORDER_BUILD_WONDER:
4237 log_debug(" orders: building wonder");
4238 dst_tile = unit_tile(punit);
4240 fc_assert_ret_val_msg(dst_tile, FALSE, "No tile for ordered unit");
4242 if (tile_city(dst_tile) == NULL) {
4243 cancel_orders(punit, " build wonder order with no city");
4244 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4245 _("Orders for %s aborted since they "
4246 "give a location without a city."),
4247 unit_link(punit));
4248 return TRUE;
4251 handle_unit_do_action(pplayer,
4252 unitid,
4253 tile_city(dst_tile)->id,
4254 0, ACTION_HELP_WONDER);
4255 if (player_unit_by_number(pplayer, unitid)) {
4256 cancel_orders(punit, " no wonder city");
4257 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4258 _("Attempt to build wonder for %s failed."),
4259 unit_link(punit));
4260 return TRUE;
4261 } else {
4262 return FALSE;
4264 case ORDER_LAST:
4265 cancel_orders(punit, " client sent invalid order!");
4266 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4267 _("Your %s has invalid orders."),
4268 unit_link(punit));
4269 return TRUE;
4272 if (last_order) {
4273 fc_assert(punit->has_orders == FALSE);
4274 log_debug(" stopping because orders are complete");
4275 return TRUE;
4278 if (punit->orders.index == punit->orders.length) {
4279 fc_assert(punit->orders.repeat);
4280 /* Start over. */
4281 log_debug(" repeating orders.");
4282 punit->orders.index = 0;
4284 } /* end while */
4287 /****************************************************************************
4288 Return the vision the unit will have at the given tile. The base vision
4289 range may be modified by effects.
4291 Note that vision MUST be independent of transported_by for this to work
4292 properly.
4293 ****************************************************************************/
4294 int get_unit_vision_at(struct unit *punit, struct tile *ptile,
4295 enum vision_layer vlayer)
4297 const int base = (unit_type_get(punit)->vision_radius_sq
4298 + get_unittype_bonus(unit_owner(punit), ptile,
4299 unit_type_get(punit),
4300 EFT_UNIT_VISION_RADIUS_SQ));
4301 switch (vlayer) {
4302 case V_MAIN:
4303 return base;
4304 case V_INVIS:
4305 return MIN(base, 2);
4306 case V_COUNT:
4307 break;
4310 log_error("Unsupported vision layer variant: %d.", vlayer);
4311 return 0;
4314 /****************************************************************************
4315 Refresh the unit's vision.
4317 This function has very small overhead and can be called any time effects
4318 may have changed the vision range of the city.
4319 ****************************************************************************/
4320 void unit_refresh_vision(struct unit *punit)
4322 struct vision *uvision = punit->server.vision;
4323 const v_radius_t radius_sq =
4324 V_RADIUS(get_unit_vision_at(punit, unit_tile(punit), V_MAIN),
4325 get_unit_vision_at(punit, unit_tile(punit), V_INVIS));
4327 vision_change_sight(uvision, radius_sq);
4328 ASSERT_VISION(uvision);
4331 /****************************************************************************
4332 Refresh the vision of all units in the list - see unit_refresh_vision.
4333 ****************************************************************************/
4334 void unit_list_refresh_vision(struct unit_list *punitlist)
4336 unit_list_iterate(punitlist, punit) {
4337 unit_refresh_vision(punit);
4338 } unit_list_iterate_end;
4341 /****************************************************************************
4342 Used to implement the game rule controlled by the unitwaittime setting.
4343 Notifies the unit owner if the unit is unable to act.
4344 ****************************************************************************/
4345 bool unit_can_do_action_now(const struct unit *punit)
4347 time_t dt;
4349 if (!punit) {
4350 return FALSE;
4353 if (game.server.unitwaittime <= 0) {
4354 return TRUE;
4357 if (punit->server.action_turn != game.info.turn - 1) {
4358 return TRUE;
4361 dt = time(NULL) - punit->server.action_timestamp;
4362 if (dt < game.server.unitwaittime) {
4363 char buf[64];
4364 format_time_duration(game.server.unitwaittime - dt, buf, sizeof(buf));
4365 notify_player(unit_owner(punit), unit_tile(punit), E_BAD_COMMAND,
4366 ftc_server, _("Your unit may not act for another %s "
4367 "this turn. See /help unitwaittime."), buf);
4368 return FALSE;
4371 return TRUE;
4374 /****************************************************************************
4375 Mark a unit as having done something at the current time. This is used
4376 in conjunction with unit_can_do_action_now() and the unitwaittime setting.
4377 ****************************************************************************/
4378 void unit_did_action(struct unit *punit)
4380 if (!punit) {
4381 return;
4384 punit->server.action_timestamp = time(NULL);
4385 punit->server.action_turn = game.info.turn;
4388 /**************************************************************************
4389 Units (usually barbarian units) may disband spontaneously if they are
4390 far from any enemy units or cities. It is to remove barbarians that do
4391 not engage into any activity for a long time.
4392 **************************************************************************/
4393 bool unit_can_be_retired(struct unit *punit)
4395 /* check if there is enemy nearby */
4396 square_iterate(unit_tile(punit), 3, ptile) {
4397 if (is_enemy_city_tile(ptile, unit_owner(punit))
4398 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4399 return FALSE;
4402 square_iterate_end;
4404 return TRUE;