Freeciv-3.2
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;
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,
153 struct player *killer);
154
155static int get_unit_vision_base(const struct unit *punit,
156 enum vision_layer vlayer,
157 const int base);
158static int unit_vision_range_modifiers(const struct unit *punit,
159 const struct tile *ptile);
160
161/**********************************************************************/
177{
178 struct unit_type *which[U_LAST];
179 int i, num = 0;
180
181 if (role_tech != -1) {
182 for (i = 0; i < num_role_units(role_tech); i++) {
184 const int minplayers = 2;
185 int players = 0;
186
187 /* Note, if there's only one player in the game this check will always
188 * fail. */
189 players_iterate(pplayer) {
190 if (!is_barbarian(pplayer)
192 players++;
193 }
195
196 if (players > minplayers) {
197 which[num++] = iunit;
198 }
199 }
200 }
201 if (num == 0) {
202 for (i = 0; i < num_role_units(role); i++) {
203 which[num++] = get_role_unit(role, i);
204 }
205 }
206
207 /* Ruleset code should ensure there is at least one unit for each
208 * possibly-required role, or check before calling this function. */
209 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
210 role, role_tech);
211
212 return which[fc_rand(num)];
213}
214
215/**********************************************************************/
223
224/**********************************************************************/
238 bool settler)
239{
240 const struct veteran_system *vsystem;
241 const struct veteran_level *vlevel;
242 int chance;
243
245
249
252
253 if (punit->veteran + 1 >= vsystem->levels
255 return FALSE;
256 } else if (!settler) {
258
259 /* The modification is tacked on as a multiplier to the base chance.
260 * For example with a base chance of 50% for green units and a modifier
261 * of +50% the end chance is 75%. */
262 chance = vlevel->base_raise_chance * mod / 100;
263 } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
264 chance = base_chance * vlevel->work_raise_chance / 100;
265 } else {
266 /* No battle and no work done. */
267 return FALSE;
268 }
269
270 if (fc_rand(100) < chance) {
271 punit->veteran++;
272 return TRUE;
273 }
274
275 return FALSE;
276}
277
278/**********************************************************************/
288bool unit_versus_unit(struct unit *attacker, struct unit *defender,
289 int *att_hp, int *def_hp, int *att_vet, int *def_vet,
290 const struct action *paction)
291{
292 int attackpower = get_total_attack_power(attacker, defender, paction);
293 int defensepower = get_total_defense_power(attacker, defender);
295 struct player *plr1 = unit_owner(attacker);
296 struct player *plr2 = unit_owner(defender);
297 struct civ_map *nmap = &(wld.map);
298 int max_rounds;
299 int rounds;
300 int att_strength;
301 int def_strength;
302
303 *att_hp = attacker->hp;
304 *def_hp = defender->hp;
305 get_modified_firepower(nmap, attacker, defender,
307
308 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
309 "defense firepower:%d", attackpower, defensepower,
311
314
317
318 /* In a combat between equal strength units the values are 50% / 50%.
319 * -> scaling that to 100% by doubling, to match scale of chances
320 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
323
324 if (attackpower == 0) {
325 *att_hp = 0;
326 } else if (defensepower == 0) {
327 *def_hp = 0;
328 }
330 for (rounds = 0;
331 *att_hp > 0 && *def_hp > 0
333 rounds++) {
335 *def_hp -= attack_firepower;
336 } else {
337 *att_hp -= defense_firepower;
338 }
339 }
340 if (*att_hp < 0) {
341 *att_hp = 0;
342 }
343 if (*def_hp < 0) {
344 *def_hp = 0;
345 }
346
347 return attackpower <= 0 || defensepower <= 0;
348}
349
350/**********************************************************************/
355void unit_bombs_unit(struct unit *attacker, struct unit *defender,
356 int *att_hp, int *def_hp,
357 const struct action *paction)
358{
359 int i;
360 int rate = unit_bombard_rate(attacker);
361 int attackpower = get_total_attack_power(attacker, defender, paction);
362 int defensepower = get_total_defense_power(attacker, defender);
364 struct player *plr1 = unit_owner(attacker);
365 struct player *plr2 = unit_owner(defender);
366 struct civ_map *nmap = &(wld.map);
367
368 *att_hp = attacker->hp;
369 *def_hp = defender->hp;
370 get_modified_firepower(nmap, attacker, defender,
372
373 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
374 "defense firepower:%d", attackpower, defensepower,
376
379
380 for (i = 0; i < rate; i++) {
382 *def_hp -= attack_firepower;
383 }
384 }
385
386 if (*def_hp <= 0) {
387 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
388 /* Don't kill the target. */
389 *def_hp = 1;
390 } else {
391 *def_hp = 0;
392 }
393 }
394}
395
396/**********************************************************************/
400void combat_veterans(struct unit *attacker, struct unit *defender,
401 bool powerless, int att_vet, int def_vet)
402{
404 if (attacker->hp <= 0 || defender->hp <= 0
407 att_vet = 100;
408 def_vet = 100;
409 }
410 if (attacker->hp > 0) {
411 maybe_make_veteran(attacker, att_vet);
412 }
413 if (defender->hp > 0) {
414 maybe_make_veteran(defender, def_vet);
415 }
416 }
417 }
418}
419
420/**********************************************************************/
424static void do_upgrade_effects(struct player *pplayer)
425{
427 struct unit_list *candidates;
428
429 if (upgrades <= 0) {
430 return;
431 }
433
434 unit_list_iterate(pplayer->units, punit) {
435 /* We have to be careful not to strand units at sea, for example by
436 * upgrading a frigate to an ironclad while it was carrying a unit. */
437 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
438 unit_list_prepend(candidates, punit); /* Potential candidate :) */
439 }
441
442 while (upgrades > 0 && unit_list_size(candidates) > 0) {
443 /* Upgrade one unit. The unit is chosen at random from the list of
444 * available candidates. */
447 const struct unit_type *type_from = unit_type_get(punit);
448 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
449
452 _("%s was upgraded for free to %s."),
456 upgrades--;
457 }
458
460}
461
462/**********************************************************************/
477void player_restore_units(struct player *pplayer)
478{
479 const struct civ_map *nmap = &(wld.map);
480
481 /* 1) get Leonardo out of the way first: */
482 do_upgrade_effects(pplayer);
483
485
486 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
488
489 /* 3) Check that unit has hitpoints */
490 if (punit->hp <= 0) {
491 /* This should usually only happen for heli units, but if any other
492 * units get 0 hp somehow, catch them too. --dwp */
493 /* if 'game.server.killunhomed' is activated unhomed units are slowly
494 * killed; notify player here */
495 if (!punit->homecity && 0 < game.server.killunhomed) {
497 ftc_server, _("Your %s has run out of hit points "
498 "because it was not supported by a city."),
500 } else {
502 _("Your %s has run out of hit points."),
504 }
505
507 continue; /* Continue iterating... */
508 }
509
510 /* 4) Rescue planes if needed */
512 /* Shall we emergency return home on the last vapors? */
513
514 /* I think this is strongly against the spirit of client goto.
515 * The problem is (again) that here we know too much. -- Zamar */
516
517 if (punit->fuel <= 1
519 struct unit *carrier;
520
522 if (carrier) {
524 } else {
525 struct pf_map *pfm;
526 struct pf_parameter parameter;
527 bool alive = TRUE;
528
529 pft_fill_unit_parameter(&parameter, nmap, punit);
530 parameter.omniscience = !has_handicap(pplayer, H_MAP);
531 pfm = pf_map_new(&parameter);
532
533 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
534 if (move_cost > punit->moves_left) {
535 /* Too far */
536 break;
537 }
538
539 if (is_refuel_point(ptile, pplayer, punit)) {
540 struct pf_path *path;
541 int id = punit->id;
542
543 /* Client orders may be running for this unit - if so
544 * we free them before engaging goto. */
546
547 path = pf_map_path(pfm, ptile);
548
549 alive = adv_follow_path(punit, path, ptile);
550
551 if (!alive) {
552 log_error("rescue plane: unit %d died enroute!", id);
553 } else if (!same_pos(unit_tile(punit), ptile)) {
554 /* Enemy units probably blocked our route
555 * FIXME: We should try find alternative route around
556 * the enemy unit instead of just giving up and crashing. */
557 log_debug("rescue plane: unit %d could not move to "
558 "refuel point!", punit->id);
559 }
560
561 if (alive) {
562 /* Clear activity. Unit info will be sent in the end of
563 * the function. */
567
570 if (carrier) {
572 }
573 }
574
575 notify_player(pplayer, unit_tile(punit),
577 _("Your %s has returned to refuel."),
579 }
580 pf_path_destroy(path);
581 break;
582 }
585
586 if (!alive) {
587 /* Unit died trying to move to refuel point. */
588 return;
589 }
590 }
591 }
592
593 /* 5) Update fuel */
594 punit->fuel--;
595
596 /* 6) Automatically refuel air units in cities, airbases, and
597 * transporters (carriers). */
600 }
601 }
603
604 /* 7) Check if there are air units without fuel */
606 const struct unit_type *utype = unit_type_get(punit);
607
608 if (punit->fuel <= 0 && utype_fuel(utype)) {
609 /* Notifications sent from the lua script when unit wiped. */
611 }
613
614 /* Send all updates. */
615 unit_list_iterate(pplayer->units, punit) {
618}
619
620/**********************************************************************/
631{
632 bool was_lower;
633 const struct unit_type *utype = unit_type_get(punit);
634
635 was_lower = (punit->hp < utype->hp);
636
638
639 fc_assert(punit->hp >= 0);
640 fc_assert(punit->hp <= utype->hp);
641
642 if (punit->hp == utype->hp) {
645 }
646 }
647
648 punit->moved = FALSE;
650}
651
652/**********************************************************************/
657static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
658{
661}
662
663/**********************************************************************/
672
673/**********************************************************************/
676void execute_unit_orders(struct player *pplayer)
677{
679 if (unit_has_orders(punit)) {
681 }
683}
684
685/**********************************************************************/
688void unit_tc_effect_refresh(struct player *pplayer)
689{
690 unit_list_iterate(pplayer->units, punit) {
693}
694
695/**********************************************************************/
699{
700 /* Remember activities only after all knock-on effects of unit activities
701 * on other units have been resolved */
702 unit_list_iterate(pplayer->units, punit) {
708}
709
710/**********************************************************************/
714static int total_activity(struct tile *ptile, enum unit_activity act,
715 struct extra_type *tgt)
716{
717 int total = 0;
719
720 unit_list_iterate(ptile->units, punit) {
721 if (punit->activity == act
722 && (!tgt_matters || punit->activity_target == tgt)) {
723 total += punit->activity_count;
724 }
726
727 return total;
728}
729
730/**********************************************************************/
734static bool total_activity_done(struct tile *ptile, enum unit_activity act,
735 struct extra_type *tgt)
736{
737 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
738}
739
740/**********************************************************************/
744{
745 const struct veteran_level *vlevel;
746 const struct veteran_system *vsystem;
747
748 if (!punit) {
749 return;
750 }
751
755
758
761 /* TRANS: Your <unit> became ... rank of <veteran level>. */
762 _("Your %s became more experienced and achieved the rank "
763 "of %s."),
765}
766
767/**********************************************************************/
770static void unit_convert(struct unit *punit)
771{
772 const struct unit_type *to_type;
773 const struct unit_type *from_type;
774
776 to_type = from_type->converted_to;
777
778 if (unit_can_convert(&(wld.map), punit)) {
782 _("%s converted to %s."),
785 } else {
788 _("%s cannot be converted."),
790 }
791}
792
793/**********************************************************************/
797{
798 if (unit_has_orders(punit)) {
801 _("Orders for %s aborted because activity "
802 "is no longer available."),
805 }
806
809}
810
811/**********************************************************************/
822
823/**********************************************************************/
834
835/**********************************************************************/
849
850/**********************************************************************/
854static void update_unit_activity(struct unit *punit)
855{
856 struct player *pplayer = unit_owner(punit);
858 enum unit_activity activity = punit->activity;
859 struct tile *ptile = unit_tile(punit);
860 const struct unit_type *act_utype = unit_type_get(punit);
861
862 switch (activity) {
863 case ACTIVITY_IDLE:
864 case ACTIVITY_EXPLORE:
866 case ACTIVITY_SENTRY:
867 case ACTIVITY_GOTO:
868 case ACTIVITY_LAST:
869 /* We don't need the activity_count for the above */
870 break;
871
873 case ACTIVITY_CONVERT:
875 break;
876
877 case ACTIVITY_CLEAN:
878 case ACTIVITY_MINE:
880 case ACTIVITY_PILLAGE:
882 case ACTIVITY_PLANT:
884 case ACTIVITY_BASE:
887
888 /* Settler may become veteran when doing something useful */
891 }
892 break;
893 };
894
896
897 switch (activity) {
898 case ACTIVITY_EXPLORE:
899 /* Not accumulating activity - will be handled more like movement
900 * after the TC */
902 case ACTIVITY_IDLE:
904 case ACTIVITY_SENTRY:
905 case ACTIVITY_GOTO:
907 case ACTIVITY_CONVERT:
908 case ACTIVITY_LAST:
909 /* No default, ensure all handled */
910 break;
911
912 case ACTIVITY_PILLAGE:
917
919
920 /* Change vision if effects have changed. */
922 }
923 break;
924
925 case ACTIVITY_CLEAN:
926 /* TODO: Remove this fallback target setting when target always correctly
927 * set */
928 {
929 struct extra_type *pextra;
930
931 if (punit->activity_target == NULL) {
932 pextra = prev_extra_in_tile(ptile, ERM_CLEAN,
933 NULL, punit);
934 if (pextra != NULL) {
935 punit->activity_target = pextra;
936 }
937 } else {
939 pextra = punit->activity_target;
940 } else {
941 pextra = NULL;
942 }
943 }
944
945 if (pextra != NULL) {
946 if (total_activity_done(ptile, ACTIVITY_CLEAN, pextra)) {
947 destroy_extra(ptile, pextra);
949 }
950 }
951 }
952 break;
953
954 case ACTIVITY_BASE:
955 {
960 }
961 }
962 break;
963
965 {
970 }
971 }
972 break;
973
975 case ACTIVITY_MINE:
977 case ACTIVITY_PLANT:
979 if (total_activity_done(ptile, activity, punit->activity_target)) {
980 struct terrain *old = tile_terrain(ptile);
981
982 /* The function below could change the terrain. Therefore, we have to
983 * check the terrain (which will also do a sanity check for the tile). */
984 tile_apply_activity(ptile, activity, punit->activity_target);
985 check_terrain_change(ptile, old);
987 }
988 break;
989 }
990
991 if (unit_activity_done) {
993
995
997 if (punit2->activity == activity
998 && punit2->activity_target == act_tgt) {
999 /* This unit was helping with the work just finished.
1000 * Mark it idle (already finished) so its "current"
1001 * activity is not considered illegal
1002 * in tile_change_side_effects() . */
1004 }
1006
1008 }
1009
1010 if (activity == ACTIVITY_FORTIFYING) {
1013 punit, ptile, punit->activity_target)) {
1016 }
1017 }
1018
1019 if (activity == ACTIVITY_CONVERT) {
1022 punit, ptile, punit->activity_target)) {
1026 }
1027 }
1028
1029 if (unit_activity_done) {
1030 if (activity == ACTIVITY_PILLAGE) {
1031 /* Casus Belli for when the action is completed. */
1032 /* TODO: is it more logical to put Casus_Belli_Success here, change
1033 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1034 * trigger it when an activity successfully has began? */
1037 act_utype,
1041 }
1042 }
1043}
1044
1045/**********************************************************************/
1053
1054/**********************************************************************/
1059{
1060 switch (activity) {
1061 case ACTIVITY_PILLAGE:
1062 /* Can be set server side. */
1063 return FALSE;
1064 default:
1065 return activity_requires_target(activity);
1066 }
1067}
1068
1069/**********************************************************************/
1079 enum unit_activity *activity,
1080 struct extra_type **target)
1081{
1082 const struct civ_map *nmap = &(wld.map);
1083
1084 if (*activity == ACTIVITY_PILLAGE
1085 && *target == NULL) {
1086 struct tile *ptile = unit_tile(punit);
1087 struct extra_type *tgt;
1088 bv_extras extras = *tile_extras(ptile);
1089
1090 while ((tgt = get_preferred_pillage(extras))) {
1091
1092 BV_CLR(extras, extra_index(tgt));
1093
1094 if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
1095 *target = tgt;
1096 return;
1097 }
1098 }
1099
1100 /* Nothing we can pillage here. */
1101 *activity = ACTIVITY_IDLE;
1102 }
1103}
1104
1105/**********************************************************************/
1110 struct player *powner,
1111 struct unit_type *u_type,
1112 int sq_radius,
1113 struct tile **dst_tile)
1114{
1115 int bestvalue = 0;
1116 struct civ_map *nmap = &(wld.map);
1117
1118 /* coords of best tile in arg pointers */
1120 int value;
1121
1122 if (!is_native_tile(u_type, ptile)) {
1123 continue;
1124 }
1125
1126 if (NULL != tile_city(ptile)) {
1127 continue;
1128 }
1129
1130 if (0 < unit_list_size(ptile->units)) {
1131 continue;
1132 }
1133
1134 /* City may not have changed hands yet; see place_partisans(). */
1135 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1136 ptile, FALSE, 0);
1137 value *= 10;
1138
1139 if (tile_continent(ptile) != tile_continent(pcenter)) {
1140 value /= 2;
1141 }
1142
1143 value -= fc_rand(value/3);
1144
1145 if (value > bestvalue) {
1146 *dst_tile = ptile;
1147 bestvalue = value;
1148 }
1150
1151 return bestvalue > 0;
1152}
1153
1154/**********************************************************************/
1157void place_partisans(struct tile *pcenter, struct player *powner,
1158 int count, int sq_radius)
1159{
1160 struct tile *ptile = NULL;
1162 const struct civ_map *nmap = &(wld.map);
1163
1164 while (count-- > 0
1166 sq_radius, &ptile)) {
1167 struct unit *punit;
1168
1169 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1171 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1172 }
1173
1174 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1175 }
1176}
1177
1178/**********************************************************************/
1183bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1184 int move_cost, bool verbose)
1185{
1186 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1187
1188 if (city_owner(pcity) == unit_owner(punit)) {
1189 log_verbose("Teleported %s %s from (%d,%d) to %s",
1191 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1192 if (verbose) {
1195 _("Teleported your %s to %s."),
1197 city_link(pcity));
1198 }
1199
1200 /* Silently free orders since they won't be applicable anymore. */
1202
1203 if (move_cost == -1) {
1204 move_cost = punit->moves_left;
1205 }
1206 unit_move(punit, dst_tile, move_cost,
1208
1209 return TRUE;
1210 }
1211 return FALSE;
1212}
1213
1214/**********************************************************************/
1221void bounce_unit(struct unit *punit, bool verbose)
1222{
1223 struct player *pplayer;
1224 struct tile *punit_tile;
1225 int count = 0;
1226
1227 /* I assume that there are no topologies that have more than
1228 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1229 const int DIST = 2;
1230 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1231
1232 if (!punit) {
1233 return;
1234 }
1235
1236 pplayer = unit_owner(punit);
1238
1239 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1240 if (count >= ARRAY_SIZE(tiles)) {
1241 break;
1242 }
1243
1244 if (ptile == punit_tile) {
1245 continue;
1246 }
1247
1248 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1249 && !is_non_allied_city_tile(ptile, pplayer)
1250 && !is_non_allied_unit_tile(ptile, pplayer)) {
1251 tiles[count++] = ptile;
1252 }
1254
1255 if (count > 0) {
1256 struct tile *ptile = tiles[fc_rand(count)];
1257
1258 if (verbose) {
1259 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1260 /* TRANS: A unit is moved to resolve stack conflicts. */
1261 _("Moved your %s."),
1262 unit_link(punit));
1263 }
1264
1265 /* TODO: should a unit be able to bounce to a transport like is done
1266 * below? What if the unit can't legally enter the transport, say
1267 * because the transport is Unreachable and the unit doesn't have it in
1268 * its embarks field or because "Transport Embark" isn't enabled? Kept
1269 * like it was to preserve the old rules for now. -- Sveinung */
1270 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1271 return;
1272 }
1273
1274 /* Didn't find a place to bounce the unit, going to disband it.
1275 * Try to bounce transported units. */
1277 struct unit_list *pcargo_units;
1278
1281 bounce_unit(pcargo, verbose);
1283 }
1284
1285 if (verbose) {
1287 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1288 _("Disbanded your %s."),
1290 }
1291
1293}
1294
1295/**********************************************************************/
1300static void throw_units_from_illegal_cities(struct player *pplayer,
1301 bool verbose)
1302{
1303 struct tile *ptile;
1304 struct city *pcity;
1305 struct unit *ptrans;
1306 struct unit_list *pcargo_units;
1307
1308 /* Unload undesired units from transports, if possible. */
1309 unit_list_iterate(pplayer->units, punit) {
1310 ptile = unit_tile(punit);
1311 pcity = tile_city(ptile);
1312 if (NULL != pcity
1313 && !pplayers_allied(city_owner(pcity), pplayer)
1317 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1318 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1320 }
1321 }
1323 }
1325
1326 /* Bounce units except transported ones which will be bounced with their
1327 * transport. */
1329 ptile = unit_tile(punit);
1330 pcity = tile_city(ptile);
1331 if (NULL != pcity
1332 && !pplayers_allied(city_owner(pcity), pplayer)) {
1334 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1335 bounce_unit(punit, verbose);
1336 }
1337 }
1339
1340#ifdef FREECIV_DEBUG
1341 /* Sanity check. */
1342 unit_list_iterate(pplayer->units, punit) {
1343 ptile = unit_tile(punit);
1344 pcity = tile_city(ptile);
1345 fc_assert_msg(NULL == pcity
1346 || pplayers_allied(city_owner(pcity), pplayer),
1347 "Failed to throw %s %d from %s %d (%d, %d)",
1349 punit->id,
1350 city_name_get(pcity),
1351 pcity->id,
1352 TILE_XY(ptile));
1354#endif /* FREECIV_DEBUG */
1355}
1356
1357/**********************************************************************/
1365static void resolve_stack_conflicts(struct player *pplayer,
1366 struct player *aplayer, bool verbose)
1367{
1369 struct tile *ptile = unit_tile(punit);
1370
1371 if (is_non_allied_unit_tile(ptile, pplayer)) {
1373 if (unit_owner(aunit) == pplayer
1374 || unit_owner(aunit) == aplayer
1375 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1376 bounce_unit(aunit, verbose);
1377 }
1379 }
1381}
1382
1383/**********************************************************************/
1394void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1395 bool verbose)
1396{
1397 throw_units_from_illegal_cities(pplayer, verbose);
1399
1400 resolve_stack_conflicts(pplayer, aplayer, verbose);
1401 resolve_stack_conflicts(aplayer, pplayer, verbose);
1402}
1403
1404/**********************************************************************/
1409struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1410 const struct player *aplayer)
1411{
1412 struct unit_list *seen_units = unit_list_new();
1413
1414 /* Anybody's units inside ally's cities */
1415 city_list_iterate(aplayer->cities, pcity) {
1416 unit_list_iterate(city_tile(pcity)->units, punit) {
1417 if (can_player_see_unit(pplayer, punit)) {
1419 }
1422
1423 /* Ally's own units inside transports */
1425 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1427 }
1429
1430 /* Make sure the same unit is not added in multiple phases
1431 * (unit within transport in a city) */
1433
1434 return seen_units;
1435}
1436
1437/**********************************************************************/
1444void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1445 const struct unit_list *seen_units)
1446{
1448 /* We need to hide units previously seen by the client. */
1449 if (!can_player_see_unit(pplayer, punit)) {
1450 unit_goes_out_of_sight(pplayer, punit);
1451 }
1453
1454 city_list_iterate(aplayer->cities, pcity) {
1455 /* The player used to know what units were in these cities. Now that
1456 * they don't, they need to get a new short city packet updating the
1457 * occupied status. */
1458 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1459 send_city_info(pplayer, pcity);
1460 }
1462}
1463
1464/**********************************************************************/
1468void give_allied_visibility(struct player *pplayer,
1469 struct player *aplayer)
1470{
1472 if (can_player_see_unit(pplayer, punit)) {
1473 send_unit_info(pplayer->connections, punit);
1474 }
1476}
1477
1478/**********************************************************************/
1481static bool is_refuel_tile(const struct tile *ptile,
1482 const struct player *pplayer,
1483 const struct unit *punit)
1484{
1485 const struct unit_type *utype;
1486 const struct unit_class *pclass;
1487
1488 if (is_allied_city_tile(ptile, pplayer)) {
1489 return TRUE;
1490 }
1491
1492 utype = unit_type_get(punit);
1493 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1494 return TRUE;
1495 }
1496
1497 pclass = utype_class(utype);
1498 if (NULL != pclass->cache.refuel_extras) {
1499 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1500
1501 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1502 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1503 return TRUE;
1504 }
1506 }
1507
1508 return FALSE;
1509}
1510
1511/**********************************************************************/
1515{
1516 return unit_transported(punit) /* Carrier */
1518}
1519
1520/**********************************************************************/
1523bool is_refuel_point(const struct tile *ptile,
1524 const struct player *pplayer,
1525 const struct unit *punit)
1526{
1527 if (is_non_allied_unit_tile(ptile, pplayer)) {
1528 return FALSE;
1529 }
1530
1531 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1532}
1533
1534/**********************************************************************/
1545void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1546 int vet_loss)
1547{
1548 struct player *pplayer = unit_owner(punit);
1549 const struct unit_type *old_type = punit->utype;
1551 int old_hp = unit_type_get(punit)->hp;
1552 int lvls;
1553
1554 punit->utype = to_unit;
1555
1556 /* New type may not have the same veteran system, and we may want to
1557 * knock some levels off. */
1560 /* Keeping the old behaviour, so first clip top, then reduce */
1562
1563 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1564 * and don't kill the unit. unit_move_rate() is used to take into account
1565 * global effects like Magellan's Expedition. */
1566 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1567 if (old_mr == 0) {
1569 } else {
1571 }
1572
1574
1578 }
1579
1580 /* Update unit upkeep */
1582
1584
1586
1587 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1589
1592}
1593
1594/**********************************************************************/
1597struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1598 const struct unit_type *type, int veteran_level,
1599 int homecity_id, int moves_left)
1600{
1601 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1602 moves_left, -1, NULL);
1603}
1604
1605/**********************************************************************/
1609{
1610 if (punit->homecity != 0) {
1612
1615 }
1616 }
1617}
1618
1619/**********************************************************************/
1624struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1625 const struct unit_type *type, int veteran_level,
1626 int homecity_id, int moves_left, int hp_left,
1627 struct unit *ptrans)
1628{
1629 struct unit *punit
1630 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1632 struct city *pcity = (!homecity_id || utype_has_flag(type, UTYF_NOHOME))
1634 bool could_place;
1635
1637 could_place = place_unit(punit, pplayer, pcity, ptrans, FALSE);
1639 if (!could_place) {
1641 punit = NULL;
1642 }
1643
1644 return punit;
1645}
1646
1647/**********************************************************************/
1657struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1658 const struct unit_type *type,
1659 int veteran_level, int homecity_id,
1660 int moves_left, int hp_left)
1661{
1662 struct unit *punit;
1663
1664 fc_assert_ret_val(ptile != NULL, NULL);
1666 unit_tile_set(punit, ptile);
1667
1669 punit->homecity = 0; /* none */
1670 } else {
1672 }
1673
1674 if (hp_left >= 0) {
1675 /* Override default full HP */
1676 punit->hp = hp_left;
1677 }
1678
1679 if (moves_left >= 0) {
1680 int mr = unit_move_rate(punit);
1681
1682 /* Override default full MP */
1683 /* FIXME: there are valid situations when a unit have mp
1684 * over its move rate. Here, keeping the old behavior. */
1686 /* Assume that if moves_left < 0 then the unit is "fresh",
1687 * and not moved; else the unit has had something happen
1688 * to it (eg, bribed) which we treat as equivalent to moved.
1689 * (Otherwise could pass moved arg too...) --dwp */
1690 punit->moved = TRUE;
1691 }
1692
1693 return punit;
1694}
1695
1696/**********************************************************************/
1705bool place_unit(struct unit *punit, struct player *pplayer,
1706 struct city *pcity, struct unit *ptrans, bool force)
1707{
1708 struct tile *ptile;
1709
1710 fc_assert_ret_val(pplayer, FALSE);
1712 ptile = punit->tile;
1713 fc_assert_ret_val(ptile, FALSE);
1714
1715 /* Register unit */
1718
1719 if (ptrans) {
1720 /* Set transporter for unit. */
1722 }
1723
1725 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1726 FALSE);
1727
1728 unit_list_prepend(pplayer->units, punit);
1729 unit_list_prepend(ptile->units, punit);
1731 if (pcity && !unit_has_type_flag(punit, UTYF_NOHOME)) {
1732 fc_assert(punit->homecity == pcity->id);
1733 fc_assert(city_owner(pcity) == pplayer);
1735 /* update unit upkeep */
1736 city_units_upkeep(pcity);
1737 /* Refresh the unit's homecity. */
1738 city_refresh(pcity);
1739 send_city_info(pplayer, pcity);
1740 }
1741
1742 punit->server.vision = vision_new(pplayer, ptile);
1744
1747
1748 /* The unit may have changed the available tiles in nearby cities. */
1750 sync_cities();
1751
1753
1754 CALL_FUNC_EACH_AI(unit_created, punit);
1755 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1756
1757 return TRUE;
1758}
1759
1760/**********************************************************************/
1764 void (*callback)(struct unit *punit))
1765{
1766 /* Tried to overwrite another call back. If this assertion is triggered
1767 * in a case where two call back are needed it may be time to support
1768 * more than one unit removal call back at a time. */
1770
1772}
1773
1774/**********************************************************************/
1781
1782/**********************************************************************/
1786static void server_remove_unit_full(struct unit *punit, bool transported,
1788{
1789 struct packet_unit_remove packet;
1790 struct tile *ptile = unit_tile(punit);
1791 struct city *pcity = tile_city(ptile);
1793 struct unit *ptrans;
1794 struct player *pplayer = unit_owner(punit);
1795
1796 /* The unit is doomed. */
1798
1799#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1800 unit_list_iterate(ptile->units, pcargo) {
1803#endif /* FREECIV_DEBUG */
1804
1805 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1806 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1807
1808 /* Save transporter for updating below. */
1810 /* Unload unit. */
1812
1813 /* Since settlers plot in new cities in the minimap before they
1814 are built, so that no two settlers head towards the same city
1815 spot, we need to ensure this reservation is cleared should
1816 the settler disappear on the way. */
1818
1819 /* Clear the vision before sending unit remove. Else, we might duplicate
1820 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1821 if (punit->server.vision != NULL) {
1825 }
1826
1827 packet.unit_id = punit->id;
1828 /* Send to onlookers. */
1831 transported)) {
1832 lsend_packet_unit_remove(aplayer->connections, &packet);
1833 }
1835 /* Send to global observers. */
1839 }
1841
1842 if (punit->server.moving != NULL) {
1843 /* Do not care of this unit for running moves. */
1845 }
1846
1848 /* Run the unit removal call back. */
1850 }
1851
1852 /* check if this unit had UTYF_GAMELOSS flag */
1854 && ULR_EDITOR != reason) {
1856 _("Unable to defend %s, %s has lost the game."),
1858 player_name(pplayer));
1859 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1860 _("Losing %s meant losing the game! "
1861 "Be more careful next time!"),
1862 unit_link(punit));
1864 }
1865
1868
1871 punit = NULL;
1872
1873 if (NULL != ptrans) {
1874 /* Update the occupy info. */
1876 }
1877
1878 /* This unit may have blocked tiles of adjacent cities. Update them. */
1880 sync_cities();
1881
1882 if (phomecity) {
1885 }
1886
1887 if (pcity && pcity != phomecity) {
1888 city_refresh(pcity);
1889 send_city_info(city_owner(pcity), pcity);
1890 }
1891
1892 if (pcity && unit_list_size(ptile->units) == 0) {
1893 /* The last unit in the city was killed: update the occupied flag. */
1894 send_city_info(NULL, pcity);
1895 }
1896}
1897
1898/**********************************************************************/
1907
1908/**********************************************************************/
1911static void unit_lost_with_transport(const struct player *pplayer,
1912 struct unit *pcargo,
1913 const struct unit_type *ptransport,
1914 struct player *killer)
1915{
1917 _("%s lost when %s was lost."),
1920 /* Unit is not transported any more at this point, but it has jumped
1921 * off the transport and drowns outside. So it must be removed from
1922 * all clients.
1923 * However, we don't know if given client has received ANY updates
1924 * about the swimming unit, and we can't remove it if it's not there
1925 * in the first place -> we send it once here just to be sure it's
1926 * there. */
1929}
1930
1931/**********************************************************************/
1935static void wipe_unit_full(struct unit *punit, bool transported,
1937 struct player *killer)
1938{
1939 struct tile *ptile = unit_tile(punit);
1940 struct player *pplayer = unit_owner(punit);
1941 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1942 struct unit_list *helpless = unit_list_new();
1943 struct unit_list *imperiled = unit_list_new();
1944 struct unit_list *unsaved = unit_list_new();
1946 struct city *pexclcity;
1947 struct civ_map *nmap = &(wld.map);
1948
1949 if (killer != NULL
1952 player_loot_player(killer, pplayer);
1953 }
1954
1955 /* The unit is doomed. */
1957
1958 /* If a unit is being lost due to loss of its city, ensure that we don't
1959 * try to teleport any of its cargo to that city (which may not yet
1960 * have changed hands or disappeared). (It is assumed that the unit's
1961 * home city is always the one that is being lost/transferred/etc.) */
1962 if (reason == ULR_CITY_LOST) {
1964 } else {
1965 pexclcity = NULL;
1966 }
1967
1968 /* Remove unit itself from its transport */
1969 if (ptrans != NULL) {
1972 }
1973
1974 /* First pull all units off of the transporter. */
1976 /* Use iterate_safe as unloaded units will be removed from the list
1977 * while iterating. */
1979 bool healthy = FALSE;
1980
1981 if (!can_unit_unload(pcargo, punit)) {
1983 } else {
1984 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
1986 } else {
1987 /* These units do not need to be saved. */
1988 healthy = TRUE;
1989 }
1990 }
1991
1992 /* Could use unit_transport_unload_send() here, but that would
1993 * call send_unit_info() for the transporter unnecessarily.
1994 * Note that this means that unit might to get seen briefly
1995 * by clients other than owner's, for example as a result of
1996 * update of homecity common to this cargo and some other
1997 * destroyed unit. */
1999 if (pcargo->activity == ACTIVITY_SENTRY) {
2000 /* Activate sentried units - like planes on a disbanded carrier.
2001 * Note this will activate ground units even if they just change
2002 * transporter. */
2004 }
2005
2006 /* Unit info for unhealthy units will be sent when they are
2007 * assigned new transport or removed. */
2008 if (healthy) {
2010 }
2012 }
2013
2014 /* Now remove the unit. */
2015 server_remove_unit_full(punit, transported, reason);
2016
2017 switch (reason) {
2018 case ULR_KILLED:
2019 case ULR_EXECUTED:
2020 case ULR_SDI:
2021 case ULR_NUKE:
2022 case ULR_BRIBED:
2023 case ULR_CAPTURED:
2024 case ULR_CAUGHT:
2025 case ULR_ELIMINATED:
2026 case ULR_TRANSPORT_LOST:
2027 if (killer != NULL) {
2028 killer->score.units_killed++;
2029 }
2030 pplayer->score.units_lost++;
2031 break;
2032 case ULR_BARB_UNLEASH:
2033 case ULR_CITY_LOST:
2034 case ULR_STARVED:
2035 case ULR_UPKEEP:
2036 case ULR_NONNATIVE_TERR:
2037 case ULR_ARMISTICE:
2038 case ULR_HP_LOSS:
2039 case ULR_FUEL:
2040 case ULR_STACK_CONFLICT:
2041 case ULR_SOLD:
2042 pplayer->score.units_lost++;
2043 break;
2044 case ULR_RETIRED:
2045 case ULR_DISBANDED:
2046 case ULR_USED:
2047 case ULR_DETONATED:
2048 case ULR_MISSILE:
2049 pplayer->score.units_used++;
2050 break;
2051 case ULR_EDITOR:
2052 case ULR_PLAYER_DIED:
2053 break;
2054 }
2055
2056 /* First, sort out helpless cargo. */
2057 if (unit_list_size(helpless) > 0) {
2058 struct unit_list *remaining = unit_list_new();
2059
2060 /* Grant priority to gameloss units and units with the EvacuateFirst
2061 * unit type flag. */
2068 pexclcity)) {
2070 }
2071 } else {
2072 unit_list_prepend(remaining, pcargo);
2073 }
2075
2076 /* Handle non-priority units. */
2077 unit_list_iterate_safe(remaining, pcargo) {
2080 }
2082
2083 unit_list_destroy(remaining);
2084 }
2086
2087 /* Then, save any imperiled cargo. */
2088 if (unit_list_size(imperiled) > 0) {
2089 struct unit_list *remaining = unit_list_new();
2090
2091 /* Grant priority to gameloss units and units with the EvacuateFirst
2092 * unit type flag. */
2099 pexclcity)) {
2101 }
2102 } else {
2103 unit_list_prepend(remaining, pcargo);
2104 }
2106
2107 /* Handle non-priority units. */
2108 unit_list_iterate_safe(remaining, pcargo) {
2111 }
2113
2114 unit_list_destroy(remaining);
2115 }
2117
2118 /* Finally, kill off the unsaved units. */
2119 if (unit_list_size(unsaved) > 0) {
2123 }
2125}
2126
2127/**********************************************************************/
2136
2137/**********************************************************************/
2143static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2144 bool helpless, bool teleporting,
2145 const struct city *pexclcity)
2146{
2147 struct tile *ptile = unit_tile(punit);
2148 struct player *pplayer = unit_owner(punit);
2150
2151 /* Helpless units cannot board a transport in their current state. */
2152 if (!helpless
2153 && ptransport != NULL) {
2156 return TRUE;
2157 } else {
2158 /* Only units that cannot find transport are considered for teleport. */
2159 if (teleporting) {
2160 struct city *pcity = find_closest_city(ptile, pexclcity,
2164 if (pcity != NULL) {
2165 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2166
2168
2169 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2170 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2171 _("%s escaped the destruction of %s, and fled to %s."),
2172 tplink,
2174 city_link(pcity));
2175 return TRUE;
2176 }
2177 }
2178 }
2179 }
2180
2181 /* The unit could not use transport on the tile, and could not teleport. */
2182 return FALSE;
2183}
2184
2185/**********************************************************************/
2191struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2193{
2194 struct unit *gained_unit;
2195 int id = 0;
2196
2197#ifndef FREECIV_NDEBUG
2198 bool placed;
2199#endif
2200
2203
2204 /* Convert the unit to your cause. It's supposed that the original unit
2205 * is on a valid tile and is not transported. */
2209 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2210
2211 /* Owner changes, nationality not. */
2212 gained_unit->nationality = punit->nationality;
2213
2214 /* Copy some more unit fields */
2215 gained_unit->fuel = punit->fuel;
2216 gained_unit->paradropped = punit->paradropped;
2217 gained_unit->birth_turn = punit->birth_turn;
2218 gained_unit->current_form_turn = punit->current_form_turn;
2219
2220 /* Fog is lifted in the placing algorithm. */
2221#ifndef FREECIV_NDEBUG
2222 placed =
2223#endif
2224 place_unit(gained_unit, pplayer,
2226 NULL, FALSE);
2227
2229
2230 id = gained_unit->id;
2231
2232 /* Update unit upkeep in the new homecity */
2233 if (homecity > 0) {
2235 }
2236
2237 /* Be sure to wipe the converted unit! */
2238 /* Old homecity upkeep is updated in process */
2239#ifndef FREECIV_NDEBUG
2240 uco_wipe:
2241#endif
2242
2244
2245 if (!unit_is_alive(id)) {
2246 /* Destroyed by a script */
2247 return NULL;
2248 }
2249
2250 return gained_unit; /* Returns the replacement. */
2251}
2252
2253/**********************************************************************/
2258void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2259{
2261 struct player *pvictim = unit_owner(punit);
2262 struct player *pvictor = unit_owner(pkiller);
2263 struct tile *deftile = unit_tile(punit);
2264 int unitcount = 0;
2265 bool escaped;
2266 const struct civ_map *nmap = &(wld.map);
2267
2270
2271 /* The unit is doomed. */
2273
2277 unitcount++;
2278 }
2280
2281 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2282 if (vet) {
2284 }
2286 } else { /* Unitcount > 1 */
2287 int i;
2288 int slots = player_slot_count();
2289 int num_killed[slots];
2290 int num_escaped[slots];
2291 struct unit *other_killed[slots];
2292
2293 fc_assert(unitcount > 1);
2294
2295 /* Initialize */
2296 for (i = 0; i < slots; i++) {
2297 num_killed[i] = 0;
2298 other_killed[i] = NULL;
2299 num_escaped[i] = 0;
2300 }
2301
2302 /* Count killed units */
2304 struct player *vplayer = unit_owner(vunit);
2305
2308 escaped = FALSE;
2309
2312 && vunit->hp > 0
2313 && vunit->moves_left > pkiller->moves_left
2314 && fc_rand(2)) {
2315 int curr_def_bonus;
2316 int def_bonus = 0;
2317 struct tile *dsttile = NULL;
2318 int move_cost;
2319
2320 fc_assert(vunit->hp > 0);
2321
2323 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2324 && NULL == tile_city(ptile2)) {
2325 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2326 if (pkiller->moves_left <= vunit->moves_left - move_cost
2328 || unit_list_size(ptile2->units)) == 0) {
2330 vunit->utype);
2331 if (def_bonus <= curr_def_bonus) {
2333 dsttile = ptile2;
2334 }
2335 }
2336 }
2338
2339 if (dsttile != NULL) {
2342 NULL, NULL, dsttile,
2344 NULL, NULL)
2345 != NULL);
2346
2347 if (escaped) {
2349 unitcount--;
2350 }
2351 }
2352 }
2353
2354 if (!escaped) {
2356
2357 if (vunit != punit) {
2360 }
2361 }
2362 }
2364
2365 /* Inform the destroyer again if more than one unit was killed */
2366 if (unitcount > 1) {
2368 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2369 PL_("Your attacking %s succeeded against the %s %s "
2370 "(and %d other unit)!",
2371 "Your attacking %s succeeded against the %s %s "
2372 "(and %d other units)!", unitcount - 1),
2375 punit_link,
2376 unitcount - 1);
2377 }
2378
2379 if (vet) {
2381 }
2382
2383 /* Inform the owners: this only tells about owned units that were killed.
2384 * there may have been 20 units who died but if only 2 belonged to the
2385 * particular player they'll only learn about those.
2386 *
2387 * Also if a large number of units die you don't find out what type
2388 * they all are. */
2389 for (i = 0; i < slots; i++) {
2390 if (num_killed[i] == 1) {
2391 if (i == player_index(pvictim)) {
2395 /* TRANS: "Cannon ... the Polish Destroyer." */
2396 _("%s lost to an attack by the %s %s."),
2397 punit_link,
2399 pkiller_link);
2400 } else {
2404 /* TRANS: "Cannon lost when the Polish Destroyer
2405 * attacked the German Musketeers." */
2406 _("%s lost when the %s %s attacked the %s %s."),
2411 punit_link);
2412 }
2413 } else if (num_killed[i] > 1) {
2414 if (i == player_index(pvictim)) {
2415 int others = num_killed[i] - 1;
2416
2417 if (others == 1) {
2420 /* TRANS: "Musketeers (and Cannon) lost to an
2421 * attack from the Polish Destroyer." */
2422 _("%s (and %s) lost to an attack from the %s %s."),
2423 punit_link,
2426 pkiller_link);
2427 } else {
2430 /* TRANS: "Musketeers and 3 other units lost to
2431 * an attack from the Polish Destroyer."
2432 * (only happens with at least 2 other units) */
2433 PL_("%s and %d other unit lost to an attack "
2434 "from the %s %s.",
2435 "%s and %d other units lost to an attack "
2436 "from the %s %s.", others),
2437 punit_link,
2438 others,
2440 pkiller_link);
2441 }
2442 } else {
2445 /* TRANS: "2 units lost when the Polish Destroyer
2446 * attacked the German Musketeers."
2447 * (only happens with at least 2 other units) */
2448 PL_("%d unit lost when the %s %s attacked the %s %s.",
2449 "%d units lost when the %s %s attacked the %s %s.",
2450 num_killed[i]),
2451 num_killed[i],
2455 punit_link);
2456 }
2457 }
2458 }
2459
2460 /* Inform the owner of the units that escaped.
2461 * 'deftile' is the original tile they defended at, not where
2462 * they escaped to, as there might be multiple different tiles
2463 * different units escaped to. */
2464 for (i = 0; i < slots; i++) {
2465 if (0 < num_escaped[i]) {
2468 PL_("%d unit escaped from attack by %s %s",
2469 "%d units escaped from attack by %s %s",
2470 num_escaped[i]),
2471 num_escaped[i],
2474 );
2475 }
2476 }
2477
2478 /* Remove the units - note the logic of which units actually die
2479 * must be mimiced exactly in at least one place up above. */
2480 punit = NULL; /* Wiped during following iteration so unsafe to use */
2481
2486 }
2488 }
2489}
2490
2491/**********************************************************************/
2494void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2495{
2496 struct player *pvictim = unit_owner(punit);
2499 struct tile *deftile = unit_tile(punit);
2500 int unitcount, ransom;
2501
2502 /* The unit is doomed. */
2504
2507
2508 if (pvictim->economic.gold < ransom) {
2509 ransom = pvictim->economic.gold;
2510 }
2511
2513 PL_("%d Barbarian leader captured.",
2514 "%d Barbarian leaders captured.",
2515 unitcount),
2516 unitcount);
2518 PL_("%d gold ransom paid.",
2519 "%d gold ransom paid.",
2520 ransom),
2521 ransom);
2522 pvictor->economic.gold += ransom;
2523 pvictim->economic.gold -= ransom;
2524 send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */
2525
2526 if (vet) {
2528 }
2529
2532
2533 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2535 } else {
2536 int i;
2537 int slots = player_slot_count();
2538 int num_collected[slots];
2539
2540 fc_assert(unitcount > 1);
2541
2542 /* Initialize */
2543 for (i = 0; i < slots; i++) {
2544 num_collected[i] = 0;
2545 }
2546
2547 /* Count captured units */
2549 struct player *vplayer = unit_owner(vunit);
2550
2553
2554 for (i = 0; i < slots; i++) {
2555 if (num_collected[i] == 1) {
2558 _("%s %s collected ransom of %s."),
2561 } else if (num_collected[i] > 1) {
2564 PL_("%s %s collected ransom of %s and %d other unit.",
2565 "%s %s collected ransom of %s and %d other units.",
2566 num_collected[i] - 1),
2569 punit_link,
2570 num_collected[i] - 1);
2571 }
2572 }
2573
2577 }
2578}
2579
2580/**********************************************************************/
2584void package_unit(struct unit *punit, struct packet_unit_info *packet)
2585{
2586 packet->id = punit->id;
2587 packet->owner = player_number(unit_owner(punit));
2589 packet->tile = tile_index(unit_tile(punit));
2590 packet->facing = punit->facing;
2591 packet->homecity = punit->homecity;
2593 packet->upkeep[o] = punit->upkeep[o];
2595 packet->veteran = punit->veteran;
2597 packet->movesleft = punit->moves_left;
2598 packet->hp = punit->hp;
2599 packet->activity = punit->activity;
2601
2602 if (punit->activity_target != NULL) {
2604 } else {
2605 packet->activity_tgt = EXTRA_NONE;
2606 }
2607
2608 packet->changed_from = punit->changed_from;
2610
2611 if (punit->changed_from_target != NULL) {
2613 } else {
2614 packet->changed_from_tgt = EXTRA_NONE;
2615 }
2616
2618 packet->fuel = punit->fuel;
2619 packet->goto_tile = (NULL != punit->goto_tile
2620 ? tile_index(punit->goto_tile) : -1);
2621 packet->paradropped = punit->paradropped;
2622 packet->done_moving = punit->done_moving;
2623 packet->stay = punit->stay;
2624 packet->birth_turn = punit->birth_turn;
2626 if (!unit_transported(punit)) {
2627 packet->transported = FALSE;
2628 packet->transported_by = 0;
2629 } else {
2630 packet->transported = TRUE;
2632 }
2633 if (punit->carrying != NULL) {
2634 packet->carrying = goods_index(punit->carrying);
2635 } else {
2636 packet->carrying = -1;
2637 }
2638 packet->occupied = (get_transporter_occupancy(punit) > 0);
2639 packet->battlegroup = punit->battlegroup;
2640 packet->has_orders = punit->has_orders;
2641 if (punit->has_orders) {
2642 packet->orders_length = punit->orders.length;
2643 packet->orders_index = punit->orders.index;
2644 packet->orders_repeat = punit->orders.repeat;
2646 memcpy(packet->orders, punit->orders.list,
2647 punit->orders.length * sizeof(struct unit_order));
2648 } else {
2649 packet->orders_length = packet->orders_index = 0;
2650 packet->orders_repeat = packet->orders_vigilant = FALSE;
2651 /* No need to initialize array. */
2652 }
2653
2658}
2659
2660/**********************************************************************/
2666 struct packet_unit_short_info *packet,
2667 enum unit_info_use packet_use, int info_city_id)
2668{
2669 packet->packet_use = packet_use;
2670 packet->info_city_id = info_city_id;
2671
2672 packet->id = punit->id;
2673 packet->owner = player_number(unit_owner(punit));
2674 packet->tile = tile_index(unit_tile(punit));
2675 packet->facing = punit->facing;
2676 packet->veteran = punit->veteran;
2678 packet->hp = punit->hp;
2679 packet->occupied = (get_transporter_occupancy(punit) > 0);
2681 || punit->activity == ACTIVITY_GOTO) {
2682 packet->activity = ACTIVITY_IDLE;
2683 } else {
2684 packet->activity = punit->activity;
2685 }
2686
2687 if (punit->activity_target == NULL) {
2688 packet->activity_tgt = EXTRA_NONE;
2689 } else {
2691 }
2692
2693 /* Transported_by information is sent to the client even for units that
2694 * aren't fully known. Note that for non-allied players, any transported
2695 * unit can't be seen at all. For allied players we have to know if
2696 * transporters have room in them so that we can load units properly. */
2697 if (!unit_transported(punit)) {
2698 packet->transported = FALSE;
2699 packet->transported_by = 0;
2700 } else {
2701 packet->transported = TRUE;
2703 }
2704}
2705
2706/**********************************************************************/
2709void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2710{
2712 if (punit->server.moving != NULL) {
2713 /* Update status of 'pplayer' vision for 'punit'. */
2715 }
2716}
2717
2718/**********************************************************************/
2722void send_unit_info(struct conn_list *dest, struct unit *punit)
2723{
2724 const struct player *powner;
2725 struct packet_unit_info info;
2727 struct unit_move_data *pdata;
2728
2729 if (dest == NULL) {
2730 dest = game.est_connections;
2731 }
2732
2734
2736 package_unit(punit, &info);
2739
2740 conn_list_iterate(dest, pconn) {
2741 struct player *pplayer = conn_get_player(pconn);
2742
2743 /* Be careful to consider all cases where pplayer is NULL... */
2744 if (pplayer == NULL) {
2745 if (pconn->observer) {
2747 }
2748 } else if (pplayer == powner) {
2750 if (pdata != NULL) {
2751 BV_SET(pdata->can_see_unit, player_index(pplayer));
2752 }
2753 } else if (can_player_see_unit(pplayer, punit)) {
2755 if (pdata != NULL) {
2756 BV_SET(pdata->can_see_unit, player_index(pplayer));
2757 }
2758 }
2760}
2761
2762/**********************************************************************/
2767{
2768 conn_list_do_buffer(dest);
2769 conn_list_iterate(dest, pconn) {
2770 struct player *pplayer = pconn->playing;
2771
2772 if (NULL == pplayer && !pconn->observer) {
2773 continue;
2774 }
2775
2778 send_unit_info(dest, punit);
2781 }
2784 flush_packets();
2785}
2786
2787/**********************************************************************/
2794static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2795 const struct action *paction)
2796{
2797 struct city *pcity = NULL;
2798 int pop_loss;
2799
2800 pcity = tile_city(ptile);
2801
2803
2804 /* unit in a city may survive */
2805 if (pcity && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2806 continue;
2807 }
2809 _("Your %s was nuked by %s."),
2811 pplayer == unit_owner(punit)
2812 ? _("yourself")
2813 : nation_plural_for_player(pplayer));
2814 if (unit_owner(punit) != pplayer) {
2815 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2816 _("The %s %s was nuked."),
2819 }
2820 wipe_unit(punit, ULR_NUKE, pplayer);
2822
2823
2824 if (pcity) {
2825 struct player *owner = city_owner(pcity);
2826 char city_name[MAX_LEN_LINK];
2827
2829
2831 _("%s was nuked by %s."),
2832 city_name,
2833 pplayer == owner
2834 ? _("yourself")
2835 : nation_plural_for_player(pplayer));
2836
2837 if (owner != pplayer) {
2838 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2839 _("You nuked %s."),
2840 city_name);
2841 }
2842
2843 pop_loss = round((game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100.0);
2844 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
2845 /* Send city size reduction to everyone seeing it */
2846 send_city_info(NULL, pcity);
2847 } else {
2848 /* City was destroyed */
2850 _("%s was destroyed by the nuke."),
2851 city_name);
2852 if (owner != pplayer) {
2853 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2854 _("Your nuke destroyed %s."),
2855 city_name);
2856 }
2857 }
2858 }
2859
2860 if (fc_rand(2) == 1) {
2861 struct extra_type *pextra;
2862
2863 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
2864 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2865 tile_add_extra(ptile, pextra);
2866 update_tile_knowledge(ptile);
2867 }
2868 }
2869}
2870
2871/**********************************************************************/
2880 const struct unit_type *act_utype,
2881 struct player *pplayer, struct tile *ptile)
2882{
2885 &(const struct req_context) {
2886 .player = pplayer,
2887 /* City: Wait for users before choosing
2888 * home city or target tile city */
2889 .tile = ptile,
2890 .unittype = act_utype,
2891 .action = paction,
2892 },
2893 NULL,
2895
2897 do_nuke_tile(pplayer, ptile1, paction);
2899
2900 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
2901 API_TYPE_PLAYER, pplayer);
2903 _("The %s detonated a nuke!"),
2904 nation_plural_for_player(pplayer));
2905}
2906
2907/**********************************************************************/
2911bool do_airline(struct unit *punit, struct city *pdest_city,
2912 const struct action *paction)
2913{
2915
2918 _("%s transported successfully."),
2919 unit_link(punit));
2920
2923 /* Can only airlift to allied and domestic cities */
2924 FALSE, FALSE,
2925 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
2927
2928 /* Update airlift fields. */
2930 psrc_city->airlift--;
2932 }
2934 pdest_city->airlift--;
2936 }
2937
2938 return TRUE;
2939}
2940
2941/**********************************************************************/
2944void do_explore(struct unit *punit)
2945{
2946 switch (manage_auto_explorer(punit)) {
2947 case MR_DEATH:
2948 /* don't use punit! */
2949 return;
2950 case MR_NOT_ALLOWED:
2951 /* Needed for something else */
2952 return;
2953 case MR_OK:
2954 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2955 * but don't count on this. See PR#39792.
2956 */
2958 break;
2959 }
2960
2962 default:
2964
2965 /* FIXME: When the manage_auto_explorer() call changes the activity from
2966 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2967 * alone. We reset it here. See PR#12931. */
2969 break;
2970 }
2971
2972 send_unit_info(NULL, punit); /* probably duplicate */
2973}
2974
2975/**********************************************************************/
2980bool do_paradrop(struct unit *punit, struct tile *ptile,
2981 const struct action *paction)
2982{
2983 struct player *pplayer = unit_owner(punit);
2984 struct player *tgt_player = tile_owner(ptile);
2985 const struct unit_type *act_utype = unit_type_get(punit);
2986 const struct city *pcity;
2987
2988 /* Hard requirements */
2989 /* FIXME: hard requirements belong in common/actions's
2990 * is_action_possible() and the explanation texts belong in
2991 * server/unithand's action not enabled system (expl_act_not_enabl(),
2992 * ane_kind, explain_why_no_action_enabled(), etc)
2993 */
2994 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
2995 /* Only take in account values from player map. */
2996 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
2997
2998 if (NULL == plrtile->site) {
2999 bv_extras fbv;
3000
3001 dbv_to_bv(fbv.vec, &(plrtile->extras));
3002
3004 &fbv)) {
3005 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3006 _("This unit cannot paradrop into %s."),
3008 return FALSE;
3009 }
3010 }
3011
3012 if (NULL != plrtile->site
3013 && plrtile->owner != NULL
3014 && !pplayers_allied(pplayer, plrtile->owner)
3016 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3017 /* TRANS: Paratroopers ... Paradrop Unit */
3018 _("%s cannot conquer a city with \"%s\"."),
3021 return FALSE;
3022 }
3023
3024 if (NULL != plrtile->site
3025 && plrtile->owner != NULL
3026 && (pplayers_non_attack(pplayer, plrtile->owner)
3027 || (player_diplstate_get(pplayer, plrtile->owner)->type
3028 == DS_ALLIANCE)
3029 || (player_diplstate_get(pplayer, plrtile->owner)->type
3030 == DS_TEAM))
3032 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3033 _("Cannot attack unless you declare war first."));
3034 return FALSE;
3035 }
3036 }
3037
3038
3039 /* Kill the unit when the landing goes wrong. */
3040
3041 /* Safe terrain, really? Not transformed since player last saw it. */
3042 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3043 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3044 || !unit_could_load_at(punit, ptile))) {
3045 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3046 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3047 _("Your %s paradropped into the %s and was lost."),
3050 pplayer->score.units_lost++;
3052 return TRUE;
3053 }
3054
3055 pcity = tile_city(ptile);
3056
3057 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3059 || is_non_allied_unit_tile(ptile, pplayer)) {
3060 struct player *main_victim = NULL;
3061 struct player *secondary_victim = NULL;
3063
3064 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3065 maybe_make_contact(ptile, pplayer);
3066 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3067 _("Your %s was killed by enemy units at the "
3068 "paradrop destination."),
3070 /* TODO: Should defender score.units_killed get increased too?
3071 * What if there's units of several allied players? Should the
3072 * city owner or owner of the first/random unit get the kill? */
3073 pplayer->score.units_lost++;
3074
3075 if (pcity != NULL) {
3076 struct player *owner = city_owner(pcity);
3077
3078 if (!pplayers_at_war(pplayer, owner)) {
3080 } else {
3082 }
3083
3085 } else {
3087 }
3088
3089 if (main_victim == NULL) {
3090 unit_list_iterate(ptile->units, tgt) {
3091 struct player *owner = unit_owner(tgt);
3092
3093 if (!pplayers_at_war(pplayer, owner)) {
3095 break;
3096 } else if (secondary_victim == NULL) {
3098 }
3100
3101 if (main_victim == NULL) {
3102 /* There's no victim with whom the attacker isn't in war,
3103 * fallback to one with whom there's already a war. */
3105 }
3106 }
3107
3109 main_victim, ptile,
3110 victim_link);
3111
3113 return TRUE;
3114 }
3115
3116 /* All ok */
3118 if (unit_move(punit, ptile,
3119 /* Done by Action_Success_Actor_Move_Cost */
3120 0,
3121 NULL, BV_ISSET(paction->sub_results,
3125 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3126 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3127 /* Ensure we finished on valid state. */
3130 }
3131
3132 /* May cause an incident */
3134 ptile, tile_link(ptile));
3135
3136 return TRUE;
3137}
3138
3139/**********************************************************************/
3143static bool hut_get_limited(struct unit *punit)
3144{
3145 bool ok = TRUE;
3146 int hut_chance = fc_rand(12);
3147 struct player *pplayer = unit_owner(punit);
3148 const struct civ_map *nmap = &(wld.map);
3149
3150 /* 1 in 12 to get barbarians */
3151 if (hut_chance != 0) {
3152 int cred = 25;
3153
3155 PL_("You found %d gold.",
3156 "You found %d gold.", cred), cred);
3157 pplayer->economic.gold += cred;
3160 notify_player(pplayer, unit_tile(punit),
3162 _("An abandoned village is here."));
3163 } else {
3165 _("Your %s has been killed by barbarians!"),
3168 ok = FALSE;
3169 }
3170
3171 return ok;
3172}
3173
3174/**********************************************************************/
3178static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3179{
3180 struct player *pplayer = unit_owner(punit);
3181 int id = punit->id;
3182 struct tile *ptile = unit_tile(punit);
3183 bool hut = FALSE;
3184 const struct req_context context = {
3185 .player = pplayer,
3186 .tile = ptile,
3187 };
3188
3190 if (tile_has_extra(ptile, pextra)
3191 && are_reqs_active(&context, tile_owner(ptile), &pextra->rmreqs,
3193 ) {
3194 hut = TRUE;
3195 /* FIXME: are all enter-removes extras worth counting? */
3196 pplayer->server.huts++;
3197
3198 destroy_extra(ptile, pextra);
3200
3201 /* FIXME: enable different classes
3202 * to behave differently with different huts */
3203 if (frighten_hut) {
3204 script_server_signal_emit("hut_frighten", punit,
3205 extra_rule_name(pextra));
3206 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3207 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3209 } else {
3210 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3211 }
3212
3213 /* We need punit for the callbacks, can't continue if the unit died */
3214 if (!unit_is_alive(id)) {
3215 break;
3216 }
3217 }
3219
3220 if (hut) {
3221 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3222 }
3223 return;
3224}
3225
3226/**********************************************************************/
3230{
3231 bv_player can_see_unit;
3232
3235
3236 BV_CLR_ALL(can_see_unit);
3237 players_iterate(pplayer) {
3238 if (can_player_see_unit(pplayer, punit)) {
3239 BV_SET(can_see_unit, player_index(pplayer));
3240 }
3242
3244
3245 players_iterate(pplayer) {
3246 if (BV_ISSET(can_see_unit, player_index(pplayer))
3247 && !can_player_see_unit(pplayer, punit)) {
3248 unit_goes_out_of_sight(pplayer, punit);
3249 }
3251
3254}
3255
3256/**********************************************************************/
3260 struct unit *ptrans,
3261 bool force)
3262{
3263 bool had_cargo;
3264
3267
3269
3271
3272 if (!had_cargo) {
3273 /* Transport's loaded status changed */
3275 }
3276}
3277
3278/**********************************************************************/
3282{
3283 struct unit *ptrans;
3284
3286
3288
3290
3292
3295}
3296
3297/**********************************************************************/
3301static void autoattack_prob_free(struct autoattack_prob *prob)
3302{
3303 free(prob);
3304}
3305
3306/**********************************************************************/
3315static int compare_units(const struct autoattack_prob *const *p1,
3316 const struct autoattack_prob *const *q1)
3317{
3318 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3319 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3320
3321 /* Sort by transport depth first. This makes sure that no transport
3322 * attacks before its cargo does -- cargo sorts earlier in the list. */
3323 {
3324 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3325
3326 /* Walk the transport stacks in parallel, so as to bail out as soon as
3327 * one of them is empty (avoid walking deep stacks more often than
3328 * necessary). */
3329 while (p1trans && q1trans) {
3332 }
3333 if (!p1trans && q1trans) {
3334 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3335 * earlier in the list (p1 > q1). */
3336 return 1;
3337 } else if (p1trans && !q1trans) {
3338 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3339 return -1;
3340 }
3341 /* else same depth, so move on to checking win chance: */
3342 }
3343
3344 /* Put the units with the highest probability of success first. The up
3345 * side of this is that units with bonuses against the victim attacks
3346 * before other units. The downside is that strong units can be led
3347 * away by sacrificial units. */
3348 return (-1
3349 /* Assume the worst. */
3350 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3351}
3352
3353/**********************************************************************/
3358{
3359 struct autoattack_prob_list *autoattack;
3360 int moves = punit->moves_left;
3361 int sanity1 = punit->id;
3362 struct civ_map *nmap = &(wld.map);
3363
3364 if (!game.server.autoattack) {
3365 return TRUE;
3366 }
3367
3369
3370 /* Kludge to prevent attack power from dropping to zero during calc */
3372
3373 adjc_iterate(nmap, unit_tile(punit), ptile) {
3374 /* First add all eligible units to a autoattack list */
3375 unit_list_iterate(ptile->units, penemy) {
3377 struct tile *tgt_tile = unit_tile(punit);
3378
3379 fc_assert_action(tgt_tile, continue);
3380
3381 probability->prob =
3385 punit, NULL);
3386
3387 if (action_prob_possible(probability->prob)) {
3388 probability->unit_id = penemy->id;
3390 } else {
3392 }
3395
3396 /* Sort the potential attackers from highest to lowest success
3397 * probability. */
3398 if (autoattack_prob_list_size(autoattack) >= 2) {
3400 }
3401
3403 int sanity2 = penemy->id;
3404 struct tile *ptile = unit_tile(penemy);
3405 struct unit *enemy_defender = get_defender(nmap, punit, ptile, NULL);
3406 double punitwin, penemywin;
3407 double threshold = 0.25;
3408 struct tile *tgt_tile = unit_tile(punit);
3409
3411
3412 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3413 /* Don't leave city defenseless */
3414 threshold = 0.90;
3415 }
3416
3417 if (NULL != enemy_defender) {
3419 } else {
3420 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3421 punitwin = 1.0;
3422 }
3423
3424 /* Previous attacks may have changed the odds. Recalculate. */
3425 peprob->prob =
3429 punit, NULL);
3430
3431 if (!action_prob_possible(peprob->prob)) {
3432 /* No longer legal. */
3433 continue;
3434 }
3435
3436 /* Assume the worst. */
3438
3439 if ((penemywin > 1.0 - punitwin
3441 && penemywin > threshold) {
3442
3443#ifdef REALLY_DEBUG_THIS
3444 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3447 1.0 - punitwin, threshold);
3448#endif
3449
3454 } else {
3455#ifdef REALLY_DEBUG_THIS
3456 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3459 1.0 - punitwin, threshold);
3460#endif
3461 continue;
3462 }
3463
3466 }
3469 } else {
3470 autoattack_prob_list_destroy(autoattack);
3471 return FALSE; /* moving unit dead */
3472 }
3474
3475 autoattack_prob_list_destroy(autoattack);
3477 /* We could have lost movement in combat */
3480 return TRUE;
3481 } else {
3482 return FALSE;
3483 }
3484}
3485
3486/**********************************************************************/
3489static void cancel_orders(struct unit *punit, char *dbg_msg)
3490{
3493 log_debug("%s", dbg_msg);
3494}
3495
3496/**********************************************************************/
3501{
3502 bool alone_in_city;
3503
3504 if (NULL != tile_city(unit_tile(punit))) {
3505 int count = 0;
3506
3508 /* Consider only units not transported. */
3509 if (!unit_transported(aunit)) {
3510 count++;
3511 }
3513
3514 alone_in_city = (1 == count);
3515 } else {
3517 }
3518
3519 /* There may be sentried units with a sightrange > 3, but we don't
3520 wake them up if the punit is farther away than 3. */
3521 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3522 unit_list_iterate(ptile->units, penemy) {
3524 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3525
3527 && penemy->activity == ACTIVITY_SENTRY
3528 && radius_sq >= distance_sq
3529 /* If the unit moved on a city, and the unit is alone, consider
3530 * it is visible. */
3531 && (alone_in_city
3533 /* on board transport; don't awaken */
3537 }
3540
3541 /* Wakeup patrolling units we bump into.
3542 We do not wakeup units further away than 3 squares... */
3543 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3544 unit_list_iterate(ptile->units, ppatrol) {
3545 if (punit != ppatrol
3547 && ppatrol->orders.vigilant) {
3549 cancel_orders(ppatrol, " stopping because of nearby enemy");
3552 _("Orders for %s aborted after enemy movement was "
3553 "spotted."),
3555 }
3556 }
3559}
3560
3561/**********************************************************************/
3571 struct tile *src_tile,
3572 struct tile *dst_tile,
3573 bool passenger,
3575{
3576 struct city *fromcity = tile_city(src_tile);
3577 struct city *tocity = tile_city(dst_tile);
3578 struct city *homecity_start_pos = NULL;
3579 struct city *homecity_end_pos = NULL;
3585 const struct unit_type *type_end_pos = type_start_pos;
3588 int saved_id = punit->id;
3589 bool alive = TRUE;
3590 const struct civ_map *nmap = &(wld.map);
3591
3593 if (!passenger) {
3594 /* The unit that does the move may conquer. */
3596 }
3597
3598 /* Run for passengers too. A passenger may have been killed when its
3599 * transport conquered a city. (unit_conquer_city() can cause Lua code
3600 * to run) */
3601
3603 if (alive) {
3604 /* In case script has changed something about unit */
3608 }
3609 }
3610
3611 if (homecity_id_start_pos != 0) {
3613 }
3616 } else {
3618 }
3619
3620 /* We only do refreshes for non-AI players to now make sure the AI turns
3621 doesn't take too long. Perhaps we should make a special refresh_city
3622 functions that only refreshed happines. */
3623
3624 /* might have changed owners or may be destroyed */
3626
3627 if (tocity) { /* entering a city */
3628 if (tocity->owner == pplayer_end_pos) {
3632 }
3633 }
3634 if (homecity_start_pos) {
3636 }
3637 }
3638
3639 if (fromcity) { /* leaving a city */
3640 if (homecity_start_pos) {
3642 }
3644 && fromcity->owner == pplayer_start_pos
3648 }
3649 }
3650
3651 /* Entering/leaving a fortress or friendly territory */
3653 bool friendly_end = FALSE;
3654
3657 } else {
3659 type_end_pos);
3660
3661 if (max_friendliness_range >= 0
3664 } else {
3667
3668 if (max_friendliness_range >= 0
3671 }
3672 }
3673 }
3674
3675 if (friendly_end) {
3678 }
3679 }
3680
3684 }
3691 }
3692
3694 sync_cities();
3695
3696 return alive;
3697}
3698
3699/**********************************************************************/
3703static void check_unit_activity(struct unit *punit)
3704{
3705 switch (punit->activity) {
3706 case ACTIVITY_IDLE:
3707 case ACTIVITY_SENTRY:
3708 case ACTIVITY_EXPLORE:
3709 case ACTIVITY_GOTO:
3710 break;
3711 case ACTIVITY_CLEAN:
3712 case ACTIVITY_MINE:
3713 case ACTIVITY_IRRIGATE:
3714 case ACTIVITY_CULTIVATE:
3715 case ACTIVITY_PLANT:
3716 case ACTIVITY_FORTIFIED:
3717 case ACTIVITY_PILLAGE:
3718 case ACTIVITY_TRANSFORM:
3720 case ACTIVITY_BASE:
3721 case ACTIVITY_GEN_ROAD:
3722 case ACTIVITY_CONVERT:
3723 case ACTIVITY_LAST:
3725 break;
3726 };
3727}
3728
3729/**********************************************************************/
3733 const struct tile *psrctile,
3734 const struct tile *pdesttile)
3735{
3736 struct unit_move_data *pdata;
3737 struct player *powner = unit_owner(punit);
3738
3739 if (punit->server.moving) {
3740 /* Recursive moving (probably due to a script). */
3742 pdata->ref_count++;
3743 fc_assert_msg(pdata->punit == punit,
3744 "Unit number %d (%p) was going to die, but "
3745 "server attempts to move it.",
3746 punit->id, punit);
3747 fc_assert_msg(pdata->old_vision == NULL,
3748 "Unit number %d (%p) has done an incomplete move.",
3749 punit->id, punit);
3750 } else {
3751 pdata = fc_malloc(sizeof(*pdata));
3752 pdata->ref_count = 1;
3753 pdata->punit = punit;
3755 BV_CLR_ALL(pdata->can_see_unit);
3756 }
3757 pdata->powner = powner;
3758 BV_CLR_ALL(pdata->can_see_move);
3759 pdata->old_vision = punit->server.vision;
3760
3761 return pdata;
3762}
3763
3764/**********************************************************************/
3768 const struct tile *psrctile,
3769 struct tile *pdesttile)
3770{
3771 struct vision *new_vision;
3772 struct unit *punit = pdata->punit;
3774 const v_radius_t radius_sq
3778
3779 /* Remove unit from the source tile. */
3781
3782#ifndef FREECIV_NDEBUG
3783 bool success =
3784#endif
3787
3788 /* Set new tile. */
3791
3792 if (unit_transported(punit)) {
3793 /* Silently free orders since they won't be applicable anymore. */
3795 }
3796
3797 /* Check unit activity. */
3801
3802 /* We first unfog the destination, then send the move,
3803 * and then fog the old territory. This means that the player
3804 * gets a chance to see the newly explored territory while the
3805 * client moves the unit, and both areas are visible during the
3806 * move */
3807
3808 /* Enhance vision if unit steps into a fortress */
3811 vision_change_sight(new_vision, radius_sq);
3813}
3814
3815/**********************************************************************/
3819{
3821 fc_assert_ret(pdata->ref_count > 0);
3822 fc_assert_msg(pdata->old_vision == NULL,
3823 "Unit number %d (%p) has done an incomplete move.",
3824 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3825
3826 pdata->ref_count--;
3827 if (pdata->ref_count == 0) {
3828 if (pdata->punit != NULL) {
3829 fc_assert(pdata->punit->server.moving == pdata);
3830 pdata->punit->server.moving = NULL;
3831 }
3832 free(pdata);
3833 }
3834}
3835
3836/**********************************************************************/
3840 const struct tile *psrctile,
3841 struct tile *pdesttile,
3842 bool adj)
3843{
3846 struct unit_move_data *pdata;
3847
3848 /* Make new data for 'punit'. */
3851
3852 /* Add all contained units. */
3854 struct unit_move_data *cargo_data;
3855
3859
3860 /* Determine the players able to see the move(s), now that the player
3861 * vision has been increased. */
3862 if (adj) {
3863 /* Main unit for adjacent move: the move is visible for every player
3864 * able to see on the matching unit layer. */
3865 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
3866
3870 BV_SET(pdata->can_see_unit, player_index(oplayer));
3871 BV_SET(pdata->can_see_move, player_index(oplayer));
3872 }
3874 }
3875
3877
3879
3880 if (adj && pmove_data->punit == punit) {
3881 /* If positions are adjacent, we have already handled 'punit'. See
3882 * above. */
3883 continue;
3884 }
3885
3887 if ((adj
3889 pmove_data != pdata))
3891 pmove_data != pdata)) {
3892 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3893 BV_SET(pmove_data->can_see_move, player_index(oplayer));
3894 }
3896 pmove_data != pdata)) {
3897 /* The unit was seen with its source tile even if it was
3898 * teleported. */
3899 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3900 }
3903
3904 return plist;
3905}
3906
3907/**********************************************************************/
3918bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3919 struct unit *embark_to, bool find_embark_target,
3921 bool enter_hut, bool frighten_hut)
3922{
3923 struct player *pplayer;
3924 struct tile *psrctile;
3925 struct city *psrccity;
3926 struct city *pdestcity;
3927 struct unit *ptransporter;
3930 struct unit_move_data_list *plist;
3931 struct unit_move_data *pdata;
3932 int saved_id;
3933 bool unit_lives;
3934 bool adj;
3935 enum direction8 facing;
3936
3937 /* Some checks. */
3940
3941 pplayer = unit_owner(punit);
3942 saved_id = punit->id;
3945
3947
3948 /* Unload the unit if on a transport. */
3950 if (ptransporter != NULL) {
3951 /* Unload unit _before_ setting the new tile! */
3953 /* Send updated information to anyone watching that transporter
3954 * was unloading cargo. */
3956 }
3957
3958 /* Wakup units next to us before we move. */
3960
3961 /* Make info packets at 'psrctile'. */
3962 if (adj) {
3963 /* If tiles are adjacent, we will show the move to users able
3964 * to see it. */
3967 }
3968
3969 /* Set unit orientation */
3970 if (adj) {
3971 /* Only change orientation when moving to adjacent tile */
3972 punit->facing = facing;
3973 }
3974
3976
3977 /* Move magic. */
3978 punit->moved = TRUE;
3979 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3980 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3981 /* The next order may not require any remaining move fragments. */
3983 }
3984
3985 /* No longer relevant. */
3988
3989 /* Claim ownership of fortress? */
3992 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3993 * Even if original unit cannot claim other kind of bases, the
3994 * first claimed base will have influence over other bases,
3995 * or something like that. */
3996 tile_claim_bases(pdesttile, pplayer);
3997 }
3998
4000 fc_assert(pdata->punit == punit);
4001
4002 /* Check timeout settings. */
4005
4006 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4007 * if they are ever seen. */
4009 /* Increase the timeout if an enemy unit moves and the
4010 * timeoutaddenemymove setting is in use. */
4011 if (penemy->is_connected
4012 && pplayer != penemy
4013 && pplayers_at_war(pplayer, penemy)
4014 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4016 break;
4017 }
4019
4022 }
4023 }
4024
4026 /* The unit can perform an action to the city at the destination tile.
4027 * A long distance move (like an airlift) doesn't ask what action to
4028 * perform before moving. Ask now. */
4029
4032 }
4033
4034 /* Notifications of the move to the clients. */
4035 if (adj) {
4036 /* Special case: 'punit' is moving to adjacent position. Then we show
4037 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4038
4039 /* Make info packets at 'pdesttile'. */
4042
4045
4046 if (aplayer == NULL) {
4047 if (pconn->observer) {
4048 /* Global observers see all... */
4051 }
4052 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4053 if (aplayer == pplayer) {
4056 } else {
4059 }
4060 }
4062 }
4063
4064 /* Other moves. */
4066 if (adj && pmove_data == pdata) {
4067 /* If positions are adjacent, we have already shown 'punit' move.
4068 * See above. */
4069 continue;
4070 }
4071
4072 /* Make info packets at 'pdesttile'. */
4076
4079
4080 if (aplayer == NULL) {
4081 if (pconn->observer) {
4082 /* Global observers see all... */
4084 }
4085 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4086 if (aplayer == pmove_data->powner) {
4088 } else {
4090 }
4091 }
4094
4095 /* Clear old vision. */
4097 if (pmove_data->old_vision != NULL) {
4098 vision_clear_sight(pmove_data->old_vision);
4099 vision_free(pmove_data->old_vision);
4100 pmove_data->old_vision = NULL;
4101 }
4103
4104 /* Move consequences. */
4106 struct unit *aunit = pmove_data->punit;
4107
4108 if (aunit != NULL
4109 && unit_owner(aunit) == pmove_data->powner
4110 && unit_tile(aunit) == pdesttile) {
4112 pdata != pmove_data,
4114 }
4116
4117 unit_lives = (pdata->punit == punit);
4118
4119 /* Wakeup units and make contact. */
4120 if (unit_lives) {
4122 }
4123 maybe_make_contact(pdesttile, pplayer);
4124
4125 if (unit_lives) {
4126 /* Special checks for ground units in the ocean. */
4128 if (embark_to != NULL) {
4130 } else if (find_embark_target) {
4131 /* TODO: Consider to stop supporting find_embark_target and make all
4132 * callers that wants auto loading set embark_to. */
4134 } else {
4136 }
4137 if (ptransporter) {
4139
4140 /* Set activity to sentry if boarding a ship. */
4141 if (is_human(pplayer)
4146 }
4147
4149 }
4150 }
4151 }
4152
4153 /* Remove units going out of sight. */
4155 struct unit *aunit = pmove_data->punit;
4156
4157 if (aunit == NULL) {
4158 continue; /* Died! */
4159 }
4160
4162 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4165 }
4168
4169 /* Inform the owner's client about actor unit arrival. Can, depending on
4170 * the client settings, cause the client to start the process that makes
4171 * the action selection dialog pop up. */
4173 if (pdestcity != NULL) {
4174 /* Arrival in a city counts. */
4175
4177 struct unit *ptrans;
4178 bool ok;
4179 struct unit *act_unit;
4180 struct player *act_player;
4181
4182 act_unit = pmove_data->punit;
4184
4185 if (act_unit == NULL
4186 || !unit_is_alive(act_unit->id)) {
4187 /* The unit died before reaching this point. */
4188 continue;
4189 }
4190
4191 if (unit_tile(act_unit) != pdesttile) {
4192 /* The unit didn't arrive at the destination tile. */
4193 continue;
4194 }
4195
4196 if (!is_human(act_player)) {
4197 /* Only humans need reminders. */
4198 continue;
4199 }
4200
4201 if (!unit_transported(act_unit)) {
4202 /* Don't show the action selection dialog again. Non transported
4203 * units are handled before they move to the tile. */
4204 continue;
4205 }
4206
4207 /* Open action dialog only if 'act_unit' and all its transporters
4208 * (recursively) don't have orders. */
4210 /* The unit it self has orders. */
4211 continue;
4212 }
4213
4216 if (NULL == ptrans) {
4217 /* No (recursive) transport has orders. */
4218 ok = TRUE;
4219 break;
4220 } else if (unit_has_orders(ptrans)) {
4221 /* A unit transporting the unit has orders */
4222 ok = FALSE;
4223 break;
4224 }
4225 }
4226
4227 if (!ok) {
4228 /* A unit transporting act_unit has orders. */
4229 continue;
4230 }
4231
4233 /* There is a valid target. */
4234
4235 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4236 act_unit->action_decision_tile = pdesttile;
4237
4238 /* Let the client know that this unit wants the player to decide
4239 * what to do. */
4241 }
4243 }
4244
4246 /* Check cities at source and destination. */
4248 if (psrccity != NULL) {
4250 }
4251 if (pdestcity != NULL) {
4253 }
4254
4255 if (unit_lives) {
4256 /* Let the scripts run ... */
4259 }
4260
4261 if (unit_lives) {
4262 /* Autoattack. */
4264 }
4265
4266 if (unit_lives && (enter_hut || frighten_hut)) {
4267 /* Is there a hut? */
4271 }
4272
4274
4275 if (unit_lives) {
4276 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4277 }
4278
4279 return unit_lives;
4280}
4281
4282/**********************************************************************/
4286 struct tile *ptile)
4287{
4288 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
4290}
4291
4292/**********************************************************************/
4299{
4300 bool cancel = FALSE;
4301 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4302 struct player *pplayer = unit_owner(punit);
4303
4304 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4305 struct unit *penemy = tile_non_allied_unit(ptile, pplayer);
4306 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4307
4308 if ((penemy && can_player_see_unit(pplayer, penemy))
4310 && pdcity->occupied)) {
4311 cancel = TRUE;
4312 break;
4313 }
4315
4316 return cancel;
4317}
4318
4319/**********************************************************************/
4327static inline bool player_is_watching(struct unit *punit, const bool fresh)
4328{
4329 /* The player just sent the orders to the unit. The unit has moves left.
4330 * It is therefore safe to assume that the player already is paying
4331 * attention to the unit. */
4332 return fresh && punit->moves_left > 0;
4333}
4334
4335/**********************************************************************/
4354bool execute_orders(struct unit *punit, const bool fresh)
4355{
4356 struct act_prob prob;
4357 bool performed;
4358 const char *name;
4359 bool res, last_order;
4360 int unitid = punit->id;
4361 struct player *pplayer = unit_owner(punit);
4362 int moves_made = 0;
4363 const struct civ_map *nmap = &(wld.map);
4364
4366
4367 if (punit->activity != ACTIVITY_IDLE) {
4368 /* Unit's in the middle of an activity; wait for it to finish. */
4370 return TRUE;
4371 }
4372
4373 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4374
4375 /* Any time the orders are canceled we should give the player a message. */
4376
4377 while (TRUE) {
4378 struct unit_order order;
4379
4380 struct action *oaction;
4381
4382 struct tile *dst_tile;
4383 struct city *tgt_city;
4384 struct unit *tgt_unit;
4385 int tgt_id;
4386 int sub_tgt_id;
4387 struct extra_type *pextra;
4388
4389 if (punit->done_moving) {
4390 log_debug(" stopping because we're done this turn");
4391 return TRUE;
4392 }
4393
4395 /* "Patrol" orders are stopped if an enemy is near. */
4396 cancel_orders(punit, " stopping because of nearby enemy");
4398 _("Orders for %s aborted as there are units nearby."),
4399 unit_link(punit));
4400 return TRUE;
4401 }
4402
4403 if (moves_made == punit->orders.length) {
4404 /* For repeating orders, don't repeat more than once per turn. */
4405 log_debug(" stopping because we ran a round");
4408 return TRUE;
4409 }
4410 moves_made++;
4411
4412 order = punit->orders.list[punit->orders.index];
4413
4414 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4415 * this far. */
4417 || action_id_exists(order.action)),
4418 continue);
4419
4420 switch (order.order) {
4421 case ORDER_MOVE:
4422 case ORDER_ACTION_MOVE:
4423 case ORDER_FULL_MP:
4424 if (0 == punit->moves_left) {
4425 log_debug(" stopping because of no more move points");
4426 return TRUE;
4427 }
4428 break;
4431 log_debug(" stopping. Not enough move points this turn");
4432 return TRUE;
4433 }
4434 break;
4435 case ORDER_ACTIVITY:
4436 case ORDER_LAST:
4437 /* Those actions don't require moves left. */
4438 break;
4439 }
4440
4442 && punit->orders.index + 1 == punit->orders.length);
4443
4444 if (last_order) {
4445 /* Clear the orders before we engage in the move. That way any
4446 * has_orders checks will yield FALSE and this will be treated as
4447 * a normal move. This is important: for instance a caravan goto
4448 * will popup the caravan dialog on the last move only. */
4450 }
4451
4452 /* Advance the orders one step forward. This is needed because any
4453 * updates sent to the client as a result of the action should include
4454 * the new index value. Note that we have to send_unit_info somewhere
4455 * after this point so that the client is properly updated. */
4456 punit->orders.index++;
4457
4458 switch (order.order) {
4459 case ORDER_FULL_MP:
4461 /* If the unit doesn't have full MP then it just waits until the
4462 * next turn. We assume that the next turn it will have full MP
4463 * (there's no check for that). */
4465 log_debug(" waiting this turn");
4467 }
4468 break;
4469 case ORDER_ACTIVITY:
4470 {
4471 enum unit_activity activity = order.activity;
4472
4473 fc_assert(activity == ACTIVITY_SENTRY);
4474
4475 if (can_unit_do_activity(nmap, punit, activity)) {
4477 set_unit_activity(punit, activity);
4479
4480 break;
4481 }
4482 }
4483
4484 cancel_orders(punit, " orders canceled because of failed activity");
4486 _("Orders for %s aborted since they "
4487 "give an invalid activity."),
4488 unit_link(punit));
4489 return TRUE;
4490 case ORDER_MOVE:
4491 case ORDER_ACTION_MOVE:
4492 /* Move unit */
4493 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4494 cancel_orders(punit, " move order sent us to invalid location");
4496 _("Orders for %s aborted since they "
4497 "give an invalid location."),
4498 unit_link(punit));
4499 return TRUE;
4500 }
4501
4502 if (order.order != ORDER_ACTION_MOVE
4504 /* Plain move required: no attack, trade route etc. */
4505 cancel_orders(punit, " orders canceled because of enemy");
4507 _("Orders for %s aborted as there "
4508 "are units in the way."),
4509 unit_link(punit));
4510 return TRUE;
4511 }
4512
4513 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4515 order.order != ORDER_ACTION_MOVE);
4516 if (!player_unit_by_number(pplayer, unitid)) {
4517 log_debug(" unit died while moving.");
4518 /* A player notification should already have been sent. */
4519 return FALSE;
4520 }
4521
4522 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4523 /* Movement succeeded but unit didn't move. */
4524 log_debug(" orders resulted in combat.");
4526 return TRUE;
4527 }
4528
4529 if (!res) {
4530 fc_assert(0 <= punit->moves_left);
4531
4532 /* Movement failed (ZOC, etc.) */
4533 cancel_orders(punit, " attempt to move failed.");
4534
4536 /* The final move "failed" because the unit needs to ask the
4537 * player what action it should take.
4538 *
4539 * The action decision request notifies the player. Its
4540 * location at the unit's last order makes it clear to the
4541 * player who the decision is for. ("The Spy I sent to Berlin
4542 * has arrived.")
4543 *
4544 * A notification message is therefore redundant. */
4545 && !(last_order
4548 /* The player may have missed this. No one else will announce it
4549 * in a satisfying manner. Inform the player. */
4550 notify_player(pplayer, unit_tile(punit),
4552 _("Orders for %s aborted because of failed move."),
4553 unit_link(punit));
4554 }
4555
4556 return TRUE;
4557 }
4558 break;
4561
4562 /* Checked in unit_order_list_is_sane() */
4563 fc_assert_action(oaction != NULL, continue);
4564
4565 log_debug(" orders: doing action %s", action_rule_name(oaction));
4566
4567 dst_tile = index_to_tile(&(wld.map), order.target);
4568
4569 if (dst_tile == NULL) {
4570 /* Could be at the edge of the map while trying to target a tile
4571 * outside of it. */
4572
4573 cancel_orders(punit, " target location doesn't exist");
4575 order.action, dst_tile, NULL, NULL);
4576
4577 return TRUE;
4578 }
4579
4580 /* Get the target city from the target tile. */
4582
4583 if (tgt_city == NULL
4585 /* This action targets a city but no city target was found. */
4586
4587 cancel_orders(punit, " perform action vs city with no city");
4589 order.action, dst_tile, tgt_city, NULL);
4590
4591 return TRUE;
4592 }
4593
4594 /* Get a target unit at the target tile. */
4596
4597 if (tgt_unit == NULL
4599 /* This action targets a unit but no target unit was found. */
4600
4601 cancel_orders(punit, " perform action vs unit with no unit");
4603 order.action, dst_tile, tgt_city, tgt_unit);
4604
4605 return TRUE;
4606 }
4607
4608 /* Server side sub target assignment */
4609 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4610 && order.sub_target == NO_TARGET) {
4611 /* Try to find a sub target. */
4613 } else {
4614 /* The client should have specified a sub target if needed */
4615 sub_tgt_id = order.sub_target;
4616 }
4617
4618 /* Get a target extra at the target tile */
4619 pextra = (sub_tgt_id == NO_TARGET ?
4620 NULL :
4621 extra_by_number(sub_tgt_id));
4622
4624 && pextra != NULL
4625 && actres_creates_extra(oaction->result, pextra)
4626 && tile_has_extra(dst_tile, pextra)) {
4627 /* Already there. Move on to the next order. */
4628 break;
4629 }
4630
4632 && pextra != NULL
4633 && actres_removes_extra(oaction->result, pextra)
4634 && !tile_has_extra(dst_tile, pextra)) {
4635 /* Already not there. Move on to the next order. */
4636 break;
4637 }
4638
4639 /* No target selected. */
4640 tgt_id = -1;
4641
4642 /* Assume impossible until told otherwise. */
4643 prob = ACTPROB_IMPOSSIBLE;
4644
4645 switch (action_id_get_target_kind(order.action)) {
4646 case ATK_UNITS:
4647 prob = action_prob_vs_stack(nmap, punit, order.action,
4648 dst_tile);
4649 tgt_id = dst_tile->index;
4650 break;
4651 case ATK_TILE:
4652 prob = action_prob_vs_tile(nmap, punit, order.action,
4653 dst_tile, pextra);
4654 tgt_id = dst_tile->index;
4655 break;
4656 case ATK_EXTRAS:
4657 prob = action_prob_vs_extras(nmap, punit, order.action,
4658 dst_tile, pextra);
4659 tgt_id = dst_tile->index;
4660 break;
4661 case ATK_CITY:
4662 prob = action_prob_vs_city(nmap, punit, order.action,
4663 tgt_city);
4664 tgt_id = tgt_city->id;
4665 break;
4666 case ATK_UNIT:
4667 prob = action_prob_vs_unit(nmap, punit, order.action,
4668 tgt_unit);
4669
4670 tgt_id = tgt_unit->id;
4671 break;
4672 case ATK_SELF:
4673 prob = action_prob_self(nmap, punit, order.action);
4674
4675 tgt_id = unitid;
4676 break;
4677 case ATK_COUNT:
4678 log_error("Invalid action target kind");
4679
4680 /* The check below will abort and cancel the orders because prob
4681 * was initialized to impossible above this switch statement. */
4682
4683 break;
4684 }
4685
4686 if (!action_prob_possible(prob)) {
4687 /* The player has enough information to know that this action is
4688 * against the rules. Don't risk any punishment by trying to
4689 * perform it. */
4690
4691 cancel_orders(punit, " illegal action");
4693 _("%s could not do %s to %s."),
4697
4698 /* Try to explain what rule made it illegal. */
4700 order.action, dst_tile, tgt_city, tgt_unit);
4701
4702 return TRUE;
4703 }
4704
4706 /* This action needs a name. */
4708 } else {
4709 /* This action doesn't need a name. */
4710 name = "";
4711 }
4712
4714 unitid,
4715 tgt_id,
4716 sub_tgt_id,
4717 name,
4718 order.action,
4720
4721 if (!player_unit_by_number(pplayer, unitid)) {
4722 /* The unit "died" while performing the action. */
4723 return FALSE;
4724 }
4725
4726 if (!performed) {
4727 /* The action wasn't performed as ordered. */
4728
4729 cancel_orders(punit, " failed action");
4731 _("Orders for %s aborted because "
4732 "doing %s to %s failed."),
4736
4737 return TRUE;
4738 }
4739
4740 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4742 /* Done at turn change. */
4745 break;
4746 }
4747
4748 break;
4749 case ORDER_LAST:
4750 /* Should be caught when loading the unit orders from the savegame or
4751 * when receiving the unit orders from the client. */
4752 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4753 cancel_orders(punit, " invalid order!");
4755 _("Your %s has invalid orders."),
4756 unit_link(punit));
4757 return TRUE;
4758 }
4759
4760 if (last_order) {
4762 log_debug(" stopping because orders are complete");
4763 return TRUE;
4764 }
4765
4766 if (punit->orders.index == punit->orders.length) {
4768 /* Start over. */
4769 log_debug(" repeating orders.");
4770 punit->orders.index = 0;
4771 }
4772 } /* end while */
4773}
4774
4775/**********************************************************************/
4782static int get_unit_vision_base(const struct unit *punit,
4783 enum vision_layer vlayer,
4784 const int base)
4785{
4786 switch (vlayer) {
4787 case V_MAIN:
4788 return MAX(0, base);
4789 case V_INVIS:
4790 case V_SUBSURFACE:
4791 return CLIP(0, base, 2);
4792 case V_COUNT:
4793 break;
4794 }
4795
4796 log_error("Unsupported vision layer variant: %d.", vlayer);
4797
4798 return 0;
4799}
4800
4801/**********************************************************************/
4804static int unit_vision_range_modifiers(const struct unit *punit,
4805 const struct tile *ptile)
4806{
4807 const struct unit_type *utype = unit_type_get(punit);
4808
4809 return (utype->vision_radius_sq
4811 &(const struct req_context) {
4812 .player = unit_owner(punit),
4813 .tile = ptile,
4814 .unittype = utype,
4815 .unit = punit,
4816 },
4818}
4819
4820/**********************************************************************/
4827int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
4828 enum vision_layer vlayer)
4829{
4832}
4833
4834/**********************************************************************/
4841{
4842 struct vision *uvision = punit->server.vision;
4843 const struct tile *utile = unit_tile(punit);
4844 int mod = unit_vision_range_modifiers(punit, utile);
4845 const v_radius_t radius_sq
4849
4850 vision_change_sight(uvision, radius_sq);
4852}
4853
4854/**********************************************************************/
4863
4864/**********************************************************************/
4869{
4870 time_t dt;
4871
4872 if (!punit) {
4873 return FALSE;
4874 }
4875
4876 if (game.server.unitwaittime <= 0) {
4877 return TRUE;
4878 }
4879
4880 if (punit->server.action_turn != game.info.turn - 1) {
4881 return TRUE;
4882 }
4883
4885 if (dt < game.server.unitwaittime) {
4886 char buf[64];
4889 ftc_server, _("Your unit may not act for another %s "
4890 "this turn. See /help unitwaittime."), buf);
4891 return FALSE;
4892 }
4893
4894 return TRUE;
4895}
4896
4897/**********************************************************************/
4902{
4903 if (!punit) {
4904 return;
4905 }
4906
4909}
4910
4911/**********************************************************************/
4917{
4918 /* check if there is enemy nearby */
4919 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
4921 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4922 return FALSE;
4923 }
4924 }
4926
4927 return TRUE;
4928}
4929
4930/**********************************************************************/
4933void random_movements(struct player *pplayer)
4934{
4935 const struct civ_map *nmap = &(wld.map);
4936
4937 game.server.random_move_time = pplayer;
4938
4941 bool moved = TRUE;
4942 struct tile *curtile = unit_tile(punit);
4943 int id = punit->id;
4944
4945 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
4946 /*
4947 * List of all 8 directions
4948 */
4949 enum direction8 dirs[8] = {
4952 };
4953 int n;
4954
4955 moved = FALSE;
4956
4957 for (n = 8; n > 0 && !moved; n--) {
4958 enum direction8 choice = (enum direction8) fc_rand(n);
4959 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
4960
4961 if (dest != NULL) {
4963 dest))) {
4964 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
4966 moved = TRUE;
4967 break;
4968 }
4969 }
4970
4971 if (!moved) {
4973 NULL)) {
4974 if (unit_perform_action(pplayer, id, tile_index(dest),
4976 ACT_REQ_RULES)) {
4977 moved = TRUE;
4978 }
4980 punit, dest, NULL)) {
4981 if (unit_perform_action(pplayer, id, tile_index(dest),
4983 ACT_REQ_RULES)) {
4984 moved = TRUE;
4985 }
4987 punit, dest, NULL)) {
4988 if (unit_perform_action(pplayer, id, tile_index(dest),
4990 ACT_REQ_RULES)) {
4991 moved = TRUE;
4992 }
4993 }
4994 }
4995 }
4996
4997 if (!moved) {
4998 /* Choice was bad, so replace it with the last direction
4999 * in the list. On the next iteration, one fewer choice
5000 * will remain. */
5001 dirs[choice] = dirs[n - 1];
5002 }
5003 }
5004 }
5005 }
5007
5009}
const char * action_name_translation(const struct action *action)
Definition actions.c:1991
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:6292
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2011
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5821
struct act_prob action_prob_vs_tile(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5342
const char * action_rule_name(const struct action *action)
Definition actions.c:1977
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1880
bool is_action_enabled_unit_on_tile(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4082
struct act_prob action_prob_vs_extras(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5425
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:5495
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:4984
bool action_id_exists(const action_id act_id)
Definition actions.c:1829
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5881
struct act_prob action_prob_vs_stack(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:5259
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:5067
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5932
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
#define action_has_result(_act_, _res_)
Definition actions.h:431
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:676
#define ACTPROB_IMPOSSIBLE
Definition actions.h:922
#define action_id_get_target_kind(act_id)
Definition actions.h:652
#define action_id_has_result_safe(act_id, result)
Definition actions.h:665
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 actres_removes_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:803
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:782
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:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#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)
void dbv_to_bv(unsigned char *dest, const struct dbv *src)
Definition bitvector.c:235
#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 is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile, int distance)
Definition city.c:2092
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
bool city_exists_within_max_city_map(const struct civ_map *nmap, const struct tile *ptile, bool may_be_on_center)
Definition city.c:2112
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:770
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:734
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:746
#define output_type_iterate(output)
Definition city.h:845
#define city_owner(_pcity_)
Definition city.h:563
#define city_list_iterate_end
Definition city.h:510
#define output_type_iterate_end
Definition city.h:851
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3333
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:458
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2363
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:856
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2216
void sync_cities(void)
Definition citytools.c:3342
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1987
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3156
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:763
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:478
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:989
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:712
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1020
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:767
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:610
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:836
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:409
char * incite_cost
Definition comments.c:75
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:763
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2931
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2658
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2688
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:74
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct player *other_player, enum effect_type effect_type)
Definition effects.c:748
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:1070
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:828
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:283
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:790
struct extra_type * extra_by_number(int id)
Definition extras.c:183
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:203
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:353
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
#define extra_type_by_rmcause_iterate_end
Definition extras.h:358
#define extra_index(_e_)
Definition extras.h:183
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:353
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_list_iterate_end
Definition extras.h:167
#define NO_TARGET
Definition fc_types.h:354
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:349
@ RPT_CERTAIN
Definition fc_types.h:701
@ AUT_NONE
Definition fc_types.h:370
@ HB_DISABLED
Definition fc_types.h:1290
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#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:62
int current_turn_timeout(void)
Definition game.c:848
struct world wld
Definition game.c:63
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:124
struct unit * game_unit_by_number(int id)
Definition game.c:116
struct city * game_city_by_number(int id)
Definition game.c:107
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1036
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
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:82
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:641
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:667
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:940
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:371
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:1328
#define adjc_iterate_end
Definition map.h:433
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
#define square_iterate_end
Definition map.h:394
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:293
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:401
#define circle_iterate_end
Definition map.h:404
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2533
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2621
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1919
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2220
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2556
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2724
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:920
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:864
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1439
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:1995
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1382
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2521
#define map_get_player_site(_ptile_, _pplayer_)
Definition maphand.h:93
#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:290
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:331
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:911
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:342
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:491
@ MR_OK
Definition movement.h:35
@ MR_NOT_ALLOWED
Definition movement.h:53
@ MR_DEATH
Definition movement.h:36
static const char * name_translation_get(const struct name_translation *ptrans)
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:463
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
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:291
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:238
unit_info_use
Definition packets.h:66
@ UNIT_INFO_IDENTITY
Definition packets.h:67
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)
void dlsend_packet_unit_remove(struct conn_list *dest, int unit_id)
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 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:1229
struct player * player_by_number(const int player_id)
Definition player.c:849
bool can_player_see_unit_at(const struct player *pplayer, const struct unit *punit, const struct tile *ptile, bool is_transported)
Definition player.c:1034
int player_slot_count(void)
Definition player.c:418
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1104
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1388
int player_index(const struct player *pplayer)
Definition player.c:829
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
struct player_slot * slots
Definition player.c:51
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1459
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define is_ai(plr)
Definition player.h:230
#define is_human(plr)
Definition player.h:229
void player_update_last_war_action(struct player *pplayer)
Definition plrhand.c:865
void player_status_add(struct player *plr, enum player_status pstatus)
Definition plrhand.c:3212
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2361
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1146
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1593
void player_loot_player(struct player *pvictor, struct player *pvictim)
Definition plrhand.c:411
#define phase_players_iterate(pplayer)
Definition plrhand.h:113
#define phase_players_iterate_end
Definition plrhand.h:118
#define fc_rand(_size)
Definition rand.h:56
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)
void script_server_signal_emit(const char *signal_name,...)
void script_server_remove_exported_object(void *object)
void flush_packets(void)
Definition sernet.c:381
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1967
#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:2020
struct act_prob prob
Definition unittools.c:115
Definition city.h:320
int id
Definition city.h:326
struct tile * tile
Definition city.h:322
struct unit_list * units_supported
Definition city.h:406
int unitwaittime
Definition game.h:202
struct player * random_move_time
Definition game.h:279
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:136
int killunhomed
Definition game.h:158
struct civ_game::@31::@35 server
int ransom_gold
Definition game.h:179
bool autoattack
Definition game.h:135
int timeoutaddenemymove
Definition game.h:212
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:197
int units_used
Definition player.h:106
int units_lost
Definition player.h:104
struct unit_list * units
Definition player.h:280
struct conn_list * connections
Definition player.h:296
int huts
Definition player.h:347
bool is_alive
Definition player.h:266
struct player_economic economic
Definition player.h:282
struct player_score score
Definition player.h:281
struct player::@70::@72 server
const struct player * player
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
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:522
enum vision_layer vlayer
Definition unittype.h:569
Definition unit.h:138
time_t action_timestamp
Definition unit.h:245
int length
Definition unit.h:195
int upkeep[O_LAST]
Definition unit.h:148
bool has_orders
Definition unit.h:193
struct unit::@80 orders
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:244
bool vigilant
Definition unit.h:197
int hp
Definition unit.h:151
int fuel
Definition unit.h:153
struct extra_type * changed_from_target
Definition unit.h:170
int current_form_turn
Definition unit.h:208
bool stay
Definition unit.h:205
enum direction8 facing
Definition unit.h:142
struct unit::@81::@84 server
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:253
struct unit_move_data * moving
Definition unit.h:247
int action_turn
Definition unit.h:246
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:207
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:250
enum server_side_agent ssa_controller
Definition unit.h:172
struct civ_map map
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:550
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:215
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:681
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:233
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:418
int tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:196
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:88
#define tile_terrain(_tile)
Definition tile.h:110
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:120
#define tile_continent(_tile)
Definition tile.h:92
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
#define tile_owner(_tile)
Definition tile.h:96
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:1306
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1783
void free_unit_orders(struct unit *punit)
Definition unit.c:1769
bool unit_is_alive(int id)
Definition unit.c:2253
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:526
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2370
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1088
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1245
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2441
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2390
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2183
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:841
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1624
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:868
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1729
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1255
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1988
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2425
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:752
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2451
bool unit_has_orders(const struct unit *punit)
Definition unit.c:202
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1912
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2035
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:566
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:907
#define unit_tile(_pu)
Definition unit.h:397
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:420
#define unit_cargo_iterate_end
Definition unit.h:573
@ 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:408
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:570
#define CHECK_UNIT(punit)
Definition unit.h:270
#define unit_owner(_pu)
Definition unit.h:396
@ UU_OK
Definition unit.h:61
#define unit_home(_pu_)
Definition unit.h:394
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:432
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:2492
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6471
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:3313
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5533
#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_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, const struct action *paction)
Definition unittools.c:355
void unit_did_action(struct unit *punit)
Definition unittools.c:4901
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3301
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2494
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:2911
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1157
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:2143
static struct unit_move_data_list * construct_move_data_list(struct unit *punit, const struct tile *psrctile, struct tile *pdesttile, bool adj)
Definition unittools.c:3839
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4354
static void unit_convert(struct unit *punit)
Definition unittools.c:770
void update_unit_activities(struct player *pplayer)
Definition unittools.c:666
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1300
#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:1545
void random_movements(struct player *pplayer)
Definition unittools.c:4933
bool unit_versus_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, int *att_vet, int *def_vet, const struct action *paction)
Definition unittools.c:288
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1786
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1409
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1481
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1911
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1444
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4285
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:400
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1394
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:2879
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3818
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1763
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3178
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2584
#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:2709
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:657
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3500
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:714
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:814
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3259
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3357
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:698
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:676
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:1109
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2722
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1935
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1365
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3703
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:630
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:424
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3732
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1705
void notify_unit_experience(struct unit *punit)
Definition unittools.c:743
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:796
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:2665
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:1657
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1468
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1049
#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:1624
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1902
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1777
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4827
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:219
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4840
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:1597
void do_explore(struct unit *punit)
Definition unittools.c:2944
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3229
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:4868
#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:2131
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:688
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:2980
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4327
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4782
void player_restore_units(struct player *pplayer)
Definition unittools.c:477
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1523
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4804
static void update_unit_activity(struct unit *punit)
Definition unittools.c:854
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3281
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1514
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Definition unittools.c:175
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3489
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:4916
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:734
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:826
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2191
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1183
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2794
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3143
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1078
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3315
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:841
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:3570
void unit_get_goods(struct unit *punit)
Definition unittools.c:1608
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2766
static bool maybe_become_veteran_real(struct unit *punit, int base_chance, bool settler)
Definition unittools.c:237
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4298
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:3918
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3767
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4857
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2258
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1221
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1058
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:1569
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, bool consider_reg_impr_req)
Definition unittype.c:1968
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2253
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2568
int num_role_units(int role)
Definition unittype.c:2203
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1927
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1703
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2499
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
const struct veteran_level * vsystem_veteran_level(const struct veteran_system *vsystem, int level)
Definition unittype.c:2585
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:1560
#define utype_class(_t_)
Definition unittype.h:749
#define utype_fuel(ptype)
Definition unittype.h:839
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
#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:129
short int v_radius_t[V_COUNT]
Definition vision.h:83