Freeciv-3.1
Loading...
Searching...
No Matches
unittools.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
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"
30
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"
48
49/* common/scriptcore */
50#include "luascript_signal.h"
51#include "luascript_types.h"
52
53/* aicore */
54#include "path_finding.h"
55#include "pf_tools.h"
56
57/* server/scripting */
58#include "script_server.h"
59
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"
76
77/* server/advisors */
78#include "advgoto.h"
79#include "autoexplorer.h"
80#include "autosettlers.h"
81
82/* ai */
83#include "handicaps.h"
84
85#include "unittools.h"
86
87
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). */
93 struct unit *punit; /* NULL for invalidating. */
94 struct player *powner;
95 bv_player can_see_unit;
96 bv_player can_see_move;
98};
99
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
108
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. */
116};
117
118#define SPECLIST_TAG autoattack_prob
119#define SPECLIST_TYPE struct autoattack_prob
120#include "speclist.h"
121
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); \
126 \
127 if (_unit_ == NULL) { \
128 continue; \
129 }
130
131#define autoattack_prob_list_iterate_safe_end LIST_ITERATE_END
132
133static void unit_restore_hitpoints(struct unit *punit);
134static void unit_restore_movepoints(struct player *pplayer, struct unit *punit);
135static void update_unit_activity(struct unit *punit);
136static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
137 bool helpless, bool teleporting,
138 const struct city *pexclcity);
139static void wakeup_neighbor_sentries(struct unit *punit);
140static void do_upgrade_effects(struct player *pplayer);
141
142static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
143
144static bool maybe_become_veteran_real(struct unit *punit, int base_chance,
145 bool settler);
146
147static void unit_transport_load_tp_status(struct unit *punit,
148 struct unit *ptrans,
149 bool force);
150
151static void wipe_unit_full(struct unit *punit, bool transported,
152 enum unit_loss_reason reason,
153 struct player *killer);
154
155static int get_unit_vision_base(struct unit *punit, enum vision_layer vlayer,
156 const int base);
157static int unit_vision_range_modifiers(struct unit *punit,
158 const struct tile *ptile);
159
160/**********************************************************************/
174struct unit_type *find_a_unit_type(enum unit_role_id role,
175 enum unit_role_id role_tech)
176{
177 struct unit_type *which[U_LAST];
178 int i, num = 0;
179
180 if (role_tech != -1) {
181 for (i = 0; i < num_role_units(role_tech); i++) {
182 struct unit_type *iunit = get_role_unit(role_tech, i);
183 const int minplayers = 2;
184 int players = 0;
185
186 /* Note, if there's only one player in the game this check will always
187 * fail. */
188 players_iterate(pplayer) {
189 if (!is_barbarian(pplayer)
190 && can_player_build_unit_direct(pplayer, iunit)) {
191 players++;
192 }
194 if (players > minplayers) {
195 which[num++] = iunit;
196 }
197 }
198 }
199 if (num == 0) {
200 for (i = 0; i < num_role_units(role); i++) {
201 which[num++] = get_role_unit(role, i);
202 }
203 }
204
205 /* Ruleset code should ensure there is at least one unit for each
206 * possibly-required role, or check before calling this function. */
207 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
208 role, role_tech);
209
210 return which[fc_rand(num)];
211}
212
213/**********************************************************************/
217bool maybe_make_veteran(struct unit *punit, int base_chance)
218{
219 return maybe_become_veteran_real(punit, base_chance, FALSE);
220}
221
222/**********************************************************************/
235static bool maybe_become_veteran_real(struct unit *punit, int base_chance,
236 bool settler)
237{
238 const struct veteran_system *vsystem;
239 const struct veteran_level *vlevel;
240 int chance;
241
242 fc_assert_ret_val(punit != NULL, FALSE);
243
245 fc_assert_ret_val(vsystem != NULL, FALSE);
247
249 fc_assert_ret_val(vlevel != NULL, FALSE);
250
251 if (punit->veteran + 1 >= vsystem->levels
252 || unit_has_type_flag(punit, UTYF_NO_VETERAN)) {
253 return FALSE;
254 } else if (!settler) {
255 int mod = base_chance + get_unit_bonus(punit, EFT_VETERAN_COMBAT);
256
257 /* The modification is tacked on as a multiplier to the base chance.
258 * For example with a base chance of 50% for green units and a modifier
259 * of +50% the end chance is 75%. */
260 chance = vlevel->base_raise_chance * mod / 100;
261 } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
262 chance = base_chance * vlevel->work_raise_chance / 100;
263 } else {
264 /* No battle and no work done. */
265 return FALSE;
266 }
267
268 if (fc_rand(100) < chance) {
269 punit->veteran++;
270 return TRUE;
271 }
272
273 return FALSE;
274}
275
276/**********************************************************************/
286bool unit_versus_unit(struct unit *attacker, struct unit *defender,
287 int *att_hp, int *def_hp, int *att_vet, int *def_vet)
288{
289 int attackpower = get_total_attack_power(attacker, defender);
290 int defensepower = get_total_defense_power(attacker, defender);
291 int attack_firepower, defense_firepower;
292 struct player *plr1 = unit_owner(attacker);
293 struct player *plr2 = unit_owner(defender);
294 struct civ_map *nmap = &(wld.map);
295 int max_rounds;
296 int rounds;
297 int att_strength;
298 int def_strength;
299
300 *att_hp = attacker->hp;
301 *def_hp = defender->hp;
302 get_modified_firepower(nmap, attacker, defender,
303 &attack_firepower, &defense_firepower);
304
305 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
306 "defense firepower:%d", attackpower, defensepower,
307 attack_firepower, defense_firepower);
308
311
312 att_strength = attackpower * attacker->hp * attack_firepower;
313 def_strength = defensepower * defender->hp * defense_firepower;
314
315 /* In a combat between equal strength units the values are 50% / 50%.
316 * -> scaling that to 100% by doubling, to match scale of chances
317 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
318 *att_vet = def_strength * 2 / (att_strength + def_strength);
319 *def_vet = att_strength * 2 / (att_strength + def_strength);
320
321 if (attackpower == 0) {
322 *att_hp = 0;
323 } else if (defensepower == 0) {
324 *def_hp = 0;
325 }
326 max_rounds = get_unit_bonus(attacker, EFT_COMBAT_ROUNDS);
327 for (rounds = 0;
328 *att_hp > 0 && *def_hp > 0
329 && (max_rounds <= 0 || max_rounds > rounds);
330 rounds++) {
331 if (fc_rand(attackpower + defensepower) >= defensepower) {
332 *def_hp -= attack_firepower;
333 } else {
334 *att_hp -= defense_firepower;
335 }
336 }
337 if (*att_hp < 0) {
338 *att_hp = 0;
339 }
340 if (*def_hp < 0) {
341 *def_hp = 0;
342 }
343
344 return attackpower <= 0 || defensepower <= 0;
345}
346
347/**********************************************************************/
352void unit_bombs_unit(struct unit *attacker, struct unit *defender,
353 int *att_hp, int *def_hp)
354{
355 int i;
356 int rate = unit_bombard_rate(attacker);
357 int attackpower = get_total_attack_power(attacker, defender);
358 int defensepower = get_total_defense_power(attacker, defender);
359 int attack_firepower, defense_firepower;
360 struct player *plr1 = unit_owner(attacker);
361 struct player *plr2 = unit_owner(defender);
362 struct civ_map *nmap = &(wld.map);
363
364 *att_hp = attacker->hp;
365 *def_hp = defender->hp;
366 get_modified_firepower(nmap, attacker, defender,
367 &attack_firepower, &defense_firepower);
368
369 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
370 "defense firepower:%d", attackpower, defensepower,
371 attack_firepower, defense_firepower);
372
375
376 for (i = 0; i < rate; i++) {
377 if (fc_rand(attackpower + defensepower) >= defensepower) {
378 *def_hp -= attack_firepower;
379 }
380 }
381
382 /* Don't kill the target. */
383 if (*def_hp <= 0) {
384 *def_hp = 1;
385 }
386}
387
388/**********************************************************************/
392void combat_veterans(struct unit *attacker, struct unit *defender,
393 bool powerless, int att_vet, int def_vet)
394{
395 if (!powerless || !game.info.only_real_fight_makes_veteran) {
396 if (attacker->hp <= 0 || defender->hp <= 0
399 att_vet = 100;
400 def_vet = 100;
401 }
402 if (attacker->hp > 0) {
403 maybe_make_veteran(attacker, att_vet);
404 }
405 if (defender->hp > 0) {
406 maybe_make_veteran(defender, def_vet);
407 }
408 }
409 }
410}
411
412/**********************************************************************/
416static void do_upgrade_effects(struct player *pplayer)
417{
418 int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT);
419 struct unit_list *candidates;
420
421 if (upgrades <= 0) {
422 return;
423 }
424 candidates = unit_list_new();
425
426 unit_list_iterate(pplayer->units, punit) {
427 /* We have to be careful not to strand units at sea, for example by
428 * upgrading a frigate to an ironclad while it was carrying a unit. */
429 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
430 unit_list_prepend(candidates, punit); /* Potential candidate :) */
431 }
433
434 while (upgrades > 0 && unit_list_size(candidates) > 0) {
435 /* Upgrade one unit. The unit is chosen at random from the list of
436 * available candidates. */
437 int candidate_to_upgrade = fc_rand(unit_list_size(candidates));
438 struct unit *punit = unit_list_get(candidates, candidate_to_upgrade);
439 const struct unit_type *type_from = unit_type_get(punit);
440 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
441
443 notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
444 _("%s was upgraded for free to %s."),
445 utype_name_translation(type_from),
447 unit_list_remove(candidates, punit);
448 upgrades--;
449 }
450
451 unit_list_destroy(candidates);
452}
453
454/**********************************************************************/
469void player_restore_units(struct player *pplayer)
470{
471 const struct civ_map *nmap = &(wld.map);
472
473 /* 1) get Leonardo out of the way first: */
474 do_upgrade_effects(pplayer);
475
477
478 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
480
481 /* 3) Check that unit has hitpoints */
482 if (punit->hp <= 0) {
483 /* This should usually only happen for heli units, but if any other
484 * units get 0 hp somehow, catch them too. --dwp */
485 /* if 'game.server.killunhomed' is activated unhomed units are slowly
486 * killed; notify player here */
487 if (!punit->homecity && 0 < game.server.killunhomed) {
488 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
489 ftc_server, _("Your %s has run out of hit points "
490 "because it was not supported by a city."),
492 } else {
493 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
494 _("Your %s has run out of hit points."),
496 }
497
498 wipe_unit(punit, ULR_HP_LOSS, NULL);
499 continue; /* Continue iterating... */
500 }
501
502 /* 4) Rescue planes if needed */
504 /* Shall we emergency return home on the last vapors? */
505
506 /* I think this is strongly against the spirit of client goto.
507 * The problem is (again) that here we know too much. -- Zamar */
508
509 if (punit->fuel <= 1
511 struct unit *carrier;
512
513 carrier = transporter_for_unit(punit);
514 if (carrier) {
516 } else {
517 struct pf_map *pfm;
518 struct pf_parameter parameter;
519 bool alive = TRUE;
520
521 pft_fill_unit_parameter(&parameter, nmap, punit);
522 parameter.omniscience = !has_handicap(pplayer, H_MAP);
523 pfm = pf_map_new(&parameter);
524
525 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
526 if (move_cost > punit->moves_left) {
527 /* Too far */
528 break;
529 }
530
531 if (is_refuel_point(ptile, pplayer, punit)) {
532 struct pf_path *path;
533 int id = punit->id;
534
535 /* Client orders may be running for this unit - if so
536 * we free them before engaging goto. */
538
539 path = pf_map_path(pfm, ptile);
540
541 alive = adv_follow_path(punit, path, ptile);
542
543 if (!alive) {
544 log_error("rescue plane: unit %d died enroute!", id);
545 } else if (!same_pos(unit_tile(punit), ptile)) {
546 /* Enemy units probably blocked our route
547 * FIXME: We should try find alternative route around
548 * the enemy unit instead of just giving up and crashing. */
549 log_debug("rescue plane: unit %d could not move to "
550 "refuel point!", punit->id);
551 }
552
553 if (alive) {
554 /* Clear activity. Unit info will be sent in the end of
555 * the function. */
556 unit_activity_handling(punit, ACTIVITY_IDLE);
558 punit->goto_tile = NULL;
559
561 carrier = transporter_for_unit(punit);
562 if (carrier) {
564 }
565 }
566
567 notify_player(pplayer, unit_tile(punit),
568 E_UNIT_ORDERS, ftc_server,
569 _("Your %s has returned to refuel."),
571 }
572 pf_path_destroy(path);
573 break;
574 }
576 pf_map_destroy(pfm);
577
578 if (!alive) {
579 /* Unit died trying to move to refuel point. */
580 return;
581 }
582 }
583 }
584
585 /* 5) Update fuel */
586 punit->fuel--;
587
588 /* 6) Automatically refuel air units in cities, airbases, and
589 * transporters (carriers). */
592 }
593 }
595
596 /* 7) Check if there are air units without fuel */
598 const struct unit_type *utype = unit_type_get(punit);
599
600 if (punit->fuel <= 0 && utype_fuel(utype)) {
601 /* Notifications sent from the lua script when unit wiped. */
602 wipe_unit(punit, ULR_FUEL, NULL);
603 }
605
606 /* Send all updates. */
607 unit_list_iterate(pplayer->units, punit) {
608 send_unit_info(NULL, punit);
610}
611
612/**********************************************************************/
623{
624 bool was_lower;
625 const struct unit_type *utype = unit_type_get(punit);
626
627 was_lower = (punit->hp < utype->hp);
628
630
631 fc_assert(punit->hp >= 0);
632 fc_assert(punit->hp <= utype->hp);
633
634 if (punit->hp == utype->hp) {
635 if (was_lower && punit->activity == ACTIVITY_SENTRY) {
636 set_unit_activity(punit, ACTIVITY_IDLE);
637 }
638 }
639
640 punit->moved = FALSE;
642}
643
644/**********************************************************************/
649static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
650{
653}
654
655/**********************************************************************/
664
665/**********************************************************************/
668void execute_unit_orders(struct player *pplayer)
669{
671 if (unit_has_orders(punit)) {
673 }
675}
676
677/**********************************************************************/
680void unit_tc_effect_refresh(struct player *pplayer)
681{
682 unit_list_iterate(pplayer->units, punit) {
685}
686
687/**********************************************************************/
691{
692 /* Remember activities only after all knock-on effects of unit activities
693 * on other units have been resolved */
694 unit_list_iterate(pplayer->units, punit) {
698 send_unit_info(NULL, punit);
700}
701
702/**********************************************************************/
706static int total_activity(struct tile *ptile, enum unit_activity act,
707 struct extra_type *tgt)
708{
709 int total = 0;
710 bool tgt_matters = activity_requires_target(act);
711
712 unit_list_iterate(ptile->units, punit) {
713 if (punit->activity == act
714 && (!tgt_matters || punit->activity_target == tgt)) {
715 total += punit->activity_count;
716 }
718
719 return total;
720}
721
722/**********************************************************************/
726static bool total_activity_done(struct tile *ptile, enum unit_activity act,
727 struct extra_type *tgt)
728{
729 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
730}
731
732/**********************************************************************/
736{
737 const struct veteran_level *vlevel;
738#ifndef FREECIV_NDEBUG
739 const struct veteran_system *vsystem;
740#endif
741
742 if (!punit) {
743 return;
744 }
745
746#ifndef FREECIV_NDEBUG
748 fc_assert_ret(vsystem != NULL);
749 fc_assert_ret(vsystem->levels > punit->veteran);
750#endif /* FREECIV_NDEBUG */
751
753 fc_assert_ret(vlevel != NULL);
754
756 E_UNIT_BECAME_VET, ftc_server,
757 /* TRANS: Your <unit> became ... rank of <veteran level>. */
758 _("Your %s became more experienced and achieved the rank "
759 "of %s."),
761}
762
763/**********************************************************************/
766static void unit_convert(struct unit *punit)
767{
768 const struct unit_type *to_type;
769 const struct unit_type *from_type;
770
771 from_type = unit_type_get(punit);
772 to_type = from_type->converted_to;
773
774 if (unit_can_convert(&(wld.map), punit)) {
775 transform_unit(punit, to_type, 0);
777 E_UNIT_UPGRADED, ftc_server,
778 _("%s converted to %s."),
779 utype_name_translation(from_type),
780 utype_name_translation(to_type));
781 } else {
783 E_UNIT_UPGRADED, ftc_server,
784 _("%s cannot be converted."),
785 utype_name_translation(from_type));
786 }
787}
788
789/**********************************************************************/
793{
794 if (unit_has_orders(punit)) {
796 E_UNIT_ORDERS, ftc_server,
797 _("Orders for %s aborted because activity "
798 "is no longer available."),
801 }
802
803 set_unit_activity(punit, ACTIVITY_IDLE);
804 send_unit_info(NULL, punit);
805}
806
807/**********************************************************************/
818
819/**********************************************************************/
830
831/**********************************************************************/
845
846/**********************************************************************/
852static void update_unit_activity(struct unit *punit)
853{
854 struct player *pplayer = unit_owner(punit);
855 bool unit_activity_done = FALSE;
856 enum unit_activity activity = punit->activity;
857 struct tile *ptile = unit_tile(punit);
858 const struct unit_type *act_utype = unit_type_get(punit);
859
860 switch (activity) {
861 case ACTIVITY_IDLE:
862 case ACTIVITY_EXPLORE:
863 case ACTIVITY_FORTIFIED:
864 case ACTIVITY_SENTRY:
865 case ACTIVITY_GOTO:
866 case ACTIVITY_PATROL_UNUSED:
867 case ACTIVITY_UNKNOWN:
868 case ACTIVITY_LAST:
869 /* We don't need the activity_count for the above */
870 break;
871
872 case ACTIVITY_FORTIFYING:
873 case ACTIVITY_CONVERT:
875 break;
876
877 case ACTIVITY_POLLUTION:
878 case ACTIVITY_MINE:
879 case ACTIVITY_IRRIGATE:
880 case ACTIVITY_PILLAGE:
881 case ACTIVITY_CULTIVATE:
882 case ACTIVITY_PLANT:
883 case ACTIVITY_TRANSFORM:
884 case ACTIVITY_FALLOUT:
885 case ACTIVITY_BASE:
886 case ACTIVITY_GEN_ROAD:
888
889 /* settler may become veteran when doing something useful */
892 }
893 break;
894 case ACTIVITY_OLD_ROAD:
895 case ACTIVITY_OLD_RAILROAD:
896 case ACTIVITY_FORTRESS:
897 case ACTIVITY_AIRBASE:
899 break;
900 };
901
903
904 switch (activity) {
905 case ACTIVITY_IDLE:
906 case ACTIVITY_FORTIFIED:
907 case ACTIVITY_SENTRY:
908 case ACTIVITY_GOTO:
909 case ACTIVITY_UNKNOWN:
910 case ACTIVITY_FORTIFYING:
911 case ACTIVITY_CONVERT:
912 case ACTIVITY_PATROL_UNUSED:
913 case ACTIVITY_LAST:
914 /* no default, ensure all handled */
915 break;
916
917 case ACTIVITY_EXPLORE:
919 return;
920
921 case ACTIVITY_PILLAGE:
922 if (total_activity_done(ptile, ACTIVITY_PILLAGE,
925 unit_activity_done = TRUE;
926
928
929 /* Change vision if effects have changed. */
931 }
932 break;
933
934 case ACTIVITY_POLLUTION:
935 /* TODO: Remove this fallback target setting when target always correctly
936 * set */
937 if (punit->activity_target == NULL) {
938 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANPOLLUTION,
939 NULL, punit);
940 }
941 if (total_activity_done(ptile, ACTIVITY_POLLUTION, punit->activity_target)) {
943 unit_activity_done = TRUE;
944 }
945 break;
946
947 case ACTIVITY_FALLOUT:
948 /* TODO: Remove this fallback target setting when target always correctly
949 * set */
950 if (punit->activity_target == NULL) {
951 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANFALLOUT,
952 NULL, punit);
953 }
954 if (total_activity_done(ptile, ACTIVITY_FALLOUT, punit->activity_target)) {
956 unit_activity_done = TRUE;
957 }
958 break;
959
960 case ACTIVITY_BASE:
961 {
962 if (total_activity(ptile, ACTIVITY_BASE, punit->activity_target)
963 >= tile_activity_time(ACTIVITY_BASE, ptile, punit->activity_target)) {
965 unit_activity_done = TRUE;
966 }
967 }
968 break;
969
970 case ACTIVITY_GEN_ROAD:
971 {
972 if (total_activity(ptile, ACTIVITY_GEN_ROAD, punit->activity_target)
973 >= tile_activity_time(ACTIVITY_GEN_ROAD, ptile, punit->activity_target)) {
975 unit_activity_done = TRUE;
976 }
977 }
978 break;
979
980 case ACTIVITY_IRRIGATE:
981 case ACTIVITY_MINE:
982 case ACTIVITY_CULTIVATE:
983 case ACTIVITY_PLANT:
984 case ACTIVITY_TRANSFORM:
985 if (total_activity_done(ptile, activity, punit->activity_target)) {
986 struct terrain *old = tile_terrain(ptile);
987
988 /* The function below could change the terrain. Therefore, we have to
989 * check the terrain (which will also do a sanity check for the tile). */
990 tile_apply_activity(ptile, activity, punit->activity_target);
991 check_terrain_change(ptile, old);
992 unit_activity_done = TRUE;
993 }
994 break;
995
996 case ACTIVITY_OLD_ROAD:
997 case ACTIVITY_OLD_RAILROAD:
998 case ACTIVITY_FORTRESS:
999 case ACTIVITY_AIRBASE:
1001 break;
1002 }
1003
1004 if (unit_activity_done) {
1005 update_tile_knowledge(ptile);
1006 if (ACTIVITY_CULTIVATE == activity
1007 || ACTIVITY_PLANT == activity
1008 || ACTIVITY_TRANSFORM == activity) {
1009 unit_list_iterate(ptile->units, punit2) {
1010 if (punit2->activity == activity) {
1012
1013 set_unit_activity(punit2, ACTIVITY_IDLE);
1014 }
1016 } else {
1017 struct extra_type *act_tgt = punit->activity_target;
1018
1019 unit_list_iterate(ptile->units, punit2) {
1020 if (punit2->activity == activity
1021 && punit2->activity_target == act_tgt) {
1022 /* This unit was helping with the work just finished.
1023 * Mark it idle (already finished) so its "current"
1024 * activity is not considered illegal
1025 * in tile_change_side_effects() . */
1026 set_unit_activity(punit2, ACTIVITY_IDLE);
1027 }
1029 }
1030
1032 }
1033
1034 if (activity == ACTIVITY_FORTIFYING) {
1036 >= action_id_get_act_time(ACTION_FORTIFY,
1037 punit, ptile, punit->activity_target)) {
1038 set_unit_activity(punit, ACTIVITY_FORTIFIED);
1039 unit_activity_done = TRUE;
1040 }
1041 }
1042
1043 if (activity == ACTIVITY_CONVERT) {
1045 >= action_id_get_act_time(ACTION_CONVERT,
1046 punit, ptile, punit->activity_target)) {
1048 set_unit_activity(punit, ACTIVITY_IDLE);
1049 unit_activity_done = TRUE;
1050 }
1051 }
1052
1053 if (unit_activity_done) {
1054 if (activity == ACTIVITY_PILLAGE) {
1055 /* Casus Belli for when the action is completed. */
1056 /* TODO: is it more logical to put Casus_Belli_Success here, change
1057 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1058 * trigger it when an activity successfully has began? */
1061 act_utype,
1065 }
1066 }
1067}
1068
1069/**********************************************************************/
1074{
1075 punit->changed_from = ACTIVITY_IDLE;
1076}
1077
1078/**********************************************************************/
1082bool unit_activity_needs_target_from_client(enum unit_activity activity)
1083{
1084 switch (activity) {
1085 case ACTIVITY_PILLAGE:
1086 /* Can be set server side. */
1087 return FALSE;
1088 default:
1089 return activity_requires_target(activity);
1090 }
1091}
1092
1093/**********************************************************************/
1103 enum unit_activity *activity,
1104 struct extra_type **target)
1105{
1106 const struct civ_map *nmap = &(wld.map);
1107
1108 if (*activity == ACTIVITY_PILLAGE
1109 && *target == NULL) {
1110 struct tile *ptile = unit_tile(punit);
1111 struct extra_type *tgt;
1112 bv_extras extras = *tile_extras(ptile);
1113
1114 while ((tgt = get_preferred_pillage(extras))) {
1115
1116 BV_CLR(extras, extra_index(tgt));
1117
1118 if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
1119 *target = tgt;
1120 return;
1121 }
1122 }
1123
1124 /* Nothing we can pillage here. */
1125 *activity = ACTIVITY_IDLE;
1126 }
1127}
1128
1129/**********************************************************************/
1133static bool find_a_good_partisan_spot(struct tile *pcenter,
1134 struct player *powner,
1135 struct unit_type *u_type,
1136 int sq_radius,
1137 struct tile **dst_tile)
1138{
1139 int bestvalue = 0;
1140 struct civ_map *nmap = &(wld.map);
1141
1142 /* coords of best tile in arg pointers */
1143 circle_iterate(nmap, pcenter, sq_radius, ptile) {
1144 int value;
1145
1146 if (!is_native_tile(u_type, ptile)) {
1147 continue;
1148 }
1149
1150 if (NULL != tile_city(ptile)) {
1151 continue;
1152 }
1153
1154 if (0 < unit_list_size(ptile->units)) {
1155 continue;
1156 }
1157
1158 /* City may not have changed hands yet; see place_partisans(). */
1159 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1160 ptile, FALSE, 0);
1161 value *= 10;
1162
1163 if (tile_continent(ptile) != tile_continent(pcenter)) {
1164 value /= 2;
1165 }
1166
1167 value -= fc_rand(value/3);
1168
1169 if (value > bestvalue) {
1170 *dst_tile = ptile;
1171 bestvalue = value;
1172 }
1174
1175 return bestvalue > 0;
1176}
1177
1178/**********************************************************************/
1181void place_partisans(struct tile *pcenter, struct player *powner,
1182 int count, int sq_radius)
1183{
1184 struct tile *ptile = NULL;
1185 struct unit_type *u_type = get_role_unit(L_PARTISAN, 0);
1186 const struct civ_map *nmap = &(wld.map);
1187
1188 while (count-- > 0
1189 && find_a_good_partisan_spot(pcenter, powner, u_type,
1190 sq_radius, &ptile)) {
1191 struct unit *punit;
1192
1193 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1194 if (can_unit_do_activity(nmap, punit, ACTIVITY_FORTIFYING)) {
1195 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1196 }
1197
1198 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1199 }
1200}
1201
1202/**********************************************************************/
1207bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1208 int move_cost, bool verbose)
1209{
1210 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1211
1212 if (city_owner(pcity) == unit_owner(punit)) {
1213 log_verbose("Teleported %s %s from (%d,%d) to %s",
1215 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1216 if (verbose) {
1218 E_UNIT_RELOCATED, ftc_server,
1219 _("Teleported your %s to %s."),
1221 city_link(pcity));
1222 }
1223
1224 /* Silently free orders since they won't be applicable anymore. */
1226
1227 if (move_cost == -1) {
1228 move_cost = punit->moves_left;
1229 }
1230 unit_move(punit, dst_tile, move_cost,
1231 NULL, FALSE, FALSE, FALSE, FALSE, FALSE);
1232
1233 return TRUE;
1234 }
1235 return FALSE;
1236}
1237
1238/**********************************************************************/
1245void bounce_unit(struct unit *punit, bool verbose)
1246{
1247 struct player *pplayer;
1248 struct tile *punit_tile;
1249 int count = 0;
1250
1251 /* I assume that there are no topologies that have more than
1252 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1253 const int DIST = 2;
1254 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1255
1256 if (!punit) {
1257 return;
1258 }
1259
1260 pplayer = unit_owner(punit);
1261 punit_tile = unit_tile(punit);
1262
1263 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1264 if (count >= ARRAY_SIZE(tiles)) {
1265 break;
1266 }
1267
1268 if (ptile == punit_tile) {
1269 continue;
1270 }
1271
1272 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1273 && !is_non_allied_city_tile(ptile, pplayer)
1274 && !is_non_allied_unit_tile(ptile, pplayer)) {
1275 tiles[count++] = ptile;
1276 }
1278
1279 if (count > 0) {
1280 struct tile *ptile = tiles[fc_rand(count)];
1281
1282 if (verbose) {
1283 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1284 /* TRANS: A unit is moved to resolve stack conflicts. */
1285 _("Moved your %s."),
1286 unit_link(punit));
1287 }
1288
1289 /* TODO: should a unit be able to bounce to a transport like is done
1290 * below? What if the unit can't legally enter the transport, say
1291 * because the transport is Unreachable and the unit doesn't have it in
1292 * its embarks field or because "Transport Embark" isn't enabled? Kept
1293 * like it was to preserve the old rules for now. -- Sveinung */
1294 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1295 return;
1296 }
1297
1298 /* Didn't find a place to bounce the unit, going to disband it.
1299 * Try to bounce transported units. */
1301 struct unit_list *pcargo_units;
1302
1303 pcargo_units = unit_transport_cargo(punit);
1304 unit_list_iterate_safe(pcargo_units, pcargo) {
1305 bounce_unit(pcargo, verbose);
1307 }
1308
1309 if (verbose) {
1310 notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1311 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1312 _("Disbanded your %s."),
1314 }
1315
1316 wipe_unit(punit, ULR_STACK_CONFLICT, NULL);
1317}
1318
1319/**********************************************************************/
1324static void throw_units_from_illegal_cities(struct player *pplayer,
1325 bool verbose)
1326{
1327 struct tile *ptile;
1328 struct city *pcity;
1329 struct unit *ptrans;
1330 struct unit_list *pcargo_units;
1331
1332 /* Unload undesired units from transports, if possible. */
1333 unit_list_iterate(pplayer->units, punit) {
1334 ptile = unit_tile(punit);
1335 pcity = tile_city(ptile);
1336 if (NULL != pcity
1337 && !pplayers_allied(city_owner(pcity), pplayer)
1339 pcargo_units = unit_transport_cargo(punit);
1340 unit_list_iterate(pcargo_units, pcargo) {
1341 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1342 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1344 }
1345 }
1347 }
1349
1350 /* Bounce units except transported ones which will be bounced with their
1351 * transport. */
1353 ptile = unit_tile(punit);
1354 pcity = tile_city(ptile);
1355 if (NULL != pcity
1356 && !pplayers_allied(city_owner(pcity), pplayer)) {
1357 ptrans = unit_transport_get(punit);
1358 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1359 bounce_unit(punit, verbose);
1360 }
1361 }
1363
1364#ifdef FREECIV_DEBUG
1365 /* Sanity check. */
1366 unit_list_iterate(pplayer->units, punit) {
1367 ptile = unit_tile(punit);
1368 pcity = tile_city(ptile);
1369 fc_assert_msg(NULL == pcity
1370 || pplayers_allied(city_owner(pcity), pplayer),
1371 "Failed to throw %s %d from %s %d (%d, %d)",
1373 punit->id,
1374 city_name_get(pcity),
1375 pcity->id,
1376 TILE_XY(ptile));
1378#endif /* FREECIV_DEBUG */
1379}
1380
1381/**********************************************************************/
1389static void resolve_stack_conflicts(struct player *pplayer,
1390 struct player *aplayer, bool verbose)
1391{
1393 struct tile *ptile = unit_tile(punit);
1394
1395 if (is_non_allied_unit_tile(ptile, pplayer)) {
1396 unit_list_iterate_safe(ptile->units, aunit) {
1397 if (unit_owner(aunit) == pplayer
1398 || unit_owner(aunit) == aplayer
1399 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1400 bounce_unit(aunit, verbose);
1401 }
1403 }
1405}
1406
1407/**********************************************************************/
1418void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1419 bool verbose)
1420{
1421 throw_units_from_illegal_cities(pplayer, verbose);
1422 throw_units_from_illegal_cities(aplayer, verbose);
1423
1424 resolve_stack_conflicts(pplayer, aplayer, verbose);
1425 resolve_stack_conflicts(aplayer, pplayer, verbose);
1426}
1427
1428/**********************************************************************/
1433struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1434 const struct player *aplayer)
1435{
1436 struct unit_list *seen_units = unit_list_new();
1437
1438 /* Anybody's units inside ally's cities */
1439 city_list_iterate(aplayer->cities, pcity) {
1440 unit_list_iterate(city_tile(pcity)->units, punit) {
1441 if (can_player_see_unit(pplayer, punit)) {
1442 unit_list_append(seen_units, punit);
1443 }
1446
1447 /* Ally's own units inside transports */
1448 unit_list_iterate(aplayer->units, punit) {
1449 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1450 unit_list_append(seen_units, punit);
1451 }
1453
1454 /* Make sure the same unit is not added in multiple phases
1455 * (unit within transport in a city) */
1456 unit_list_unique(seen_units);
1457
1458 return seen_units;
1459}
1460
1461/**********************************************************************/
1468void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1469 const struct unit_list *seen_units)
1470{
1471 unit_list_iterate(seen_units, punit) {
1472 /* We need to hide units previously seen by the client. */
1473 if (!can_player_see_unit(pplayer, punit)) {
1474 unit_goes_out_of_sight(pplayer, punit);
1475 }
1477
1478 city_list_iterate(aplayer->cities, pcity) {
1479 /* The player used to know what units were in these cities. Now that
1480 * they don't, they need to get a new short city packet updating the
1481 * occupied status. */
1482 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1483 send_city_info(pplayer, pcity);
1484 }
1486}
1487
1488/**********************************************************************/
1492void give_allied_visibility(struct player *pplayer,
1493 struct player *aplayer)
1494{
1495 unit_list_iterate(aplayer->units, punit) {
1496 if (can_player_see_unit(pplayer, punit)) {
1497 send_unit_info(pplayer->connections, punit);
1498 }
1500}
1501
1502/**********************************************************************/
1505static bool is_refuel_tile(const struct tile *ptile,
1506 const struct player *pplayer,
1507 const struct unit *punit)
1508{
1509 const struct unit_type *utype;
1510 const struct unit_class *pclass;
1511
1512 if (is_allied_city_tile(ptile, pplayer)) {
1513 return TRUE;
1514 }
1515
1516 utype = unit_type_get(punit);
1517 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1518 return TRUE;
1519 }
1520
1521 pclass = utype_class(utype);
1522 if (NULL != pclass->cache.refuel_extras) {
1523 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1524
1526 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1527 return TRUE;
1528 }
1530 }
1531
1532 return FALSE;
1533}
1534
1535/**********************************************************************/
1539{
1540 return unit_transported(punit) /* Carrier */
1542}
1543
1544/**********************************************************************/
1547bool is_refuel_point(const struct tile *ptile,
1548 const struct player *pplayer,
1549 const struct unit *punit)
1550{
1551 if (is_non_allied_unit_tile(ptile, pplayer)) {
1552 return FALSE;
1553 }
1554
1555 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1556}
1557
1558/**********************************************************************/
1569void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1570 int vet_loss)
1571{
1572 struct player *pplayer = unit_owner(punit);
1573 const struct unit_type *old_type = punit->utype;
1574 int old_mr = unit_move_rate(punit);
1575 int old_hp = unit_type_get(punit)->hp;
1576 int lvls;
1577
1578 punit->utype = to_unit;
1579
1580 /* New type may not have the same veteran system, and we may want to
1581 * knock some levels off. */
1582 lvls = utype_veteran_system(to_unit)->levels - 1;
1583 punit->veteran = MIN(punit->veteran, lvls);
1584 /* Keeping the old behaviour, so first clip top, then reduce */
1585 punit->veteran = MAX(punit->veteran - vet_loss, 0);
1586
1587 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1588 * and don't kill the unit. unit_move_rate() is used to take into account
1589 * global effects like Magellan's Expedition. */
1590 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1591 if (old_mr == 0) {
1593 } else {
1595 }
1596
1600 }
1601
1602 /* update unit upkeep */
1604
1606
1608
1609 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1611
1612 send_unit_info(NULL, punit);
1614}
1615
1616/**********************************************************************/
1619struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1620 const struct unit_type *type, int veteran_level,
1621 int homecity_id, int moves_left)
1622{
1623 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1624 moves_left, -1, NULL);
1625}
1626
1627/**********************************************************************/
1631{
1632 if (punit->homecity != 0) {
1633 struct city *home = game_city_by_number(punit->homecity);
1634
1635 if (home != NULL && game.info.goods_selection == GSM_LEAVING) {
1637 }
1638 }
1639}
1640
1641/**********************************************************************/
1646struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1647 const struct unit_type *type, int veteran_level,
1648 int homecity_id, int moves_left, int hp_left,
1649 struct unit *ptrans)
1650{
1651 struct unit *punit
1652 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1653 homecity_id, moves_left, hp_left);
1654 struct city *pcity = (!homecity_id || utype_has_flag(type, UTYF_NOHOME))
1655 ? NULL : game_city_by_number(homecity_id);
1656 bool could_place;
1657
1658 fc_assert_ret_val(punit, NULL);
1659 could_place = place_unit(punit, pplayer, pcity, ptrans, FALSE);
1660 fc_assert(could_place);
1661 if (!could_place) {
1663 punit = NULL;
1664 }
1665
1666 return punit;
1667}
1668
1669/**********************************************************************/
1679struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1680 const struct unit_type *type,
1681 int veteran_level, int homecity_id,
1682 int moves_left, int hp_left)
1683{
1684 struct unit *punit;
1685
1686 fc_assert_ret_val(ptile != NULL, NULL);
1687 punit = unit_virtual_create(pplayer, NULL, type, veteran_level);
1688 unit_tile_set(punit, ptile);
1689
1690 if (utype_has_flag(type, UTYF_NOHOME)) {
1691 punit->homecity = 0; /* none */
1692 } else {
1693 punit->homecity = homecity_id;
1694 }
1695
1696 if (hp_left >= 0) {
1697 /* Override default full HP */
1698 punit->hp = hp_left;
1699 }
1700
1701 if (moves_left >= 0) {
1702 int mr = unit_move_rate(punit);
1703
1704 /* Override default full MP */
1705 /* FIXME: there are valid situations when a unit have mp
1706 * over its move rate. Here, keeping the old behavior. */
1708 /* Assume that if moves_left < 0 then the unit is "fresh",
1709 * and not moved; else the unit has had something happen
1710 * to it (eg, bribed) which we treat as equivalent to moved.
1711 * (Otherwise could pass moved arg too...) --dwp */
1712 punit->moved = TRUE;
1713 }
1714
1715 return punit;
1716}
1717
1718/**********************************************************************/
1727bool place_unit(struct unit *punit, struct player *pplayer,
1728 struct city *pcity, struct unit *ptrans, bool force)
1729{
1730 struct tile *ptile;
1731
1732 fc_assert_ret_val(pplayer, FALSE);
1734 ptile = punit->tile;
1735 fc_assert_ret_val(ptile, FALSE);
1736
1737 /* Register unit */
1740
1741 if (ptrans) {
1742 /* Set transporter for unit. */
1743 unit_transport_load_tp_status(punit, ptrans, force);
1744 }
1745
1747 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1748 FALSE);
1749
1750 unit_list_prepend(pplayer->units, punit);
1751 unit_list_prepend(ptile->units, punit);
1753 if (pcity && !unit_has_type_flag(punit, UTYF_NOHOME)) {
1754 fc_assert(punit->homecity == pcity->id);
1755 fc_assert(city_owner(pcity) == pplayer);
1756 unit_list_prepend(pcity->units_supported, punit);
1757 /* update unit upkeep */
1758 city_units_upkeep(pcity);
1759 /* Refresh the unit's homecity. */
1760 city_refresh(pcity);
1761 send_city_info(pplayer, pcity);
1762 }
1763
1764 punit->server.vision = vision_new(pplayer, ptile);
1766
1767 send_unit_info(NULL, punit);
1769
1770 /* The unit may have changed the available tiles in nearby cities. */
1772 sync_cities();
1773
1775
1776 CALL_FUNC_EACH_AI(unit_created, punit);
1777 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1778
1779 return TRUE;
1780}
1781
1782/**********************************************************************/
1786 void (*callback)(struct unit *punit))
1787{
1788 /* Tried to overwrite another call back. If this assertion is triggered
1789 * in a case where two call back are needed it may be time to support
1790 * more than one unit removal call back at a time. */
1792
1794}
1795
1796/**********************************************************************/
1800{
1802}
1803
1804/**********************************************************************/
1808static void server_remove_unit_full(struct unit *punit, bool transported,
1809 enum unit_loss_reason reason)
1810{
1811 struct packet_unit_remove packet;
1812 struct tile *ptile = unit_tile(punit);
1813 struct city *pcity = tile_city(ptile);
1814 struct city *phomecity = game_city_by_number(punit->homecity);
1815 struct unit *ptrans;
1816 struct player *pplayer = unit_owner(punit);
1817
1818 /* The unit is doomed. */
1820
1821#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1822 unit_list_iterate(ptile->units, pcargo) {
1825#endif /* FREECIV_DEBUG */
1826
1827 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1828 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1829
1830 /* Save transporter for updating below. */
1831 ptrans = unit_transport_get(punit);
1832 /* Unload unit. */
1834
1835 /* Since settlers plot in new cities in the minimap before they
1836 are built, so that no two settlers head towards the same city
1837 spot, we need to ensure this reservation is cleared should
1838 the settler disappear on the way. */
1840
1841 /* Clear the vision before sending unit remove. Else, we might duplicate
1842 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1843 if (punit->server.vision != NULL) {
1846 punit->server.vision = NULL;
1847 }
1848
1849 packet.unit_id32 = punit->id;
1850 packet.unit_id16 = packet.unit_id32;
1851 /* Send to onlookers. */
1852 players_iterate(aplayer) {
1854 transported)) {
1855 lsend_packet_unit_remove(aplayer->connections, &packet);
1856 }
1858 /* Send to global observers. */
1860 if (conn_is_global_observer(pconn)) {
1861 send_packet_unit_remove(pconn, &packet);
1862 }
1864
1865 if (punit->server.moving != NULL) {
1866 /* Do not care of this unit for running moves. */
1867 punit->server.moving->punit = NULL;
1868 }
1869
1870 if (punit->server.removal_callback != NULL) {
1871 /* Run the unit removal call back. */
1873 }
1874
1875 /* check if this unit had UTYF_GAMELOSS flag */
1876 if (unit_has_type_flag(punit, UTYF_GAMELOSS) && unit_owner(punit)->is_alive
1877 && ULR_EDITOR != reason) {
1878 notify_conn(game.est_connections, ptile, E_UNIT_LOST_MISC, ftc_server,
1879 _("Unable to defend %s, %s has lost the game."),
1881 player_name(pplayer));
1882 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1883 _("Losing %s meant losing the game! "
1884 "Be more careful next time!"),
1885 unit_link(punit));
1886 player_status_add(unit_owner(punit), PSTATUS_DYING);
1887 }
1888
1889 /* Have to pass new ULR_UPKEEP as ULR_DISBAND for compatibility reasons.
1890 * Changes in freeciv-3.2 */
1892 unit_loss_reason_name((reason == ULR_UPKEEP)
1893 ? ULR_DISBANDED
1894 : reason));
1895
1898 punit = NULL;
1899
1900 if (NULL != ptrans) {
1901 /* Update the occupy info. */
1902 send_unit_info(NULL, ptrans);
1903 }
1904
1905 /* This unit may have blocked tiles of adjacent cities. Update them. */
1907 sync_cities();
1908
1909 if (phomecity) {
1910 city_refresh(phomecity);
1911 send_city_info(city_owner(phomecity), phomecity);
1912 }
1913
1914 if (pcity && pcity != phomecity) {
1915 city_refresh(pcity);
1916 send_city_info(city_owner(pcity), pcity);
1917 }
1918
1919 if (pcity && unit_list_size(ptile->units) == 0) {
1920 /* The last unit in the city was killed: update the occupied flag. */
1921 send_city_info(NULL, pcity);
1922 }
1923}
1924
1925/**********************************************************************/
1929static void server_remove_unit(struct unit *punit,
1930 enum unit_loss_reason reason)
1931{
1933}
1934
1935/**********************************************************************/
1938static void unit_lost_with_transport(const struct player *pplayer,
1939 struct unit *pcargo,
1940 const struct unit_type *ptransport,
1941 struct player *killer)
1942{
1943 notify_player(pplayer, unit_tile(pcargo), E_UNIT_LOST_MISC, ftc_server,
1944 _("%s lost when %s was lost."),
1945 unit_tile_link(pcargo),
1946 utype_name_translation(ptransport));
1947 /* Unit is not transported any more at this point, but it has jumped
1948 * off the transport and drowns outside. So it must be removed from
1949 * all clients.
1950 * However, we don't know if given client has received ANY updates
1951 * about the swimming unit, and we can't remove it if it's not there
1952 * in the first place -> we send it once here just to be sure it's
1953 * there. */
1954 send_unit_info(NULL, pcargo);
1955 wipe_unit_full(pcargo, FALSE, ULR_TRANSPORT_LOST, killer);
1956}
1957
1958/**********************************************************************/
1962static void wipe_unit_full(struct unit *punit, bool transported,
1963 enum unit_loss_reason reason,
1964 struct player *killer)
1965{
1966 struct tile *ptile = unit_tile(punit);
1967 struct player *pplayer = unit_owner(punit);
1968 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1969 struct unit_list *helpless = unit_list_new();
1970 struct unit_list *imperiled = unit_list_new();
1971 struct unit_list *unsaved = unit_list_new();
1972 struct unit *ptrans = unit_transport_get(punit);
1973 struct city *pexclcity;
1974 struct civ_map *nmap = &(wld.map);
1975
1976 if (killer != NULL
1977 && (game.info.gameloss_style & GAMELOSS_STYLE_LOOT)
1978 && unit_has_type_flag(punit, UTYF_GAMELOSS)) {
1979 int ransom = fc_rand(1 + pplayer->economic.gold);
1980 int n;
1981
1982 /* Give map */
1983 if (give_distorted_map(pplayer, killer, 50, TRUE)) {
1984 notify_player(killer, NULL, E_HUT_MAP,
1985 ftc_server,
1986 _("You looted parts of %s map!"),
1988 }
1989
1990 log_debug("victim has money: %d", pplayer->economic.gold);
1991
1992 if (ransom > 0) {
1993 notify_player(killer, NULL, E_HUT_GOLD,
1994 ftc_server,
1995 PL_("You loot %d gold!", "You loot %d gold!", ransom),
1996 ransom);
1997 }
1998 killer->economic.gold += ransom;
1999 pplayer->economic.gold -= ransom;
2000
2001 n = 1 + fc_rand(3);
2002
2003 while (n > 0) {
2004 Tech_type_id ttid;
2005
2006 /* steal_a_tech() handles also notifying of the player */
2007 ttid = steal_a_tech(killer, pplayer, A_UNSET);
2008
2009 if (ttid == A_NONE) {
2010 log_debug("Worthless enemy doesn't have more techs to steal.");
2011 break;
2012 } else {
2013 log_debug("Pressed tech %s from captured enemy",
2015 if (!fc_rand(3)) {
2016 break; /* Out of luck */
2017 }
2018 n--;
2019 }
2020 }
2021
2022 {
2023 /* Try to submit some cities */
2024 int vcsize = city_list_size(pplayer->cities);
2025 int evcsize = vcsize;
2026 int conqsize;
2027
2028 if (evcsize < 3) {
2029 evcsize = 0;
2030 } else {
2031 evcsize -=3;
2032 }
2033
2034 /* About a quarter on average with high numbers less probable */
2035 conqsize = fc_rand(fc_rand(evcsize));
2036
2037 log_debug("conqsize=%d", conqsize);
2038
2039 if (conqsize > 0) {
2040 bool palace = game.server.savepalace;
2041 bool submit = FALSE;
2042
2043 game.server.savepalace = FALSE; /* Moving it around is dumb */
2044
2045 city_list_iterate_safe(pplayer->cities, pcity) {
2046 /* Kindly ask the citizens to submit */
2047 if (fc_rand(vcsize) < conqsize) {
2048 submit = TRUE;
2049 }
2050 vcsize--;
2051 if (submit) {
2052 conqsize--;
2053 /* Transfer city to the victorious player
2054 * kill all its units outside of a radius of 7,
2055 * give verbose messages of every unit transferred,
2056 * and raze buildings according to raze chance
2057 * (also removes palace) */
2058 notify_player(killer, city_tile(pcity), E_UNIT_WIN_ATT,
2059 ftc_server,
2060 /* TRANS: Getting a city as loot */
2061 _("You conquer %s as loot!"),
2062 city_link(pcity));
2063
2064 (void) transfer_city(killer, pcity, 7, TRUE, TRUE, TRUE,
2065 !is_barbarian(killer));
2066 submit = FALSE;
2067 }
2068 if (conqsize <= 0) {
2069 break;
2070 }
2072 game.server.savepalace = palace;
2073 }
2074 }
2075 }
2076
2077 /* The unit is doomed. */
2079
2080 /* If a unit is being lost due to loss of its city, ensure that we don't
2081 * try to teleport any of its cargo to that city (which may not yet
2082 * have changed hands or disappeared). (It is assumed that the unit's
2083 * home city is always the one that is being lost/transferred/etc.) */
2084 if (reason == ULR_CITY_LOST) {
2085 pexclcity = unit_home(punit);
2086 } else {
2087 pexclcity = NULL;
2088 }
2089
2090 /* Remove unit itself from its transport */
2091 if (ptrans != NULL) {
2093 send_unit_info(NULL, ptrans);
2094 }
2095
2096 /* First pull all units off of the transporter. */
2098 /* Use iterate_safe as unloaded units will be removed from the list
2099 * while iterating. */
2101 bool healthy = FALSE;
2102
2103 if (!can_unit_unload(pcargo, punit)) {
2104 unit_list_prepend(helpless, pcargo);
2105 } else {
2106 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
2107 unit_list_prepend(imperiled, pcargo);
2108 } else {
2109 /* These units do not need to be saved. */
2110 healthy = TRUE;
2111 }
2112 }
2113
2114 /* Could use unit_transport_unload_send() here, but that would
2115 * call send_unit_info() for the transporter unnecessarily.
2116 * Note that this means that unit might to get seen briefly
2117 * by clients other than owner's, for example as a result of
2118 * update of homecity common to this cargo and some other
2119 * destroyed unit. */
2120 unit_transport_unload(pcargo);
2121 if (pcargo->activity == ACTIVITY_SENTRY) {
2122 /* Activate sentried units - like planes on a disbanded carrier.
2123 * Note this will activate ground units even if they just change
2124 * transporter. */
2125 set_unit_activity(pcargo, ACTIVITY_IDLE);
2126 }
2127
2128 /* Unit info for unhealthy units will be sent when they are
2129 * assigned new transport or removed. */
2130 if (healthy) {
2131 send_unit_info(NULL, pcargo);
2132 }
2134 }
2135
2136 /* Now remove the unit. */
2137 server_remove_unit_full(punit, transported, reason);
2138
2139 switch (reason) {
2140 case ULR_KILLED:
2141 case ULR_EXECUTED:
2142 case ULR_SDI:
2143 case ULR_NUKE:
2144 case ULR_BRIBED:
2145 case ULR_CAPTURED:
2146 case ULR_CAUGHT:
2147 case ULR_ELIMINATED:
2148 case ULR_TRANSPORT_LOST:
2149 if (killer != NULL) {
2150 killer->score.units_killed++;
2151 }
2152 pplayer->score.units_lost++;
2153 break;
2154 case ULR_BARB_UNLEASH:
2155 case ULR_CITY_LOST:
2156 case ULR_STARVED:
2157 case ULR_UPKEEP:
2158 case ULR_NONNATIVE_TERR:
2159 case ULR_ARMISTICE:
2160 case ULR_HP_LOSS:
2161 case ULR_FUEL:
2162 case ULR_STACK_CONFLICT:
2163 case ULR_SOLD:
2164 pplayer->score.units_lost++;
2165 break;
2166 case ULR_RETIRED:
2167 case ULR_DISBANDED:
2168 case ULR_USED:
2169 case ULR_EDITOR:
2170 case ULR_PLAYER_DIED:
2171 case ULR_DETONATED:
2172 case ULR_MISSILE:
2173 break;
2174 }
2175
2176 /* First, sort out helpless cargo. */
2177 if (unit_list_size(helpless) > 0) {
2178 struct unit_list *remaining = unit_list_new();
2179
2180 /* Grant priority to gameloss units and units with the EvacuateFirst
2181 * unit type flag. */
2182 unit_list_iterate_safe(helpless, pcargo) {
2183 if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
2184 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
2185 if (!try_to_save_unit(pcargo, putype_save, TRUE,
2186 unit_has_type_flag(pcargo,
2187 UTYF_EVAC_FIRST),
2188 pexclcity)) {
2189 unit_list_prepend(unsaved, pcargo);
2190 }
2191 } else {
2192 unit_list_prepend(remaining, pcargo);
2193 }
2195
2196 /* Handle non-priority units. */
2197 unit_list_iterate_safe(remaining, pcargo) {
2198 if (!try_to_save_unit(pcargo, putype_save, TRUE, FALSE, pexclcity)) {
2199 unit_list_prepend(unsaved, pcargo);
2200 }
2202
2203 unit_list_destroy(remaining);
2204 }
2205 unit_list_destroy(helpless);
2206
2207 /* Then, save any imperiled cargo. */
2208 if (unit_list_size(imperiled) > 0) {
2209 struct unit_list *remaining = unit_list_new();
2210
2211 /* Grant priority to gameloss units and units with the EvacuateFirst
2212 * unit type flag. */
2213 unit_list_iterate_safe(imperiled, pcargo) {
2214 if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
2215 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
2216 if (!try_to_save_unit(pcargo, putype_save, FALSE,
2217 unit_has_type_flag(pcargo,
2218 UTYF_EVAC_FIRST),
2219 pexclcity)) {
2220 unit_list_prepend(unsaved, pcargo);
2221 }
2222 } else {
2223 unit_list_prepend(remaining, pcargo);
2224 }
2226
2227 /* Handle non-priority units. */
2228 unit_list_iterate_safe(remaining, pcargo) {
2229 if (!try_to_save_unit(pcargo, putype_save, FALSE, FALSE, pexclcity)) {
2230 unit_list_prepend(unsaved, pcargo);
2231 }
2233
2234 unit_list_destroy(remaining);
2235 }
2236 unit_list_destroy(imperiled);
2237
2238 /* Finally, kill off the unsaved units. */
2239 if (unit_list_size(unsaved) > 0) {
2240 unit_list_iterate_safe(unsaved, dying_unit) {
2241 unit_lost_with_transport(pplayer, dying_unit, putype_save, killer);
2243 }
2244 unit_list_destroy(unsaved);
2245}
2246
2247/**********************************************************************/
2251void wipe_unit(struct unit *punit, enum unit_loss_reason reason,
2252 struct player *killer)
2253{
2254 wipe_unit_full(punit, unit_transported(punit), reason, killer);
2255}
2256
2257/**********************************************************************/
2263static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2264 bool helpless, bool teleporting,
2265 const struct city *pexclcity)
2266{
2267 struct tile *ptile = unit_tile(punit);
2268 struct player *pplayer = unit_owner(punit);
2269 struct unit *ptransport = transporter_for_unit(punit);
2270
2271 /* Helpless units cannot board a transport in their current state. */
2272 if (!helpless
2273 && ptransport != NULL) {
2275 send_unit_info(NULL, punit);
2276 return TRUE;
2277 } else {
2278 /* Only units that cannot find transport are considered for teleport. */
2279 if (teleporting) {
2280 struct city *pcity = find_closest_city(ptile, pexclcity,
2283 utype_class(pttype));
2284 if (pcity != NULL) {
2285 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2286
2287 sz_strlcpy(tplink, unit_link(punit));
2288
2289 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2290 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2291 _("%s escaped the destruction of %s, and fled to %s."),
2292 tplink,
2293 utype_name_translation(pttype),
2294 city_link(pcity));
2295 return TRUE;
2296 }
2297 }
2298 }
2299 }
2300
2301 /* The unit could not use transport on the tile, and could not teleport. */
2302 return FALSE;
2303}
2304
2305/**********************************************************************/
2311struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2312 int homecity, enum unit_loss_reason reason)
2313{
2314 struct unit *gained_unit;
2315 int id = 0;
2316
2317#ifndef FREECIV_NDEBUG
2318 bool placed;
2319#endif
2320
2323
2324 /* Convert the unit to your cause. It's supposed that the original unit
2325 * is on a valid tile and is not transported. */
2326 gained_unit = unit_virtual_prepare(pplayer, unit_tile(punit),
2329 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2330
2331 /* Owner changes, nationality not. */
2332 gained_unit->nationality = punit->nationality;
2333
2334 /* Copy some more unit fields */
2335 gained_unit->fuel = punit->fuel;
2336 gained_unit->paradropped = punit->paradropped;
2337 gained_unit->server.birth_turn = punit->server.birth_turn;
2338
2339 /* Fog is lifted in the placing algorithm. */
2340#ifndef FREECIV_NDEBUG
2341 placed =
2342#endif
2343 place_unit(gained_unit, pplayer,
2345 NULL, FALSE);
2346
2347 fc_assert_action(placed, unit_virtual_destroy(gained_unit); goto uco_wipe);
2348
2349 id = gained_unit->id;
2350
2351 /* Update unit upkeep in the new homecity */
2352 if (homecity > 0) {
2354 }
2355
2356 /* Be sure to wipe the converted unit! */
2357 /* Old homecity upkeep is updated in process */
2358#ifndef FREECIV_NDEBUG
2359 uco_wipe:
2360#endif
2361
2362 wipe_unit(punit, reason, NULL);
2363
2364 if (!unit_is_alive(id)) {
2365 /* Destroyed by a script */
2366 return NULL;
2367 }
2368
2369 return gained_unit; /* Returns the replacement. */
2370}
2371
2372/**********************************************************************/
2377void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2378{
2379 char pkiller_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK];
2380 struct player *pvictim = unit_owner(punit);
2381 struct player *pvictor = unit_owner(pkiller);
2382 struct tile *deftile = unit_tile(punit);
2383 int ransom, unitcount = 0;
2384 bool escaped;
2385 bool collect_ransom = FALSE;
2386 const struct civ_map *nmap = &(wld.map);
2387
2388 sz_strlcpy(pkiller_link, unit_link(pkiller));
2389 sz_strlcpy(punit_link, unit_tile_link(punit));
2390
2391 /* The unit is doomed. */
2393
2394 /* barbarian leader ransom hack */
2395 if (is_barbarian(pvictim)
2396 && uclass_has_flag(unit_class_get(pkiller), UCF_COLLECT_RANSOM)) {
2397 collect_ransom = TRUE;
2398
2399 unit_list_iterate(deftile->units, capture) {
2400 if (!unit_has_type_role(capture, L_BARBARIAN_LEADER)) {
2401 /* Cannot get ransom when there are other kind of units in the tile */
2402 collect_ransom = FALSE;
2403 break;
2404 }
2406
2407 if (collect_ransom) {
2408 unitcount = unit_list_size(deftile->units);
2409 ransom = unitcount * game.server.ransom_gold;
2410
2411 if (pvictim->economic.gold < ransom) {
2412 ransom = pvictim->economic.gold;
2413 }
2414
2415 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2416 PL_("%d Barbarian leader captured.",
2417 "%d Barbarian leaders captured.",
2418 unitcount),
2419 unitcount);
2420 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2421 PL_("%d gold ransom paid.",
2422 "%d gold ransom paid.",
2423 ransom),
2424 ransom);
2425 pvictor->economic.gold += ransom;
2426 pvictim->economic.gold -= ransom;
2427 send_player_info_c(pvictor, NULL); /* let me see my new gold :-) */
2428 }
2429 }
2430
2431 if (unitcount == 0) {
2432 unit_list_iterate(deftile->units, vunit) {
2433 if (pplayers_at_war(pvictor, unit_owner(vunit))
2434 && is_unit_reachable_at(vunit, pkiller, deftile)) {
2435 unitcount++;
2436 }
2438 }
2439
2440 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2441 if (vet) {
2442 notify_unit_experience(pkiller);
2443 }
2444 wipe_unit(punit, ULR_KILLED, pvictor);
2445 } else { /* unitcount > 1 */
2446 int i;
2447 int slots = player_slot_count();
2448 int num_killed[slots];
2449 int num_escaped[slots];
2450 struct unit *other_killed[slots];
2451
2452 fc_assert(unitcount > 1);
2453
2454 /* initialize */
2455 for (i = 0; i < slots; i++) {
2456 num_killed[i] = 0;
2457 other_killed[i] = NULL;
2458 num_escaped[i] = 0;
2459 }
2460
2461 /* count killed units */
2462 unit_list_iterate_safe(deftile->units, vunit) {
2463 struct player *vplayer = unit_owner(vunit);
2464
2465 if (pplayers_at_war(pvictor, vplayer)
2466 && is_unit_reachable_at(vunit, pkiller, deftile)) {
2467 escaped = FALSE;
2468
2469 if (unit_has_type_flag(vunit, UTYF_CANESCAPE)
2470 && !unit_has_type_flag(pkiller, UTYF_CANKILLESCAPING)
2471 && vunit->hp > 0
2472 && vunit->moves_left > pkiller->moves_left
2473 && fc_rand(2)) {
2474 int curr_def_bonus;
2475 int def_bonus = 0;
2476 struct tile *dsttile = NULL;
2477 int move_cost;
2478
2479 fc_assert(vunit->hp > 0);
2480
2481 adjc_iterate(nmap, deftile, ptile2) {
2482 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2483 && NULL == tile_city(ptile2)) {
2484 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2485 if (pkiller->moves_left <= vunit->moves_left - move_cost
2486 && (is_allied_unit_tile(ptile2, pvictim)
2487 || unit_list_size(ptile2->units)) == 0) {
2488 curr_def_bonus = tile_extras_defense_bonus(ptile2,
2489 vunit->utype);
2490 if (def_bonus <= curr_def_bonus) {
2491 def_bonus = curr_def_bonus;
2492 dsttile = ptile2;
2493 }
2494 }
2495 }
2497
2498 if (dsttile != NULL) {
2499 escaped = (action_auto_perf_unit_do(AAPC_UNIT_STACK_DEATH,
2500 vunit, tile_owner(dsttile),
2501 NULL, NULL, dsttile,
2502 tile_city(dsttile),
2503 NULL, NULL)
2504 != NULL);
2505
2506 if (escaped) {
2507 num_escaped[player_index(vplayer)]++;
2508 unitcount--;
2509 }
2510 }
2511 }
2512
2513 if (!escaped) {
2514 num_killed[player_index(vplayer)]++;
2515
2516 if (vunit != punit) {
2517 other_killed[player_index(vplayer)] = vunit;
2518 other_killed[player_index(pvictor)] = vunit;
2519 }
2520 }
2521 }
2523
2524 /* Inform the destroyer again if more than one unit was killed */
2525 if (unitcount > 1 && !collect_ransom) {
2526 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2527 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2528 PL_("Your attacking %s succeeded against the %s %s "
2529 "(and %d other unit)!",
2530 "Your attacking %s succeeded against the %s %s "
2531 "(and %d other units)!", unitcount - 1),
2532 pkiller_link,
2534 punit_link,
2535 unitcount - 1);
2536 }
2537
2538 if (vet) {
2539 notify_unit_experience(pkiller);
2540 }
2541
2542 /* inform the owners: this only tells about owned units that were killed.
2543 * there may have been 20 units who died but if only 2 belonged to the
2544 * particular player they'll only learn about those.
2545 *
2546 * Also if a large number of units die you don't find out what type
2547 * they all are. */
2548 for (i = 0; i < slots; i++) {
2549 if (num_killed[i] == 1) {
2550 if (i == player_index(pvictim)) {
2551 fc_assert(other_killed[i] == NULL);
2552 notify_player(player_by_number(i), deftile,
2553 E_UNIT_LOST_DEF, ftc_server,
2554 /* TRANS: "Cannon ... the Polish Destroyer." */
2555 _("%s lost to an attack by the %s %s."),
2556 punit_link,
2558 pkiller_link);
2559 } else {
2560 fc_assert(other_killed[i] != punit);
2561 notify_player(player_by_number(i), deftile,
2562 E_UNIT_LOST_DEF, ftc_server,
2563 /* TRANS: "Cannon lost when the Polish Destroyer
2564 * attacked the German Musketeers." */
2565 _("%s lost when the %s %s attacked the %s %s."),
2566 unit_link(other_killed[i]),
2568 pkiller_link,
2570 punit_link);
2571 }
2572 } else if (num_killed[i] > 1) {
2573 if (i == player_index(pvictim)) {
2574 int others = num_killed[i] - 1;
2575
2576 if (others == 1) {
2577 notify_player(player_by_number(i), deftile,
2578 E_UNIT_LOST_DEF, ftc_server,
2579 /* TRANS: "Musketeers (and Cannon) lost to an
2580 * attack from the Polish Destroyer." */
2581 _("%s (and %s) lost to an attack from the %s %s."),
2582 punit_link,
2583 unit_link(other_killed[i]),
2585 pkiller_link);
2586 } else {
2587 notify_player(player_by_number(i), deftile,
2588 E_UNIT_LOST_DEF, ftc_server,
2589 /* TRANS: "Musketeers and 3 other units lost to
2590 * an attack from the Polish Destroyer."
2591 * (only happens with at least 2 other units) */
2592 PL_("%s and %d other unit lost to an attack "
2593 "from the %s %s.",
2594 "%s and %d other units lost to an attack "
2595 "from the %s %s.", others),
2596 punit_link,
2597 others,
2599 pkiller_link);
2600 }
2601 } else {
2602 notify_player(player_by_number(i), deftile,
2603 E_UNIT_LOST_DEF, ftc_server,
2604 /* TRANS: "2 units lost when the Polish Destroyer
2605 * attacked the German Musketeers."
2606 * (only happens with at least 2 other units) */
2607 PL_("%d unit lost when the %s %s attacked the %s %s.",
2608 "%d units lost when the %s %s attacked the %s %s.",
2609 num_killed[i]),
2610 num_killed[i],
2612 pkiller_link,
2614 punit_link);
2615 }
2616 }
2617 }
2618
2619 /* Inform the owner of the units that escaped.
2620 * 'deftile' is the original tile they defended at, not where
2621 * they escaped to, as there might be multiple different tiles
2622 * different units escaped to. */
2623 for (i = 0; i < slots; i++) {
2624 if (0 < num_escaped[i]) {
2625 notify_player(player_by_number(i), deftile,
2626 E_UNIT_ESCAPED, ftc_server,
2627 PL_("%d unit escaped from attack by %s %s",
2628 "%d units escaped from attack by %s %s",
2629 num_escaped[i]),
2630 num_escaped[i],
2631 pkiller_link,
2633 );
2634 }
2635 }
2636
2637 /* remove the units - note the logic of which units actually die
2638 * must be mimiced exactly in at least one place up above. */
2639 punit = NULL; /* wiped during following iteration so unsafe to use */
2640
2641 unit_list_iterate_safe(deftile->units, punit2) {
2642 if (pplayers_at_war(pvictor, unit_owner(punit2))
2643 && is_unit_reachable_at(punit2, pkiller, deftile)) {
2644 wipe_unit(punit2, ULR_KILLED, pvictor);
2645 }
2647 }
2648}
2649
2650/**********************************************************************/
2654void package_unit(struct unit *punit, struct packet_unit_info *packet)
2655{
2656 packet->id32 = punit->id;
2657 packet->id16 = packet->id32;
2658 packet->owner = player_number(unit_owner(punit));
2660 packet->tile = tile_index(unit_tile(punit));
2661 packet->facing = punit->facing;
2662 packet->homecity32 = punit->homecity;
2663 packet->homecity16 = packet->homecity32;
2665 packet->upkeep[o] = punit->upkeep[o];
2667 packet->veteran = punit->veteran;
2669 packet->movesleft = punit->moves_left;
2670 packet->hp = punit->hp;
2671 packet->activity = punit->activity;
2673
2674 if (punit->activity_target != NULL) {
2676 } else {
2677 packet->activity_tgt = EXTRA_NONE;
2678 }
2679
2680 packet->changed_from = punit->changed_from;
2682
2683 if (punit->changed_from_target != NULL) {
2685 } else {
2686 packet->changed_from_tgt = EXTRA_NONE;
2687 }
2688
2690 packet->fuel = punit->fuel;
2691 packet->goto_tile = (NULL != punit->goto_tile
2692 ? tile_index(punit->goto_tile) : -1);
2693 packet->paradropped = punit->paradropped;
2694 packet->done_moving = punit->done_moving;
2695 packet->stay = punit->stay;
2696 if (!unit_transported(punit)) {
2697 packet->transported = FALSE;
2698 packet->transported_by32 = 0;
2699 packet->transported_by16 = 0;
2700 } else {
2701 packet->transported = TRUE;
2703 packet->transported_by16 = packet->transported_by32;
2704 }
2705 if (punit->carrying != NULL) {
2706 packet->carrying = goods_index(punit->carrying);
2707 } else {
2708 packet->carrying = -1;
2709 }
2710 packet->occupied = (get_transporter_occupancy(punit) > 0);
2711 packet->battlegroup = punit->battlegroup;
2712 packet->has_orders = punit->has_orders;
2713 if (punit->has_orders) {
2714 packet->orders_length = punit->orders.length;
2715 packet->orders_index = punit->orders.index;
2716 packet->orders_repeat = punit->orders.repeat;
2718 memcpy(packet->orders, punit->orders.list,
2719 punit->orders.length * sizeof(struct unit_order));
2720 } else {
2721 packet->orders_length = packet->orders_index = 0;
2722 packet->orders_repeat = packet->orders_vigilant = FALSE;
2723 /* No need to initialize array. */
2724 }
2725
2730}
2731
2732/**********************************************************************/
2738 struct packet_unit_short_info *packet,
2739 enum unit_info_use packet_use, int info_city_id)
2740{
2741 packet->packet_use = packet_use;
2742 packet->info_city_id32 = info_city_id;
2743 packet->info_city_id16 = packet->info_city_id32;
2744
2745 packet->id32 = punit->id;
2746 packet->id16 = packet->id32;
2747 packet->owner = player_number(unit_owner(punit));
2748 packet->tile = tile_index(unit_tile(punit));
2749 packet->facing = punit->facing;
2750 packet->veteran = punit->veteran;
2752 packet->hp = punit->hp;
2753 packet->occupied = (get_transporter_occupancy(punit) > 0);
2754 if (punit->activity == ACTIVITY_EXPLORE
2755 || punit->activity == ACTIVITY_GOTO) {
2756 packet->activity = ACTIVITY_IDLE;
2757 } else {
2758 packet->activity = punit->activity;
2759 }
2760
2761 if (punit->activity_target == NULL) {
2762 packet->activity_tgt = EXTRA_NONE;
2763 } else {
2765 }
2766
2767 /* Transported_by information is sent to the client even for units that
2768 * aren't fully known. Note that for non-allied players, any transported
2769 * unit can't be seen at all. For allied players we have to know if
2770 * transporters have room in them so that we can load units properly. */
2771 if (!unit_transported(punit)) {
2772 packet->transported = FALSE;
2773 packet->transported_by32 = 0;
2774 packet->transported_by16 = 0;
2775 } else {
2776 packet->transported = TRUE;
2778 packet->transported_by16 = packet->transported_by32;
2779 }
2780}
2781
2782/**********************************************************************/
2785void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2786{
2788 if (punit->server.moving != NULL) {
2789 /* Update status of 'pplayer' vision for 'punit'. */
2791 }
2792}
2793
2794/**********************************************************************/
2798void send_unit_info(struct conn_list *dest, struct unit *punit)
2799{
2800 const struct player *powner;
2801 struct packet_unit_info info;
2802 struct packet_unit_short_info sinfo;
2803 struct unit_move_data *pdata;
2804
2805 if (dest == NULL) {
2806 dest = game.est_connections;
2807 }
2808
2810
2812 package_unit(punit, &info);
2814 pdata = punit->server.moving;
2815
2816 conn_list_iterate(dest, pconn) {
2817 struct player *pplayer = conn_get_player(pconn);
2818
2819 /* Be careful to consider all cases where pplayer is NULL... */
2820 if (pplayer == NULL) {
2821 if (pconn->observer) {
2822 send_packet_unit_info(pconn, &info);
2823 }
2824 } else if (pplayer == powner) {
2825 send_packet_unit_info(pconn, &info);
2826 if (pdata != NULL) {
2827 BV_SET(pdata->can_see_unit, player_index(pplayer));
2828 }
2829 } else if (can_player_see_unit(pplayer, punit)) {
2830 send_packet_unit_short_info(pconn, &sinfo, FALSE);
2831 if (pdata != NULL) {
2832 BV_SET(pdata->can_see_unit, player_index(pplayer));
2833 }
2834 }
2836}
2837
2838/**********************************************************************/
2842void send_all_known_units(struct conn_list *dest)
2843{
2844 conn_list_do_buffer(dest);
2845 conn_list_iterate(dest, pconn) {
2846 struct player *pplayer = pconn->playing;
2847
2848 if (NULL == pplayer && !pconn->observer) {
2849 continue;
2850 }
2851
2852 players_iterate(unitowner) {
2853 unit_list_iterate(unitowner->units, punit) {
2854 send_unit_info(dest, punit);
2857 }
2860 flush_packets();
2861}
2862
2863/**********************************************************************/
2870static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
2871{
2872 struct city *pcity = NULL;
2873 int pop_loss;
2874
2875 pcity = tile_city(ptile);
2876
2878
2879 /* unit in a city may survive */
2880 if (pcity && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2881 continue;
2882 }
2883 notify_player(unit_owner(punit), ptile, E_UNIT_LOST_MISC, ftc_server,
2884 _("Your %s was nuked by %s."),
2886 pplayer == unit_owner(punit)
2887 ? _("yourself")
2888 : nation_plural_for_player(pplayer));
2889 if (unit_owner(punit) != pplayer) {
2890 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2891 _("The %s %s was nuked."),
2894 }
2895 wipe_unit(punit, ULR_NUKE, pplayer);
2897
2898
2899 if (pcity) {
2900 struct player *owner = city_owner(pcity);
2901 char city_name[MAX_LEN_LINK];
2902
2903 sz_strlcpy(city_name, city_link(pcity));
2904
2905 notify_player(owner, ptile, E_CITY_NUKED, ftc_server,
2906 _("%s was nuked by %s."),
2907 city_name,
2908 pplayer == owner
2909 ? _("yourself")
2910 : nation_plural_for_player(pplayer));
2911
2912 if (owner != pplayer) {
2913 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2914 _("You nuked %s."),
2915 city_name);
2916 }
2917
2918 pop_loss = round((game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100.0);
2919 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
2920 /* Send city size reduction to everyone seeing it */
2921 send_city_info(NULL, pcity);
2922 } else {
2923 /* City was destroyed */
2924 notify_player(owner, ptile, E_CITY_NUKED, ftc_server,
2925 _("%s was destroyed by the nuke."),
2926 city_name);
2927 if (owner != pplayer) {
2928 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2929 _("Your nuke destroyed %s."),
2930 city_name);
2931 }
2932 }
2933 }
2934
2935 if (fc_rand(2) == 1) {
2936 struct extra_type *pextra;
2937
2938 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
2939 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2940 tile_add_extra(ptile, pextra);
2941 update_tile_knowledge(ptile);
2942 }
2943 }
2944}
2945
2946/**********************************************************************/
2950void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
2951{
2952 square_iterate(&(wld.map), ptile, 1, ptile1) {
2953 do_nuke_tile(pplayer, ptile1);
2955
2956 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
2957 API_TYPE_PLAYER, pplayer);
2958 notify_conn(NULL, ptile, E_NUKE, ftc_server,
2959 _("The %s detonated a nuke!"),
2960 nation_plural_for_player(pplayer));
2961}
2962
2963/**********************************************************************/
2967bool do_airline(struct unit *punit, struct city *pdest_city,
2968 const struct action *paction)
2969{
2970 struct city *psrc_city = tile_city(unit_tile(punit));
2971
2973 E_UNIT_RELOCATED, ftc_server,
2974 _("%s transported successfully."),
2975 unit_link(punit));
2976
2977 unit_move(punit, pdest_city->tile, punit->moves_left,
2978 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
2979 /* Can only airlift to allied and domestic cities */
2980 FALSE, FALSE,
2981 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
2982 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
2983
2984 /* Update airlift fields. */
2985 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
2986 psrc_city->airlift--;
2987 send_city_info(city_owner(psrc_city), psrc_city);
2988 }
2989 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
2990 pdest_city->airlift--;
2991 send_city_info(city_owner(pdest_city), pdest_city);
2992 }
2993
2994 return TRUE;
2995}
2996
2997/**********************************************************************/
3000void do_explore(struct unit *punit)
3001{
3002 switch (manage_auto_explorer(punit)) {
3003 case MR_DEATH:
3004 /* don't use punit! */
3005 return;
3006 case MR_NOT_ALLOWED:
3007 /* Needed for something else */
3008 return;
3009 case MR_OK:
3010 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3011 * but don't count on this. See PR#39792.
3012 */
3013 if (punit->activity == ACTIVITY_EXPLORE) {
3014 break;
3015 }
3016
3018 default:
3019 unit_activity_handling(punit, ACTIVITY_IDLE);
3020
3021 /* FIXME: When the manage_auto_explorer() call changes the activity from
3022 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3023 * alone. We reset it here. See PR#12931. */
3024 punit->ssa_controller = SSA_NONE;
3025 break;
3026 }
3027
3028 send_unit_info(NULL, punit); /* probably duplicate */
3029}
3030
3031/**********************************************************************/
3036bool do_paradrop(struct unit *punit, struct tile *ptile,
3037 const struct action *paction)
3038{
3039 struct player *pplayer = unit_owner(punit);
3040 struct player *tgt_player = tile_owner(ptile);
3041 const struct unit_type *act_utype = unit_type_get(punit);
3042 const struct city *pcity;
3043
3044 /* Hard requirements */
3045 /* FIXME: hard requirements belong in common/actions's
3046 * is_action_possible() and the explanation texts belong in
3047 * server/unithand's action not enabled system (expl_act_not_enabl(),
3048 * ane_kind, explain_why_no_action_enabled(), etc)
3049 */
3050 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3051 /* Only take in account values from player map. */
3052 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3053
3054 if (NULL == plrtile->site
3056 &(plrtile->extras))) {
3057 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3058 _("This unit cannot paradrop into %s."),
3060 return FALSE;
3061 }
3062
3063 if (NULL != plrtile->site
3064 && plrtile->owner != NULL
3065 && !pplayers_allied(pplayer, plrtile->owner)
3066 && !action_has_result(paction, ACTRES_PARADROP_CONQUER)) {
3067 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3068 /* TRANS: Paratroopers ... Paradrop Unit */
3069 _("%s cannot conquer a city with \"%s\"."),
3071 action_name_translation(paction));
3072 return FALSE;
3073 }
3074
3075 if (NULL != plrtile->site
3076 && plrtile->owner != NULL
3077 && (pplayers_non_attack(pplayer, plrtile->owner)
3078 || (player_diplstate_get(pplayer, plrtile->owner)->type
3079 == DS_ALLIANCE)
3080 || (player_diplstate_get(pplayer, plrtile->owner)->type
3081 == DS_TEAM))
3082 && action_has_result(paction, ACTRES_PARADROP_CONQUER)) {
3083 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3084 _("Cannot attack unless you declare war first."));
3085 return FALSE;
3086 }
3087 }
3088
3089
3090 /* Kill the unit when the landing goes wrong. */
3091
3092 /* Safe terrain, really? Not transformed since player last saw it. */
3093 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3094 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3095 || !unit_could_load_at(punit, ptile))) {
3096 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3097 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3098 _("Your %s paradropped into the %s and was lost."),
3101 pplayer->score.units_lost++;
3102 server_remove_unit(punit, ULR_NONNATIVE_TERR);
3103 return TRUE;
3104 }
3105
3106 pcity = tile_city(ptile);
3107
3108 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3109 && !action_has_result(paction, ACTRES_PARADROP_CONQUER))
3110 || is_non_allied_unit_tile(ptile, pplayer)) {
3111 struct player *main_victim = NULL;
3112 struct player *secondary_victim = NULL;
3113 char victim_link[MAX_LEN_LINK];
3114
3115 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3116 maybe_make_contact(ptile, pplayer);
3117 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3118 _("Your %s was killed by enemy units at the "
3119 "paradrop destination."),
3121 /* TODO: Should defender score.units_killed get increased too?
3122 * What if there's units of several allied players? Should the
3123 * city owner or owner of the first/random unit get the kill? */
3124 pplayer->score.units_lost++;
3125
3126 if (pcity != NULL) {
3127 struct player *owner = city_owner(pcity);
3128
3129 if (!pplayers_at_war(pplayer, owner)) {
3130 main_victim = owner;
3131 } else {
3132 secondary_victim = owner;
3133 }
3134
3135 sz_strlcpy(victim_link, city_link(pcity));
3136 } else {
3137 sz_strlcpy(victim_link, tile_link(ptile));
3138 }
3139
3140 if (main_victim == NULL) {
3141 unit_list_iterate(ptile->units, tgt) {
3142 struct player *owner = unit_owner(tgt);
3143
3144 if (!pplayers_at_war(pplayer, owner)) {
3145 main_victim = owner;
3146 break;
3147 } else if (secondary_victim == NULL) {
3148 secondary_victim = owner;
3149 }
3151
3152 if (main_victim == NULL) {
3153 /* There's no victim with whom the attacker isn't in war,
3154 * fallback to one with whom there's already a war. */
3155 main_victim = secondary_victim;
3156 }
3157 }
3158
3159 action_consequence_caught(paction, pplayer, act_utype,
3160 main_victim, ptile,
3161 victim_link);
3162
3163 server_remove_unit(punit, ULR_KILLED);
3164 return TRUE;
3165 }
3166
3167 /* All ok */
3169 if (unit_move(punit, ptile,
3170 /* Done by Action_Success_Actor_Move_Cost */
3171 0,
3172 NULL, BV_ISSET(paction->sub_results,
3173 ACT_SUB_RES_MAY_EMBARK),
3174 paction->result == ACTRES_PARADROP_CONQUER,
3175 paction->result == ACTRES_PARADROP_CONQUER,
3176 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3177 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3178 /* Ensure we finished on valid state. */
3181 }
3182
3183 /* May cause an incident */
3184 action_consequence_success(paction, pplayer, act_utype, tgt_player,
3185 ptile, tile_link(ptile));
3186
3187 return TRUE;
3188}
3189
3190/**********************************************************************/
3194static bool hut_get_limited(struct unit *punit)
3195{
3196 bool ok = TRUE;
3197 int hut_chance = fc_rand(12);
3198 struct player *pplayer = unit_owner(punit);
3199 /* 1 in 12 to get barbarians */
3200 if (hut_chance != 0) {
3201 int cred = 25;
3202 notify_player(pplayer, unit_tile(punit), E_HUT_GOLD, ftc_server,
3203 PL_("You found %d gold.",
3204 "You found %d gold.", cred), cred);
3205 pplayer->economic.gold += cred;
3207 || unit_has_type_flag(punit, UTYF_GAMELOSS)) {
3208 notify_player(pplayer, unit_tile(punit),
3209 E_HUT_BARB_CITY_NEAR, ftc_server,
3210 _("An abandoned village is here."));
3211 } else {
3212 notify_player(pplayer, unit_tile(punit), E_HUT_BARB_KILLED, ftc_server,
3213 _("Your %s has been killed by barbarians!"),
3215 wipe_unit(punit, ULR_BARB_UNLEASH, NULL);
3216 ok = FALSE;
3217 }
3218 return ok;
3219}
3220
3221/**********************************************************************/
3225static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3226{
3227 struct player *pplayer = unit_owner(punit);
3228 int id = punit->id;
3229 struct tile *ptile = unit_tile(punit);
3230 bool hut = FALSE;
3231 const struct req_context context = {
3232 .player = pplayer,
3233 .tile = ptile,
3234 };
3235
3236 extra_type_by_rmcause_iterate(ERM_ENTER, pextra) {
3237 if (tile_has_extra(ptile, pextra)
3238 && are_reqs_active(&context, tile_owner(ptile), &pextra->rmreqs,
3240 ) {
3241 hut = TRUE;
3242 /* FIXME: are all enter-removes extras worth counting? */
3243 pplayer->server.huts++;
3244
3245 destroy_extra(ptile, pextra);
3247
3248 /* FIXME: enable different classes
3249 * to behave differently with different huts */
3250 if (frighten_hut) {
3251 script_server_signal_emit("hut_frighten", punit,
3252 extra_rule_name(pextra));
3253 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3254 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3255 (void) hut_get_limited(punit);
3256 } else {
3257 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3258 }
3259
3260 /* We need punit for the callbacks, can't continue if the unit died */
3261 if (!unit_is_alive(id)) {
3262 break;
3263 }
3264 }
3266
3267 if (hut) {
3268 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3269 }
3270 return;
3271}
3272
3273/**********************************************************************/
3276void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
3277{
3278 bv_player can_see_unit;
3279
3280 fc_assert_ret(punit != NULL);
3281 fc_assert_ret(ptrans != NULL);
3282
3283 BV_CLR_ALL(can_see_unit);
3284 players_iterate(pplayer) {
3285 if (can_player_see_unit(pplayer, punit)) {
3286 BV_SET(can_see_unit, player_index(pplayer));
3287 }
3289
3291
3292 players_iterate(pplayer) {
3293 if (BV_ISSET(can_see_unit, player_index(pplayer))
3294 && !can_player_see_unit(pplayer, punit)) {
3295 unit_goes_out_of_sight(pplayer, punit);
3296 }
3298
3299 send_unit_info(NULL, punit);
3300 send_unit_info(NULL, ptrans);
3301}
3302
3303/**********************************************************************/
3307 struct unit *ptrans,
3308 bool force)
3309{
3310 bool had_cargo;
3311
3312 fc_assert_ret(punit != NULL);
3313 fc_assert_ret(ptrans != NULL);
3314
3315 had_cargo = get_transporter_occupancy(ptrans) > 0;
3316
3317 unit_transport_load(punit, ptrans, force);
3318
3319 if (!had_cargo) {
3320 /* Transport's loaded status changed */
3321 send_unit_info(NULL, ptrans);
3322 }
3323}
3324
3325/**********************************************************************/
3329{
3330 struct unit *ptrans;
3331
3333
3334 ptrans = unit_transport_get(punit);
3335
3336 fc_assert_ret(ptrans);
3337
3339
3340 send_unit_info(NULL, punit);
3341 send_unit_info(NULL, ptrans);
3342}
3343
3344/**********************************************************************/
3348static void autoattack_prob_free(struct autoattack_prob *prob)
3349{
3350 free(prob);
3351}
3352
3353/**********************************************************************/
3362static int compare_units(const struct autoattack_prob *const *p1,
3363 const struct autoattack_prob *const *q1)
3364{
3365 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3366 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3367
3368 /* Sort by transport depth first. This makes sure that no transport
3369 * attacks before its cargo does -- cargo sorts earlier in the list. */
3370 {
3371 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3372
3373 /* Walk the transport stacks in parallel, so as to bail out as soon as
3374 * one of them is empty (avoid walking deep stacks more often than
3375 * necessary). */
3376 while (p1trans && q1trans) {
3377 p1trans = unit_transport_get(p1trans);
3378 q1trans = unit_transport_get(q1trans);
3379 }
3380 if (!p1trans && q1trans) {
3381 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3382 * earlier in the list (p1 > q1). */
3383 return 1;
3384 } else if (p1trans && !q1trans) {
3385 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3386 return -1;
3387 }
3388 /* else same depth, so move on to checking win chance: */
3389 }
3390
3391 /* Put the units with the highest probability of success first. The up
3392 * side of this is that units with bonuses against the victim attacks
3393 * before other units. The downside is that strong units can be led
3394 * away by sacrificial units. */
3395 return (-1
3396 /* Assume the worst. */
3397 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3398}
3399
3400/**********************************************************************/
3405{
3406 struct autoattack_prob_list *autoattack;
3407 int moves = punit->moves_left;
3408 int sanity1 = punit->id;
3409 struct civ_map *nmap = &(wld.map);
3410
3411 if (!game.server.autoattack) {
3412 return TRUE;
3413 }
3414
3415 autoattack = autoattack_prob_list_new_full(autoattack_prob_free);
3416
3417 /* Kludge to prevent attack power from dropping to zero during calc */
3419
3420 adjc_iterate(nmap, unit_tile(punit), ptile) {
3421 /* First add all eligible units to a autoattack list */
3422 unit_list_iterate(ptile->units, penemy) {
3423 struct autoattack_prob *probability = fc_malloc(sizeof(*probability));
3424 struct tile *tgt_tile = unit_tile(punit);
3425
3426 fc_assert_action(tgt_tile, continue);
3427
3428 probability->prob =
3429 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ,
3430 penemy, unit_owner(punit), NULL, NULL,
3431 tgt_tile, tile_city(tgt_tile),
3432 punit, NULL);
3433
3434 if (action_prob_possible(probability->prob)) {
3435 probability->unit_id = penemy->id;
3436 autoattack_prob_list_prepend(autoattack, probability);
3437 } else {
3438 FC_FREE(probability);
3439 }
3442
3443 /* Sort the potential attackers from highest to lowest success
3444 * probability. */
3445 if (autoattack_prob_list_size(autoattack) >= 2) {
3446 autoattack_prob_list_sort(autoattack, &compare_units);
3447 }
3448
3449 autoattack_prob_list_iterate_safe(autoattack, peprob, penemy) {
3450 int sanity2 = penemy->id;
3451 struct tile *ptile = unit_tile(penemy);
3452 struct unit *enemy_defender = get_defender(nmap, punit, ptile);
3453 double punitwin, penemywin;
3454 double threshold = 0.25;
3455 struct tile *tgt_tile = unit_tile(punit);
3456
3457 fc_assert(tgt_tile);
3458
3459 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3460 /* Don't leave city defenseless */
3461 threshold = 0.90;
3462 }
3463
3464 if (NULL != enemy_defender) {
3465 punitwin = unit_win_chance(nmap, punit, enemy_defender);
3466 } else {
3467 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3468 punitwin = 1.0;
3469 }
3470
3471 /* Previous attacks may have changed the odds. Recalculate. */
3472 peprob->prob =
3473 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ,
3474 penemy, unit_owner(punit), NULL, NULL,
3475 tgt_tile, tile_city(tgt_tile),
3476 punit, NULL);
3477
3478 if (!action_prob_possible(peprob->prob)) {
3479 /* No longer legal. */
3480 continue;
3481 }
3482
3483 /* Assume the worst. */
3484 penemywin = action_prob_to_0_to_1_pessimist(peprob->prob);
3485
3486 if ((penemywin > 1.0 - punitwin
3487 || unit_has_type_flag(punit, UTYF_PROVOKING))
3488 && penemywin > threshold) {
3489
3490#ifdef REALLY_DEBUG_THIS
3491 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3493 TILE_XY(unit_tile(punit)), penemywin,
3494 1.0 - punitwin, threshold);
3495#endif
3496
3497 unit_activity_handling(penemy, ACTIVITY_IDLE);
3498 action_auto_perf_unit_do(AAPC_UNIT_MOVED_ADJ,
3499 penemy, unit_owner(punit), NULL, NULL,
3500 tgt_tile, tile_city(tgt_tile), punit, NULL);
3501 } else {
3502#ifdef REALLY_DEBUG_THIS
3503 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3505 TILE_XY(unit_tile(punit)), penemywin,
3506 1.0 - punitwin, threshold);
3507#endif
3508 continue;
3509 }
3510
3511 if (game_unit_by_number(sanity2)) {
3512 send_unit_info(NULL, penemy);
3513 }
3514 if (game_unit_by_number(sanity1)) {
3515 send_unit_info(NULL, punit);
3516 } else {
3517 autoattack_prob_list_destroy(autoattack);
3518 return FALSE; /* moving unit dead */
3519 }
3521
3522 autoattack_prob_list_destroy(autoattack);
3523 if (game_unit_by_number(sanity1)) {
3524 /* We could have lost movement in combat */
3525 punit->moves_left = MIN(punit->moves_left, moves);
3526 send_unit_info(NULL, punit);
3527 return TRUE;
3528 } else {
3529 return FALSE;
3530 }
3531}
3532
3533/**********************************************************************/
3536static void cancel_orders(struct unit *punit, char *dbg_msg)
3537{
3539 send_unit_info(NULL, punit);
3540 log_debug("%s", dbg_msg);
3541}
3542
3543/**********************************************************************/
3548{
3549 bool alone_in_city;
3550
3551 if (NULL != tile_city(unit_tile(punit))) {
3552 int count = 0;
3553
3555 /* Consider only units not transported. */
3556 if (!unit_transported(aunit)) {
3557 count++;
3558 }
3560
3561 alone_in_city = (1 == count);
3562 } else {
3563 alone_in_city = FALSE;
3564 }
3565
3566 /* There may be sentried units with a sightrange > 3, but we don't
3567 wake them up if the punit is farther away than 3. */
3568 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3569 unit_list_iterate(ptile->units, penemy) {
3570 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3571 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3572
3574 && penemy->activity == ACTIVITY_SENTRY
3575 && radius_sq >= distance_sq
3576 /* If the unit moved on a city, and the unit is alone, consider
3577 * it is visible. */
3578 && (alone_in_city
3580 /* on board transport; don't awaken */
3581 && can_unit_exist_at_tile(&(wld.map), penemy, unit_tile(penemy))) {
3582 set_unit_activity(penemy, ACTIVITY_IDLE);
3583 send_unit_info(NULL, penemy);
3584 }
3587
3588 /* Wakeup patrolling units we bump into.
3589 We do not wakeup units further away than 3 squares... */
3590 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3591 unit_list_iterate(ptile->units, ppatrol) {
3592 if (punit != ppatrol
3593 && unit_has_orders(ppatrol)
3594 && ppatrol->orders.vigilant) {
3595 if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
3596 cancel_orders(ppatrol, " stopping because of nearby enemy");
3597 notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
3598 E_UNIT_ORDERS, ftc_server,
3599 _("Orders for %s aborted after enemy movement was "
3600 "spotted."),
3601 unit_link(ppatrol));
3602 }
3603 }
3606}
3607
3608/**********************************************************************/
3618 struct tile *src_tile,
3619 struct tile *dst_tile,
3620 bool passenger,
3621 bool conquer_city_allowed)
3622{
3623 struct city *fromcity = tile_city(src_tile);
3624 struct city *tocity = tile_city(dst_tile);
3625 struct city *homecity_start_pos = NULL;
3626 struct city *homecity_end_pos = NULL;
3627 int homecity_id_start_pos = punit->homecity;
3628 int homecity_id_end_pos = punit->homecity;
3629 struct player *pplayer_start_pos = unit_owner(punit);
3630 struct player *pplayer_end_pos = pplayer_start_pos;
3631 const struct unit_type *type_start_pos = unit_type_get(punit);
3632 const struct unit_type *type_end_pos = type_start_pos;
3633 bool refresh_homecity_start_pos = FALSE;
3634 bool refresh_homecity_end_pos = FALSE;
3635 int saved_id = punit->id;
3636 bool alive = TRUE;
3637 const struct civ_map *nmap = &(wld.map);
3638
3639 if (tocity && conquer_city_allowed) {
3640 if (!passenger) {
3641 /* The unit that does the move may conquer. */
3642 unit_conquer_city(punit, tocity);
3643 }
3644
3645 /* Run for passengers too. A passenger may have been killed when its
3646 * transport conquered a city. (unit_conquer_city() can cause Lua code
3647 * to run) */
3648
3649 alive = unit_is_alive(saved_id);
3650 if (alive) {
3651 /* In case script has changed something about unit */
3652 pplayer_end_pos = unit_owner(punit);
3653 type_end_pos = unit_type_get(punit);
3654 homecity_id_end_pos = punit->homecity;
3655 }
3656 }
3657
3658 if (homecity_id_start_pos != 0) {
3659 homecity_start_pos = game_city_by_number(homecity_id_start_pos);
3660 }
3661 if (homecity_id_start_pos != homecity_id_end_pos) {
3662 homecity_end_pos = game_city_by_number(homecity_id_end_pos);
3663 } else {
3664 homecity_end_pos = homecity_start_pos;
3665 }
3666
3667 /* We only do refreshes for non-AI players to now make sure the AI turns
3668 doesn't take too long. Perhaps we should make a special refresh_city
3669 functions that only refreshed happines. */
3670
3671 /* might have changed owners or may be destroyed */
3672 tocity = tile_city(dst_tile);
3673
3674 if (tocity) { /* entering a city */
3675 if (tocity->owner == pplayer_end_pos) {
3676 if (tocity != homecity_end_pos && is_human(pplayer_end_pos)) {
3677 city_refresh(tocity);
3678 send_city_info(pplayer_end_pos, tocity);
3679 }
3680 }
3681 if (homecity_start_pos) {
3682 refresh_homecity_start_pos = TRUE;
3683 }
3684 }
3685
3686 if (fromcity) { /* leaving a city */
3687 if (homecity_start_pos) {
3688 refresh_homecity_start_pos = TRUE;
3689 }
3690 if (fromcity != homecity_start_pos
3691 && fromcity->owner == pplayer_start_pos
3692 && is_human(pplayer_start_pos)) {
3693 city_refresh(fromcity);
3694 send_city_info(pplayer_start_pos, fromcity);
3695 }
3696 }
3697
3698 /* Entering/leaving a fortress or friendly territory */
3699 if (homecity_start_pos || homecity_end_pos) {
3700 if ((game.info.happyborders != HB_DISABLED && tile_owner(src_tile) != tile_owner(dst_tile))
3702 type_end_pos)
3703 && is_friendly_city_near(nmap, pplayer_end_pos, dst_tile))
3705 type_start_pos)
3706 && is_friendly_city_near(nmap, pplayer_start_pos, src_tile))) {
3707 refresh_homecity_start_pos = TRUE;
3708 refresh_homecity_end_pos = TRUE;
3709 }
3710 }
3711
3712 if (refresh_homecity_start_pos && is_human(pplayer_start_pos)) {
3713 city_refresh(homecity_start_pos);
3714 send_city_info(pplayer_start_pos, homecity_start_pos);
3715 }
3716 if (refresh_homecity_end_pos
3717 && (!refresh_homecity_start_pos
3718 || homecity_start_pos != homecity_end_pos)
3719 && is_human(pplayer_end_pos)) {
3720 city_refresh(homecity_end_pos);
3721 send_city_info(pplayer_end_pos, homecity_end_pos);
3722 }
3723
3724 city_map_update_tile_now(dst_tile);
3725 sync_cities();
3726
3727 return alive;
3728}
3729
3730/**********************************************************************/
3734static void check_unit_activity(struct unit *punit)
3735{
3736 switch (punit->activity) {
3737 case ACTIVITY_IDLE:
3738 case ACTIVITY_SENTRY:
3739 case ACTIVITY_EXPLORE:
3740 case ACTIVITY_GOTO:
3741 break;
3742 case ACTIVITY_POLLUTION:
3743 case ACTIVITY_MINE:
3744 case ACTIVITY_IRRIGATE:
3745 case ACTIVITY_CULTIVATE:
3746 case ACTIVITY_PLANT:
3747 case ACTIVITY_FORTIFIED:
3748 case ACTIVITY_FORTRESS:
3749 case ACTIVITY_PILLAGE:
3750 case ACTIVITY_TRANSFORM:
3751 case ACTIVITY_UNKNOWN:
3752 case ACTIVITY_AIRBASE:
3753 case ACTIVITY_FORTIFYING:
3754 case ACTIVITY_FALLOUT:
3755 case ACTIVITY_PATROL_UNUSED:
3756 case ACTIVITY_BASE:
3757 case ACTIVITY_GEN_ROAD:
3758 case ACTIVITY_CONVERT:
3759 case ACTIVITY_OLD_ROAD:
3760 case ACTIVITY_OLD_RAILROAD:
3761 case ACTIVITY_LAST:
3762 set_unit_activity(punit, ACTIVITY_IDLE);
3763 break;
3764 };
3765}
3766
3767/**********************************************************************/
3771 struct tile *psrctile,
3772 struct tile *pdesttile)
3773{
3774 struct unit_move_data *pdata;
3775 struct player *powner = unit_owner(punit);
3776
3777 if (punit->server.moving) {
3778 /* Recursive moving (probably due to a script). */
3779 pdata = punit->server.moving;
3780 pdata->ref_count++;
3781 fc_assert_msg(pdata->punit == punit,
3782 "Unit number %d (%p) was going to die, but "
3783 "server attempts to move it.",
3784 punit->id, punit);
3785 fc_assert_msg(pdata->old_vision == NULL,
3786 "Unit number %d (%p) has done an incomplete move.",
3787 punit->id, punit);
3788 } else {
3789 pdata = fc_malloc(sizeof(*pdata));
3790 pdata->ref_count = 1;
3791 pdata->punit = punit;
3792 punit->server.moving = pdata;
3793 BV_CLR_ALL(pdata->can_see_unit);
3794 }
3795 pdata->powner = powner;
3796 BV_CLR_ALL(pdata->can_see_move);
3797 pdata->old_vision = punit->server.vision;
3798
3799 return pdata;
3800}
3801
3802/**********************************************************************/
3805static void unit_move_by_data(struct unit_move_data *pdata,
3806 struct tile *psrctile, struct tile *pdesttile)
3807{
3808 struct vision *new_vision;
3809 struct unit *punit = pdata->punit;
3810 int mod = unit_vision_range_modifiers(punit, pdesttile);
3811 const v_radius_t radius_sq =
3812 V_RADIUS(get_unit_vision_base(punit, V_MAIN, mod),
3813 get_unit_vision_base(punit, V_INVIS, mod),
3814 get_unit_vision_base(punit, V_SUBSURFACE, mod));
3815
3816 /* Remove unit from the source tile. */
3817 fc_assert(unit_tile(punit) == psrctile);
3818
3819#ifndef FREECIV_NDEBUG
3820 bool success =
3821#endif
3822 unit_list_remove(psrctile->units, punit);
3823 fc_assert(success);
3824
3825 /* Set new tile. */
3826 unit_tile_set(punit, pdesttile);
3827 unit_list_prepend(pdesttile->units, punit);
3828
3829 if (unit_transported(punit)) {
3830 /* Silently free orders since they won't be applicable anymore. */
3832 }
3833
3834 /* Check unit activity. */
3838
3839 /* We first unfog the destination, then send the move,
3840 * and then fog the old territory. This means that the player
3841 * gets a chance to see the newly explored territory while the
3842 * client moves the unit, and both areas are visible during the
3843 * move */
3844
3845 /* Enhance vision if unit steps into a fortress */
3846 new_vision = vision_new(pdata->powner, pdesttile);
3847 punit->server.vision = new_vision;
3848 vision_change_sight(new_vision, radius_sq);
3849 ASSERT_VISION(new_vision);
3850}
3851
3852/**********************************************************************/
3855static void unit_move_data_unref(struct unit_move_data *pdata)
3856{
3857 fc_assert_ret(pdata != NULL);
3858 fc_assert_ret(pdata->ref_count > 0);
3859 fc_assert_msg(pdata->old_vision == NULL,
3860 "Unit number %d (%p) has done an incomplete move.",
3861 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3862
3863 pdata->ref_count--;
3864 if (pdata->ref_count == 0) {
3865 if (pdata->punit != NULL) {
3866 fc_assert(pdata->punit->server.moving == pdata);
3867 pdata->punit->server.moving = NULL;
3868 }
3869 free(pdata);
3870 }
3871}
3872
3873/**********************************************************************/
3884bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3885 struct unit *embark_to, bool find_embark_target,
3886 bool conquer_city_allowed, bool conquer_extras_allowed,
3887 bool enter_hut, bool frighten_hut)
3888{
3889 struct player *pplayer;
3890 struct tile *psrctile;
3891 struct city *psrccity;
3892 struct city *pdestcity;
3893 struct unit *ptransporter;
3894 struct packet_unit_info src_info, dest_info;
3895 struct packet_unit_short_info src_sinfo, dest_sinfo;
3896 struct unit_move_data_list *plist =
3897 unit_move_data_list_new_full(unit_move_data_unref);
3898 struct unit_move_data *pdata;
3899 int saved_id;
3900 bool unit_lives;
3901 bool adj;
3902 enum direction8 facing;
3903
3904 /* Some checks. */
3905 fc_assert_ret_val(punit != NULL, FALSE);
3906 fc_assert_ret_val(pdesttile != NULL, FALSE);
3907
3908 pplayer = unit_owner(punit);
3909 saved_id = punit->id;
3910 psrctile = unit_tile(punit);
3911 adj = base_get_direction_for_step(&(wld.map), psrctile, pdesttile, &facing);
3912
3914
3915 /* Unload the unit if on a transport. */
3916 ptransporter = unit_transport_get(punit);
3917 if (ptransporter != NULL) {
3918 /* Unload unit _before_ setting the new tile! */
3920 /* Send updated information to anyone watching that transporter
3921 * was unloading cargo. */
3922 send_unit_info(NULL, ptransporter);
3923 }
3924
3925 /* Wakup units next to us before we move. */
3927
3928 /* Make info packets at 'psrctile'. */
3929 if (adj) {
3930 /* If tiles are adjacent, we will show the move to users able
3931 * to see it. */
3932 package_unit(punit, &src_info);
3934 }
3935
3936 /* Make new data for 'punit'. */
3937 pdata = unit_move_data(punit, psrctile, pdesttile);
3938 unit_move_data_list_prepend(plist, pdata);
3939
3940 /* Set unit orientation */
3941 if (adj) {
3942 /* Only change orientation when moving to adjacent tile */
3943 punit->facing = facing;
3944 }
3945
3946 /* Move magic. */
3947 punit->moved = TRUE;
3948 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3949 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3950 /* The next order may not require any remaining move fragments. */
3952 }
3953
3954 /* No longer relevant. */
3956 punit->action_decision_want = ACT_DEC_NOTHING;
3957
3958 if (!adj
3959 && action_tgt_city(punit, pdesttile, FALSE)) {
3960 /* The unit can perform an action to the city at the destination tile.
3961 * A long distance move (like an airlift) doesn't ask what action to
3962 * perform before moving. Ask now. */
3963
3964 punit->action_decision_want = ACT_DEC_PASSIVE;
3965 punit->action_decision_tile = pdesttile;
3966 }
3967
3968 /* Claim ownership of fortress? */
3969 if (conquer_extras_allowed
3971 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3972 * Even if original unit cannot claim other kind of bases, the
3973 * first claimed base will have influence over other bases,
3974 * or something like that. */
3975 tile_claim_bases(pdesttile, pplayer);
3976 }
3977
3978 /* Move all contained units. */
3979 unit_cargo_iterate(punit, pcargo) {
3980 pdata = unit_move_data(pcargo, psrctile, pdesttile);
3981 unit_move_data_list_append(plist, pdata);
3983
3984 /* Get data for 'punit'. */
3985 pdata = unit_move_data_list_front(plist);
3986
3987 /* Determine the players able to see the move(s), now that the player
3988 * vision has been increased. */
3989 if (adj) {
3990 /* Main unit for adjacent move: the move is visible for every player
3991 * able to see on the matching unit layer. */
3992 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
3993
3994 players_iterate(oplayer) {
3995 if (map_is_known_and_seen(psrctile, oplayer, vlayer)
3996 || map_is_known_and_seen(pdesttile, oplayer, vlayer)) {
3997 BV_SET(pdata->can_see_unit, player_index(oplayer));
3998 BV_SET(pdata->can_see_move, player_index(oplayer));
3999 }
4001 }
4002
4003 unit_move_data_list_iterate(plist, pmove_data) {
4004
4005 unit_move_by_data(pmove_data, psrctile, pdesttile);
4006
4007 if (adj && pmove_data == pdata) {
4008 /* If positions are adjacent, we have already handled 'punit'. See
4009 * above. */
4010 continue;
4011 }
4012
4013 players_iterate(oplayer) {
4014 if ((adj
4015 && can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
4016 pmove_data != pdata))
4017 || can_player_see_unit_at(oplayer, pmove_data->punit, pdesttile,
4018 pmove_data != pdata)) {
4019 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4020 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4021 }
4022 if (can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
4023 pmove_data != pdata)) {
4024 /* The unit was seen with its source tile even if it was
4025 * teleported. */
4026 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4027 }
4030
4031 /* Check timeout settings. */
4033 bool new_information_for_enemy = FALSE;
4034
4035 phase_players_iterate(penemy) {
4036 /* Increase the timeout if an enemy unit moves and the
4037 * timeoutaddenemymove setting is in use. */
4038 if (penemy->is_connected
4039 && pplayer != penemy
4040 && pplayers_at_war(pplayer, penemy)
4041 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4042 new_information_for_enemy = TRUE;
4043 break;
4044 }
4046
4047 if (new_information_for_enemy) {
4049 }
4050 }
4051
4052 /* Notifications of the move to the clients. */
4053 if (adj) {
4054 /* Special case: 'punit' is moving to adjacent position. Then we show
4055 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4056
4057 /* Make info packets at 'pdesttile'. */
4058 package_unit(punit, &dest_info);
4060
4062 struct player *aplayer = conn_get_player(pconn);
4063
4064 if (aplayer == NULL) {
4065 if (pconn->observer) {
4066 /* Global observers see all... */
4067 send_packet_unit_info(pconn, &src_info);
4068 send_packet_unit_info(pconn, &dest_info);
4069 }
4070 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4071 if (aplayer == pplayer) {
4072 send_packet_unit_info(pconn, &src_info);
4073 send_packet_unit_info(pconn, &dest_info);
4074 } else {
4075 send_packet_unit_short_info(pconn, &src_sinfo, FALSE);
4076 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
4077 }
4078 }
4080 }
4081
4082 /* Other moves. */
4083 unit_move_data_list_iterate(plist, pmove_data) {
4084 if (adj && pmove_data == pdata) {
4085 /* If positions are adjacent, we have already shown 'punit' move.
4086 * See above. */
4087 continue;
4088 }
4089
4090 /* Make info packets at 'pdesttile'. */
4091 package_unit(pmove_data->punit, &dest_info);
4092 package_short_unit(pmove_data->punit, &dest_sinfo,
4094
4096 struct player *aplayer = conn_get_player(pconn);
4097
4098 if (aplayer == NULL) {
4099 if (pconn->observer) {
4100 /* Global observers see all... */
4101 send_packet_unit_info(pconn, &dest_info);
4102 }
4103 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4104 if (aplayer == pmove_data->powner) {
4105 send_packet_unit_info(pconn, &dest_info);
4106 } else {
4107 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
4108 }
4109 }
4112
4113 /* Clear old vision. */
4114 unit_move_data_list_iterate(plist, pmove_data) {
4115 if (pmove_data->old_vision != NULL) {
4116 vision_clear_sight(pmove_data->old_vision);
4117 vision_free(pmove_data->old_vision);
4118 pmove_data->old_vision = NULL;
4119 }
4121
4122 /* Move consequences. */
4123 unit_move_data_list_iterate(plist, pmove_data) {
4124 struct unit *aunit = pmove_data->punit;
4125
4126 if (aunit != NULL
4127 && unit_owner(aunit) == pmove_data->powner
4128 && unit_tile(aunit) == pdesttile) {
4129 (void) unit_move_consequences(aunit, psrctile, pdesttile,
4130 pdata != pmove_data,
4131 conquer_city_allowed);
4132 }
4134
4135 unit_lives = (pdata->punit == punit);
4136
4137 /* Wakeup units and make contact. */
4138 if (unit_lives) {
4140 }
4141 maybe_make_contact(pdesttile, pplayer);
4142
4143 if (unit_lives) {
4144 /* Special checks for ground units in the ocean. */
4145 if (embark_to || !can_unit_survive_at_tile(&(wld.map), punit, pdesttile)) {
4146 if (embark_to != NULL) {
4147 ptransporter = embark_to;
4148 } else if (find_embark_target) {
4149 /* TODO: Consider to stop supporting find_embark_target and make all
4150 * callers that wants auto loading set embark_to. */
4151 ptransporter = transporter_for_unit(punit);
4152 } else {
4153 ptransporter = NULL;
4154 }
4155 if (ptransporter) {
4157
4158 /* Set activity to sentry if boarding a ship. */
4159 if (is_human(pplayer)
4161 && punit->ssa_controller == SSA_NONE
4162 && !can_unit_exist_at_tile(&(wld.map), punit, pdesttile)) {
4163 set_unit_activity(punit, ACTIVITY_SENTRY);
4164 }
4165
4166 send_unit_info(NULL, punit);
4167 }
4168 }
4169 }
4170
4171 /* Remove units going out of sight. */
4172 unit_move_data_list_iterate_rev(plist, pmove_data) {
4173 struct unit *aunit = pmove_data->punit;
4174
4175 if (aunit == NULL) {
4176 continue; /* Died! */
4177 }
4178
4179 players_iterate(aplayer) {
4180 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4181 && !can_player_see_unit(aplayer, aunit)) {
4182 unit_goes_out_of_sight(aplayer, aunit);
4183 }
4186
4187 /* Inform the owner's client about actor unit arrival. Can, depending on
4188 * the client settings, cause the client to start the process that makes
4189 * the action selection dialog pop up. */
4190 pdestcity = tile_city(pdesttile);
4191 if (pdestcity != NULL) {
4192 /* Arrival in a city counts. */
4193
4194 unit_move_data_list_iterate(plist, pmove_data) {
4195 struct unit *ptrans;
4196 bool ok;
4197 struct unit *act_unit;
4198 struct player *act_player;
4199
4200 act_unit = pmove_data->punit;
4201 act_player = unit_owner(act_unit);
4202
4203 if (act_unit == NULL
4204 || !unit_is_alive(act_unit->id)) {
4205 /* The unit died before reaching this point. */
4206 continue;
4207 }
4208
4209 if (unit_tile(act_unit) != pdesttile) {
4210 /* The unit didn't arrive at the destination tile. */
4211 continue;
4212 }
4213
4214 if (!is_human(act_player)) {
4215 /* Only humans need reminders. */
4216 continue;
4217 }
4218
4219 if (!unit_transported(act_unit)) {
4220 /* Don't show the action selection dialog again. Non transported
4221 * units are handled before they move to the tile. */
4222 continue;
4223 }
4224
4225 /* Open action dialog only if 'act_unit' and all its transporters
4226 * (recursively) don't have orders. */
4227 if (unit_has_orders(act_unit)) {
4228 /* The unit it self has orders. */
4229 continue;
4230 }
4231
4232 for (ptrans = unit_transport_get(act_unit);;
4233 ptrans = unit_transport_get(ptrans)) {
4234 if (NULL == ptrans) {
4235 /* No (recursive) transport has orders. */
4236 ok = TRUE;
4237 break;
4238 } else if (unit_has_orders(ptrans)) {
4239 /* A unit transporting the unit has orders */
4240 ok = FALSE;
4241 break;
4242 }
4243 }
4244
4245 if (!ok) {
4246 /* A unit transporting act_unit has orders. */
4247 continue;
4248 }
4249
4250 if (action_tgt_city(act_unit, pdesttile, FALSE)) {
4251 /* There is a valid target. */
4252
4253 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4254 act_unit->action_decision_tile = pdesttile;
4255
4256 /* Let the client know that this unit wants the player to decide
4257 * what to do. */
4258 send_unit_info(player_reply_dest(act_player), act_unit);
4259 }
4261 }
4262
4263 unit_move_data_list_destroy(plist);
4264 /* Check cities at source and destination. */
4265 psrccity = tile_city(psrctile);
4266 if (psrccity != NULL) {
4267 refresh_dumb_city(psrccity);
4268 }
4269 if (pdestcity != NULL) {
4270 refresh_dumb_city(pdestcity);
4271 }
4272
4273 if (unit_lives) {
4274 /* Let the scripts run ... */
4275 script_server_signal_emit("unit_moved", punit, psrctile, pdesttile);
4276 unit_lives = unit_is_alive(saved_id);
4277 }
4278
4279 if (unit_lives) {
4280 /* Autoattack. */
4281 unit_lives = unit_survive_autoattack(punit);
4282 }
4283
4284 if (unit_lives && (enter_hut || frighten_hut)) {
4285 /* Is there a hut? */
4288 unit_lives = unit_is_alive(saved_id);
4289 }
4290
4292
4293 if (unit_lives) {
4294 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4295 }
4296
4297 return unit_lives;
4298}
4299
4300/**********************************************************************/
4304 struct tile *ptile)
4305{
4306 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
4308}
4309
4310/**********************************************************************/
4317{
4318 bool cancel = FALSE;
4319 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4320 struct player *pplayer = unit_owner(punit);
4321
4322 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4323 struct unit *penemy = tile_non_allied_unit(ptile, pplayer);
4324 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4325
4326 if ((penemy && can_player_see_unit(pplayer, penemy))
4327 || (pdcity && !pplayers_allied(pplayer, vision_site_owner(pdcity))
4328 && pdcity->occupied)) {
4329 cancel = TRUE;
4330 break;
4331 }
4333
4334 return cancel;
4335}
4336
4337/**********************************************************************/
4345static inline bool player_is_watching(struct unit *punit, const bool fresh)
4346{
4347 /* The player just sent the orders to the unit. The unit has moves left.
4348 * It is therefore safe to assume that the player already is paying
4349 * attention to the unit. */
4350 return fresh && punit->moves_left > 0;
4351}
4352
4353/**********************************************************************/
4372bool execute_orders(struct unit *punit, const bool fresh)
4373{
4374 struct act_prob prob;
4375 bool performed;
4376 const char *name;
4377 bool res, last_order;
4378 int unitid = punit->id;
4379 struct player *pplayer = unit_owner(punit);
4380 int moves_made = 0;
4381 const struct civ_map *nmap = &(wld.map);
4382
4384
4385 if (punit->activity != ACTIVITY_IDLE) {
4386 /* Unit's in the middle of an activity; wait for it to finish. */
4388 return TRUE;
4389 }
4390
4391 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4392
4393 /* Any time the orders are canceled we should give the player a message. */
4394
4395 while (TRUE) {
4396 struct unit_order order;
4397
4398 struct action *oaction;
4399
4400 struct tile *dst_tile;
4401 struct city *tgt_city;
4402 struct unit *tgt_unit;
4403 int tgt_id;
4404 int sub_tgt_id;
4405 struct extra_type *pextra;
4406
4407 if (punit->done_moving) {
4408 log_debug(" stopping because we're done this turn");
4409 return TRUE;
4410 }
4411
4413 /* "Patrol" orders are stopped if an enemy is near. */
4414 cancel_orders(punit, " stopping because of nearby enemy");
4415 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4416 _("Orders for %s aborted as there are units nearby."),
4417 unit_link(punit));
4418 return TRUE;
4419 }
4420
4421 if (moves_made == punit->orders.length) {
4422 /* For repeating orders, don't repeat more than once per turn. */
4423 log_debug(" stopping because we ran a round");
4425 send_unit_info(NULL, punit);
4426 return TRUE;
4427 }
4428 moves_made++;
4429
4430 order = punit->orders.list[punit->orders.index];
4431
4432 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4433 * this far. */
4435 || action_id_exists(order.action)),
4436 continue);
4437
4438 switch (order.order) {
4439 case ORDER_MOVE:
4440 case ORDER_ACTION_MOVE:
4441 case ORDER_FULL_MP:
4442 if (0 == punit->moves_left) {
4443 log_debug(" stopping because of no more move points");
4444 return TRUE;
4445 }
4446 break;
4449 log_debug(" stopping. Not enough move points this turn");
4450 return TRUE;
4451 }
4452 break;
4453 case ORDER_ACTIVITY:
4454 case ORDER_LAST:
4455 /* Those actions don't require moves left. */
4456 break;
4457 }
4458
4459 last_order = (!punit->orders.repeat
4460 && punit->orders.index + 1 == punit->orders.length);
4461
4462 if (last_order) {
4463 /* Clear the orders before we engage in the move. That way any
4464 * has_orders checks will yield FALSE and this will be treated as
4465 * a normal move. This is important: for instance a caravan goto
4466 * will popup the caravan dialog on the last move only. */
4468 }
4469
4470 /* Advance the orders one step forward. This is needed because any
4471 * updates sent to the client as a result of the action should include
4472 * the new index value. Note that we have to send_unit_info somewhere
4473 * after this point so that the client is properly updated. */
4474 punit->orders.index++;
4475
4476 switch (order.order) {
4477 case ORDER_FULL_MP:
4479 /* If the unit doesn't have full MP then it just waits until the
4480 * next turn. We assume that the next turn it will have full MP
4481 * (there's no check for that). */
4483 log_debug(" waiting this turn");
4484 send_unit_info(NULL, punit);
4485 }
4486 break;
4487 case ORDER_ACTIVITY:
4488 {
4489 enum unit_activity activity = order.activity;
4490
4491 fc_assert(activity == ACTIVITY_SENTRY);
4492
4493 if (can_unit_do_activity(nmap, punit, activity)) {
4495 set_unit_activity(punit, activity);
4496 send_unit_info(NULL, punit);
4497
4498 break;
4499 }
4500 }
4501
4502 cancel_orders(punit, " orders canceled because of failed activity");
4503 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4504 _("Orders for %s aborted since they "
4505 "give an invalid activity."),
4506 unit_link(punit));
4507 return TRUE;
4508 case ORDER_MOVE:
4509 case ORDER_ACTION_MOVE:
4510 /* Move unit */
4511 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4512 cancel_orders(punit, " move order sent us to invalid location");
4513 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4514 _("Orders for %s aborted since they "
4515 "give an invalid location."),
4516 unit_link(punit));
4517 return TRUE;
4518 }
4519
4520 if (order.order != ORDER_ACTION_MOVE
4521 && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
4522 /* Plain move required: no attack, trade route etc. */
4523 cancel_orders(punit, " orders canceled because of enemy");
4524 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4525 _("Orders for %s aborted as there "
4526 "are units in the way."),
4527 unit_link(punit));
4528 return TRUE;
4529 }
4530
4531 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4532 res = unit_move_handling(punit, dst_tile,
4533 order.order != ORDER_ACTION_MOVE);
4534 if (!player_unit_by_number(pplayer, unitid)) {
4535 log_debug(" unit died while moving.");
4536 /* A player notification should already have been sent. */
4537 return FALSE;
4538 }
4539
4540 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4541 /* Movement succeeded but unit didn't move. */
4542 log_debug(" orders resulted in combat.");
4543 send_unit_info(NULL, punit);
4544 return TRUE;
4545 }
4546
4547 if (!res) {
4548 fc_assert(0 <= punit->moves_left);
4549
4550 /* Movement failed (ZOC, etc.) */
4551 cancel_orders(punit, " attempt to move failed.");
4552
4553 if (!player_is_watching(punit, fresh)
4554 /* The final move "failed" because the unit needs to ask the
4555 * player what action it should take.
4556 *
4557 * The action decision request notifies the player. Its
4558 * location at the unit's last order makes it clear to the
4559 * player who the decision is for. ("The Spy I sent to Berlin
4560 * has arrived.")
4561 *
4562 * A notification message is therefore redundant. */
4563 && !(last_order
4564 && punit->action_decision_want == ACT_DEC_ACTIVE
4565 && punit->action_decision_tile == dst_tile)) {
4566 /* The player may have missed this. No one else will announce it
4567 * in a satisfying manner. Inform the player. */
4568 notify_player(pplayer, unit_tile(punit),
4569 E_UNIT_ORDERS, ftc_server,
4570 _("Orders for %s aborted because of failed move."),
4571 unit_link(punit));
4572 }
4573
4574 return TRUE;
4575 }
4576 break;
4578 oaction = action_by_number(order.action);
4579
4580 /* Checked in unit_order_list_is_sane() */
4581 fc_assert_action(oaction != NULL, continue);
4582
4583 log_debug(" orders: doing action %s", action_rule_name(oaction));
4584
4585 dst_tile = index_to_tile(&(wld.map), order.target);
4586
4587 if (dst_tile == NULL) {
4588 /* Could be at the edge of the map while trying to target a tile
4589 * outside of it. */
4590
4591 cancel_orders(punit, " target location doesn't exist");
4592 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4593 order.action, dst_tile, NULL, NULL);
4594
4595 return TRUE;
4596 }
4597
4598 /* Get the target city from the target tile. */
4599 tgt_city = tile_city(dst_tile);
4600
4601 if (tgt_city == NULL
4602 && action_id_get_target_kind(order.action) == ATK_CITY) {
4603 /* This action targets a city but no city target was found. */
4604
4605 cancel_orders(punit, " perform action vs city with no city");
4606 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4607 order.action, dst_tile, tgt_city, NULL);
4608
4609 return TRUE;
4610 }
4611
4612 /* Get a target unit at the target tile. */
4613 tgt_unit = action_tgt_unit(punit, dst_tile, TRUE);
4614
4615 if (tgt_unit == NULL
4616 && action_id_get_target_kind(order.action) == ATK_UNIT) {
4617 /* This action targets a unit but no target unit was found. */
4618
4619 cancel_orders(punit, " perform action vs unit with no unit");
4620 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4621 order.action, dst_tile, tgt_city, tgt_unit);
4622
4623 return TRUE;
4624 }
4625
4626 /* Server side sub target assignment */
4627 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4628 && order.sub_target == NO_TARGET) {
4629 /* Try to find a sub target. */
4630 sub_tgt_id = action_sub_target_id_for_action(oaction, punit);
4631 } else {
4632 /* The client should have specified a sub target if needed */
4633 sub_tgt_id = order.sub_target;
4634 }
4635
4636 /* Get a target extra at the target tile */
4637 pextra = (sub_tgt_id == NO_TARGET ?
4638 NULL :
4639 extra_by_number(sub_tgt_id));
4640
4641 if (action_get_sub_target_kind(oaction) == ASTK_EXTRA_NOT_THERE
4642 && pextra != NULL
4643 && action_creates_extra(oaction, pextra)
4644 && tile_has_extra(dst_tile, pextra)) {
4645 /* Already there. Move on to the next order. */
4646 break;
4647 }
4648
4649 if (action_get_sub_target_kind(oaction) == ASTK_EXTRA
4650 && pextra != NULL
4651 && action_removes_extra(oaction, pextra)
4652 && !tile_has_extra(dst_tile, pextra)) {
4653 /* Already not there. Move on to the next order. */
4654 break;
4655 }
4656
4657 /* No target selected. */
4658 tgt_id = -1;
4659
4660 /* Assume impossible until told otherwise. */
4661 prob = ACTPROB_IMPOSSIBLE;
4662
4663 switch (action_id_get_target_kind(order.action)) {
4664 case ATK_UNITS:
4665 prob = action_prob_vs_units(punit, order.action,
4666 dst_tile);
4667 tgt_id = dst_tile->index;
4668 break;
4669 case ATK_TILE:
4670 prob = action_prob_vs_tile(punit, order.action,
4671 dst_tile, pextra);
4672 tgt_id = dst_tile->index;
4673 break;
4674 case ATK_EXTRAS:
4675 prob = action_prob_vs_extras(punit, order.action,
4676 dst_tile, pextra);
4677 tgt_id = dst_tile->index;
4678 break;
4679 case ATK_CITY:
4680 prob = action_prob_vs_city(nmap, punit, order.action,
4681 tgt_city);
4682 tgt_id = tgt_city->id;
4683 break;
4684 case ATK_UNIT:
4685 prob = action_prob_vs_unit(nmap, punit, order.action,
4686 tgt_unit);
4687
4688 tgt_id = tgt_unit->id;
4689 break;
4690 case ATK_SELF:
4691 prob = action_prob_self(punit, order.action);
4692
4693 tgt_id = unitid;
4694 break;
4695 case ATK_COUNT:
4696 log_error("Invalid action target kind");
4697
4698 /* The check below will abort and cancel the orders because prob
4699 * was initialized to impossible above this switch statement. */
4700
4701 break;
4702 }
4703
4704 if (!action_prob_possible(prob)) {
4705 /* The player has enough information to know that this action is
4706 * against the rules. Don't risk any punishment by trying to
4707 * perform it. */
4708
4709 cancel_orders(punit, " illegal action");
4710 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4711 _("%s could not do %s to %s."),
4714 tile_link(dst_tile));
4715
4716 /* Try to explain what rule made it illegal. */
4717 illegal_action_msg(unit_owner(punit), E_BAD_COMMAND, punit,
4718 order.action, dst_tile, tgt_city, tgt_unit);
4719
4720 return TRUE;
4721 }
4722
4723 if (action_id_has_result_safe(order.action, ACTRES_FOUND_CITY)) {
4724 /* This action needs a name. */
4726 } else {
4727 /* This action doesn't need a name. */
4728 name = "";
4729 }
4730
4731 performed = unit_perform_action(pplayer,
4732 unitid,
4733 tgt_id,
4734 sub_tgt_id,
4735 name,
4736 order.action,
4737 ACT_REQ_PLAYER);
4738
4739 if (!player_unit_by_number(pplayer, unitid)) {
4740 /* The unit "died" while performing the action. */
4741 return FALSE;
4742 }
4743
4744 if (!performed) {
4745 /* The action wasn't performed as ordered. */
4746
4747 cancel_orders(punit, " failed action");
4748 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4749 _("Orders for %s aborted because "
4750 "doing %s to %s failed."),
4753 tile_link(dst_tile));
4754
4755 return TRUE;
4756 }
4757
4758 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4760 /* Done at turn change. */
4762 send_unit_info(NULL, punit);
4763 break;
4764 }
4765
4766 break;
4767 case ORDER_LAST:
4768 /* Should be caught when loading the unit orders from the savegame or
4769 * when receiving the unit orders from the client. */
4770 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4771 cancel_orders(punit, " invalid order!");
4772 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4773 _("Your %s has invalid orders."),
4774 unit_link(punit));
4775 return TRUE;
4776 }
4777
4778 if (last_order) {
4780 log_debug(" stopping because orders are complete");
4781 return TRUE;
4782 }
4783
4784 if (punit->orders.index == punit->orders.length) {
4786 /* Start over. */
4787 log_debug(" repeating orders.");
4788 punit->orders.index = 0;
4789 }
4790 } /* end while */
4791}
4792
4793/**********************************************************************/
4800static int get_unit_vision_base(struct unit *punit, enum vision_layer vlayer,
4801 const int base)
4802{
4803 switch (vlayer) {
4804 case V_MAIN:
4805 return MAX(0, base);
4806 case V_INVIS:
4807 case V_SUBSURFACE:
4808 return CLIP(0, base, 2);
4809 case V_COUNT:
4810 break;
4811 }
4812
4813 log_error("Unsupported vision layer variant: %d.", vlayer);
4814
4815 return 0;
4816}
4817
4818/**********************************************************************/
4822 const struct tile *ptile)
4823{
4824 const struct unit_type *utype = unit_type_get(punit);
4825
4826 return (utype->vision_radius_sq
4828 utype, NULL,
4829 EFT_UNIT_VISION_RADIUS_SQ));
4830}
4831
4832/**********************************************************************/
4839int get_unit_vision_at(struct unit *punit, const struct tile *ptile,
4840 enum vision_layer vlayer)
4841{
4844}
4845
4846/**********************************************************************/
4853{
4854 struct vision *uvision = punit->server.vision;
4855 const struct tile *utile = unit_tile(punit);
4856 int mod = unit_vision_range_modifiers(punit, utile);
4857 const v_radius_t radius_sq =
4858 V_RADIUS(get_unit_vision_base(punit, V_MAIN, mod),
4859 get_unit_vision_base(punit, V_INVIS, mod),
4860 get_unit_vision_base(punit, V_SUBSURFACE, mod));
4861
4862 vision_change_sight(uvision, radius_sq);
4863 ASSERT_VISION(uvision);
4864}
4865
4866/**********************************************************************/
4869void unit_list_refresh_vision(struct unit_list *punitlist)
4870{
4871 unit_list_iterate(punitlist, punit) {
4874}
4875
4876/**********************************************************************/
4881{
4882 time_t dt;
4883
4884 if (!punit) {
4885 return FALSE;
4886 }
4887
4888 if (game.server.unitwaittime <= 0) {
4889 return TRUE;
4890 }
4891
4892 if (punit->server.action_turn != game.info.turn - 1) {
4893 return TRUE;
4894 }
4895
4896 dt = time(NULL) - punit->server.action_timestamp;
4897 if (dt < game.server.unitwaittime) {
4898 char buf[64];
4899 format_time_duration(game.server.unitwaittime - dt, buf, sizeof(buf));
4900 notify_player(unit_owner(punit), unit_tile(punit), E_BAD_COMMAND,
4901 ftc_server, _("Your unit may not act for another %s "
4902 "this turn. See /help unitwaittime."), buf);
4903 return FALSE;
4904 }
4905
4906 return TRUE;
4907}
4908
4909/**********************************************************************/
4914{
4915 if (!punit) {
4916 return;
4917 }
4918
4919 punit->server.action_timestamp = time(NULL);
4921}
4922
4923/**********************************************************************/
4929{
4930 /* check if there is enemy nearby */
4931 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
4933 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4934 return FALSE;
4935 }
4936 }
4938
4939 return TRUE;
4940}
bool action_removes_extra(const struct action *paction, const struct extra_type *pextra)
Definition actions.c:2312
const char * action_name_translation(const struct action *action)
Definition actions.c:1890
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:7224
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1910
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Definition actions.c:6380
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6707
const char * action_rule_name(const struct action *action)
Definition actions.c:1876
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1751
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6225
struct act_prob action_prob_vs_units(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:6141
struct act_prob action_prob_vs_city(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Definition actions.c:5870
struct act_prob action_prob_vs_extras(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6309
bool action_id_exists(const action_id act_id)
Definition actions.c:1697
bool action_creates_extra(const struct action *paction, const struct extra_type *pextra)
Definition actions.c:2224
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:6767
struct act_prob action_prob_vs_unit(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5953
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:6818
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
#define action_has_result(_act_, _res_)
Definition actions.h:448
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:683
#define ACTPROB_IMPOSSIBLE
Definition actions.h:927
#define action_id_get_target_kind(act_id)
Definition actions.h:655
#define action_id_has_result_safe(act_id, result)
Definition actions.h:668
void action_consequence_complete(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
void action_consequence_caught(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct act_prob action_auto_perf_unit_prob(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
const struct action * action_auto_perf_unit_do(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
void action_consequence_success(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:384
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool city_exists_within_max_city_map(const struct tile *ptile, bool may_be_on_center)
Definition city.c:2080
const char * city_name_get(const struct city *pcity)
Definition city.c:1111
bool is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile)
Definition city.c:2061
#define city_list_iterate_safe(citylist, _city)
Definition city.h:502
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:741
#define city_list_iterate(citylist, pcity)
Definition city.h:488
#define city_tile(_pcity_)
Definition city.h:544
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:705
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:717
#define output_type_iterate(output)
Definition city.h:812
#define city_owner(_pcity_)
Definition city.h:543
#define city_list_iterate_end
Definition city.h:490
#define city_list_iterate_safe_end
Definition city.h:524
#define output_type_iterate_end
Definition city.h:818
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3222
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:451
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2320
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Definition citytools.c:849
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2181
void sync_cities(void)
Definition citytools.c:3231
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1956
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3019
bool transfer_city(struct player *ptaker, struct city *pcity, int kill_outside, bool transfer_unit_verbose, bool resolve_stack, bool raze, bool build_free)
Definition citytools.c:1065
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:807
bool city_refresh(struct city *pcity)
Definition cityturn.c:161
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:85
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:928
int get_virtual_defense_power(const struct civ_map *nmap, const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, struct tile *ptile, bool fortified, int veteran)
Definition combat.c:657
int unit_bombard_rate(struct unit *punit)
Definition combat.c:959
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:712
int get_total_attack_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:567
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender)
Definition combat.c:438
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile)
Definition combat.c:781
void get_modified_firepower(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, int *att_fp, int *def_fp)
Definition combat.c:369
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:760
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:365
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:355
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:750
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
#define conn_list_iterate_end
Definition connection.h:115
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2839
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2570
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2600
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:992
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, const struct action *paction, enum effect_type effect_type)
Definition effects.c:957
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:267
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:765
struct extra_type * extra_by_number(int id)
Definition extras.c:175
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:195
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:159
#define extra_type_by_rmcause_iterate_end
Definition extras.h:334
#define extra_index(_e_)
Definition extras.h:177
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:329
#define EXTRA_NONE
Definition extras.h:82
#define extra_type_list_iterate_end
Definition extras.h:161
#define NO_TARGET
Definition fc_types.h:324
int Tech_type_id
Definition fc_types.h:347
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:319
@ RPT_CERTAIN
Definition fc_types.h:586
@ AUT_NONE
Definition fc_types.h:340
@ HB_DISABLED
Definition fc_types.h:1142
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:82
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
const char * tile_link(const struct tile *ptile)
const struct ft_color ftc_server
const char * city_link(const struct city *pcity)
const char * unit_link(const struct unit *punit)
const char * unit_tile_link(const struct unit *punit)
#define MAX_LEN_LINK
struct civ_game game
Definition game.c:57
int current_turn_timeout(void)
Definition game.c:828
struct world wld
Definition game.c:58
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:119
struct unit * game_unit_by_number(int id)
Definition game.c:111
struct city * game_city_by_number(int id)
Definition game.c:102
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1034
struct city * owner
Definition citydlg.c:219
GType type
Definition repodlgs.c:1312
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
@ H_LIMITEDHUTS
Definition handicaps.h:20
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:81
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:211
#define log_test
Definition log.h:136
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:639
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:665
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:454
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:369
bool base_get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile, enum direction8 *dir)
Definition map.c:1326
#define adjc_iterate_end
Definition map.h:427
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
#define square_iterate_end
Definition map.h:388
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:287
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:395
#define circle_iterate_end
Definition map.h:398
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2517
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2605
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1903
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2204
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2540
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2708
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:900
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:856
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1427
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:1979
bool give_distorted_map(struct player *pfrom, struct player *pto, int prob, bool reveal_cities)
Definition maphand.c:2680
struct vision_site * map_get_player_site(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1359
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1370
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2505
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:275
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:316
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:869
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:327
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:476
@ MR_OK
Definition movement.h:33
@ MR_NOT_ALLOWED
Definition movement.h:50
@ MR_DEATH
Definition movement.h:34
static const char * name_translation_get(const struct name_translation *ptrans)
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:462
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:177
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:292
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:239
unit_info_use
Definition packets.h:81
@ UNIT_INFO_IDENTITY
Definition packets.h:82
int send_packet_unit_remove(struct connection *pc, const struct packet_unit_remove *packet)
void lsend_packet_unit_remove(struct conn_list *dest, const struct packet_unit_remove *packet)
int send_packet_unit_short_info(struct connection *pc, const struct packet_unit_short_info *packet, bool force_to_send)
int send_packet_unit_info(struct connection *pc, const struct packet_unit_info *packet)
void dlsend_packet_unit_remove(struct conn_list *dest, int unit_id16, int unit_id32)
void pf_path_destroy(struct pf_path *path)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
void pf_map_destroy(struct pf_map *pfm)
#define pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1205
struct player * player_by_number(const int player_id)
Definition player.c:840
bool can_player_see_unit_at(const struct player *pplayer, const struct unit *punit, const struct tile *ptile, bool is_transported)
Definition player.c:1025
int player_slot_count(void)
Definition player.c:411
int player_number(const struct player *pplayer)
Definition player.c:828
const char * player_name(const struct player *pplayer)
Definition player.c:886
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1084
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1364
int player_index(const struct player *pplayer)
Definition player.c:820
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:317
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
struct player_slot * slots
Definition player.c:50
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1435
#define players_iterate_end
Definition player.h:535
#define players_iterate(_pplayer)
Definition player.h:530
static bool is_barbarian(const struct player *pplayer)
Definition player.h:488
#define is_ai(plr)
Definition player.h:234
#define is_human(plr)
Definition player.h:233
void player_update_last_war_action(struct player *pplayer)
Definition plrhand.c:746
void player_status_add(struct player *plr, enum player_status pstatus)
Definition plrhand.c:3042
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2191
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1000
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1425
#define phase_players_iterate(pplayer)
Definition plrhand.h:111
#define phase_players_iterate_end
Definition plrhand.h:116
#define fc_rand(_size)
Definition rand.h:34
bool are_reqs_active(const struct req_context *context, const struct player *other_player, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
const char * research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Definition research.c:238
struct research * research_get(const struct player *pplayer)
Definition research.c:126
void script_server_signal_emit(const char *signal_name,...)
void script_server_remove_exported_object(void *object)
void flush_packets(void)
Definition sernet.c:379
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1954
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
int identity_number(void)
Definition srv_main.c:1952
enum action_result result
Definition actions.h:382
bv_action_sub_results sub_results
Definition actions.h:383
enum act_tgt_compl target_complexity
Definition actions.h:390
struct act_prob prob
Definition unittools.c:115
Definition city.h:309
int id
Definition city.h:315
struct player * owner
Definition city.h:312
int airlift
Definition city.h:365
struct tile * tile
Definition city.h:311
struct unit_list * units_supported
Definition city.h:391
int unitwaittime
Definition game.h:197
struct civ_game::@30::@34 server
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:131
int killunhomed
Definition game.h:153
bool savepalace
Definition game.h:186
int ransom_gold
Definition game.h:174
bool autoattack
Definition game.h:130
int timeoutaddenemymove
Definition game.h:207
enum gameloss_style gameloss_style
enum goods_selection_method goods_selection
enum happyborders_type happyborders
int nuke_defender_survival_chance_pct
bool only_real_fight_makes_veteran
enum airlifting_style airlifting_style
bool only_killing_makes_veteran
bool combat_odds_scaled_veterancy
int upkeep[O_LAST]
enum action_decision action_decision_want
struct unit_order orders[MAX_LEN_ROUTE]
enum unit_activity activity
Unit_type_id type
enum unit_activity changed_from
enum direction8 facing
enum server_side_agent ssa_controller
enum direction8 facing
enum diplstate_type type
Definition player.h:201
int units_killed
Definition player.h:112
int units_lost
Definition player.h:113
bv_extras extras
Definition maphand.h:36
struct vision_site * site
Definition maphand.h:31
struct terrain * terrain
Definition maphand.h:33
struct player * owner
Definition maphand.h:34
struct city_list * cities
Definition player.h:281
struct unit_list * units
Definition player.h:282
struct conn_list * connections
Definition player.h:298
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
struct player_economic economic
Definition player.h:284
struct player_score score
Definition player.h:283
struct player::@69::@71 server
const struct player * player
Definition tile.h:49
int index
Definition tile.h:50
struct unit_list * units
Definition tile.h:57
struct unit_class::@85 cache
struct extra_type_list * refuel_extras
Definition unittype.h:155
bv_player can_see_unit
Definition unittools.c:95
struct player * powner
Definition unittools.c:94
bv_player can_see_move
Definition unittools.c:96
struct unit * punit
Definition unittools.c:93
struct vision * old_vision
Definition unittools.c:97
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
int vision_radius_sq
Definition unittype.h:503
enum vision_layer vlayer
Definition unittype.h:550
const struct unit_type * converted_to
Definition unittype.h:511
Definition unit.h:138
time_t action_timestamp
Definition unit.h:243
int length
Definition unit.h:195
int upkeep[O_LAST]
Definition unit.h:148
bool has_orders
Definition unit.h:193
enum action_decision action_decision_want
Definition unit.h:202
int battlegroup
Definition unit.h:191
enum unit_activity activity
Definition unit.h:157
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
bool moved
Definition unit.h:173
int index
Definition unit.h:195
struct vision * vision
Definition unit.h:242
bool vigilant
Definition unit.h:197
int hp
Definition unit.h:151
struct unit::@79 orders
int fuel
Definition unit.h:153
struct extra_type * changed_from_target
Definition unit.h:170
bool stay
Definition unit.h:205
enum direction8 facing
Definition unit.h:142
struct tile * tile
Definition unit.h:140
struct extra_type * activity_target
Definition unit.h:164
int activity_count
Definition unit.h:162
struct unit_order * list
Definition unit.h:198
enum unit_activity changed_from
Definition unit.h:168
struct player * nationality
Definition unit.h:144
bool repeat
Definition unit.h:196
void(* removal_callback)(struct unit *punit)
Definition unit.h:251
struct unit_move_data * moving
Definition unit.h:245
int action_turn
Definition unit.h:244
struct unit::@80::@83 server
int homecity
Definition unit.h:146
bool paradropped
Definition unit.h:174
bool done_moving
Definition unit.h:181
int birth_turn
Definition unit.h:235
struct goods_type * carrying
Definition unit.h:186
struct tile * goto_tile
Definition unit.h:155
struct tile * action_decision_tile
Definition unit.h:203
const struct unit_type * utype
Definition unit.h:139
int veteran
Definition unit.h:152
int changed_from_count
Definition unit.h:169
bool dying
Definition unit.h:248
enum server_side_agent ssa_controller
Definition unit.h:172
int base_raise_chance
Definition unittype.h:471
struct name_translation name
Definition unittype.h:468
int work_raise_chance
Definition unittype.h:472
bool occupied
Definition vision.h:117
struct civ_map map
#define sz_strlcpy(dest, src)
Definition support.h:161
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:109
#define A_NONE
Definition tech.h:43
#define A_UNSET
Definition tech.h:48
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
Definition techtools.c:1207
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:226
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:538
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:940
bool tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:193
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:209
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:658
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:227
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:412
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:87
#define tile_terrain(_tile)
Definition tile.h:109
#define TILE_XY(ptile)
Definition tile.h:42
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:119
#define tile_continent(_tile)
Definition tile.h:91
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
#define tile_owner(_tile)
Definition tile.h:95
struct goods_type * goods_from_city_to_unit(struct city *src, struct unit *punit)
Goods_type_id goods_index(const struct goods_type *pgood)
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer)
Definition unit.c:1333
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1769
void free_unit_orders(struct unit *punit)
Definition unit.c:1755
bool unit_is_alive(int id)
Definition unit.c:2239
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:505
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2356
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1108
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1272
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2427
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2376
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2169
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:846
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1619
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:873
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1715
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1282
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1974
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2411
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:771
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2437
bool unit_has_orders(const struct unit *punit)
Definition unit.c:207
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1898
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2021
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:541
bool can_unit_do_activity_targeted(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, struct extra_type *target)
Definition unit.c:912
#define unit_tile(_pu)
Definition unit.h:388
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:411
#define unit_cargo_iterate_end
Definition unit.h:562
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:399
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:559
#define CHECK_UNIT(punit)
Definition unit.h:268
#define unit_owner(_pu)
Definition unit.h:387
@ UU_OK
Definition unit.h:61
#define unit_home(_pu_)
Definition unit.h:386
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:423
void illegal_action_msg(struct player *pplayer, const enum event_type event, struct unit *actor, const action_id stopped_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:2352
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6176
bool unit_perform_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id_incoming, const char *name, const action_id action_type, const enum action_requester requester)
Definition unithand.c:3173
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5237
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void unit_did_action(struct unit *punit)
Definition unittools.c:4913
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3348
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:2967
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1181
static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype, bool helpless, bool teleporting, const struct city *pexclcity)
Definition unittools.c:2263
static void unit_move_by_data(struct unit_move_data *pdata, struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3805
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4372
static void unit_convert(struct unit *punit)
Definition unittools.c:766
void update_unit_activities(struct player *pplayer)
Definition unittools.c:658
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1324
#define unit_move_data_list_iterate_rev_end
Definition unittools.c:107
void transform_unit(struct unit *punit, const struct unit_type *to_unit, int vet_loss)
Definition unittools.c:1569
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1808
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1433
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1505
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1938
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1468
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4303
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:392
static int unit_vision_range_modifiers(struct unit *punit, const struct tile *ptile)
Definition unittools.c:4821
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1418
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3855
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1785
void unit_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp)
Definition unittools.c:352
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3225
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2654
#define unit_move_data_list_iterate_end
Definition unittools.c:104
void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
Definition unittools.c:2785
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:649
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3547
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:706
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:810
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3306
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3404
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:690
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:668
static bool find_a_good_partisan_spot(struct tile *pcenter, struct player *powner, struct unit_type *u_type, int sq_radius, struct tile **dst_tile)
Definition unittools.c:1133
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2798
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1962
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1389
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3734
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:622
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:416
int get_unit_vision_at(struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4839
bool unit_versus_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, int *att_vet, int *def_vet)
Definition unittools.c:286
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1727
void notify_unit_experience(struct unit *punit)
Definition unittools.c:735
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:792
void package_short_unit(struct unit *punit, struct packet_unit_short_info *packet, enum unit_info_use packet_use, int info_city_id)
Definition unittools.c:2737
struct unit * unit_virtual_prepare(struct player *pplayer, struct tile *ptile, const struct unit_type *type, int veteran_level, int homecity_id, int moves_left, int hp_left)
Definition unittools.c:1679
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1492
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1073
#define unit_move_data_list_iterate(_plist, _pdata)
Definition unittools.c:102
struct unit * create_unit_full(struct player *pplayer, struct tile *ptile, const struct unit_type *type, int veteran_level, int homecity_id, int moves_left, int hp_left, struct unit *ptrans)
Definition unittools.c:1646
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1929
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1799
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:217
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4852
struct unit * create_unit(struct player *pplayer, struct tile *ptile, const struct unit_type *type, int veteran_level, int homecity_id, int moves_left)
Definition unittools.c:1619
void do_explore(struct unit *punit)
Definition unittools.c:3000
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3276
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:4880
#define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, _unit_)
Definition unittools.c:122
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2251
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:680
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3036
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4345
void player_restore_units(struct player *pplayer)
Definition unittools.c:469
void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
Definition unittools.c:2950
static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
Definition unittools.c:2870
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1547
static void update_unit_activity(struct unit *punit)
Definition unittools.c:852
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3328
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1538
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Definition unittools.c:174
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3536
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:4928
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:726
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:822
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2311
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1207
static int get_unit_vision_base(struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4800
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3194
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1102
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3362
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:837
static bool unit_move_consequences(struct unit *punit, struct tile *src_tile, struct tile *dst_tile, bool passenger, bool conquer_city_allowed)
Definition unittools.c:3617
void unit_get_goods(struct unit *punit)
Definition unittools.c:1630
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2842
static bool maybe_become_veteran_real(struct unit *punit, int base_chance, bool settler)
Definition unittools.c:235
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4316
bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost, struct unit *embark_to, bool find_embark_target, bool conquer_city_allowed, bool conquer_extras_allowed, bool enter_hut, bool frighten_hut)
Definition unittools.c:3884
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4869
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2377
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1245
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1082
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1621
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2301
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1639
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2615
int num_role_units(int role)
Definition unittype.c:2251
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1979
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1755
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype)
Definition unittype.c:2015
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2546
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:202
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2631
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:753
#define utype_class(_t_)
Definition unittype.h:736
#define utype_fuel(ptype)
Definition unittype.h:822
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
#define U_LAST
Definition unittype.h:40
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
void vision_free(struct vision *vision)
Definition vision.c:50
#define ASSERT_VISION(v)
Definition vision.h:98
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition vision.h:96
#define vision_site_owner(v)
Definition vision.h:128
short int v_radius_t[V_COUNT]
Definition vision.h:83