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