Freeciv-3.3
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 "autoworkers.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 worker);
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/**********************************************************************/
239 bool worker)
240{
241 const struct veteran_system *vsystem;
242 const struct veteran_level *vlevel;
243 int chance;
244 const struct civ_map *nmap = &(wld.map);
245
247
251
254
255 if (punit->veteran + 1 >= vsystem->levels
257 return FALSE;
258 } else if (!worker) {
260
261 /* The modification is tacked on as a multiplier to the base chance.
262 * For example with a base chance of 50% for green units and a modifier
263 * of +50% the end chance is 75%. */
264 chance = vlevel->base_raise_chance * mod / 100;
267
268 chance = vlevel->work_raise_chance * mod / 100;
269 } else {
270 /* No battle and no work done. */
271 return FALSE;
272 }
273
274 if (fc_rand(100) < chance) {
275 punit->veteran++;
276 return TRUE;
277 }
278
279 return FALSE;
280}
281
282/**********************************************************************/
292bool unit_versus_unit(struct unit *attacker, struct unit *defender,
293 int *att_hp, int *def_hp, int *att_vet, int *def_vet,
294 const struct action *paction)
295{
296 int attackpower = get_total_attack_power(attacker, defender, paction);
297 int defensepower = get_total_defense_power(attacker, defender);
299 struct player *plr1 = unit_owner(attacker);
300 struct player *plr2 = unit_owner(defender);
301 struct civ_map *nmap = &(wld.map);
302 int max_rounds;
303 int rounds;
304 int att_strength;
305 int def_strength;
306
307 *att_hp = attacker->hp;
308 *def_hp = defender->hp;
309 get_modified_firepower(nmap, attacker, defender,
311
312 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
313 "defense firepower:%d", attackpower, defensepower,
315
318
321
322 /* In a combat between equal strength units the values are 50% / 50%.
323 * -> scaling that to 100% by doubling, to match scale of chances
324 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
327
328 if (attackpower == 0) {
329 *att_hp = 0;
330 } else if (defensepower == 0) {
331 *def_hp = 0;
332 }
334 for (rounds = 0;
335 *att_hp > 0 && *def_hp > 0
337 rounds++) {
339 *def_hp -= attack_firepower;
340 } else {
341 *att_hp -= defense_firepower;
342 }
343 }
344 if (*att_hp < 0) {
345 *att_hp = 0;
346 }
347 if (*def_hp < 0) {
348 *def_hp = 0;
349 }
350
351 return attackpower <= 0 || defensepower <= 0;
352}
353
354/**********************************************************************/
360void unit_bombs_unit(struct unit *attacker, struct unit *defender,
361 int *att_hp, int *def_hp,
362 const struct action *paction)
363{
364 int i;
365 int rate = unit_bombard_rate(attacker);
366 int attackpower = get_total_attack_power(attacker, defender, paction);
367 int defensepower = get_total_defense_power(attacker, defender);
369 struct player *plr1 = unit_owner(attacker);
370 struct player *plr2 = unit_owner(defender);
371 struct civ_map *nmap = &(wld.map);
372
373 *att_hp = attacker->hp;
374 *def_hp = defender->hp;
375 get_modified_firepower(nmap, attacker, defender,
377
378 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
379 "defense firepower:%d", attackpower, defensepower,
381
384
385 for (i = 0; i < rate; i++) {
387 *def_hp -= attack_firepower;
388 }
389 }
390
391 if (*def_hp <= 0) {
392 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
393 /* Don't kill the target. */
394 *def_hp = 1;
395 } else {
396 *def_hp = 0;
397 }
398 }
399}
400
401/**********************************************************************/
405void combat_veterans(struct unit *attacker, struct unit *defender,
406 bool powerless, int att_vet, int def_vet)
407{
409 if (attacker->hp <= 0 || defender->hp <= 0
412 att_vet = 100;
413 def_vet = 100;
414 }
415 if (attacker->hp > 0) {
416 maybe_make_veteran(attacker, att_vet);
417 }
418 if (defender->hp > 0) {
419 maybe_make_veteran(defender, def_vet);
420 }
421 }
422 }
423}
424
425/**********************************************************************/
429static void do_upgrade_effects(struct player *pplayer)
430{
432 struct unit_list *candidates;
433
434 if (upgrades <= 0) {
435 return;
436 }
438
439 unit_list_iterate(pplayer->units, punit) {
440 /* We have to be careful not to strand units at sea, for example by
441 * upgrading a frigate to an ironclad while it was carrying a unit. */
442 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
443 unit_list_prepend(candidates, punit); /* Potential candidate :) */
444 }
446
447 while (upgrades > 0 && unit_list_size(candidates) > 0) {
448 /* Upgrade one unit. The unit is chosen at random from the list of
449 * available candidates. */
452 const struct unit_type *type_from = unit_type_get(punit);
453 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
454
457 _("%s was upgraded for free to %s."),
461 upgrades--;
462 }
463
465}
466
467/**********************************************************************/
482void player_restore_units(struct player *pplayer)
483{
484 const struct civ_map *nmap = &(wld.map);
485
486 /* 1) get Leonardo out of the way first: */
487 do_upgrade_effects(pplayer);
488
490
491 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
493
494 /* 3) Check that unit has hitpoints */
495 if (punit->hp <= 0) {
496 /* This should usually only happen for heli units, but if any other
497 * units get 0 hp somehow, catch them too. --dwp */
498 /* if 'game.server.killunhomed' is activated unhomed units are slowly
499 * killed; notify player here */
500 if (!punit->homecity && 0 < game.server.killunhomed) {
502 ftc_server, _("Your %s has run out of hit points "
503 "because it was not supported by a city."),
505 } else {
507 _("Your %s has run out of hit points."),
509 }
510
512 continue; /* Continue iterating... */
513 }
514
515 /* 4) Rescue planes if needed */
517 /* Shall we emergency return home on the last vapors? */
518
519 /* I think this is strongly against the spirit of client goto.
520 * The problem is (again) that here we know too much. -- Zamar */
521
522 if (punit->fuel <= 1
524 struct unit *carrier;
525
527 if (carrier) {
529 } else {
530 struct pf_map *pfm;
531 struct pf_parameter parameter;
532 bool alive = TRUE;
533
534 pft_fill_unit_parameter(&parameter, nmap, punit);
535 parameter.omniscience = !has_handicap(pplayer, H_MAP);
536 pfm = pf_map_new(&parameter);
537
538 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
539 if (move_cost > punit->moves_left) {
540 /* Too far */
541 break;
542 }
543
544 if (is_refuel_point(ptile, pplayer, punit)) {
545 struct pf_path *path;
546 int id = punit->id;
547
548 /* Client orders may be running for this unit - if so
549 * we free them before engaging goto. */
551
552 path = pf_map_path(pfm, ptile);
553
554 alive = adv_follow_path(punit, path, ptile);
555
556 if (!alive) {
557 log_error("rescue plane: unit %d died enroute!", id);
558 } else if (!same_pos(unit_tile(punit), ptile)) {
559 /* Enemy units probably blocked our route
560 * FIXME: We should try find alternative route around
561 * the enemy unit instead of just giving up and crashing. */
562 log_debug("rescue plane: unit %d could not move to "
563 "refuel point!", punit->id);
564 }
565
566 if (alive) {
567 /* Clear activity. Unit info will be sent in the end of
568 * the function. */
572
575 if (carrier) {
577 }
578 }
579
580 notify_player(pplayer, unit_tile(punit),
582 _("Your %s has returned to refuel."),
584 }
585 pf_path_destroy(path);
586 break;
587 }
590
591 if (!alive) {
592 /* Unit died trying to move to refuel point. */
593 return;
594 }
595 }
596 }
597
598 /* 5) Update fuel */
599 punit->fuel--;
600
601 /* 6) Automatically refuel air units in cities, airbases, and
602 * transporters (carriers). */
605 }
606 }
608
609 /* 7) Check if there are air units without fuel */
611 const struct unit_type *utype = unit_type_get(punit);
612
613 if (punit->fuel <= 0 && utype_fuel(utype)) {
614 /* Notifications sent from the lua script when unit wiped. */
616 }
618
619 /* Send all updates. */
620 unit_list_iterate(pplayer->units, punit) {
623}
624
625/**********************************************************************/
636{
637 bool was_lower;
638 const struct unit_type *utype = unit_type_get(punit);
639
640 was_lower = (punit->hp < utype->hp);
641
643
644 fc_assert(punit->hp >= 0);
645 fc_assert(punit->hp <= utype->hp);
646
647 if (punit->hp == utype->hp) {
650 }
651 }
652
653 punit->moved = FALSE;
655}
656
657/**********************************************************************/
662static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
663{
666}
667
668/**********************************************************************/
677
678/**********************************************************************/
681void execute_unit_orders(struct player *pplayer)
682{
684 if (unit_has_orders(punit)) {
686 }
688}
689
690/**********************************************************************/
693void unit_tc_effect_refresh(struct player *pplayer)
694{
695 unit_list_iterate(pplayer->units, punit) {
698}
699
700/**********************************************************************/
704{
705 /* Remember activities only after all knock-on effects of unit activities
706 * on other units have been resolved */
707 unit_list_iterate(pplayer->units, punit) {
713}
714
715/**********************************************************************/
719static int total_activity(struct tile *ptile, enum unit_activity act,
720 struct extra_type *tgt)
721{
722 int total = 0;
724
725 unit_list_iterate(ptile->units, punit) {
726 if (punit->activity == act
727 && (!tgt_matters || punit->activity_target == tgt)) {
728 total += punit->activity_count;
729 }
731
732 return total;
733}
734
735/**********************************************************************/
739static bool total_activity_done(struct tile *ptile, enum unit_activity act,
740 struct extra_type *tgt)
741{
742 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
743}
744
745/**********************************************************************/
749{
750 const struct veteran_level *vlevel;
751 const struct veteran_system *vsystem;
752
753 if (!punit) {
754 return;
755 }
756
760
763
766 /* TRANS: Your <unit> became ... rank of <veteran level>. */
767 _("Your %s became more experienced and achieved the rank "
768 "of %s."),
770}
771
772/**********************************************************************/
775static void unit_convert(struct unit *punit)
776{
777 const struct unit_type *to_type;
778 const struct unit_type *from_type;
779
781 to_type = from_type->converted_to;
782
783 if (unit_can_convert(&(wld.map), punit)) {
787 _("%s converted to %s."),
790 } else {
793 _("%s cannot be converted."),
795 }
796}
797
798/**********************************************************************/
802{
803 if (unit_has_orders(punit)) {
806 _("Orders for %s aborted because activity "
807 "is no longer available."),
810 }
811
814}
815
816/**********************************************************************/
827
828/**********************************************************************/
839
840/**********************************************************************/
854
855/**********************************************************************/
859static void update_unit_activity(struct unit *punit)
860{
861 struct player *pplayer = unit_owner(punit);
863 enum unit_activity activity = punit->activity;
864 struct tile *ptile = unit_tile(punit);
865 const struct unit_type *act_utype = unit_type_get(punit);
866
867 switch (activity) {
868 case ACTIVITY_IDLE:
869 case ACTIVITY_EXPLORE:
871 case ACTIVITY_SENTRY:
872 case ACTIVITY_GOTO:
873 case ACTIVITY_LAST:
874 /* We don't need the activity_count for the above */
875 break;
876
878 case ACTIVITY_CONVERT:
880 break;
881
882 case ACTIVITY_CLEAN:
883 case ACTIVITY_MINE:
885 case ACTIVITY_PILLAGE:
887 case ACTIVITY_PLANT:
889 case ACTIVITY_BASE:
892
893 /* Worker may become veteran when doing something useful */
896 }
897 break;
898 };
899
901
902 switch (activity) {
903 case ACTIVITY_EXPLORE:
904 /* Not accumulating activity - will be handled more like movement
905 * after the TC */
907 case ACTIVITY_IDLE:
909 case ACTIVITY_SENTRY:
910 case ACTIVITY_GOTO:
912 case ACTIVITY_CONVERT:
913 case ACTIVITY_LAST:
914 /* No default, ensure all handled */
915 break;
916
917 case ACTIVITY_PILLAGE:
922
924
925 /* Change vision if effects have changed. */
927 }
928 break;
929
930 case ACTIVITY_CLEAN:
931 /* TODO: Remove this fallback target setting when target always correctly
932 * set */
933 {
934 struct extra_type *pextra;
935
936 if (punit->activity_target == NULL) {
937 pextra = prev_extra_in_tile(ptile, ERM_CLEAN,
938 NULL, punit);
939 if (pextra != NULL) {
940 punit->activity_target = pextra;
941 }
942 } else {
944 pextra = punit->activity_target;
945 } else {
946 pextra = NULL;
947 }
948 }
949
950 if (pextra != NULL) {
951 if (total_activity_done(ptile, ACTIVITY_CLEAN, pextra)) {
952 destroy_extra(ptile, pextra);
954 }
955 }
956 }
957 break;
958
959 case ACTIVITY_BASE:
960 {
965 }
966 }
967 break;
968
970 {
975 }
976 }
977 break;
978
980 case ACTIVITY_MINE:
982 case ACTIVITY_PLANT:
984 if (total_activity_done(ptile, activity, punit->activity_target)) {
985 struct terrain *old = tile_terrain(ptile);
986
987 /* The function below could change the terrain. Therefore, we have to
988 * check the terrain (which will also do a sanity check for the tile). */
989 tile_apply_activity(ptile, activity, punit->activity_target);
992 }
993 break;
994 }
995
996 if (unit_activity_done) {
998
1000
1001 unit_list_iterate(ptile->units, punit2) {
1002 if (punit2->activity == activity
1003 && punit2->activity_target == act_tgt) {
1004 /* This unit was helping with the work just finished.
1005 * Mark it idle (already finished) so its "current"
1006 * activity is not considered illegal
1007 * in tile_change_side_effects() . */
1009 }
1011
1013 }
1014
1015 if (activity == ACTIVITY_FORTIFYING) {
1018 punit, ptile, punit->activity_target)) {
1021 }
1022 }
1023
1024 if (activity == ACTIVITY_CONVERT) {
1027 punit, ptile, punit->activity_target)) {
1031 }
1032 }
1033
1034 if (unit_activity_done) {
1035 if (activity == ACTIVITY_PILLAGE) {
1036 /* Casus Belli for when the action is completed. */
1037 /* TODO: is it more logical to put Casus_Belli_Success here, change
1038 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1039 * trigger it when an activity successfully has began? */
1042 act_utype,
1046 }
1047 }
1048}
1049
1050/**********************************************************************/
1058
1059/**********************************************************************/
1064{
1065 switch (activity) {
1066 case ACTIVITY_PILLAGE:
1067 /* Can be set server side. */
1068 return FALSE;
1069 default:
1070 return activity_requires_target(activity);
1071 }
1072}
1073
1074/**********************************************************************/
1084 enum unit_activity *activity,
1085 enum gen_action action,
1086 struct extra_type **target)
1087{
1088 const struct civ_map *nmap = &(wld.map);
1089
1090 if (*activity == ACTIVITY_PILLAGE
1091 && *target == nullptr) {
1092 struct tile *ptile = unit_tile(punit);
1093 struct extra_type *tgt;
1094 bv_extras extras = *tile_extras(ptile);
1095
1096 while ((tgt = get_preferred_pillage(extras))) {
1097
1098 BV_CLR(extras, extra_index(tgt));
1099
1101 tgt)) {
1102 *target = tgt;
1103 return;
1104 }
1105 }
1106
1107 /* Nothing we can pillage here. */
1108 *activity = ACTIVITY_IDLE;
1109 }
1110}
1111
1112/**********************************************************************/
1117 struct player *powner,
1118 struct unit_type *u_type,
1119 int sq_radius,
1120 struct tile **dst_tile)
1121{
1122 int bestvalue = 0;
1123 struct civ_map *nmap = &(wld.map);
1124
1125 /* coords of best tile in arg pointers */
1127 int value;
1128
1129 if (!is_native_tile(u_type, ptile)) {
1130 continue;
1131 }
1132
1133 if (NULL != tile_city(ptile)) {
1134 continue;
1135 }
1136
1137 if (0 < unit_list_size(ptile->units)) {
1138 continue;
1139 }
1140
1141 /* City may not have changed hands yet; see place_partisans(). */
1142 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1143 ptile, FALSE, 0);
1144 value *= 10;
1145
1146 if (tile_continent(ptile) != tile_continent(pcenter)) {
1147 value /= 2;
1148 }
1149
1150 value -= fc_rand(value/3);
1151
1152 if (value > bestvalue) {
1153 *dst_tile = ptile;
1154 bestvalue = value;
1155 }
1157
1158 return bestvalue > 0;
1159}
1160
1161/**********************************************************************/
1164void place_partisans(struct tile *pcenter, struct player *powner,
1165 int count, int sq_radius)
1166{
1167 struct tile *ptile = NULL;
1169 const struct civ_map *nmap = &(wld.map);
1170
1171 while (count-- > 0
1173 sq_radius, &ptile)) {
1174 struct unit *punit;
1176
1177 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1179 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1180 punit->action = action;
1181 }
1182
1183 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1184 }
1185}
1186
1187/**********************************************************************/
1193 int move_cost, bool verbose)
1194{
1195 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1196
1197 if (city_owner(pcity) == unit_owner(punit)) {
1198 log_verbose("Teleported %s %s from (%d,%d) to %s",
1201 if (verbose) {
1204 _("Teleported your %s to %s."),
1206 city_link(pcity));
1207 }
1208
1209 /* Silently free orders since they won't be applicable anymore. */
1211
1212 if (move_cost == -1) {
1213 move_cost = punit->moves_left;
1214 }
1215 unit_move(punit, dst_tile, move_cost,
1217
1218 return TRUE;
1219 }
1220 return FALSE;
1221}
1222
1223/**********************************************************************/
1230void bounce_unit(struct unit *punit, bool verbose)
1231{
1232 struct player *pplayer;
1233 struct tile *punit_tile;
1234 int count = 0;
1235
1236 /* I assume that there are no topologies that have more than
1237 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1238 const int DIST = 2;
1239 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1240
1241 if (!punit) {
1242 return;
1243 }
1244
1245 pplayer = unit_owner(punit);
1247
1248 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1249 if (count >= ARRAY_SIZE(tiles)) {
1250 break;
1251 }
1252
1253 if (ptile == punit_tile) {
1254 continue;
1255 }
1256
1257 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1258 && !is_non_allied_city_tile(ptile, pplayer)
1259 && !is_non_allied_unit_tile(ptile, pplayer,
1261 tiles[count++] = ptile;
1262 }
1264
1265 if (count > 0) {
1266 struct tile *ptile = tiles[fc_rand(count)];
1267
1268 if (verbose) {
1269 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1270 /* TRANS: A unit is moved to resolve stack conflicts. */
1271 _("Moved your %s."),
1272 unit_link(punit));
1273 }
1274
1275 /* TODO: should a unit be able to bounce to a transport like is done
1276 * below? What if the unit can't legally enter the transport, say
1277 * because the transport is Unreachable and the unit doesn't have it in
1278 * its embarks field or because "Transport Embark" isn't enabled? Kept
1279 * like it was to preserve the old rules for now. -- Sveinung */
1280 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1281 return;
1282 }
1283
1284 /* Didn't find a place to bounce the unit, going to disband it.
1285 * Try to bounce transported units. */
1287 struct unit_list *pcargo_units;
1288
1291 bounce_unit(pcargo, verbose);
1293 }
1294
1295 if (verbose) {
1297 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1298 _("Disbanded your %s."),
1300 }
1301
1303}
1304
1305/**********************************************************************/
1310static void throw_units_from_illegal_cities(struct player *pplayer,
1311 bool verbose)
1312{
1313 struct tile *ptile;
1314 struct city *pcity;
1315 struct unit *ptrans;
1316 struct unit_list *pcargo_units;
1317
1318 /* Unload undesired units from transports, if possible. */
1319 unit_list_iterate(pplayer->units, punit) {
1320 ptile = unit_tile(punit);
1321 pcity = tile_city(ptile);
1322 if (NULL != pcity
1323 && !pplayers_allied(city_owner(pcity), pplayer)
1327 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1328 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1330 }
1331 }
1333 }
1335
1336 /* Bounce units except transported ones which will be bounced with their
1337 * transport. */
1339 ptile = unit_tile(punit);
1340 pcity = tile_city(ptile);
1341 if (NULL != pcity
1342 && !pplayers_allied(city_owner(pcity), pplayer)) {
1344 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1345 bounce_unit(punit, verbose);
1346 }
1347 }
1349
1350#ifdef FREECIV_DEBUG
1351 /* Sanity check. */
1352 unit_list_iterate(pplayer->units, punit) {
1353 ptile = unit_tile(punit);
1354 pcity = tile_city(ptile);
1356 || pplayers_allied(city_owner(pcity), pplayer),
1357 "Failed to throw %s %d from %s %d (%d, %d)",
1359 punit->id,
1361 pcity->id,
1362 TILE_XY(ptile));
1364#endif /* FREECIV_DEBUG */
1365}
1366
1367/**********************************************************************/
1375static void resolve_stack_conflicts(struct player *pplayer,
1376 struct player *aplayer, bool verbose)
1377{
1379 struct tile *ptile = unit_tile(punit);
1380
1381 /* Can pass FALSE 'everyone_non_allied' since no flagless
1382 * unit could be stacked there to begin with. */
1383 if (is_non_allied_unit_tile(ptile, pplayer, FALSE)) {
1385 if (unit_owner(aunit) == pplayer
1386 || unit_owner(aunit) == aplayer
1387 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1388 bounce_unit(aunit, verbose);
1389 }
1391 }
1393}
1394
1395/**********************************************************************/
1406void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1407 bool verbose)
1408{
1409 throw_units_from_illegal_cities(pplayer, verbose);
1411
1412 resolve_stack_conflicts(pplayer, aplayer, verbose);
1413 resolve_stack_conflicts(aplayer, pplayer, verbose);
1414}
1415
1416/**********************************************************************/
1421struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1422 const struct player *aplayer)
1423{
1424 struct unit_list *seen_units = unit_list_new();
1425
1426 /* Anybody's units inside ally's cities */
1427 city_list_iterate(aplayer->cities, pcity) {
1429 if (can_player_see_unit(pplayer, punit)) {
1431 }
1434
1435 /* Ally's own units inside transports */
1437 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1439 }
1441
1442 /* Make sure the same unit is not added in multiple phases
1443 * (unit within transport in a city) */
1445
1446 return seen_units;
1447}
1448
1449/**********************************************************************/
1456void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1457 const struct unit_list *seen_units)
1458{
1460 /* We need to hide units previously seen by the client. */
1461 if (!can_player_see_unit(pplayer, punit)) {
1462 unit_goes_out_of_sight(pplayer, punit);
1463 }
1465
1466 city_list_iterate(aplayer->cities, pcity) {
1467 /* The player used to know what units were in these cities. Now that
1468 * they don't, they need to get a new short city packet updating the
1469 * occupied status. */
1470 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1471 send_city_info(pplayer, pcity);
1472 }
1474}
1475
1476/**********************************************************************/
1480void give_allied_visibility(struct player *pplayer,
1481 struct player *aplayer)
1482{
1484 if (can_player_see_unit(pplayer, punit)) {
1485 send_unit_info(pplayer->connections, punit);
1486 }
1488}
1489
1490/**********************************************************************/
1493static bool is_refuel_tile(const struct tile *ptile,
1494 const struct player *pplayer,
1495 const struct unit *punit)
1496{
1497 const struct unit_type *utype;
1498 const struct unit_class *pclass;
1499
1500 if (is_allied_city_tile(ptile, pplayer)) {
1501 return TRUE;
1502 }
1503
1504 utype = unit_type_get(punit);
1505 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1506 return TRUE;
1507 }
1508
1509 pclass = utype_class(utype);
1510 if (NULL != pclass->cache.refuel_extras) {
1511 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1512
1513 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1514 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1515 return TRUE;
1516 }
1518 }
1519
1520 return FALSE;
1521}
1522
1523/**********************************************************************/
1527{
1528 return unit_transported(punit) /* Carrier */
1530}
1531
1532/**********************************************************************/
1535bool is_refuel_point(const struct tile *ptile,
1536 const struct player *pplayer,
1537 const struct unit *punit)
1538{
1539 if (is_non_allied_unit_tile(ptile, pplayer,
1541 return FALSE;
1542 }
1543
1544 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1545}
1546
1547/**********************************************************************/
1558void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1559 int vet_loss)
1560{
1561 struct player *pplayer = unit_owner(punit);
1562 const struct unit_type *old_type = punit->utype;
1564 int old_hp = unit_type_get(punit)->hp;
1565 int lvls;
1566
1567 punit->utype = to_unit;
1568
1569 /* New type may not have the same veteran system, and we may want to
1570 * knock some levels off. */
1573 /* Keeping the old behavior, so first clip top, then reduce */
1575
1576 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1577 * and don't kill the unit. unit_move_rate() is used to take into account
1578 * global effects like Magellan's Expedition. */
1579 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1580 if (old_mr == 0) {
1582 } else {
1584 }
1585
1587
1591 }
1592
1593 /* Update unit upkeep */
1595
1597
1599
1600 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1602
1605}
1606
1607/**********************************************************************/
1610struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1611 const struct unit_type *type, int veteran_level,
1612 int homecity_id, int moves_left)
1613{
1614 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1615 moves_left, -1, NULL);
1616}
1617
1618/**********************************************************************/
1622{
1623 if (punit->homecity != 0) {
1625
1628 }
1629 }
1630}
1631
1632/**********************************************************************/
1637struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1638 const struct unit_type *type, int veteran_level,
1639 int homecity_id, int moves_left, int hp_left,
1640 struct unit *ptrans)
1641{
1642 struct unit *punit
1643 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1647 bool could_place;
1648
1652 if (!could_place) {
1654 punit = NULL;
1655 }
1656
1657 return punit;
1658}
1659
1660/**********************************************************************/
1670struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1671 const struct unit_type *type,
1672 int veteran_level, int homecity_id,
1673 int moves_left, int hp_left)
1674{
1675 struct unit *punit;
1676
1677 fc_assert_ret_val(ptile != NULL, NULL);
1679 unit_tile_set(punit, ptile);
1680
1682 punit->homecity = 0; /* none */
1683 } else {
1685 }
1686
1687 if (hp_left >= 0) {
1688 /* Override default full HP */
1689 punit->hp = hp_left;
1690 }
1691
1692 if (moves_left >= 0) {
1693 int mr = unit_move_rate(punit);
1694
1695 /* Override default full MP */
1696 /* FIXME: there are valid situations when a unit have mp
1697 * over its move rate. Here, keeping the old behavior. */
1699 /* Assume that if moves_left < 0 then the unit is "fresh",
1700 * and not moved; else the unit has had something happen
1701 * to it (eg, bribed) which we treat as equivalent to moved.
1702 * (Otherwise could pass moved arg too...) --dwp */
1703 punit->moved = TRUE;
1704 }
1705
1706 return punit;
1707}
1708
1709/**********************************************************************/
1718bool place_unit(struct unit *punit, struct player *pplayer,
1719 struct city *pcity, struct unit *ptrans, bool force)
1720{
1721 struct tile *ptile;
1722
1723 fc_assert_ret_val(pplayer, FALSE);
1725 ptile = punit->tile;
1726 fc_assert_ret_val(ptile, FALSE);
1727
1728 /* Register unit */
1731
1732 if (ptrans) {
1733 /* Set transporter for unit. */
1735 }
1736
1738 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1739 FALSE);
1740
1741 unit_list_prepend(pplayer->units, punit);
1742 unit_list_prepend(ptile->units, punit);
1743 unit_make_contact(punit, ptile, nullptr);
1746 fc_assert(city_owner(pcity) == pplayer);
1747 unit_list_prepend(pcity->units_supported, punit);
1748 /* update unit upkeep */
1750 /* Refresh the unit's homecity. */
1752 send_city_info(pplayer, pcity);
1753 }
1754
1755 punit->server.vision = vision_new(pplayer, ptile);
1757
1759
1762
1763 /* The unit may have changed the available tiles in nearby cities. */
1765 sync_cities();
1766
1767 CALL_FUNC_EACH_AI(unit_created, punit);
1768 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1769
1770 return TRUE;
1771}
1772
1773/**********************************************************************/
1777 void (*callback)(struct unit *punit))
1778{
1779 /* Tried to overwrite another call back. If this assertion is triggered
1780 * in a case where two call back are needed it may be time to support
1781 * more than one unit removal call back at a time. */
1783
1785}
1786
1787/**********************************************************************/
1794
1795/**********************************************************************/
1799static void server_remove_unit_full(struct unit *punit, bool transported,
1801{
1802 struct packet_unit_remove packet;
1803 struct tile *ptile = unit_tile(punit);
1804 struct city *pcity = tile_city(ptile);
1806 struct unit *ptrans;
1807 struct player *pplayer = unit_owner(punit);
1808
1809 /* The unit is doomed. */
1811
1812#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1813 unit_list_iterate(ptile->units, pcargo) {
1816#endif /* FREECIV_DEBUG */
1817
1818 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1819 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1820
1821 /* Save transporter for updating below. */
1823 /* Unload unit. */
1825
1826 /* Since settlers plot in new cities in the minimap before they
1827 are built, so that no two settlers head towards the same city
1828 spot, we need to ensure this reservation is cleared should
1829 the settler disappear on the way. */
1831
1832 /* Clear the vision before sending unit remove. Else, we might duplicate
1833 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1834 if (punit->server.vision != NULL) {
1838 }
1839
1840 packet.unit_id = punit->id;
1841 /* Send to onlookers. */
1844 transported)) {
1845 lsend_packet_unit_remove(aplayer->connections, &packet);
1846 }
1848 /* Send to global observers. */
1852 }
1854
1855 if (punit->server.moving != NULL) {
1856 /* Do not care of this unit for running moves. */
1858 }
1859
1861 /* Run the unit removal call back. */
1863 }
1864
1865 /* check if this unit had UTYF_GAMELOSS flag */
1867 && ULR_EDITOR != reason) {
1869 _("Unable to defend %s, %s has lost the game."),
1871 player_name(pplayer));
1872 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1873 _("Losing %s meant losing the game! "
1874 "Be more careful next time!"),
1875 unit_link(punit));
1877 }
1878
1881
1884 punit = NULL;
1885
1886 if (NULL != ptrans) {
1887 /* Update the occupy info. */
1889 }
1890
1891 /* This unit may have blocked tiles of adjacent cities. Update them. */
1893 sync_cities();
1894
1895 if (phomecity) {
1898 }
1899
1900 if (pcity && pcity != phomecity) {
1903 }
1904
1905 if (pcity && unit_list_size(ptile->units) == 0) {
1906 /* The last unit in the city was killed: update the occupied flag. */
1908 }
1909}
1910
1911/**********************************************************************/
1920
1921/**********************************************************************/
1924static void unit_lost_with_transport(const struct player *pplayer,
1925 struct unit *pcargo,
1926 const struct unit_type *ptransport,
1927 struct player *killer)
1928{
1930 _("%s lost when %s was lost."),
1933 /* Unit is not transported any more at this point, but it has jumped
1934 * off the transport and drowns outside. So it must be removed from
1935 * all clients.
1936 * However, we don't know if given client has received ANY updates
1937 * about the swimming unit, and we can't remove it if it's not there
1938 * in the first place -> we send it once here just to be sure it's
1939 * there. */
1942}
1943
1944/**********************************************************************/
1948static void wipe_unit_full(struct unit *punit, bool transported,
1950 struct player *killer)
1951{
1952 struct tile *ptile = unit_tile(punit);
1953 struct player *pplayer = unit_owner(punit);
1954 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1955 struct unit_list *helpless = unit_list_new();
1956 struct unit_list *imperiled = unit_list_new();
1957 struct unit_list *unsaved = unit_list_new();
1959 struct city *pexclcity;
1960 struct civ_map *nmap = &(wld.map);
1961
1962 if (killer != NULL
1965 player_loot_player(killer, pplayer);
1966 }
1967
1968 /* The unit is doomed. */
1970
1971 /* If a unit is being lost due to loss of its city, ensure that we don't
1972 * try to teleport any of its cargo to that city (which may not yet
1973 * have changed hands or disappeared). (It is assumed that the unit's
1974 * home city is always the one that is being lost/transferred/etc.) */
1975 if (reason == ULR_CITY_LOST) {
1977 } else {
1978 pexclcity = NULL;
1979 }
1980
1981 /* Remove unit itself from its transport */
1982 if (ptrans != NULL) {
1985 }
1986
1987 /* First pull all units off of the transporter. */
1989 /* Use iterate_safe as unloaded units will be removed from the list
1990 * while iterating. */
1992 bool healthy = FALSE;
1993
1994 if (!can_unit_unload(pcargo, punit)) {
1996 } else {
1997 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
1999 } else {
2000 /* These units do not need to be saved. */
2001 healthy = TRUE;
2002 }
2003 }
2004
2005 /* Could use unit_transport_unload_send() here, but that would
2006 * call send_unit_info() for the transporter unnecessarily.
2007 * Note that this means that unit might to get seen briefly
2008 * by clients other than owner's, for example as a result of
2009 * update of homecity common to this cargo and some other
2010 * destroyed unit. */
2012 if (pcargo->activity == ACTIVITY_SENTRY) {
2013 /* Activate sentried units - like planes on a disbanded carrier.
2014 * Note this will activate ground units even if they just change
2015 * transporter. */
2017 }
2018
2019 /* Unit info for unhealthy units will be sent when they are
2020 * assigned new transport or removed. */
2021 if (healthy) {
2023 }
2025 }
2026
2027 /* Now remove the unit. */
2028 server_remove_unit_full(punit, transported, reason);
2029
2030 switch (reason) {
2031 case ULR_KILLED:
2032 case ULR_EXECUTED:
2033 case ULR_SDI:
2034 case ULR_NUKE:
2035 case ULR_BRIBED:
2036 case ULR_CAPTURED:
2037 case ULR_CAUGHT:
2038 case ULR_ELIMINATED:
2039 case ULR_TRANSPORT_LOST:
2040 if (killer != NULL) {
2041 killer->score.units_killed++;
2042 }
2043 pplayer->score.units_lost++;
2044 break;
2045 case ULR_BARB_UNLEASH:
2046 case ULR_CITY_LOST:
2047 case ULR_STARVED:
2048 case ULR_UPKEEP:
2049 case ULR_NONNATIVE_TERR:
2050 case ULR_ARMISTICE:
2051 case ULR_HP_LOSS:
2052 case ULR_FUEL:
2053 case ULR_STACK_CONFLICT:
2054 case ULR_SOLD:
2055 pplayer->score.units_lost++;
2056 break;
2057 case ULR_RETIRED:
2058 case ULR_DISBANDED:
2059 case ULR_USED:
2060 case ULR_DETONATED:
2061 case ULR_MISSILE:
2062 pplayer->score.units_used++;
2063 break;
2064 case ULR_EDITOR:
2065 case ULR_PLAYER_DIED:
2066 break;
2067 }
2068
2069 /* First, sort out helpless cargo. */
2070 if (unit_list_size(helpless) > 0) {
2071 struct unit_list *remaining = unit_list_new();
2072
2073 /* Grant priority to gameloss units and units with the EvacuateFirst
2074 * unit type flag. */
2081 pexclcity)) {
2083 }
2084 } else {
2085 unit_list_prepend(remaining, pcargo);
2086 }
2088
2089 /* Handle non-priority units. */
2090 unit_list_iterate_safe(remaining, pcargo) {
2093 }
2095
2096 unit_list_destroy(remaining);
2097 }
2099
2100 /* Then, save any imperiled cargo. */
2101 if (unit_list_size(imperiled) > 0) {
2102 struct unit_list *remaining = unit_list_new();
2103
2104 /* Grant priority to gameloss units and units with the EvacuateFirst
2105 * unit type flag. */
2112 pexclcity)) {
2114 }
2115 } else {
2116 unit_list_prepend(remaining, pcargo);
2117 }
2119
2120 /* Handle non-priority units. */
2121 unit_list_iterate_safe(remaining, pcargo) {
2124 }
2126
2127 unit_list_destroy(remaining);
2128 }
2130
2131 /* Finally, kill off the unsaved units. */
2132 if (unit_list_size(unsaved) > 0) {
2136 }
2138}
2139
2140/**********************************************************************/
2149
2150/**********************************************************************/
2156static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2157 bool helpless, bool teleporting,
2158 const struct city *pexclcity)
2159{
2160 struct tile *ptile = unit_tile(punit);
2161 struct player *pplayer = unit_owner(punit);
2163
2164 /* Helpless units cannot board a transport in their current state. */
2165 if (!helpless
2166 && ptransport != NULL) {
2169 return TRUE;
2170 } else {
2171 /* Only units that cannot find transport are considered for teleport. */
2172 if (teleporting) {
2173 struct city *pcity = find_closest_city(ptile, pexclcity,
2177 if (pcity != NULL) {
2178 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2179
2181
2183 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2184 _("%s escaped the destruction of %s, and fled to %s."),
2185 tplink,
2187 city_link(pcity));
2188 return TRUE;
2189 }
2190 }
2191 }
2192 }
2193
2194 /* The unit could not use transport on the tile, and could not teleport. */
2195 return FALSE;
2196}
2197
2198/**********************************************************************/
2204struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2206{
2207 struct unit *gained_unit;
2208 int id = 0;
2209
2210#ifndef FREECIV_NDEBUG
2211 bool placed;
2212#endif
2213
2216
2217 /* Convert the unit to your cause. It's supposed that the original unit
2218 * is on a valid tile and is not transported. */
2222 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2223
2224 /* Owner changes, nationality not. */
2225 gained_unit->nationality = punit->nationality;
2226
2227 /* Copy some more unit fields */
2228 gained_unit->fuel = punit->fuel;
2229 gained_unit->paradropped = punit->paradropped;
2230 gained_unit->birth_turn = punit->birth_turn;
2231 gained_unit->current_form_turn = punit->current_form_turn;
2232
2233 /* Fog is lifted in the placing algorithm. */
2234#ifndef FREECIV_NDEBUG
2235 placed =
2236#endif
2237 place_unit(gained_unit, pplayer,
2239 NULL, FALSE);
2240
2242
2243 id = gained_unit->id;
2244
2245 /* Update unit upkeep in the new homecity */
2246 if (homecity > 0) {
2248 }
2249
2250 /* Be sure to wipe the converted unit! */
2251 /* Old homecity upkeep is updated in process */
2252#ifndef FREECIV_NDEBUG
2253 uco_wipe:
2254#endif
2255
2257
2258 if (!unit_is_alive(id)) {
2259 /* Destroyed by a script */
2260 return NULL;
2261 }
2262
2263 return gained_unit; /* Returns the replacement. */
2264}
2265
2266/**********************************************************************/
2271void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2272{
2274 struct player *pvictim = unit_owner(punit);
2275 struct player *pvictor = unit_owner(pkiller);
2276 struct tile *deftile = unit_tile(punit);
2277 int unitcount = 0;
2278 bool escaped;
2281 const struct civ_map *nmap = &(wld.map);
2282
2285
2286 /* The unit is doomed. */
2288
2290 if ((flagless_killer
2294 unitcount++;
2295 }
2297
2298 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2299 if (vet) {
2301 }
2303 } else { /* Unitcount > 1 */
2304 int i;
2305 int slots = player_slot_count();
2306 int num_killed[slots];
2307 int num_escaped[slots];
2308 struct unit *other_killed[slots];
2309
2310 fc_assert(unitcount > 1);
2311
2312 /* Initialize */
2313 for (i = 0; i < slots; i++) {
2314 num_killed[i] = 0;
2315 other_killed[i] = NULL;
2316 num_escaped[i] = 0;
2317 }
2318
2319 /* Count killed units */
2321 struct player *vplayer = unit_owner(vunit);
2322
2325 escaped = FALSE;
2326
2329 && vunit->hp > 0
2330 && vunit->moves_left > pkiller->moves_left
2331 && fc_rand(2)) {
2332 int curr_def_bonus;
2333 int def_bonus = 0;
2334 struct tile *dsttile = NULL;
2335 int move_cost;
2336
2337 fc_assert(vunit->hp > 0);
2338
2340 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2341 && NULL == tile_city(ptile2)) {
2342 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2343 if (pkiller->moves_left <= vunit->moves_left - move_cost
2345 || unit_list_size(ptile2->units)) == 0) {
2347 vunit->utype);
2348 if (def_bonus <= curr_def_bonus) {
2350 dsttile = ptile2;
2351 }
2352 }
2353 }
2355
2356 if (dsttile != NULL) {
2359 NULL, NULL, dsttile,
2361 NULL, NULL)
2362 != NULL);
2363
2364 if (escaped) {
2366 unitcount--;
2367 }
2368 }
2369 }
2370
2371 if (!escaped) {
2373
2374 if (vunit != punit) {
2377 }
2378 }
2379 }
2381
2382 /* Inform the destroyer again if more than one unit was killed */
2383 if (unitcount > 1) {
2384 if (flagless_victim) {
2386 /* TRANS: "... Cannon ... Destroyer ...." */
2387 PL_("Your attacking %s succeeded against %s "
2388 "(and %d other unit)!",
2389 "Your attacking %s succeeded against %s "
2390 "(and %d other units)!", unitcount - 1),
2392 punit_link,
2393 unitcount - 1);
2394 } else {
2396 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2397 PL_("Your attacking %s succeeded against the %s %s "
2398 "(and %d other unit)!",
2399 "Your attacking %s succeeded against the %s %s "
2400 "(and %d other units)!", unitcount - 1),
2403 punit_link,
2404 unitcount - 1);
2405 }
2406 }
2407
2408 if (vet) {
2410 }
2411
2412 /* Inform the owners: this only tells about owned units that were killed.
2413 * there may have been 20 units who died but if only 2 belonged to the
2414 * particular player they'll only learn about those.
2415 *
2416 * Also if a large number of units die you don't find out what type
2417 * they all are. */
2418 for (i = 0; i < slots; i++) {
2419 if (num_killed[i] == 1) {
2420 if (i == player_index(pvictim)) {
2422
2423 if (flagless_killer) {
2426 /* TRANS: "Cannon ... Destroyer." */
2427 _("%s lost to an attack by %s."),
2428 punit_link,
2429 pkiller_link);
2430 } else {
2433 /* TRANS: "Cannon ... the Polish Destroyer." */
2434 _("%s lost to an attack by the %s %s."),
2435 punit_link,
2437 pkiller_link);
2438 }
2439 } else {
2441
2442 if (flagless_victim) {
2443 if (flagless_killer) {
2446 /* TRANS: "Cannon lost when Destroyer
2447 * attacked Musketeers." */
2448 _("%s lost when %s attacked %s."),
2451 punit_link);
2452 } else {
2455 /* TRANS: "Cannon lost when the Polish Destroyer
2456 * attacked Musketeers." */
2457 _("%s lost when the %s %s attacked %s."),
2461 punit_link);
2462 }
2463 } else {
2464 if (flagless_killer) {
2467 /* TRANS: "Cannon lost when Destroyer
2468 * attacked the German Musketeers." */
2469 _("%s lost when %s attacked the %s %s."),
2473 punit_link);
2474 } else {
2477 /* TRANS: "Cannon lost when the Polish Destroyer
2478 * attacked the German Musketeers." */
2479 _("%s lost when the %s %s attacked the %s %s."),
2484 punit_link);
2485 }
2486 }
2487 }
2488 } else if (num_killed[i] > 1) {
2489 if (i == player_index(pvictim)) {
2490 int others = num_killed[i] - 1;
2491
2492 if (others == 1) {
2493 if (flagless_killer) {
2496 /* TRANS: "Musketeers (and Cannon) lost to an
2497 * attack from Destroyer." */
2498 _("%s (and %s) lost to an attack from %s."),
2499 punit_link,
2501 pkiller_link);
2502 } else {
2505 /* TRANS: "Musketeers (and Cannon) lost to an
2506 * attack from the Polish Destroyer." */
2507 _("%s (and %s) lost to an attack from the %s %s."),
2508 punit_link,
2511 pkiller_link);
2512 }
2513 } else {
2514 if (flagless_killer) {
2517 /* TRANS: "Musketeers and 3 other units lost to
2518 * an attack from Destroyer."
2519 * (only happens with at least 2 other units) */
2520 PL_("%s and %d other unit lost to an attack "
2521 "from %s.",
2522 "%s and %d other units lost to an attack "
2523 "from %s.", others),
2524 punit_link,
2525 others,
2526 pkiller_link);
2527 } else {
2530 /* TRANS: "Musketeers and 3 other units lost to
2531 * an attack from the Polish Destroyer."
2532 * (only happens with at least 2 other units) */
2533 PL_("%s and %d other unit lost to an attack "
2534 "from the %s %s.",
2535 "%s and %d other units lost to an attack "
2536 "from the %s %s.", others),
2537 punit_link,
2538 others,
2540 pkiller_link);
2541 }
2542 }
2543 } else {
2544 if (flagless_victim) {
2545 if (flagless_killer) {
2548 /* TRANS: "2 units lost when Destroyer
2549 * attacked Musketeers."
2550 * (only happens with at least 2 other units) */
2551 PL_("%d unit lost when %s attacked %s.",
2552 "%d units lost when %s attacked %s.",
2553 num_killed[i]),
2554 num_killed[i],
2556 punit_link);
2557 } else {
2560 /* TRANS: "2 units lost when the Polish Destroyer
2561 * attacked Musketeers."
2562 * (only happens with at least 2 other units) */
2563 PL_("%d unit lost when the %s %s attacked %s.",
2564 "%d units lost when the %s %s attacked %s.",
2565 num_killed[i]),
2566 num_killed[i],
2569 punit_link);
2570 }
2571 } else {
2572 if (flagless_killer) {
2575 /* TRANS: "2 units lost when Destroyer
2576 * attacked the German Musketeers."
2577 * (only happens with at least 2 other units) */
2578 PL_("%d unit lost when %s attacked the %s %s.",
2579 "%d units lost when %s attacked the %s %s.",
2580 num_killed[i]),
2581 num_killed[i],
2584 punit_link);
2585 } else {
2588 /* TRANS: "2 units lost when the Polish Destroyer
2589 * attacked the German Musketeers."
2590 * (only happens with at least 2 other units) */
2591 PL_("%d unit lost when the %s %s attacked the %s %s.",
2592 "%d units lost when the %s %s attacked the %s %s.",
2593 num_killed[i]),
2594 num_killed[i],
2598 punit_link);
2599 }
2600 }
2601 }
2602 }
2603 }
2604
2605 /* Inform the owner of the units that escaped.
2606 * 'deftile' is the original tile they defended at, not where
2607 * they escaped to, as there might be multiple different tiles
2608 * different units escaped to. */
2609 for (i = 0; i < slots; i++) {
2610 if (0 < num_escaped[i]) {
2611 if (flagless_killer) {
2614 PL_("%d unit escaped from attack by %s",
2615 "%d units escaped from attack by %s",
2616 num_escaped[i]),
2617 num_escaped[i],
2618 pkiller_link);
2619 } else {
2622 PL_("%d unit escaped from attack by %s %s",
2623 "%d units escaped from attack by %s %s",
2624 num_escaped[i]),
2625 num_escaped[i],
2627 pkiller_link);
2628 }
2629 }
2630 }
2631
2632 /* Remove the units - note the logic of which units actually die
2633 * must be mimiced exactly in at least one place up above. */
2634 punit = NULL; /* Wiped during following iteration so unsafe to use */
2635
2640 }
2642 }
2643}
2644
2645/**********************************************************************/
2648void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2649{
2650 struct player *pvictim = unit_owner(punit);
2653 struct tile *deftile = unit_tile(punit);
2654 int unitcount, ransom;
2655
2656 /* The unit is doomed. */
2658
2661
2662 if (pvictim->economic.gold < ransom) {
2663 ransom = pvictim->economic.gold;
2664 }
2665
2667 PL_("%d Barbarian leader captured.",
2668 "%d Barbarian leaders captured.",
2669 unitcount),
2670 unitcount);
2672 PL_("%d gold ransom paid.",
2673 "%d gold ransom paid.",
2674 ransom),
2675 ransom);
2676 pvictor->economic.gold += ransom;
2677 pvictim->economic.gold -= ransom;
2678 send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */
2679
2680 if (vet) {
2682 }
2683
2686
2687 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2689 } else {
2690 int i;
2691 int slots = player_slot_count();
2692 int num_collected[slots];
2693
2694 fc_assert(unitcount > 1);
2695
2696 /* Initialize */
2697 for (i = 0; i < slots; i++) {
2698 num_collected[i] = 0;
2699 }
2700
2701 /* Count captured units */
2703 struct player *vplayer = unit_owner(vunit);
2704
2707
2708 for (i = 0; i < slots; i++) {
2709 if (num_collected[i] == 1) {
2712 _("%s %s collected ransom of %s."),
2715 } else if (num_collected[i] > 1) {
2718 PL_("%s %s collected ransom of %s and %d other unit.",
2719 "%s %s collected ransom of %s and %d other units.",
2720 num_collected[i] - 1),
2723 punit_link,
2724 num_collected[i] - 1);
2725 }
2726 }
2727
2731 }
2732}
2733
2734/**********************************************************************/
2738void package_unit(struct unit *punit, struct packet_unit_info *packet)
2739{
2740 packet->id = punit->id;
2741 packet->owner = player_number(unit_owner(punit));
2743 packet->tile = tile_index(unit_tile(punit));
2744 packet->facing = punit->facing;
2745 packet->homecity = punit->homecity;
2747 packet->upkeep[o] = punit->upkeep[o];
2749 packet->veteran = punit->veteran;
2751 packet->movesleft = punit->moves_left;
2752 packet->hp = punit->hp;
2753 packet->activity = punit->activity;
2755
2756 if (punit->activity_target != NULL) {
2758 } else {
2759 packet->activity_tgt = EXTRA_NONE;
2760 }
2761
2762 packet->changed_from = punit->changed_from;
2764
2765 if (punit->changed_from_target != NULL) {
2767 } else {
2768 packet->changed_from_tgt = EXTRA_NONE;
2769 }
2770
2772 packet->fuel = punit->fuel;
2773 packet->goto_tile = (NULL != punit->goto_tile
2774 ? tile_index(punit->goto_tile) : -1);
2775 packet->paradropped = punit->paradropped;
2776 packet->done_moving = punit->done_moving;
2777 packet->stay = punit->stay;
2778 packet->birth_turn = punit->birth_turn;
2780 if (!unit_transported(punit)) {
2781 packet->transported = FALSE;
2782 packet->transported_by = 0;
2783 } else {
2784 packet->transported = TRUE;
2786 }
2787 if (punit->carrying != NULL) {
2788 packet->carrying = goods_index(punit->carrying);
2789 } else {
2790 packet->carrying = -1;
2791 }
2792 packet->occupied = (get_transporter_occupancy(punit) > 0);
2793 packet->battlegroup = punit->battlegroup;
2794 packet->has_orders = punit->has_orders;
2795 if (punit->has_orders) {
2796 packet->orders_length = punit->orders.length;
2797 packet->orders_index = punit->orders.index;
2798 packet->orders_repeat = punit->orders.repeat;
2800 memcpy(packet->orders, punit->orders.list,
2801 punit->orders.length * sizeof(struct unit_order));
2802 } else {
2803 packet->orders_length = packet->orders_index = 0;
2804 packet->orders_repeat = packet->orders_vigilant = FALSE;
2805 /* No need to initialize array. */
2806 }
2807
2812}
2813
2814/**********************************************************************/
2820 struct packet_unit_short_info *packet,
2821 enum unit_info_use packet_use, int info_city_id)
2822{
2823 packet->packet_use = packet_use;
2824 packet->info_city_id = info_city_id;
2825
2826 packet->id = punit->id;
2827
2829 packet->owner = OWNER_NONE;
2830 } else {
2831 packet->owner = player_number(unit_owner(punit));
2832 }
2833
2834 packet->tile = tile_index(unit_tile(punit));
2835 packet->facing = punit->facing;
2836 packet->veteran = punit->veteran;
2838 packet->hp = punit->hp;
2839 packet->occupied = (get_transporter_occupancy(punit) > 0);
2841 || punit->activity == ACTIVITY_GOTO) {
2842 packet->activity = ACTIVITY_IDLE;
2843 } else {
2844 packet->activity = punit->activity;
2845 }
2846
2847 if (punit->activity_target == nullptr) {
2848 packet->activity_tgt = EXTRA_NONE;
2849 } else {
2851 }
2852
2853 /* Transported_by information is sent to the client even for units that
2854 * aren't fully known. Note that for non-allied players, any transported
2855 * unit can't be seen at all. For allied players we have to know if
2856 * transporters have room in them so that we can load units properly. */
2857 if (!unit_transported(punit)) {
2858 packet->transported = FALSE;
2859 packet->transported_by = 0;
2860 } else {
2861 packet->transported = TRUE;
2863 }
2864}
2865
2866/**********************************************************************/
2869void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2870{
2872 if (punit->server.moving != NULL) {
2873 /* Update status of 'pplayer' vision for 'punit'. */
2875 }
2876}
2877
2878/**********************************************************************/
2882void send_unit_info(struct conn_list *dest, struct unit *punit)
2883{
2884 const struct player *powner;
2885 struct packet_unit_info info;
2887 struct unit_move_data *pdata;
2888
2889 if (dest == NULL) {
2890 dest = game.est_connections;
2891 }
2892
2894
2896 package_unit(punit, &info);
2899
2900 conn_list_iterate(dest, pconn) {
2901 struct player *pplayer = conn_get_player(pconn);
2902
2903 /* Be careful to consider all cases where pplayer is NULL... */
2904 if (pplayer == NULL) {
2905 if (pconn->observer) {
2907 }
2908 } else if (pplayer == powner) {
2910 if (pdata != NULL) {
2911 BV_SET(pdata->can_see_unit, player_index(pplayer));
2912 }
2913 } else if (can_player_see_unit(pplayer, punit)) {
2915 if (pdata != NULL) {
2916 BV_SET(pdata->can_see_unit, player_index(pplayer));
2917 }
2918 }
2920}
2921
2922/**********************************************************************/
2927{
2928 conn_list_do_buffer(dest);
2929 conn_list_iterate(dest, pconn) {
2930 struct player *pplayer = pconn->playing;
2931
2932 if (NULL == pplayer && !pconn->observer) {
2933 continue;
2934 }
2935
2938 send_unit_info(dest, punit);
2941 }
2944 flush_packets();
2945}
2946
2947/**********************************************************************/
2954static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2955 const struct action *paction)
2956{
2957 struct city *pcity = NULL;
2958 int pop_loss;
2959
2960 pcity = tile_city(ptile);
2961
2963
2964 /* unit in a city may survive */
2966 continue;
2967 }
2969 _("Your %s was nuked by %s."),
2971 pplayer == unit_owner(punit)
2972 ? _("yourself")
2973 : nation_plural_for_player(pplayer));
2974 if (unit_owner(punit) != pplayer) {
2975 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2976 _("The %s %s was nuked."),
2979 }
2980 wipe_unit(punit, ULR_NUKE, pplayer);
2982
2983
2984 if (pcity) {
2985 struct player *owner = city_owner(pcity);
2986 char city_name[MAX_LEN_LINK];
2987
2989
2991 _("%s was nuked by %s."),
2992 city_name,
2993 pplayer == owner
2994 ? _("yourself")
2995 : nation_plural_for_player(pplayer));
2996
2997 if (owner != pplayer) {
2998 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2999 _("You nuked %s."),
3000 city_name);
3001 }
3002
3004 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
3005 /* Send city size reduction to everyone seeing it */
3007 } else {
3008 /* City was destroyed */
3010 _("%s was destroyed by the nuke."),
3011 city_name);
3012 if (owner != pplayer) {
3013 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3014 _("Your nuke destroyed %s."),
3015 city_name);
3016 }
3017 }
3018 }
3019
3020 if (fc_rand(2) == 1) {
3021 struct extra_type *pextra;
3022
3023 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
3024 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
3025 tile_add_extra(ptile, pextra);
3026 update_tile_knowledge(ptile);
3027 }
3028 }
3029}
3030
3031/**********************************************************************/
3040 const struct unit_type *act_utype,
3041 struct player *pplayer, struct tile *ptile)
3042{
3045 &(const struct req_context) {
3046 .player = pplayer,
3047 /* City: Wait for users before choosing
3048 * home city or target tile city */
3049 .tile = ptile,
3050 .unittype = act_utype,
3051 .action = paction,
3052 },
3053 NULL,
3055
3057 do_nuke_tile(pplayer, ptile1, paction);
3059
3060 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
3061 API_TYPE_PLAYER, pplayer);
3063 _("The %s detonated a nuke!"),
3064 nation_plural_for_player(pplayer));
3065}
3066
3067/**********************************************************************/
3071bool do_airline(struct unit *punit, struct city *pdest_city,
3072 const struct action *paction)
3073{
3075
3078 _("%s transported successfully."),
3079 unit_link(punit));
3080
3083 /* Can only airlift to allied and domestic cities */
3084 FALSE, FALSE,
3085 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3087
3088 /* Update airlift fields. */
3090 psrc_city->airlift--;
3092 }
3094 pdest_city->airlift--;
3096 }
3097
3098 return TRUE;
3099}
3100
3101/**********************************************************************/
3104void do_explore(struct unit *punit)
3105{
3106 switch (manage_auto_explorer(punit)) {
3107 case MR_DEATH:
3108 /* don't use punit! */
3109 return;
3110 case MR_NOT_ALLOWED:
3111 /* Needed for something else */
3112 return;
3113 case MR_OK:
3114 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3115 * but don't count on this. See PR#39792.
3116 */
3118 break;
3119 }
3120
3122 default:
3124
3125 /* FIXME: When the manage_auto_explorer() call changes the activity from
3126 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3127 * alone. We reset it here. See PR#12931. */
3129 break;
3130 }
3131
3132 send_unit_info(NULL, punit); /* Probably duplicate */
3133}
3134
3135/**********************************************************************/
3140bool do_paradrop(struct unit *punit, struct tile *ptile,
3141 const struct action *paction)
3142{
3143 struct player *pplayer = unit_owner(punit);
3144 struct player *tgt_player = tile_owner(ptile);
3145 const struct unit_type *act_utype = unit_type_get(punit);
3146 const struct city *pcity;
3147
3148 /* Hard requirements */
3149 /* FIXME: hard requirements belong in common/actions's
3150 * is_action_possible() and the explanation texts belong in
3151 * server/unithand's action not enabled system (expl_act_not_enabl(),
3152 * ane_kind, explain_why_no_action_enabled(), etc)
3153 */
3154 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3155 /* Only take in account values from player map. */
3156 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3157
3158 if (NULL == plrtile->site) {
3159 bv_extras fbv;
3160
3161 dbv_to_bv(fbv.vec, &(plrtile->extras));
3162
3164 &fbv)) {
3165 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3166 _("This unit cannot paradrop into %s."),
3168 return FALSE;
3169 }
3170 }
3171
3172 if (NULL != plrtile->site
3173 && plrtile->owner != NULL
3174 && !pplayers_allied(pplayer, plrtile->owner)
3176 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3177 /* TRANS: Paratroopers ... Paradrop Unit */
3178 _("%s cannot conquer a city with \"%s\"."),
3181 return FALSE;
3182 }
3183
3184 if (NULL != plrtile->site
3185 && plrtile->owner != NULL
3186 && (pplayers_non_attack(pplayer, plrtile->owner)
3187 || (player_diplstate_get(pplayer, plrtile->owner)->type
3188 == DS_ALLIANCE)
3189 || (player_diplstate_get(pplayer, plrtile->owner)->type
3190 == DS_TEAM))
3192 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3193 _("Cannot attack unless you declare war first."));
3194 return FALSE;
3195 }
3196 }
3197
3198
3199 /* Kill the unit when the landing goes wrong. */
3200
3201 /* Safe terrain, really? Not transformed since player last saw it. */
3202 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3203 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3204 || !unit_could_load_at(punit, ptile))) {
3205 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3206 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3207 _("Your %s paradropped into the %s and was lost."),
3210 pplayer->score.units_lost++;
3212 return TRUE;
3213 }
3214
3215 pcity = tile_city(ptile);
3216
3217 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3219 || is_non_allied_unit_tile(ptile, pplayer,
3221 struct player *main_victim = NULL;
3222 struct player *secondary_victim = NULL;
3224
3225 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3226 unit_make_contact(punit, ptile, pplayer);
3227 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3228 _("Your %s was killed by enemy units at the "
3229 "paradrop destination."),
3231 /* TODO: Should defender score.units_killed get increased too?
3232 * What if there's units of several allied players? Should the
3233 * city owner or owner of the first/random unit get the kill? */
3234 pplayer->score.units_lost++;
3235
3236 if (pcity != NULL) {
3237 struct player *owner = city_owner(pcity);
3238
3239 if (!pplayers_at_war(pplayer, owner)) {
3241 } else {
3243 }
3244
3246 } else {
3248 }
3249
3250 if (main_victim == NULL) {
3251 unit_list_iterate(ptile->units, tgt) {
3252 struct player *owner = unit_owner(tgt);
3253
3254 if (!pplayers_at_war(pplayer, owner)) {
3256 break;
3257 } else if (secondary_victim == NULL) {
3259 }
3261
3262 if (main_victim == NULL) {
3263 /* There's no victim with whom the attacker isn't in war,
3264 * fallback to one with whom there's already a war. */
3266 }
3267 }
3268
3270 main_victim, ptile,
3271 victim_link);
3272
3274 return TRUE;
3275 }
3276
3277 /* All ok */
3279 if (unit_move(punit, ptile,
3280 /* Done by Action_Success_Actor_Move_Cost */
3281 0,
3282 NULL, BV_ISSET(paction->sub_results,
3286 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3287 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3288 /* Ensure we finished on valid state. */
3291 }
3292
3293 /* May cause an incident */
3295 ptile, tile_link(ptile));
3296
3297 return TRUE;
3298}
3299
3300/**********************************************************************/
3304static bool hut_get_limited(struct unit *punit)
3305{
3306 bool ok = TRUE;
3307 int hut_chance = fc_rand(12);
3308 struct player *pplayer = unit_owner(punit);
3309 const struct civ_map *nmap = &(wld.map);
3310
3311 /* 1 in 12 to get barbarians */
3312 if (hut_chance != 0) {
3313 int cred = 25;
3314
3316 PL_("You found %d gold.",
3317 "You found %d gold.", cred), cred);
3318 pplayer->economic.gold += cred;
3321 notify_player(pplayer, unit_tile(punit),
3323 _("An abandoned village is here."));
3324 } else {
3326 _("Your %s has been killed by barbarians!"),
3329 ok = FALSE;
3330 }
3331
3332 return ok;
3333}
3334
3335/**********************************************************************/
3339static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3340{
3341 struct player *pplayer = unit_owner(punit);
3342 int id = punit->id;
3343 struct tile *ptile = unit_tile(punit);
3344 bool hut = FALSE;
3345 const struct req_context context = {
3346 .player = pplayer,
3347 .tile = ptile,
3348 };
3349
3351 if (tile_has_extra(ptile, pextra)
3353 &(const struct req_context) {
3354 .player = tile_owner(ptile),
3355 },
3356 &pextra->rmreqs,
3358 ) {
3359 hut = TRUE;
3360 /* FIXME: are all enter-removes extras worth counting? */
3361 pplayer->server.huts++;
3362
3363 destroy_extra(ptile, pextra);
3365
3366 /* FIXME: enable different classes
3367 * to behave differently with different huts */
3368 if (frighten_hut) {
3369 script_server_signal_emit("hut_frighten", punit,
3370 extra_rule_name(pextra));
3371 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3372 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3374 } else {
3375 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3376 }
3377
3378 /* We need punit for the callbacks, can't continue if the unit died */
3379 if (!unit_is_alive(id)) {
3380 break;
3381 }
3382 }
3384
3385 if (hut) {
3386 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3387 }
3388 return;
3389}
3390
3391/**********************************************************************/
3395{
3396 bv_player can_see_unit;
3397
3400
3401 BV_CLR_ALL(can_see_unit);
3402 players_iterate(pplayer) {
3403 if (can_player_see_unit(pplayer, punit)) {
3404 BV_SET(can_see_unit, player_index(pplayer));
3405 }
3407
3409
3410 players_iterate(pplayer) {
3411 if (BV_ISSET(can_see_unit, player_index(pplayer))
3412 && !can_player_see_unit(pplayer, punit)) {
3413 unit_goes_out_of_sight(pplayer, punit);
3414 }
3416
3419}
3420
3421/**********************************************************************/
3425 struct unit *ptrans,
3426 bool force)
3427{
3428 bool had_cargo;
3429
3432
3434
3436
3437 if (!had_cargo) {
3438 /* Transport's loaded status changed */
3440 }
3441}
3442
3443/**********************************************************************/
3447{
3448 struct unit *ptrans;
3449
3451
3453
3455
3457
3460}
3461
3462/**********************************************************************/
3466static void autoattack_prob_free(struct autoattack_prob *prob)
3467{
3468 free(prob);
3469}
3470
3471/**********************************************************************/
3480static int compare_units(const struct autoattack_prob *const *p1,
3481 const struct autoattack_prob *const *q1)
3482{
3483 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3484 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3485
3486 /* Sort by transport depth first. This makes sure that no transport
3487 * attacks before its cargo does -- cargo sorts earlier in the list. */
3488 {
3489 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3490
3491 /* Walk the transport stacks in parallel, so as to bail out as soon as
3492 * one of them is empty (avoid walking deep stacks more often than
3493 * necessary). */
3494 while (p1trans && q1trans) {
3497 }
3498 if (!p1trans && q1trans) {
3499 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3500 * earlier in the list (p1 > q1). */
3501 return 1;
3502 } else if (p1trans && !q1trans) {
3503 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3504 return -1;
3505 }
3506 /* else same depth, so move on to checking win chance: */
3507 }
3508
3509 /* Put the units with the highest probability of success first. The up
3510 * side of this is that units with bonuses against the victim attacks
3511 * before other units. The downside is that strong units can be led
3512 * away by sacrificial units. */
3513 return (-1
3514 /* Assume the worst. */
3515 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3516}
3517
3518/**********************************************************************/
3523{
3524 struct autoattack_prob_list *autoattack;
3525 int moves = punit->moves_left;
3526 int sanity1 = punit->id;
3527 struct civ_map *nmap = &(wld.map);
3528
3529 if (!game.server.autoattack) {
3530 return TRUE;
3531 }
3532
3534
3535 /* Kludge to prevent attack power from dropping to zero during calc */
3537
3538 adjc_iterate(nmap, unit_tile(punit), ptile) {
3539 /* First add all eligible units to a autoattack list */
3540 unit_list_iterate(ptile->units, penemy) {
3542 struct tile *tgt_tile = unit_tile(punit);
3543
3544 fc_assert_action(tgt_tile, continue);
3545
3546 probability->prob =
3550 punit, NULL);
3551
3552 if (action_prob_possible(probability->prob)) {
3553 probability->unit_id = penemy->id;
3555 } else {
3557 }
3560
3561 /* Sort the potential attackers from highest to lowest success
3562 * probability. */
3563 if (autoattack_prob_list_size(autoattack) >= 2) {
3565 }
3566
3568 int sanity2 = penemy->id;
3569 struct tile *ptile = unit_tile(penemy);
3570 struct unit *enemy_defender = get_defender(nmap, punit, ptile, NULL);
3571 double punitwin, penemywin;
3572 double threshold = 0.25;
3573 struct tile *tgt_tile = unit_tile(punit);
3574
3576
3577 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3578 /* Don't leave city defenseless */
3579 threshold = 0.90;
3580 }
3581
3582 if (NULL != enemy_defender) {
3584 } else {
3585 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3586 punitwin = 1.0;
3587 }
3588
3589 /* Previous attacks may have changed the odds. Recalculate. */
3590 peprob->prob =
3594 punit, NULL);
3595
3596 if (!action_prob_possible(peprob->prob)) {
3597 /* No longer legal. */
3598 continue;
3599 }
3600
3601 /* Assume the worst. */
3603
3604 if ((penemywin > 1.0 - punitwin
3606 && penemywin > threshold) {
3607
3608#ifdef REALLY_DEBUG_THIS
3609 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3612 1.0 - punitwin, threshold);
3613#endif
3614
3619 } else {
3620#ifdef REALLY_DEBUG_THIS
3621 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3624 1.0 - punitwin, threshold);
3625#endif
3626 continue;
3627 }
3628
3631 }
3634 } else {
3635 autoattack_prob_list_destroy(autoattack);
3636 return FALSE; /* moving unit dead */
3637 }
3639
3640 autoattack_prob_list_destroy(autoattack);
3642 /* We could have lost movement in combat */
3645 return TRUE;
3646 } else {
3647 return FALSE;
3648 }
3649}
3650
3651/**********************************************************************/
3654static void cancel_orders(struct unit *punit, char *dbg_msg)
3655{
3658 log_debug("%s", dbg_msg);
3659}
3660
3661/**********************************************************************/
3666{
3667 bool alone_in_city;
3668
3669 if (NULL != tile_city(unit_tile(punit))) {
3670 int count = 0;
3671
3673 /* Consider only units not transported. */
3674 if (!unit_transported(aunit)) {
3675 count++;
3676 }
3678
3679 alone_in_city = (1 == count);
3680 } else {
3682 }
3683
3684 /* There may be sentried units with a sightrange > 3, but we don't
3685 wake them up if the punit is farther away than 3. */
3686 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3687 unit_list_iterate(ptile->units, penemy) {
3688 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3689 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3690
3692 && penemy->activity == ACTIVITY_SENTRY
3693 && radius_sq >= distance_sq
3694 /* If the unit moved on a city, and the unit is alone, consider
3695 * it is visible. */
3696 && (alone_in_city
3698 /* on board transport; don't awaken */
3702 }
3705
3706 /* Wakeup patrolling units we bump into.
3707 We do not wakeup units further away than 3 squares... */
3708 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3709 unit_list_iterate(ptile->units, ppatrol) {
3710 if (punit != ppatrol
3712 && ppatrol->orders.vigilant) {
3714 cancel_orders(ppatrol, " stopping because of nearby enemy");
3717 _("Orders for %s aborted after enemy movement was "
3718 "spotted."),
3720 }
3721 }
3724}
3725
3726/**********************************************************************/
3736 struct tile *src_tile,
3737 struct tile *dst_tile,
3738 bool passenger,
3740{
3741 struct city *fromcity = tile_city(src_tile);
3742 struct city *tocity = tile_city(dst_tile);
3743 struct city *homecity_start_pos = NULL;
3744 struct city *homecity_end_pos = NULL;
3750 const struct unit_type *type_end_pos = type_start_pos;
3753 int saved_id = punit->id;
3754 bool alive = TRUE;
3755 const struct civ_map *nmap = &(wld.map);
3756
3758 if (!passenger) {
3759 /* The unit that does the move may conquer. */
3761 }
3762
3763 /* Run for passengers too. A passenger may have been killed when its
3764 * transport conquered a city. (unit_conquer_city() can cause Lua code
3765 * to run) */
3766
3768 if (alive) {
3769 /* In case script has changed something about unit */
3773 }
3774 }
3775
3776 if (homecity_id_start_pos != 0) {
3778 }
3781 } else {
3783 }
3784
3785 /* We only do refreshes for non-AI players to now make sure the AI turns
3786 doesn't take too long. Perhaps we should make a special refresh_city
3787 functions that only refreshed happines. */
3788
3789 /* might have changed owners or may be destroyed */
3791
3792 if (tocity) { /* entering a city */
3793 if (tocity->owner == pplayer_end_pos) {
3797 }
3798 }
3799 if (homecity_start_pos) {
3801 }
3802 }
3803
3804 if (fromcity) { /* leaving a city */
3805 if (homecity_start_pos) {
3807 }
3809 && fromcity->owner == pplayer_start_pos
3813 }
3814 }
3815
3816 /* Entering/leaving a fortress or friendly territory */
3818 bool friendly_end = FALSE;
3819
3822 } else {
3824 type_end_pos);
3825
3826 if (max_friendliness_range >= 0
3829 } else {
3832
3833 if (max_friendliness_range >= 0
3836 }
3837 }
3838 }
3839
3840 if (friendly_end) {
3843 }
3844 }
3845
3849 }
3856 }
3857
3859 sync_cities();
3860
3861 return alive;
3862}
3863
3864/**********************************************************************/
3868static void check_unit_activity(struct unit *punit)
3869{
3870 switch (punit->activity) {
3871 case ACTIVITY_IDLE:
3872 case ACTIVITY_SENTRY:
3873 case ACTIVITY_EXPLORE:
3874 case ACTIVITY_GOTO:
3875 break;
3876 case ACTIVITY_CLEAN:
3877 case ACTIVITY_MINE:
3878 case ACTIVITY_IRRIGATE:
3879 case ACTIVITY_CULTIVATE:
3880 case ACTIVITY_PLANT:
3881 case ACTIVITY_FORTIFIED:
3882 case ACTIVITY_PILLAGE:
3883 case ACTIVITY_TRANSFORM:
3885 case ACTIVITY_BASE:
3886 case ACTIVITY_GEN_ROAD:
3887 case ACTIVITY_CONVERT:
3888 case ACTIVITY_LAST:
3890 break;
3891 };
3892}
3893
3894/**********************************************************************/
3898 const struct tile *psrctile,
3899 const struct tile *pdesttile)
3900{
3901 struct unit_move_data *pdata;
3902 struct player *powner = unit_owner(punit);
3903
3904 if (punit->server.moving) {
3905 /* Recursive moving (probably due to a script). */
3907 pdata->ref_count++;
3908 fc_assert_msg(pdata->punit == punit,
3909 "Unit number %d (%p) was going to die, but "
3910 "server attempts to move it.",
3911 punit->id, punit);
3912 fc_assert_msg(pdata->old_vision == NULL,
3913 "Unit number %d (%p) has done an incomplete move.",
3914 punit->id, punit);
3915 } else {
3916 pdata = fc_malloc(sizeof(*pdata));
3917 pdata->ref_count = 1;
3918 pdata->punit = punit;
3920 BV_CLR_ALL(pdata->can_see_unit);
3921 }
3922 pdata->powner = powner;
3923 BV_CLR_ALL(pdata->can_see_move);
3924 pdata->old_vision = punit->server.vision;
3925
3926 return pdata;
3927}
3928
3929/**********************************************************************/
3933 const struct tile *psrctile,
3934 struct tile *pdesttile)
3935{
3936 struct vision *new_vision;
3937 struct unit *punit = pdata->punit;
3939 const v_radius_t radius_sq
3943
3944 /* Remove unit from the source tile. */
3946
3947#ifndef FREECIV_NDEBUG
3948 bool success =
3949#endif
3952
3953 /* Set new tile. */
3956
3957 if (unit_transported(punit)) {
3958 /* Silently free orders since they won't be applicable anymore. */
3960 }
3961
3962 /* Check unit activity. */
3966
3967 /* We first unfog the destination, then send the move,
3968 * and then fog the old territory. This means that the player
3969 * gets a chance to see the newly explored territory while the
3970 * client moves the unit, and both areas are visible during the
3971 * move */
3972
3973 /* Enhance vision if unit steps into a fortress */
3976 vision_change_sight(new_vision, radius_sq);
3978}
3979
3980/**********************************************************************/
3984{
3986 fc_assert_ret(pdata->ref_count > 0);
3987 fc_assert_msg(pdata->old_vision == NULL,
3988 "Unit number %d (%p) has done an incomplete move.",
3989 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3990
3991 pdata->ref_count--;
3992 if (pdata->ref_count == 0) {
3993 if (pdata->punit != NULL) {
3994 fc_assert(pdata->punit->server.moving == pdata);
3995 pdata->punit->server.moving = NULL;
3996 }
3997 free(pdata);
3998 }
3999}
4000
4001/**********************************************************************/
4005 const struct tile *psrctile,
4006 struct tile *pdesttile,
4007 bool adj)
4008{
4011 struct unit_move_data *pdata;
4012
4013 /* Make new data for 'punit'. */
4016
4017 /* Add all contained units. */
4019 struct unit_move_data *cargo_data;
4020
4024
4025 /* Determine the players able to see the move(s), now that the player
4026 * vision has been increased. */
4027 if (adj) {
4028 /* Main unit for adjacent move: the move is visible for every player
4029 * able to see on the matching unit layer. */
4030 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
4031
4035 BV_SET(pdata->can_see_unit, player_index(oplayer));
4036 BV_SET(pdata->can_see_move, player_index(oplayer));
4037 }
4039 }
4040
4042
4044
4045 if (adj && pmove_data->punit == punit) {
4046 /* If positions are adjacent, we have already handled 'punit'. See
4047 * above. */
4048 continue;
4049 }
4050
4052 if ((adj
4054 pmove_data != pdata))
4056 pmove_data != pdata)) {
4057 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4058 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4059 }
4061 pmove_data != pdata)) {
4062 /* The unit was seen with its source tile even if it was
4063 * teleported. */
4064 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4065 }
4068
4069 return plist;
4070}
4071
4072/**********************************************************************/
4083bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
4084 struct unit *embark_to, bool find_embark_target,
4086 bool enter_hut, bool frighten_hut)
4087{
4088 struct player *pplayer;
4089 struct tile *psrctile;
4090 struct city *psrccity;
4091 struct city *pdestcity;
4092 struct unit *ptransporter;
4095 struct unit_move_data_list *plist;
4096 struct unit_move_data *pdata;
4097 int saved_id;
4098 bool unit_lives;
4099 bool adj;
4100 enum direction8 facing;
4102
4103 /* Some checks. */
4106
4107 pplayer = unit_owner(punit);
4108 saved_id = punit->id;
4111
4113
4114 /* Unload the unit if on a transport. */
4116 if (ptransporter != NULL) {
4117 /* Unload unit _before_ setting the new tile! */
4119 /* Send updated information to anyone watching that transporter
4120 * was unloading cargo. */
4122 }
4123
4124 /* Wakup units next to us before we move. */
4126
4127 /* Make info packets at 'psrctile'. */
4128 if (adj) {
4129 /* If tiles are adjacent, we will show the move to users able
4130 * to see it. */
4133 }
4134
4135 /* Set unit orientation */
4136 if (adj) {
4137 /* Only change orientation when moving to adjacent tile */
4138 punit->facing = facing;
4139 }
4140
4142
4143 /* Move magic. */
4144 punit->moved = TRUE;
4145 punit->moves_left = MAX(0, punit->moves_left - move_cost);
4146 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
4147 /* The next order may not require any remaining move fragments. */
4149 }
4150
4151 /* No longer relevant. */
4154
4155 /* Claim ownership of fortress? */
4158 /* Yes. We claim *all* bases if there's *any* claimable base(s).
4159 * Even if original unit cannot claim other kind of bases, the
4160 * first claimed base will have influence over other bases,
4161 * or something like that. */
4162 tile_claim_bases(pdesttile, pplayer);
4163 }
4164
4166 fc_assert(pdata->punit == punit);
4167
4168 /* Check timeout settings. */
4171
4172 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4173 * if they are ever seen. */
4175 /* Increase the timeout if an enemy unit moves and the
4176 * timeoutaddenemymove setting is in use. */
4177 if (penemy->is_connected
4178 && pplayer != penemy
4179 && pplayers_at_war(pplayer, penemy)
4180 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4182 break;
4183 }
4185
4188 }
4189 }
4190
4192 /* The unit can perform an action to the city at the destination tile.
4193 * A long distance move (like an airlift) doesn't ask what action to
4194 * perform before moving. Ask now. */
4195
4198 }
4199
4200 /* Notifications of the move to the clients. */
4201 if (adj) {
4202 /* Special case: 'punit' is moving to adjacent position. Then we show
4203 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4204
4205 /* Make info packets at 'pdesttile'. */
4208
4211
4212 if (aplayer == NULL) {
4213 if (pconn->observer) {
4214 /* Global observers see all... */
4217 }
4218 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4219 if (aplayer == pplayer) {
4222 } else {
4225 }
4226 }
4228 }
4229
4230 /* Other moves. */
4232 if (adj && pmove_data == pdata) {
4233 /* If positions are adjacent, we have already shown 'punit' move.
4234 * See above. */
4235 continue;
4236 }
4237
4238 /* Make info packets at 'pdesttile'. */
4242
4245
4246 if (aplayer == NULL) {
4247 if (pconn->observer) {
4248 /* Global observers see all... */
4250 }
4251 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4252 if (aplayer == pmove_data->powner) {
4254 } else {
4256 }
4257 }
4260
4261 /* Clear old vision. */
4263 if (pmove_data->old_vision != NULL) {
4264 vision_clear_sight(pmove_data->old_vision);
4265 vision_free(pmove_data->old_vision);
4266 pmove_data->old_vision = NULL;
4267 }
4269
4270 /* Move consequences. */
4272 struct unit *aunit = pmove_data->punit;
4273
4274 if (aunit != NULL
4275 && unit_owner(aunit) == pmove_data->powner
4276 && unit_tile(aunit) == pdesttile) {
4278 pdata != pmove_data,
4280 }
4282
4283 unit_lives = (pdata->punit == punit);
4284
4285 /* Wakeup units and make contact. */
4286 if (unit_lives) {
4288 }
4289
4290 /* Do not pass 'punit' to unit_make_contact(), as it
4291 * might refer to a dead unit.
4292 * Flagless units do not make contact. */
4293 if (!flagless) {
4294 unit_make_contact(nullptr, pdesttile, pplayer);
4295 }
4296
4297 if (unit_lives) {
4298 /* Special checks for ground units in the ocean. */
4300 if (embark_to != NULL) {
4302 } else if (find_embark_target) {
4303 /* TODO: Consider to stop supporting find_embark_target and make all
4304 * callers that wants auto loading set embark_to. */
4306 } else {
4308 }
4309 if (ptransporter) {
4311
4312 /* Set activity to sentry if boarding a ship. */
4313 if (is_human(pplayer)
4318 }
4319
4321 }
4322 }
4323 }
4324
4325 /* Remove units going out of sight. */
4327 struct unit *aunit = pmove_data->punit;
4328
4329 if (aunit == NULL) {
4330 continue; /* Died! */
4331 }
4332
4334 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4337 }
4340
4341 /* Inform the owner's client about actor unit arrival. Can, depending on
4342 * the client settings, cause the client to start the process that makes
4343 * the action selection dialog pop up. */
4345 if (pdestcity != NULL) {
4346 /* Arrival in a city counts. */
4347
4349 struct unit *ptrans;
4350 bool ok;
4351 struct unit *act_unit;
4352 struct player *act_player;
4353
4354 act_unit = pmove_data->punit;
4356
4357 if (act_unit == NULL
4358 || !unit_is_alive(act_unit->id)) {
4359 /* The unit died before reaching this point. */
4360 continue;
4361 }
4362
4363 if (unit_tile(act_unit) != pdesttile) {
4364 /* The unit didn't arrive at the destination tile. */
4365 continue;
4366 }
4367
4368 if (!is_human(act_player)) {
4369 /* Only humans need reminders. */
4370 continue;
4371 }
4372
4373 if (!unit_transported(act_unit)) {
4374 /* Don't show the action selection dialog again. Non transported
4375 * units are handled before they move to the tile. */
4376 continue;
4377 }
4378
4379 /* Open action dialog only if 'act_unit' and all its transporters
4380 * (recursively) don't have orders. */
4382 /* The unit it self has orders. */
4383 continue;
4384 }
4385
4388 if (NULL == ptrans) {
4389 /* No (recursive) transport has orders. */
4390 ok = TRUE;
4391 break;
4392 } else if (unit_has_orders(ptrans)) {
4393 /* A unit transporting the unit has orders */
4394 ok = FALSE;
4395 break;
4396 }
4397 }
4398
4399 if (!ok) {
4400 /* A unit transporting act_unit has orders. */
4401 continue;
4402 }
4403
4405 /* There is a valid target. */
4406
4407 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4408 act_unit->action_decision_tile = pdesttile;
4409
4410 /* Let the client know that this unit wants the player to decide
4411 * what to do. */
4413 }
4415 }
4416
4418 /* Check cities at source and destination. */
4420 if (psrccity != NULL) {
4422 }
4423 if (pdestcity != NULL) {
4425 }
4426
4427 if (unit_lives) {
4428 /* Let the scripts run ... */
4431 }
4432
4433 if (unit_lives) {
4434 /* Autoattack. */
4436 }
4437
4438 if (unit_lives && (enter_hut || frighten_hut)) {
4439 /* Is there a hut? */
4443 }
4444
4446
4447 if (unit_lives) {
4448 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4449 }
4450
4451 return unit_lives;
4452}
4453
4454/**********************************************************************/
4458 struct tile *ptile)
4459{
4460 struct player *owner = unit_owner(punit);
4461
4462 return (is_non_allied_unit_tile(ptile, owner,
4464 || is_non_allied_city_tile(ptile, owner));
4465}
4466
4467/**********************************************************************/
4474{
4475 bool cancel = FALSE;
4476 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4477 struct player *pplayer = unit_owner(punit);
4478
4479 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4480 struct unit *penemy = tile_non_allied_unit(ptile, pplayer,
4482 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4483
4484 if ((penemy && can_player_see_unit(pplayer, penemy))
4486 && pdcity->occupied)) {
4487 cancel = TRUE;
4488 break;
4489 }
4491
4492 return cancel;
4493}
4494
4495/**********************************************************************/
4503static inline bool player_is_watching(struct unit *punit, const bool fresh)
4504{
4505 /* The player just sent the orders to the unit. The unit has moves left.
4506 * It is therefore safe to assume that the player already is paying
4507 * attention to the unit. */
4508 return fresh && punit->moves_left > 0;
4509}
4510
4511/**********************************************************************/
4530bool execute_orders(struct unit *punit, const bool fresh)
4531{
4532 struct act_prob prob;
4533 bool performed;
4534 const char *name;
4535 bool res, last_order;
4536 int unitid = punit->id;
4537 struct player *pplayer = unit_owner(punit);
4538 int moves_made = 0;
4539 const struct civ_map *nmap = &(wld.map);
4540
4542
4543 if (punit->activity != ACTIVITY_IDLE) {
4544 /* Unit's in the middle of an activity; wait for it to finish. */
4546 return TRUE;
4547 }
4548
4549 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4550
4551 /* Any time the orders are canceled we should give the player a message. */
4552
4553 while (TRUE) {
4554 struct unit_order order;
4555
4556 struct action *oaction;
4557
4558 struct tile *dst_tile;
4559 struct city *tgt_city;
4560 struct unit *tgt_unit;
4561 int tgt_id;
4562 int sub_tgt_id;
4563 struct extra_type *pextra;
4564
4565 if (punit->done_moving) {
4566 log_debug(" stopping because we're done this turn");
4567 return TRUE;
4568 }
4569
4571 /* "Patrol" orders are stopped if an enemy is near. */
4572 cancel_orders(punit, " stopping because of nearby enemy");
4574 _("Orders for %s aborted as there are units nearby."),
4575 unit_link(punit));
4576 return TRUE;
4577 }
4578
4579 if (moves_made == punit->orders.length) {
4580 /* For repeating orders, don't repeat more than once per turn. */
4581 log_debug(" stopping because we ran a round");
4584 return TRUE;
4585 }
4586 moves_made++;
4587
4588 order = punit->orders.list[punit->orders.index];
4589
4590 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4591 * this far. */
4593 || action_id_exists(order.action)),
4594 continue);
4595
4596 switch (order.order) {
4597 case ORDER_MOVE:
4598 case ORDER_ACTION_MOVE:
4599 case ORDER_FULL_MP:
4600 if (0 == punit->moves_left) {
4601 log_debug(" stopping because of no more move points");
4602 return TRUE;
4603 }
4604 break;
4607 log_debug(" stopping. Not enough move points this turn");
4608 return TRUE;
4609 }
4610 break;
4611 case ORDER_ACTIVITY:
4612 case ORDER_LAST:
4613 /* Those actions don't require moves left. */
4614 break;
4615 }
4616
4618 && punit->orders.index + 1 == punit->orders.length);
4619
4620 if (last_order) {
4621 /* Clear the orders before we engage in the move. That way any
4622 * has_orders checks will yield FALSE and this will be treated as
4623 * a normal move. This is important: for instance a caravan goto
4624 * will popup the caravan dialog on the last move only. */
4626 }
4627
4628 /* Advance the orders one step forward. This is needed because any
4629 * updates sent to the client as a result of the action should include
4630 * the new index value. Note that we have to send_unit_info() somewhere
4631 * after this point so that the client is properly updated. */
4632 punit->orders.index++;
4633
4634 switch (order.order) {
4635 case ORDER_FULL_MP:
4637 /* If the unit doesn't have full MP then it just waits until the
4638 * next turn. We assume that the next turn it will have full MP
4639 * (there's no check for that). */
4641 log_debug(" waiting this turn");
4643 }
4644 break;
4645 case ORDER_ACTIVITY:
4646 {
4647 enum unit_activity activity = order.activity;
4648
4649 fc_assert(activity == ACTIVITY_SENTRY);
4650
4651 if (can_unit_do_activity(nmap, punit, activity, order.action)) {
4653 set_unit_activity(punit, activity, order.action);
4655
4656 break;
4657 }
4658 }
4659
4660 cancel_orders(punit, " orders canceled because of failed activity");
4662 _("Orders for %s aborted since they "
4663 "give an invalid activity."),
4664 unit_link(punit));
4665 return TRUE;
4666 case ORDER_MOVE:
4667 case ORDER_ACTION_MOVE:
4668 /* Move unit */
4669 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4670 cancel_orders(punit, " move order sent us to invalid location");
4672 _("Orders for %s aborted since they "
4673 "give an invalid location."),
4674 unit_link(punit));
4675 return TRUE;
4676 }
4677
4678 if (order.order != ORDER_ACTION_MOVE
4680 /* Plain move required: no attack, trade route etc. */
4681 cancel_orders(punit, " orders canceled because of enemy");
4683 _("Orders for %s aborted as there "
4684 "are units in the way."),
4685 unit_link(punit));
4686 return TRUE;
4687 }
4688
4689 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4691 order.order != ORDER_ACTION_MOVE);
4692 if (!player_unit_by_number(pplayer, unitid)) {
4693 log_debug(" unit died while moving.");
4694 /* A player notification should already have been sent. */
4695 return FALSE;
4696 }
4697
4698 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4699 /* Movement succeeded but unit didn't move. */
4700 log_debug(" orders resulted in combat.");
4702 return TRUE;
4703 }
4704
4705 if (!res) {
4706 fc_assert(0 <= punit->moves_left);
4707
4708 /* Movement failed (ZOC, etc.) */
4709 cancel_orders(punit, " attempt to move failed.");
4710
4712 /* The final move "failed" because the unit needs to ask the
4713 * player what action it should take.
4714 *
4715 * The action decision request notifies the player. Its
4716 * location at the unit's last order makes it clear to the
4717 * player who the decision is for. ("The Spy I sent to Berlin
4718 * has arrived.")
4719 *
4720 * A notification message is therefore redundant. */
4721 && !(last_order
4724 /* The player may have missed this. No one else will announce it
4725 * in a satisfying manner. Inform the player. */
4726 notify_player(pplayer, unit_tile(punit),
4728 _("Orders for %s aborted because of failed move."),
4729 unit_link(punit));
4730 }
4731
4732 return TRUE;
4733 }
4734 break;
4737
4738 /* Checked in unit_order_list_is_sane() */
4739 fc_assert_action(oaction != NULL, continue);
4740
4741 log_debug(" orders: doing action %s", action_rule_name(oaction));
4742
4743 dst_tile = index_to_tile(&(wld.map), order.target);
4744
4745 if (dst_tile == NULL) {
4746 /* Could be at the edge of the map while trying to target a tile
4747 * outside of it. */
4748
4749 cancel_orders(punit, " target location doesn't exist");
4751 order.action, dst_tile, NULL, NULL);
4752
4753 return TRUE;
4754 }
4755
4756 /* Get the target city from the target tile. */
4758
4759 if (tgt_city == NULL
4761 /* This action targets a city but no city target was found. */
4762
4763 cancel_orders(punit, " perform action vs city with no city");
4765 order.action, dst_tile, tgt_city, NULL);
4766
4767 return TRUE;
4768 }
4769
4770 /* Get a target unit at the target tile. */
4772
4773 if (tgt_unit == NULL
4775 /* This action targets a unit but no target unit was found. */
4776
4777 cancel_orders(punit, " perform action vs unit with no unit");
4779 order.action, dst_tile, tgt_city, tgt_unit);
4780
4781 return TRUE;
4782 }
4783
4784 /* Server side sub target assignment */
4785 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4786 && order.sub_target == NO_TARGET) {
4787 /* Try to find a sub target. */
4789 } else {
4790 /* The client should have specified a sub target if needed */
4791 sub_tgt_id = order.sub_target;
4792 }
4793
4794 /* Get a target extra at the target tile */
4795 pextra = (sub_tgt_id == NO_TARGET ?
4796 NULL :
4797 extra_by_number(sub_tgt_id));
4798
4800 && pextra != NULL
4801 && actres_creates_extra(oaction->result, pextra)
4802 && tile_has_extra(dst_tile, pextra)) {
4803 /* Already there. Move on to the next order. */
4804 break;
4805 }
4806
4808 && pextra != NULL
4809 && actres_removes_extra(oaction->result, pextra)
4810 && !tile_has_extra(dst_tile, pextra)) {
4811 /* Already not there. Move on to the next order. */
4812 break;
4813 }
4814
4815 /* No target selected. */
4816 tgt_id = -1;
4817
4818 /* Assume impossible until told otherwise. */
4819 prob = ACTPROB_IMPOSSIBLE;
4820
4821 switch (action_id_get_target_kind(order.action)) {
4822 case ATK_STACK:
4823 prob = action_prob_vs_stack(nmap, punit, order.action,
4824 dst_tile);
4825 tgt_id = dst_tile->index;
4826 break;
4827 case ATK_TILE:
4828 prob = action_prob_vs_tile(nmap, punit, order.action,
4829 dst_tile, pextra);
4830 tgt_id = dst_tile->index;
4831 break;
4832 case ATK_EXTRAS:
4833 prob = action_prob_vs_extras(nmap, punit, order.action,
4834 dst_tile, pextra);
4835 tgt_id = dst_tile->index;
4836 break;
4837 case ATK_CITY:
4838 prob = action_prob_vs_city(nmap, punit, order.action,
4839 tgt_city);
4840 tgt_id = tgt_city->id;
4841 break;
4842 case ATK_UNIT:
4843 prob = action_prob_vs_unit(nmap, punit, order.action,
4844 tgt_unit);
4845
4846 tgt_id = tgt_unit->id;
4847 break;
4848 case ATK_SELF:
4849 prob = action_prob_self(nmap, punit, order.action);
4850
4851 tgt_id = unitid;
4852 break;
4853 case ATK_COUNT:
4854 log_error("Invalid action target kind");
4855
4856 /* The check below will abort and cancel the orders because prob
4857 * was initialized to impossible above this switch statement. */
4858
4859 break;
4860 }
4861
4862 if (!action_prob_possible(prob)) {
4863 /* The player has enough information to know that this action is
4864 * against the rules. Don't risk any punishment by trying to
4865 * perform it. */
4866
4867 cancel_orders(punit, " illegal action");
4869 _("%s could not do %s to %s."),
4873
4874 /* Try to explain what rule made it illegal. */
4876 order.action, dst_tile, tgt_city, tgt_unit);
4877
4878 return TRUE;
4879 }
4880
4882 /* This action needs a name. */
4884 } else {
4885 /* This action doesn't need a name. */
4886 name = "";
4887 }
4888
4890 unitid,
4891 tgt_id,
4892 sub_tgt_id,
4893 name,
4894 order.action,
4896
4897 if (!player_unit_by_number(pplayer, unitid)) {
4898 /* The unit "died" while performing the action. */
4899 return FALSE;
4900 }
4901
4902 if (!performed) {
4903 /* The action wasn't performed as ordered. */
4904
4905 cancel_orders(punit, " failed action");
4907 _("Orders for %s aborted because "
4908 "doing %s to %s failed."),
4912
4913 return TRUE;
4914 }
4915
4916 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4918 /* Done at turn change. */
4921 break;
4922 }
4923
4924 break;
4925 case ORDER_LAST:
4926 /* Should be caught when loading the unit orders from the savegame or
4927 * when receiving the unit orders from the client. */
4928 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4929 cancel_orders(punit, " invalid order!");
4931 _("Your %s has invalid orders."),
4932 unit_link(punit));
4933 return TRUE;
4934 }
4935
4936 if (last_order) {
4938 log_debug(" stopping because orders are complete");
4939 return TRUE;
4940 }
4941
4942 if (punit->orders.index == punit->orders.length) {
4944 /* Start over. */
4945 log_debug(" repeating orders.");
4946 punit->orders.index = 0;
4947 }
4948 } /* end while */
4949}
4950
4951/**********************************************************************/
4958static int get_unit_vision_base(const struct unit *punit,
4959 enum vision_layer vlayer,
4960 const int base)
4961{
4962 switch (vlayer) {
4963 case V_MAIN:
4964 return MAX(0, base);
4965 case V_INVIS:
4966 case V_SUBSURFACE:
4967 return CLIP(0, base, 2);
4968 case V_COUNT:
4969 break;
4970 }
4971
4972 log_error("Unsupported vision layer variant: %d.", vlayer);
4973
4974 return 0;
4975}
4976
4977/**********************************************************************/
4980static int unit_vision_range_modifiers(const struct unit *punit,
4981 const struct tile *ptile)
4982{
4983 const struct unit_type *utype = unit_type_get(punit);
4984
4985 return (utype->vision_radius_sq
4987 &(const struct req_context) {
4988 .player = unit_owner(punit),
4989 .tile = ptile,
4990 .unittype = utype,
4991 .unit = punit,
4992 },
4994}
4995
4996/**********************************************************************/
5003int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
5004 enum vision_layer vlayer)
5005{
5008}
5009
5010/**********************************************************************/
5017{
5018 struct vision *uvision = punit->server.vision;
5019 const struct tile *utile = unit_tile(punit);
5020 int mod = unit_vision_range_modifiers(punit, utile);
5021 const v_radius_t radius_sq
5025
5026 vision_change_sight(uvision, radius_sq);
5028}
5029
5030/**********************************************************************/
5039
5040/**********************************************************************/
5045{
5046 time_t dt;
5047
5048 if (!punit) {
5049 return FALSE;
5050 }
5051
5052 if (game.server.unitwaittime <= 0) {
5053 return TRUE;
5054 }
5055
5056 if (punit->server.action_turn != game.info.turn - 1) {
5057 return TRUE;
5058 }
5059
5060 dt = time(NULL) - punit->server.action_timestamp;
5061 if (dt < game.server.unitwaittime) {
5062 char buf[64];
5065 ftc_server, _("Your unit may not act for another %s "
5066 "this turn. See /help unitwaittime."), buf);
5067 return FALSE;
5068 }
5069
5070 return TRUE;
5071}
5072
5073/**********************************************************************/
5078{
5079 if (!punit) {
5080 return;
5081 }
5082
5085}
5086
5087/**********************************************************************/
5093{
5094 /* check if there is enemy nearby */
5095 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
5097 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
5098 return FALSE;
5099 }
5100 }
5102
5103 return TRUE;
5104}
5105
5106/**********************************************************************/
5109void random_movements(struct player *pplayer)
5110{
5111 const struct civ_map *nmap = &(wld.map);
5112
5113 game.server.random_move_time = pplayer;
5114
5117 bool moved = TRUE;
5118 struct tile *curtile = unit_tile(punit);
5119 int id = punit->id;
5120
5121 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
5122 /*
5123 * List of all 8 directions
5124 */
5125 enum direction8 dirs[8] = {
5128 };
5129 int n;
5130
5131 moved = FALSE;
5132
5133 for (n = 8; n > 0 && !moved; n--) {
5134 enum direction8 choice = (enum direction8) fc_rand(n);
5135 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
5136
5137 if (dest != NULL) {
5139 dest))) {
5140 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
5142 moved = TRUE;
5143 break;
5144 }
5145 }
5146
5147 if (!moved) {
5149 NULL)) {
5150 if (unit_perform_action(pplayer, id, tile_index(dest),
5152 ACT_REQ_RULES)) {
5153 moved = TRUE;
5154 }
5156 punit, dest, NULL)) {
5157 if (unit_perform_action(pplayer, id, tile_index(dest),
5159 ACT_REQ_RULES)) {
5160 moved = TRUE;
5161 }
5163 punit, dest, NULL)) {
5164 if (unit_perform_action(pplayer, id, tile_index(dest),
5166 ACT_REQ_RULES)) {
5167 moved = TRUE;
5168 }
5169 }
5170 }
5171 }
5172
5173 if (!moved) {
5174 /* Choice was bad, so replace it with the last direction
5175 * in the list. On the next iteration, one fewer choice
5176 * will remain. */
5177 dirs[choice] = dirs[n - 1];
5178 }
5179 }
5180 }
5181 }
5183
5185}
5186
5187/**********************************************************************/
5192void unit_make_contact(const struct unit *punit,
5193 struct tile *ptile, struct player *pplayer)
5194{
5195 fc_assert_ret(punit != nullptr
5196 || (ptile != nullptr && pplayer != nullptr));
5197
5198 if (punit != nullptr && unit_has_type_flag(punit, UTYF_FLAGLESS)) {
5199 return; /* Flagless unit can't make contact */
5200 }
5201
5202 maybe_make_contact(ptile != nullptr ? ptile : unit_tile(punit),
5203 pplayer != nullptr ? pplayer : unit_owner(punit));
5204}
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:5546
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1250
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5068
const char * action_name_translation(const struct action *paction)
Definition actions.c:1230
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:4589
const char * action_rule_name(const struct action *action)
Definition actions.c:1216
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1119
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:3309
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:4672
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:4742
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:4231
bool action_id_exists(const action_id act_id)
Definition actions.c:1068
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5128
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:4506
bool is_action_enabled_unit_on_self(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit)
Definition actions.c:3458
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:4314
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5179
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_has_result(_act_, _res_)
Definition actions.h:184
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:441
#define ACTPROB_IMPOSSIBLE
Definition actions.h:691
#define action_id_get_target_kind(act_id)
Definition actions.h:417
#define action_id_has_result_safe(act_id, result)
Definition actions.h:430
#define ACTION_NONE
Definition actions.h:59
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:810
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:789
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:227
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
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:767
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:731
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:743
#define output_type_iterate(output)
Definition city.h:842
#define city_owner(_pcity_)
Definition city.h:560
#define city_list_iterate_end
Definition city.h:507
#define output_type_iterate_end
Definition city.h:848
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3342
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:2368
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:2220
void sync_cities(void)
Definition citytools.c:3351
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1992
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3165
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:762
bool city_refresh(struct city *pcity)
Definition cityturn.c:158
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:480
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:86
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:994
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:717
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1025
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:772
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:615
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:841
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:411
char * incite_cost
Definition comments.c:76
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:2965
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2680
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2710
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
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 int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:1066
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct req_context *other_context, enum effect_type effect_type)
Definition effects.c:744
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:824
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:804
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:213
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:208
@ RPT_CERTAIN
Definition fc_types.h:533
@ AUT_NONE
Definition fc_types.h:229
@ HB_DISABLED
Definition fc_types.h:999
#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:61
int current_turn_timeout(void)
Definition game.c:853
struct world wld
Definition game.c:62
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:123
struct unit * game_unit_by_number(int id)
Definition game.c:115
struct city * game_city_by_number(int id)
Definition game.c:106
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1039
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:182
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:212
#define log_test
Definition log.h:137
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:712
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
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:1469
#define adjc_iterate_end
Definition map.h:430
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define square_iterate_end
Definition map.h:391
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:290
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:398
#define circle_iterate_end
Definition map.h:401
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2489
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2577
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1926
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2184
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2512
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2680
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:925
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:869
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1444
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:2002
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1387
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2477
#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:278
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:362
int unit_move_rate(const struct unit *punit)
Definition movement.c:89
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:944
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:373
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:522
@ MR_OK
Definition movement.h:35
@ MR_NOT_ALLOWED
Definition movement.h:53
@ MR_DEATH
Definition movement.h:36
static mpqt_worker * worker
Definition mpgui_qt.cpp:54
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:843
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:1409
struct player_slot * slots
Definition player.c:51
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1463
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define OWNER_NONE
Definition player.h:50
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define is_ai(plr)
Definition player.h:232
#define is_human(plr)
Definition player.h:231
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:3217
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2364
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1148
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1595
void player_loot_player(struct player *pvictor, struct player *pvictim)
Definition plrhand.c:410
#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 req_context *other_context, 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:376
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1968
#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:2061
struct act_prob prob
Definition unittools.c:115
Definition city.h:317
int unitwaittime
Definition game.h:205
struct player * random_move_time
Definition game.h:283
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:139
int killunhomed
Definition game.h:161
int ransom_gold
Definition game.h:182
struct civ_game::@32::@36 server
bool autoattack
Definition game.h:138
int timeoutaddenemymove
Definition game.h:215
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:199
int units_used
Definition player.h:108
int units_lost
Definition player.h:106
struct unit_list * units
Definition player.h:282
struct conn_list * connections
Definition player.h:298
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
struct player::@73::@75 server
struct player_economic economic
Definition player.h:284
struct player_score score
Definition player.h:283
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:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
int vision_radius_sq
Definition unittype.h:527
enum vision_layer vlayer
Definition unittype.h:574
Definition unit.h:140
time_t action_timestamp
Definition unit.h:248
int length
Definition unit.h:198
int upkeep[O_LAST]
Definition unit.h:150
bool has_orders
Definition unit.h:196
enum action_decision action_decision_want
Definition unit.h:205
int battlegroup
Definition unit.h:194
enum unit_activity activity
Definition unit.h:159
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
enum gen_action action
Definition unit.h:160
struct unit::@83 orders
bool moved
Definition unit.h:176
int index
Definition unit.h:198
struct vision * vision
Definition unit.h:247
bool vigilant
Definition unit.h:200
int hp
Definition unit.h:153
int fuel
Definition unit.h:155
struct extra_type * changed_from_target
Definition unit.h:173
int current_form_turn
Definition unit.h:211
bool stay
Definition unit.h:208
enum direction8 facing
Definition unit.h:144
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:142
struct extra_type * activity_target
Definition unit.h:167
int activity_count
Definition unit.h:165
struct unit_order * list
Definition unit.h:201
enum unit_activity changed_from
Definition unit.h:171
struct player * nationality
Definition unit.h:146
bool repeat
Definition unit.h:199
void(* removal_callback)(struct unit *punit)
Definition unit.h:256
struct unit_move_data * moving
Definition unit.h:250
int action_turn
Definition unit.h:249
int homecity
Definition unit.h:148
bool paradropped
Definition unit.h:177
bool done_moving
Definition unit.h:184
int birth_turn
Definition unit.h:210
struct goods_type * carrying
Definition unit.h:189
struct tile * goto_tile
Definition unit.h:157
struct tile * action_decision_tile
Definition unit.h:206
const struct unit_type * utype
Definition unit.h:141
int veteran
Definition unit.h:154
int changed_from_count
Definition unit.h:172
bool dying
Definition unit.h:253
enum server_side_agent ssa_controller
Definition unit.h:175
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:89
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
struct goods_type * goods_from_city_to_unit(const struct city *src, const struct unit *punit)
Goods_type_id goods_index(const struct goods_type *pgood)
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1846
void free_unit_orders(struct unit *punit)
Definition unit.c:1832
bool unit_is_alive(int id)
Definition unit.c:2316
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:568
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2473
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1300
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2544
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2493
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2246
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:883
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2956
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, enum gen_action action)
Definition unit.c:913
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1687
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1792
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1310
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1140
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:2051
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2528
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:794
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2554
bool unit_has_orders(const struct unit *punit)
Definition unit.c:220
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1975
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2098
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:608
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.c:1361
bool can_unit_do_activity_targeted(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, enum gen_action action, struct extra_type *target)
Definition unit.c:954
#define unit_tile(_pu)
Definition unit.h:407
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:430
#define unit_cargo_iterate_end
Definition unit.h:588
@ ORDER_ACTION_MOVE
Definition unit.h:46
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_FULL_MP
Definition unit.h:44
@ ORDER_MOVE
Definition unit.h:40
@ ORDER_LAST
Definition unit.h:50
@ ORDER_PERFORM_ACTION
Definition unit.h:48
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:418
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:585
#define CHECK_UNIT(punit)
Definition unit.h:273
#define unit_owner(_pu)
Definition unit.h:406
@ UU_OK
Definition unit.h:62
#define unit_home(_pu_)
Definition unit.h:404
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:443
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:2515
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unithand.c:6665
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:3358
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5715
#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:360
void unit_did_action(struct unit *punit)
Definition unittools.c:5077
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3466
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2648
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:3071
void unit_make_contact(const struct unit *punit, struct tile *ptile, struct player *pplayer)
Definition unittools.c:5192
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1164
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:2156
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:4004
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4530
static void unit_convert(struct unit *punit)
Definition unittools.c:775
void update_unit_activities(struct player *pplayer)
Definition unittools.c:671
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1310
#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:1558
void random_movements(struct player *pplayer)
Definition unittools.c:5109
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:292
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1799
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1421
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1493
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1924
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1456
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4457
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:405
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1406
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:3039
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3983
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1776
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3339
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2738
#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:2869
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:662
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3665
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:719
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:819
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3424
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3522
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:703
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:681
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:1116
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2882
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1948
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1375
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3868
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:635
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:429
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3897
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1718
void notify_unit_experience(struct unit *punit)
Definition unittools.c:748
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:801
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:2819
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:1670
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1480
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1054
#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:1637
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1915
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1790
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:5003
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:219
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5016
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:1610
void do_explore(struct unit *punit)
Definition unittools.c:3104
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3394
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:5044
#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:2144
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:693
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3140
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4503
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4958
void player_restore_units(struct player *pplayer)
Definition unittools.c:482
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1535
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4980
static void update_unit_activity(struct unit *punit)
Definition unittools.c:859
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3446
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1526
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Definition unittools.c:175
static bool maybe_become_veteran_real(struct unit *punit, int base_chance, bool worker)
Definition unittools.c:238
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3654
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:5092
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:739
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:831
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1083
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2204
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1192
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2954
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3304
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3480
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:846
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:3735
void unit_get_goods(struct unit *punit)
Definition unittools.c:1621
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2926
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4473
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:4083
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3932
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:5033
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2271
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1230
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1063
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:1573
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, bool consider_reg_impr_req)
Definition unittype.c:1972
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2257
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1591
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2572
int num_role_units(int role)
Definition unittype.c:2207
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1931
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1707
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2503
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:194
const struct veteran_level * vsystem_veteran_level(const struct veteran_system *vsystem, int level)
Definition unittype.c:2589
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:1564
#define utype_class(_t_)
Definition unittype.h:754
#define utype_fuel(ptype)
Definition unittype.h:844
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:622
#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