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/**********************************************************************/
238 bool worker)
239{
240 const struct veteran_system *vsystem;
241 const struct veteran_level *vlevel;
242 int chance;
243 const struct civ_map *nmap = &(wld.map);
244
246
250
253
254 if (punit->veteran + 1 >= vsystem->levels
256 return FALSE;
257 } else if (!worker) {
259
260 /* The modification is tacked on as a multiplier to the base chance.
261 * For example with a base chance of 50% for green units and a modifier
262 * of +50% the end chance is 75%. */
263 chance = vlevel->base_raise_chance * mod / 100;
265 chance = base_chance * vlevel->work_raise_chance / 100;
266 } else {
267 /* No battle and no work done. */
268 return FALSE;
269 }
270
271 if (fc_rand(100) < chance) {
272 punit->veteran++;
273 return TRUE;
274 }
275
276 return FALSE;
277}
278
279/**********************************************************************/
289bool unit_versus_unit(struct unit *attacker, struct unit *defender,
290 int *att_hp, int *def_hp, int *att_vet, int *def_vet,
291 const struct action *paction)
292{
293 int attackpower = get_total_attack_power(attacker, defender, paction);
294 int defensepower = get_total_defense_power(attacker, defender);
296 struct player *plr1 = unit_owner(attacker);
297 struct player *plr2 = unit_owner(defender);
298 struct civ_map *nmap = &(wld.map);
299 int max_rounds;
300 int rounds;
301 int att_strength;
302 int def_strength;
303
304 *att_hp = attacker->hp;
305 *def_hp = defender->hp;
306 get_modified_firepower(nmap, attacker, defender,
308
309 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
310 "defense firepower:%d", attackpower, defensepower,
312
315
318
319 /* In a combat between equal strength units the values are 50% / 50%.
320 * -> scaling that to 100% by doubling, to match scale of chances
321 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
324
325 if (attackpower == 0) {
326 *att_hp = 0;
327 } else if (defensepower == 0) {
328 *def_hp = 0;
329 }
331 for (rounds = 0;
332 *att_hp > 0 && *def_hp > 0
334 rounds++) {
336 *def_hp -= attack_firepower;
337 } else {
338 *att_hp -= defense_firepower;
339 }
340 }
341 if (*att_hp < 0) {
342 *att_hp = 0;
343 }
344 if (*def_hp < 0) {
345 *def_hp = 0;
346 }
347
348 return attackpower <= 0 || defensepower <= 0;
349}
350
351/**********************************************************************/
356void unit_bombs_unit(struct unit *attacker, struct unit *defender,
357 int *att_hp, int *def_hp,
358 const struct action *paction)
359{
360 int i;
361 int rate = unit_bombard_rate(attacker);
362 int attackpower = get_total_attack_power(attacker, defender, paction);
363 int defensepower = get_total_defense_power(attacker, defender);
365 struct player *plr1 = unit_owner(attacker);
366 struct player *plr2 = unit_owner(defender);
367 struct civ_map *nmap = &(wld.map);
368
369 *att_hp = attacker->hp;
370 *def_hp = defender->hp;
371 get_modified_firepower(nmap, attacker, defender,
373
374 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
375 "defense firepower:%d", attackpower, defensepower,
377
380
381 for (i = 0; i < rate; i++) {
383 *def_hp -= attack_firepower;
384 }
385 }
386
387 if (*def_hp <= 0) {
388 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
389 /* Don't kill the target. */
390 *def_hp = 1;
391 } else {
392 *def_hp = 0;
393 }
394 }
395}
396
397/**********************************************************************/
401void combat_veterans(struct unit *attacker, struct unit *defender,
402 bool powerless, int att_vet, int def_vet)
403{
405 if (attacker->hp <= 0 || defender->hp <= 0
408 att_vet = 100;
409 def_vet = 100;
410 }
411 if (attacker->hp > 0) {
412 maybe_make_veteran(attacker, att_vet);
413 }
414 if (defender->hp > 0) {
415 maybe_make_veteran(defender, def_vet);
416 }
417 }
418 }
419}
420
421/**********************************************************************/
425static void do_upgrade_effects(struct player *pplayer)
426{
428 struct unit_list *candidates;
429
430 if (upgrades <= 0) {
431 return;
432 }
434
435 unit_list_iterate(pplayer->units, punit) {
436 /* We have to be careful not to strand units at sea, for example by
437 * upgrading a frigate to an ironclad while it was carrying a unit. */
438 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
439 unit_list_prepend(candidates, punit); /* Potential candidate :) */
440 }
442
443 while (upgrades > 0 && unit_list_size(candidates) > 0) {
444 /* Upgrade one unit. The unit is chosen at random from the list of
445 * available candidates. */
448 const struct unit_type *type_from = unit_type_get(punit);
449 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
450
453 _("%s was upgraded for free to %s."),
457 upgrades--;
458 }
459
461}
462
463/**********************************************************************/
478void player_restore_units(struct player *pplayer)
479{
480 const struct civ_map *nmap = &(wld.map);
481
482 /* 1) get Leonardo out of the way first: */
483 do_upgrade_effects(pplayer);
484
486
487 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
489
490 /* 3) Check that unit has hitpoints */
491 if (punit->hp <= 0) {
492 /* This should usually only happen for heli units, but if any other
493 * units get 0 hp somehow, catch them too. --dwp */
494 /* if 'game.server.killunhomed' is activated unhomed units are slowly
495 * killed; notify player here */
496 if (!punit->homecity && 0 < game.server.killunhomed) {
498 ftc_server, _("Your %s has run out of hit points "
499 "because it was not supported by a city."),
501 } else {
503 _("Your %s has run out of hit points."),
505 }
506
508 continue; /* Continue iterating... */
509 }
510
511 /* 4) Rescue planes if needed */
513 /* Shall we emergency return home on the last vapors? */
514
515 /* I think this is strongly against the spirit of client goto.
516 * The problem is (again) that here we know too much. -- Zamar */
517
518 if (punit->fuel <= 1
520 struct unit *carrier;
521
523 if (carrier) {
525 } else {
526 struct pf_map *pfm;
527 struct pf_parameter parameter;
528 bool alive = TRUE;
529
530 pft_fill_unit_parameter(&parameter, nmap, punit);
531 parameter.omniscience = !has_handicap(pplayer, H_MAP);
532 pfm = pf_map_new(&parameter);
533
534 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
535 if (move_cost > punit->moves_left) {
536 /* Too far */
537 break;
538 }
539
540 if (is_refuel_point(ptile, pplayer, punit)) {
541 struct pf_path *path;
542 int id = punit->id;
543
544 /* Client orders may be running for this unit - if so
545 * we free them before engaging goto. */
547
548 path = pf_map_path(pfm, ptile);
549
550 alive = adv_follow_path(punit, path, ptile);
551
552 if (!alive) {
553 log_error("rescue plane: unit %d died enroute!", id);
554 } else if (!same_pos(unit_tile(punit), ptile)) {
555 /* Enemy units probably blocked our route
556 * FIXME: We should try find alternative route around
557 * the enemy unit instead of just giving up and crashing. */
558 log_debug("rescue plane: unit %d could not move to "
559 "refuel point!", punit->id);
560 }
561
562 if (alive) {
563 /* Clear activity. Unit info will be sent in the end of
564 * the function. */
568
571 if (carrier) {
573 }
574 }
575
576 notify_player(pplayer, unit_tile(punit),
578 _("Your %s has returned to refuel."),
580 }
581 pf_path_destroy(path);
582 break;
583 }
586
587 if (!alive) {
588 /* Unit died trying to move to refuel point. */
589 return;
590 }
591 }
592 }
593
594 /* 5) Update fuel */
595 punit->fuel--;
596
597 /* 6) Automatically refuel air units in cities, airbases, and
598 * transporters (carriers). */
601 }
602 }
604
605 /* 7) Check if there are air units without fuel */
607 const struct unit_type *utype = unit_type_get(punit);
608
609 if (punit->fuel <= 0 && utype_fuel(utype)) {
610 /* Notifications sent from the lua script when unit wiped. */
612 }
614
615 /* Send all updates. */
616 unit_list_iterate(pplayer->units, punit) {
619}
620
621/**********************************************************************/
632{
633 bool was_lower;
634 const struct unit_type *utype = unit_type_get(punit);
635
636 was_lower = (punit->hp < utype->hp);
637
639
640 fc_assert(punit->hp >= 0);
641 fc_assert(punit->hp <= utype->hp);
642
643 if (punit->hp == utype->hp) {
646 }
647 }
648
649 punit->moved = FALSE;
651}
652
653/**********************************************************************/
658static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
659{
662}
663
664/**********************************************************************/
673
674/**********************************************************************/
677void execute_unit_orders(struct player *pplayer)
678{
680 if (unit_has_orders(punit)) {
682 }
684}
685
686/**********************************************************************/
689void unit_tc_effect_refresh(struct player *pplayer)
690{
691 unit_list_iterate(pplayer->units, punit) {
694}
695
696/**********************************************************************/
700{
701 /* Remember activities only after all knock-on effects of unit activities
702 * on other units have been resolved */
703 unit_list_iterate(pplayer->units, punit) {
709}
710
711/**********************************************************************/
715static int total_activity(struct tile *ptile, enum unit_activity act,
716 struct extra_type *tgt)
717{
718 int total = 0;
720
721 unit_list_iterate(ptile->units, punit) {
722 if (punit->activity == act
723 && (!tgt_matters || punit->activity_target == tgt)) {
724 total += punit->activity_count;
725 }
727
728 return total;
729}
730
731/**********************************************************************/
735static bool total_activity_done(struct tile *ptile, enum unit_activity act,
736 struct extra_type *tgt)
737{
738 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
739}
740
741/**********************************************************************/
745{
746 const struct veteran_level *vlevel;
747#ifndef FREECIV_NDEBUG
748 const struct veteran_system *vsystem;
749#endif
750
751 if (!punit) {
752 return;
753 }
754
755#ifndef FREECIV_NDEBUG
759#endif /* FREECIV_NDEBUG */
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 struct extra_type **target)
1086{
1087 const struct civ_map *nmap = &(wld.map);
1088
1089 if (*activity == ACTIVITY_PILLAGE
1090 && *target == NULL) {
1091 struct tile *ptile = unit_tile(punit);
1092 struct extra_type *tgt;
1093 bv_extras extras = *tile_extras(ptile);
1094
1095 while ((tgt = get_preferred_pillage(extras))) {
1096
1097 BV_CLR(extras, extra_index(tgt));
1098
1099 if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
1100 *target = tgt;
1101 return;
1102 }
1103 }
1104
1105 /* Nothing we can pillage here. */
1106 *activity = ACTIVITY_IDLE;
1107 }
1108}
1109
1110/**********************************************************************/
1115 struct player *powner,
1116 struct unit_type *u_type,
1117 int sq_radius,
1118 struct tile **dst_tile)
1119{
1120 int bestvalue = 0;
1121 struct civ_map *nmap = &(wld.map);
1122
1123 /* coords of best tile in arg pointers */
1125 int value;
1126
1127 if (!is_native_tile(u_type, ptile)) {
1128 continue;
1129 }
1130
1131 if (NULL != tile_city(ptile)) {
1132 continue;
1133 }
1134
1135 if (0 < unit_list_size(ptile->units)) {
1136 continue;
1137 }
1138
1139 /* City may not have changed hands yet; see place_partisans(). */
1140 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1141 ptile, FALSE, 0);
1142 value *= 10;
1143
1144 if (tile_continent(ptile) != tile_continent(pcenter)) {
1145 value /= 2;
1146 }
1147
1148 value -= fc_rand(value/3);
1149
1150 if (value > bestvalue) {
1151 *dst_tile = ptile;
1152 bestvalue = value;
1153 }
1155
1156 return bestvalue > 0;
1157}
1158
1159/**********************************************************************/
1162void place_partisans(struct tile *pcenter, struct player *powner,
1163 int count, int sq_radius)
1164{
1165 struct tile *ptile = NULL;
1167 const struct civ_map *nmap = &(wld.map);
1168
1169 while (count-- > 0
1171 sq_radius, &ptile)) {
1172 struct unit *punit;
1173
1174 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1176 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1177 }
1178
1179 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1180 }
1181}
1182
1183/**********************************************************************/
1188bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1189 int move_cost, bool verbose)
1190{
1191 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1192
1193 if (city_owner(pcity) == unit_owner(punit)) {
1194 log_verbose("Teleported %s %s from (%d,%d) to %s",
1196 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1197 if (verbose) {
1200 _("Teleported your %s to %s."),
1202 city_link(pcity));
1203 }
1204
1205 /* Silently free orders since they won't be applicable anymore. */
1207
1208 if (move_cost == -1) {
1209 move_cost = punit->moves_left;
1210 }
1211 unit_move(punit, dst_tile, move_cost,
1213
1214 return TRUE;
1215 }
1216 return FALSE;
1217}
1218
1219/**********************************************************************/
1226void bounce_unit(struct unit *punit, bool verbose)
1227{
1228 struct player *pplayer;
1229 struct tile *punit_tile;
1230 int count = 0;
1231
1232 /* I assume that there are no topologies that have more than
1233 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1234 const int DIST = 2;
1235 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1236
1237 if (!punit) {
1238 return;
1239 }
1240
1241 pplayer = unit_owner(punit);
1243
1244 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1245 if (count >= ARRAY_SIZE(tiles)) {
1246 break;
1247 }
1248
1249 if (ptile == punit_tile) {
1250 continue;
1251 }
1252
1253 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1254 && !is_non_allied_city_tile(ptile, pplayer)
1255 && !is_non_allied_unit_tile(ptile, pplayer,
1257 tiles[count++] = ptile;
1258 }
1260
1261 if (count > 0) {
1262 struct tile *ptile = tiles[fc_rand(count)];
1263
1264 if (verbose) {
1265 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1266 /* TRANS: A unit is moved to resolve stack conflicts. */
1267 _("Moved your %s."),
1268 unit_link(punit));
1269 }
1270
1271 /* TODO: should a unit be able to bounce to a transport like is done
1272 * below? What if the unit can't legally enter the transport, say
1273 * because the transport is Unreachable and the unit doesn't have it in
1274 * its embarks field or because "Transport Embark" isn't enabled? Kept
1275 * like it was to preserve the old rules for now. -- Sveinung */
1276 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1277 return;
1278 }
1279
1280 /* Didn't find a place to bounce the unit, going to disband it.
1281 * Try to bounce transported units. */
1283 struct unit_list *pcargo_units;
1284
1287 bounce_unit(pcargo, verbose);
1289 }
1290
1291 if (verbose) {
1293 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1294 _("Disbanded your %s."),
1296 }
1297
1299}
1300
1301/**********************************************************************/
1306static void throw_units_from_illegal_cities(struct player *pplayer,
1307 bool verbose)
1308{
1309 struct tile *ptile;
1310 struct city *pcity;
1311 struct unit *ptrans;
1312 struct unit_list *pcargo_units;
1313
1314 /* Unload undesired units from transports, if possible. */
1315 unit_list_iterate(pplayer->units, punit) {
1316 ptile = unit_tile(punit);
1317 pcity = tile_city(ptile);
1318 if (NULL != pcity
1319 && !pplayers_allied(city_owner(pcity), pplayer)
1323 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1324 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1326 }
1327 }
1329 }
1331
1332 /* Bounce units except transported ones which will be bounced with their
1333 * transport. */
1335 ptile = unit_tile(punit);
1336 pcity = tile_city(ptile);
1337 if (NULL != pcity
1338 && !pplayers_allied(city_owner(pcity), pplayer)) {
1340 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1341 bounce_unit(punit, verbose);
1342 }
1343 }
1345
1346#ifdef FREECIV_DEBUG
1347 /* Sanity check. */
1348 unit_list_iterate(pplayer->units, punit) {
1349 ptile = unit_tile(punit);
1350 pcity = tile_city(ptile);
1351 fc_assert_msg(NULL == pcity
1352 || pplayers_allied(city_owner(pcity), pplayer),
1353 "Failed to throw %s %d from %s %d (%d, %d)",
1355 punit->id,
1356 city_name_get(pcity),
1357 pcity->id,
1358 TILE_XY(ptile));
1360#endif /* FREECIV_DEBUG */
1361}
1362
1363/**********************************************************************/
1371static void resolve_stack_conflicts(struct player *pplayer,
1372 struct player *aplayer, bool verbose)
1373{
1375 struct tile *ptile = unit_tile(punit);
1376
1377 /* Can pass FALSE 'everyone_non_allied' since no flagless
1378 * unit could be stacked there to begin with. */
1379 if (is_non_allied_unit_tile(ptile, pplayer, FALSE)) {
1381 if (unit_owner(aunit) == pplayer
1382 || unit_owner(aunit) == aplayer
1383 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1384 bounce_unit(aunit, verbose);
1385 }
1387 }
1389}
1390
1391/**********************************************************************/
1402void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1403 bool verbose)
1404{
1405 throw_units_from_illegal_cities(pplayer, verbose);
1407
1408 resolve_stack_conflicts(pplayer, aplayer, verbose);
1409 resolve_stack_conflicts(aplayer, pplayer, verbose);
1410}
1411
1412/**********************************************************************/
1417struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1418 const struct player *aplayer)
1419{
1420 struct unit_list *seen_units = unit_list_new();
1421
1422 /* Anybody's units inside ally's cities */
1423 city_list_iterate(aplayer->cities, pcity) {
1424 unit_list_iterate(city_tile(pcity)->units, punit) {
1425 if (can_player_see_unit(pplayer, punit)) {
1427 }
1430
1431 /* Ally's own units inside transports */
1433 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1435 }
1437
1438 /* Make sure the same unit is not added in multiple phases
1439 * (unit within transport in a city) */
1441
1442 return seen_units;
1443}
1444
1445/**********************************************************************/
1452void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1453 const struct unit_list *seen_units)
1454{
1456 /* We need to hide units previously seen by the client. */
1457 if (!can_player_see_unit(pplayer, punit)) {
1458 unit_goes_out_of_sight(pplayer, punit);
1459 }
1461
1462 city_list_iterate(aplayer->cities, pcity) {
1463 /* The player used to know what units were in these cities. Now that
1464 * they don't, they need to get a new short city packet updating the
1465 * occupied status. */
1466 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1467 send_city_info(pplayer, pcity);
1468 }
1470}
1471
1472/**********************************************************************/
1476void give_allied_visibility(struct player *pplayer,
1477 struct player *aplayer)
1478{
1480 if (can_player_see_unit(pplayer, punit)) {
1481 send_unit_info(pplayer->connections, punit);
1482 }
1484}
1485
1486/**********************************************************************/
1489static bool is_refuel_tile(const struct tile *ptile,
1490 const struct player *pplayer,
1491 const struct unit *punit)
1492{
1493 const struct unit_type *utype;
1494 const struct unit_class *pclass;
1495
1496 if (is_allied_city_tile(ptile, pplayer)) {
1497 return TRUE;
1498 }
1499
1500 utype = unit_type_get(punit);
1501 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1502 return TRUE;
1503 }
1504
1505 pclass = utype_class(utype);
1506 if (NULL != pclass->cache.refuel_extras) {
1507 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1508
1509 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1510 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1511 return TRUE;
1512 }
1514 }
1515
1516 return FALSE;
1517}
1518
1519/**********************************************************************/
1523{
1524 return unit_transported(punit) /* Carrier */
1526}
1527
1528/**********************************************************************/
1531bool is_refuel_point(const struct tile *ptile,
1532 const struct player *pplayer,
1533 const struct unit *punit)
1534{
1535 if (is_non_allied_unit_tile(ptile, pplayer,
1537 return FALSE;
1538 }
1539
1540 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1541}
1542
1543/**********************************************************************/
1554void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1555 int vet_loss)
1556{
1557 struct player *pplayer = unit_owner(punit);
1558 const struct unit_type *old_type = punit->utype;
1560 int old_hp = unit_type_get(punit)->hp;
1561 int lvls;
1562
1563 punit->utype = to_unit;
1564
1565 /* New type may not have the same veteran system, and we may want to
1566 * knock some levels off. */
1569 /* Keeping the old behaviour, so first clip top, then reduce */
1571
1572 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1573 * and don't kill the unit. unit_move_rate() is used to take into account
1574 * global effects like Magellan's Expedition. */
1575 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1576 if (old_mr == 0) {
1578 } else {
1580 }
1581
1583
1587 }
1588
1589 /* Update unit upkeep */
1591
1593
1595
1596 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1598
1601}
1602
1603/**********************************************************************/
1606struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1607 const struct unit_type *type, int veteran_level,
1608 int homecity_id, int moves_left)
1609{
1610 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1611 moves_left, -1, NULL);
1612}
1613
1614/**********************************************************************/
1618{
1619 if (punit->homecity != 0) {
1621
1624 }
1625 }
1626}
1627
1628/**********************************************************************/
1633struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1634 const struct unit_type *type, int veteran_level,
1635 int homecity_id, int moves_left, int hp_left,
1636 struct unit *ptrans)
1637{
1638 struct unit *punit
1639 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1641 struct city *pcity = (!homecity_id || utype_has_flag(type, UTYF_NOHOME))
1643 bool could_place;
1644
1646 could_place = place_unit(punit, pplayer, pcity, ptrans, FALSE);
1648 if (!could_place) {
1650 punit = NULL;
1651 }
1652
1653 return punit;
1654}
1655
1656/**********************************************************************/
1666struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1667 const struct unit_type *type,
1668 int veteran_level, int homecity_id,
1669 int moves_left, int hp_left)
1670{
1671 struct unit *punit;
1672
1673 fc_assert_ret_val(ptile != NULL, NULL);
1675 unit_tile_set(punit, ptile);
1676
1678 punit->homecity = 0; /* none */
1679 } else {
1681 }
1682
1683 if (hp_left >= 0) {
1684 /* Override default full HP */
1685 punit->hp = hp_left;
1686 }
1687
1688 if (moves_left >= 0) {
1689 int mr = unit_move_rate(punit);
1690
1691 /* Override default full MP */
1692 /* FIXME: there are valid situations when a unit have mp
1693 * over its move rate. Here, keeping the old behavior. */
1695 /* Assume that if moves_left < 0 then the unit is "fresh",
1696 * and not moved; else the unit has had something happen
1697 * to it (eg, bribed) which we treat as equivalent to moved.
1698 * (Otherwise could pass moved arg too...) --dwp */
1699 punit->moved = TRUE;
1700 }
1701
1702 return punit;
1703}
1704
1705/**********************************************************************/
1714bool place_unit(struct unit *punit, struct player *pplayer,
1715 struct city *pcity, struct unit *ptrans, bool force)
1716{
1717 struct tile *ptile;
1718
1719 fc_assert_ret_val(pplayer, FALSE);
1721 ptile = punit->tile;
1722 fc_assert_ret_val(ptile, FALSE);
1723
1724 /* Register unit */
1727
1728 if (ptrans) {
1729 /* Set transporter for unit. */
1731 }
1732
1734 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1735 FALSE);
1736
1737 unit_list_prepend(pplayer->units, punit);
1738 unit_list_prepend(ptile->units, punit);
1739 unit_make_contact(punit, ptile, nullptr);
1740 if (pcity && !unit_has_type_flag(punit, UTYF_NOHOME)) {
1741 fc_assert(punit->homecity == pcity->id);
1742 fc_assert(city_owner(pcity) == pplayer);
1744 /* update unit upkeep */
1745 city_units_upkeep(pcity);
1746 /* Refresh the unit's homecity. */
1747 city_refresh(pcity);
1748 send_city_info(pplayer, pcity);
1749 }
1750
1751 punit->server.vision = vision_new(pplayer, ptile);
1753
1756
1757 /* The unit may have changed the available tiles in nearby cities. */
1759 sync_cities();
1760
1762
1763 CALL_FUNC_EACH_AI(unit_created, punit);
1764 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1765
1766 return TRUE;
1767}
1768
1769/**********************************************************************/
1773 void (*callback)(struct unit *punit))
1774{
1775 /* Tried to overwrite another call back. If this assertion is triggered
1776 * in a case where two call back are needed it may be time to support
1777 * more than one unit removal call back at a time. */
1779
1781}
1782
1783/**********************************************************************/
1790
1791/**********************************************************************/
1795static void server_remove_unit_full(struct unit *punit, bool transported,
1797{
1798 struct packet_unit_remove packet;
1799 struct tile *ptile = unit_tile(punit);
1800 struct city *pcity = tile_city(ptile);
1802 struct unit *ptrans;
1803 struct player *pplayer = unit_owner(punit);
1804
1805 /* The unit is doomed. */
1807
1808#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1809 unit_list_iterate(ptile->units, pcargo) {
1812#endif /* FREECIV_DEBUG */
1813
1814 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1815 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1816
1817 /* Save transporter for updating below. */
1819 /* Unload unit. */
1821
1822 /* Since settlers plot in new cities in the minimap before they
1823 are built, so that no two settlers head towards the same city
1824 spot, we need to ensure this reservation is cleared should
1825 the settler disappear on the way. */
1827
1828 /* Clear the vision before sending unit remove. Else, we might duplicate
1829 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1830 if (punit->server.vision != NULL) {
1834 }
1835
1836 packet.unit_id = punit->id;
1837 /* Send to onlookers. */
1840 transported)) {
1841 lsend_packet_unit_remove(aplayer->connections, &packet);
1842 }
1844 /* Send to global observers. */
1848 }
1850
1851 if (punit->server.moving != NULL) {
1852 /* Do not care of this unit for running moves. */
1854 }
1855
1857 /* Run the unit removal call back. */
1859 }
1860
1861 /* check if this unit had UTYF_GAMELOSS flag */
1863 && ULR_EDITOR != reason) {
1865 _("Unable to defend %s, %s has lost the game."),
1867 player_name(pplayer));
1868 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1869 _("Losing %s meant losing the game! "
1870 "Be more careful next time!"),
1871 unit_link(punit));
1873 }
1874
1877
1880 punit = NULL;
1881
1882 if (NULL != ptrans) {
1883 /* Update the occupy info. */
1885 }
1886
1887 /* This unit may have blocked tiles of adjacent cities. Update them. */
1889 sync_cities();
1890
1891 if (phomecity) {
1894 }
1895
1896 if (pcity && pcity != phomecity) {
1897 city_refresh(pcity);
1898 send_city_info(city_owner(pcity), pcity);
1899 }
1900
1901 if (pcity && unit_list_size(ptile->units) == 0) {
1902 /* The last unit in the city was killed: update the occupied flag. */
1903 send_city_info(NULL, pcity);
1904 }
1905}
1906
1907/**********************************************************************/
1916
1917/**********************************************************************/
1920static void unit_lost_with_transport(const struct player *pplayer,
1921 struct unit *pcargo,
1922 const struct unit_type *ptransport,
1923 struct player *killer)
1924{
1926 _("%s lost when %s was lost."),
1929 /* Unit is not transported any more at this point, but it has jumped
1930 * off the transport and drowns outside. So it must be removed from
1931 * all clients.
1932 * However, we don't know if given client has received ANY updates
1933 * about the swimming unit, and we can't remove it if it's not there
1934 * in the first place -> we send it once here just to be sure it's
1935 * there. */
1938}
1939
1940/**********************************************************************/
1944static void wipe_unit_full(struct unit *punit, bool transported,
1946 struct player *killer)
1947{
1948 struct tile *ptile = unit_tile(punit);
1949 struct player *pplayer = unit_owner(punit);
1950 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1951 struct unit_list *helpless = unit_list_new();
1952 struct unit_list *imperiled = unit_list_new();
1953 struct unit_list *unsaved = unit_list_new();
1955 struct city *pexclcity;
1956 struct civ_map *nmap = &(wld.map);
1957
1958 if (killer != NULL
1961 player_loot_player(killer, pplayer);
1962 }
1963
1964 /* The unit is doomed. */
1966
1967 /* If a unit is being lost due to loss of its city, ensure that we don't
1968 * try to teleport any of its cargo to that city (which may not yet
1969 * have changed hands or disappeared). (It is assumed that the unit's
1970 * home city is always the one that is being lost/transferred/etc.) */
1971 if (reason == ULR_CITY_LOST) {
1973 } else {
1974 pexclcity = NULL;
1975 }
1976
1977 /* Remove unit itself from its transport */
1978 if (ptrans != NULL) {
1981 }
1982
1983 /* First pull all units off of the transporter. */
1985 /* Use iterate_safe as unloaded units will be removed from the list
1986 * while iterating. */
1988 bool healthy = FALSE;
1989
1990 if (!can_unit_unload(pcargo, punit)) {
1992 } else {
1993 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
1995 } else {
1996 /* These units do not need to be saved. */
1997 healthy = TRUE;
1998 }
1999 }
2000
2001 /* Could use unit_transport_unload_send() here, but that would
2002 * call send_unit_info() for the transporter unnecessarily.
2003 * Note that this means that unit might to get seen briefly
2004 * by clients other than owner's, for example as a result of
2005 * update of homecity common to this cargo and some other
2006 * destroyed unit. */
2008 if (pcargo->activity == ACTIVITY_SENTRY) {
2009 /* Activate sentried units - like planes on a disbanded carrier.
2010 * Note this will activate ground units even if they just change
2011 * transporter. */
2013 }
2014
2015 /* Unit info for unhealthy units will be sent when they are
2016 * assigned new transport or removed. */
2017 if (healthy) {
2019 }
2021 }
2022
2023 /* Now remove the unit. */
2024 server_remove_unit_full(punit, transported, reason);
2025
2026 switch (reason) {
2027 case ULR_KILLED:
2028 case ULR_EXECUTED:
2029 case ULR_SDI:
2030 case ULR_NUKE:
2031 case ULR_BRIBED:
2032 case ULR_CAPTURED:
2033 case ULR_CAUGHT:
2034 case ULR_ELIMINATED:
2035 case ULR_TRANSPORT_LOST:
2036 if (killer != NULL) {
2037 killer->score.units_killed++;
2038 }
2039 pplayer->score.units_lost++;
2040 break;
2041 case ULR_BARB_UNLEASH:
2042 case ULR_CITY_LOST:
2043 case ULR_STARVED:
2044 case ULR_UPKEEP:
2045 case ULR_NONNATIVE_TERR:
2046 case ULR_ARMISTICE:
2047 case ULR_HP_LOSS:
2048 case ULR_FUEL:
2049 case ULR_STACK_CONFLICT:
2050 case ULR_SOLD:
2051 pplayer->score.units_lost++;
2052 break;
2053 case ULR_RETIRED:
2054 case ULR_DISBANDED:
2055 case ULR_USED:
2056 case ULR_DETONATED:
2057 case ULR_MISSILE:
2058 pplayer->score.units_used++;
2059 break;
2060 case ULR_EDITOR:
2061 case ULR_PLAYER_DIED:
2062 break;
2063 }
2064
2065 /* First, sort out helpless cargo. */
2066 if (unit_list_size(helpless) > 0) {
2067 struct unit_list *remaining = unit_list_new();
2068
2069 /* Grant priority to gameloss units and units with the EvacuateFirst
2070 * unit type flag. */
2077 pexclcity)) {
2079 }
2080 } else {
2081 unit_list_prepend(remaining, pcargo);
2082 }
2084
2085 /* Handle non-priority units. */
2086 unit_list_iterate_safe(remaining, pcargo) {
2089 }
2091
2092 unit_list_destroy(remaining);
2093 }
2095
2096 /* Then, save any imperiled cargo. */
2097 if (unit_list_size(imperiled) > 0) {
2098 struct unit_list *remaining = unit_list_new();
2099
2100 /* Grant priority to gameloss units and units with the EvacuateFirst
2101 * unit type flag. */
2108 pexclcity)) {
2110 }
2111 } else {
2112 unit_list_prepend(remaining, pcargo);
2113 }
2115
2116 /* Handle non-priority units. */
2117 unit_list_iterate_safe(remaining, pcargo) {
2120 }
2122
2123 unit_list_destroy(remaining);
2124 }
2126
2127 /* Finally, kill off the unsaved units. */
2128 if (unit_list_size(unsaved) > 0) {
2132 }
2134}
2135
2136/**********************************************************************/
2145
2146/**********************************************************************/
2152static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2153 bool helpless, bool teleporting,
2154 const struct city *pexclcity)
2155{
2156 struct tile *ptile = unit_tile(punit);
2157 struct player *pplayer = unit_owner(punit);
2159
2160 /* Helpless units cannot board a transport in their current state. */
2161 if (!helpless
2162 && ptransport != NULL) {
2165 return TRUE;
2166 } else {
2167 /* Only units that cannot find transport are considered for teleport. */
2168 if (teleporting) {
2169 struct city *pcity = find_closest_city(ptile, pexclcity,
2173 if (pcity != NULL) {
2174 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2175
2177
2178 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2179 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2180 _("%s escaped the destruction of %s, and fled to %s."),
2181 tplink,
2183 city_link(pcity));
2184 return TRUE;
2185 }
2186 }
2187 }
2188 }
2189
2190 /* The unit could not use transport on the tile, and could not teleport. */
2191 return FALSE;
2192}
2193
2194/**********************************************************************/
2200struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2202{
2203 struct unit *gained_unit;
2204 int id = 0;
2205
2206#ifndef FREECIV_NDEBUG
2207 bool placed;
2208#endif
2209
2212
2213 /* Convert the unit to your cause. It's supposed that the original unit
2214 * is on a valid tile and is not transported. */
2218 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2219
2220 /* Owner changes, nationality not. */
2221 gained_unit->nationality = punit->nationality;
2222
2223 /* Copy some more unit fields */
2224 gained_unit->fuel = punit->fuel;
2225 gained_unit->paradropped = punit->paradropped;
2226 gained_unit->birth_turn = punit->birth_turn;
2227 gained_unit->current_form_turn = punit->current_form_turn;
2228
2229 /* Fog is lifted in the placing algorithm. */
2230#ifndef FREECIV_NDEBUG
2231 placed =
2232#endif
2233 place_unit(gained_unit, pplayer,
2235 NULL, FALSE);
2236
2238
2239 id = gained_unit->id;
2240
2241 /* Update unit upkeep in the new homecity */
2242 if (homecity > 0) {
2244 }
2245
2246 /* Be sure to wipe the converted unit! */
2247 /* Old homecity upkeep is updated in process */
2248#ifndef FREECIV_NDEBUG
2249 uco_wipe:
2250#endif
2251
2253
2254 if (!unit_is_alive(id)) {
2255 /* Destroyed by a script */
2256 return NULL;
2257 }
2258
2259 return gained_unit; /* Returns the replacement. */
2260}
2261
2262/**********************************************************************/
2267void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2268{
2270 struct player *pvictim = unit_owner(punit);
2271 struct player *pvictor = unit_owner(pkiller);
2272 struct tile *deftile = unit_tile(punit);
2273 int unitcount = 0;
2274 bool escaped;
2277 const struct civ_map *nmap = &(wld.map);
2278
2281
2282 /* The unit is doomed. */
2284
2286 if ((flagless_killer
2290 unitcount++;
2291 }
2293
2294 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2295 if (vet) {
2297 }
2299 } else { /* Unitcount > 1 */
2300 int i;
2301 int slots = player_slot_count();
2302 int num_killed[slots];
2303 int num_escaped[slots];
2304 struct unit *other_killed[slots];
2305
2306 fc_assert(unitcount > 1);
2307
2308 /* Initialize */
2309 for (i = 0; i < slots; i++) {
2310 num_killed[i] = 0;
2311 other_killed[i] = NULL;
2312 num_escaped[i] = 0;
2313 }
2314
2315 /* Count killed units */
2317 struct player *vplayer = unit_owner(vunit);
2318
2321 escaped = FALSE;
2322
2325 && vunit->hp > 0
2326 && vunit->moves_left > pkiller->moves_left
2327 && fc_rand(2)) {
2328 int curr_def_bonus;
2329 int def_bonus = 0;
2330 struct tile *dsttile = NULL;
2331 int move_cost;
2332
2333 fc_assert(vunit->hp > 0);
2334
2336 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2337 && NULL == tile_city(ptile2)) {
2338 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2339 if (pkiller->moves_left <= vunit->moves_left - move_cost
2341 || unit_list_size(ptile2->units)) == 0) {
2343 vunit->utype);
2344 if (def_bonus <= curr_def_bonus) {
2346 dsttile = ptile2;
2347 }
2348 }
2349 }
2351
2352 if (dsttile != NULL) {
2355 NULL, NULL, dsttile,
2357 NULL, NULL)
2358 != NULL);
2359
2360 if (escaped) {
2362 unitcount--;
2363 }
2364 }
2365 }
2366
2367 if (!escaped) {
2369
2370 if (vunit != punit) {
2373 }
2374 }
2375 }
2377
2378 /* Inform the destroyer again if more than one unit was killed */
2379 if (unitcount > 1) {
2380 if (flagless_victim) {
2382 /* TRANS: "... Cannon ... Destroyer ...." */
2383 PL_("Your attacking %s succeeded against %s "
2384 "(and %d other unit)!",
2385 "Your attacking %s succeeded against %s "
2386 "(and %d other units)!", unitcount - 1),
2388 punit_link,
2389 unitcount - 1);
2390 } else {
2392 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2393 PL_("Your attacking %s succeeded against the %s %s "
2394 "(and %d other unit)!",
2395 "Your attacking %s succeeded against the %s %s "
2396 "(and %d other units)!", unitcount - 1),
2399 punit_link,
2400 unitcount - 1);
2401 }
2402 }
2403
2404 if (vet) {
2406 }
2407
2408 /* Inform the owners: this only tells about owned units that were killed.
2409 * there may have been 20 units who died but if only 2 belonged to the
2410 * particular player they'll only learn about those.
2411 *
2412 * Also if a large number of units die you don't find out what type
2413 * they all are. */
2414 for (i = 0; i < slots; i++) {
2415 if (num_killed[i] == 1) {
2416 if (i == player_index(pvictim)) {
2418
2419 if (flagless_killer) {
2422 /* TRANS: "Cannon ... Destroyer." */
2423 _("%s lost to an attack by %s."),
2424 punit_link,
2425 pkiller_link);
2426 } else {
2429 /* TRANS: "Cannon ... the Polish Destroyer." */
2430 _("%s lost to an attack by the %s %s."),
2431 punit_link,
2433 pkiller_link);
2434 }
2435 } else {
2437
2438 if (flagless_victim) {
2439 if (flagless_killer) {
2442 /* TRANS: "Cannon lost when Destroyer
2443 * attacked Musketeers." */
2444 _("%s lost when %s attacked %s."),
2447 punit_link);
2448 } else {
2451 /* TRANS: "Cannon lost when the Polish Destroyer
2452 * attacked Musketeers." */
2453 _("%s lost when the %s %s attacked %s."),
2457 punit_link);
2458 }
2459 } else {
2460 if (flagless_killer) {
2463 /* TRANS: "Cannon lost when Destroyer
2464 * attacked the German Musketeers." */
2465 _("%s lost when %s attacked the %s %s."),
2469 punit_link);
2470 } else {
2473 /* TRANS: "Cannon lost when the Polish Destroyer
2474 * attacked the German Musketeers." */
2475 _("%s lost when the %s %s attacked the %s %s."),
2480 punit_link);
2481 }
2482 }
2483 }
2484 } else if (num_killed[i] > 1) {
2485 if (i == player_index(pvictim)) {
2486 int others = num_killed[i] - 1;
2487
2488 if (others == 1) {
2489 if (flagless_killer) {
2492 /* TRANS: "Musketeers (and Cannon) lost to an
2493 * attack from Destroyer." */
2494 _("%s (and %s) lost to an attack from %s."),
2495 punit_link,
2497 pkiller_link);
2498 } else {
2501 /* TRANS: "Musketeers (and Cannon) lost to an
2502 * attack from the Polish Destroyer." */
2503 _("%s (and %s) lost to an attack from the %s %s."),
2504 punit_link,
2507 pkiller_link);
2508 }
2509 } else {
2510 if (flagless_killer) {
2513 /* TRANS: "Musketeers and 3 other units lost to
2514 * an attack from Destroyer."
2515 * (only happens with at least 2 other units) */
2516 PL_("%s and %d other unit lost to an attack "
2517 "from %s.",
2518 "%s and %d other units lost to an attack "
2519 "from %s.", others),
2520 punit_link,
2521 others,
2522 pkiller_link);
2523 } else {
2526 /* TRANS: "Musketeers and 3 other units lost to
2527 * an attack from the Polish Destroyer."
2528 * (only happens with at least 2 other units) */
2529 PL_("%s and %d other unit lost to an attack "
2530 "from the %s %s.",
2531 "%s and %d other units lost to an attack "
2532 "from the %s %s.", others),
2533 punit_link,
2534 others,
2536 pkiller_link);
2537 }
2538 }
2539 } else {
2540 if (flagless_victim) {
2541 if (flagless_killer) {
2544 /* TRANS: "2 units lost when Destroyer
2545 * attacked Musketeers."
2546 * (only happens with at least 2 other units) */
2547 PL_("%d unit lost when %s attacked %s.",
2548 "%d units lost when %s attacked %s.",
2549 num_killed[i]),
2550 num_killed[i],
2552 punit_link);
2553 } else {
2556 /* TRANS: "2 units lost when the Polish Destroyer
2557 * attacked Musketeers."
2558 * (only happens with at least 2 other units) */
2559 PL_("%d unit lost when the %s %s attacked %s.",
2560 "%d units lost when the %s %s attacked %s.",
2561 num_killed[i]),
2562 num_killed[i],
2565 punit_link);
2566 }
2567 } else {
2568 if (flagless_killer) {
2571 /* TRANS: "2 units lost when Destroyer
2572 * attacked the German Musketeers."
2573 * (only happens with at least 2 other units) */
2574 PL_("%d unit lost when %s attacked the %s %s.",
2575 "%d units lost when %s attacked the %s %s.",
2576 num_killed[i]),
2577 num_killed[i],
2580 punit_link);
2581 } else {
2584 /* TRANS: "2 units lost when the Polish Destroyer
2585 * attacked the German Musketeers."
2586 * (only happens with at least 2 other units) */
2587 PL_("%d unit lost when the %s %s attacked the %s %s.",
2588 "%d units lost when the %s %s attacked the %s %s.",
2589 num_killed[i]),
2590 num_killed[i],
2594 punit_link);
2595 }
2596 }
2597 }
2598 }
2599 }
2600
2601 /* Inform the owner of the units that escaped.
2602 * 'deftile' is the original tile they defended at, not where
2603 * they escaped to, as there might be multiple different tiles
2604 * different units escaped to. */
2605 for (i = 0; i < slots; i++) {
2606 if (0 < num_escaped[i]) {
2607 if (flagless_killer) {
2610 PL_("%d unit escaped from attack by %s",
2611 "%d units escaped from attack by %s",
2612 num_escaped[i]),
2613 num_escaped[i],
2614 pkiller_link);
2615 } else {
2618 PL_("%d unit escaped from attack by %s %s",
2619 "%d units escaped from attack by %s %s",
2620 num_escaped[i]),
2621 num_escaped[i],
2623 nation_adjective_for_player(pkiller->nationality));
2624 }
2625 }
2626 }
2627
2628 /* Remove the units - note the logic of which units actually die
2629 * must be mimiced exactly in at least one place up above. */
2630 punit = NULL; /* Wiped during following iteration so unsafe to use */
2631
2636 }
2638 }
2639}
2640
2641/**********************************************************************/
2644void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2645{
2646 struct player *pvictim = unit_owner(punit);
2649 struct tile *deftile = unit_tile(punit);
2650 int unitcount, ransom;
2651
2652 /* The unit is doomed. */
2654
2657
2658 if (pvictim->economic.gold < ransom) {
2659 ransom = pvictim->economic.gold;
2660 }
2661
2663 PL_("%d Barbarian leader captured.",
2664 "%d Barbarian leaders captured.",
2665 unitcount),
2666 unitcount);
2668 PL_("%d gold ransom paid.",
2669 "%d gold ransom paid.",
2670 ransom),
2671 ransom);
2672 pvictor->economic.gold += ransom;
2673 pvictim->economic.gold -= ransom;
2674 send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */
2675
2676 if (vet) {
2678 }
2679
2682
2683 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2685 } else {
2686 int i;
2687 int slots = player_slot_count();
2688 int num_collected[slots];
2689
2690 fc_assert(unitcount > 1);
2691
2692 /* Initialize */
2693 for (i = 0; i < slots; i++) {
2694 num_collected[i] = 0;
2695 }
2696
2697 /* Count captured units */
2699 struct player *vplayer = unit_owner(vunit);
2700
2703
2704 for (i = 0; i < slots; i++) {
2705 if (num_collected[i] == 1) {
2708 _("%s %s collected ransom of %s."),
2711 } else if (num_collected[i] > 1) {
2714 PL_("%s %s collected ransom of %s and %d other unit.",
2715 "%s %s collected ransom of %s and %d other units.",
2716 num_collected[i] - 1),
2719 punit_link,
2720 num_collected[i] - 1);
2721 }
2722 }
2723
2727 }
2728}
2729
2730/**********************************************************************/
2734void package_unit(struct unit *punit, struct packet_unit_info *packet)
2735{
2736 packet->id = punit->id;
2737 packet->owner = player_number(unit_owner(punit));
2739 packet->tile = tile_index(unit_tile(punit));
2740 packet->facing = punit->facing;
2741 packet->homecity = punit->homecity;
2743 packet->upkeep[o] = punit->upkeep[o];
2745 packet->veteran = punit->veteran;
2747 packet->movesleft = punit->moves_left;
2748 packet->hp = punit->hp;
2749 packet->activity = punit->activity;
2751
2752 if (punit->activity_target != NULL) {
2754 } else {
2755 packet->activity_tgt = EXTRA_NONE;
2756 }
2757
2758 packet->changed_from = punit->changed_from;
2760
2761 if (punit->changed_from_target != NULL) {
2763 } else {
2764 packet->changed_from_tgt = EXTRA_NONE;
2765 }
2766
2768 packet->fuel = punit->fuel;
2769 packet->goto_tile = (NULL != punit->goto_tile
2770 ? tile_index(punit->goto_tile) : -1);
2771 packet->paradropped = punit->paradropped;
2772 packet->done_moving = punit->done_moving;
2773 packet->stay = punit->stay;
2774 packet->birth_turn = punit->birth_turn;
2776 if (!unit_transported(punit)) {
2777 packet->transported = FALSE;
2778 packet->transported_by = 0;
2779 } else {
2780 packet->transported = TRUE;
2782 }
2783 if (punit->carrying != NULL) {
2784 packet->carrying = goods_index(punit->carrying);
2785 } else {
2786 packet->carrying = -1;
2787 }
2788 packet->occupied = (get_transporter_occupancy(punit) > 0);
2789 packet->battlegroup = punit->battlegroup;
2790 packet->has_orders = punit->has_orders;
2791 if (punit->has_orders) {
2792 packet->orders_length = punit->orders.length;
2793 packet->orders_index = punit->orders.index;
2794 packet->orders_repeat = punit->orders.repeat;
2796 memcpy(packet->orders, punit->orders.list,
2797 punit->orders.length * sizeof(struct unit_order));
2798 } else {
2799 packet->orders_length = packet->orders_index = 0;
2800 packet->orders_repeat = packet->orders_vigilant = FALSE;
2801 /* No need to initialize array. */
2802 }
2803
2808}
2809
2810/**********************************************************************/
2816 struct packet_unit_short_info *packet,
2817 enum unit_info_use packet_use, int info_city_id)
2818{
2819 packet->packet_use = packet_use;
2820 packet->info_city_id = info_city_id;
2821
2822 packet->id = punit->id;
2823
2825 packet->owner = OWNER_NONE;
2826 } else {
2827 packet->owner = player_number(unit_owner(punit));
2828 }
2829
2830 packet->tile = tile_index(unit_tile(punit));
2831 packet->facing = punit->facing;
2832 packet->veteran = punit->veteran;
2834 packet->hp = punit->hp;
2835 packet->occupied = (get_transporter_occupancy(punit) > 0);
2837 || punit->activity == ACTIVITY_GOTO) {
2838 packet->activity = ACTIVITY_IDLE;
2839 } else {
2840 packet->activity = punit->activity;
2841 }
2842
2843 if (punit->activity_target == nullptr) {
2844 packet->activity_tgt = EXTRA_NONE;
2845 } else {
2847 }
2848
2849 /* Transported_by information is sent to the client even for units that
2850 * aren't fully known. Note that for non-allied players, any transported
2851 * unit can't be seen at all. For allied players we have to know if
2852 * transporters have room in them so that we can load units properly. */
2853 if (!unit_transported(punit)) {
2854 packet->transported = FALSE;
2855 packet->transported_by = 0;
2856 } else {
2857 packet->transported = TRUE;
2859 }
2860}
2861
2862/**********************************************************************/
2865void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2866{
2868 if (punit->server.moving != NULL) {
2869 /* Update status of 'pplayer' vision for 'punit'. */
2871 }
2872}
2873
2874/**********************************************************************/
2878void send_unit_info(struct conn_list *dest, struct unit *punit)
2879{
2880 const struct player *powner;
2881 struct packet_unit_info info;
2883 struct unit_move_data *pdata;
2884
2885 if (dest == NULL) {
2886 dest = game.est_connections;
2887 }
2888
2890
2892 package_unit(punit, &info);
2895
2896 conn_list_iterate(dest, pconn) {
2897 struct player *pplayer = conn_get_player(pconn);
2898
2899 /* Be careful to consider all cases where pplayer is NULL... */
2900 if (pplayer == NULL) {
2901 if (pconn->observer) {
2903 }
2904 } else if (pplayer == powner) {
2906 if (pdata != NULL) {
2907 BV_SET(pdata->can_see_unit, player_index(pplayer));
2908 }
2909 } else if (can_player_see_unit(pplayer, punit)) {
2911 if (pdata != NULL) {
2912 BV_SET(pdata->can_see_unit, player_index(pplayer));
2913 }
2914 }
2916}
2917
2918/**********************************************************************/
2923{
2924 conn_list_do_buffer(dest);
2925 conn_list_iterate(dest, pconn) {
2926 struct player *pplayer = pconn->playing;
2927
2928 if (NULL == pplayer && !pconn->observer) {
2929 continue;
2930 }
2931
2934 send_unit_info(dest, punit);
2937 }
2940 flush_packets();
2941}
2942
2943/**********************************************************************/
2950static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2951 const struct action *paction)
2952{
2953 struct city *pcity = NULL;
2954 int pop_loss;
2955
2956 pcity = tile_city(ptile);
2957
2959
2960 /* unit in a city may survive */
2961 if (pcity && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2962 continue;
2963 }
2965 _("Your %s was nuked by %s."),
2967 pplayer == unit_owner(punit)
2968 ? _("yourself")
2969 : nation_plural_for_player(pplayer));
2970 if (unit_owner(punit) != pplayer) {
2971 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2972 _("The %s %s was nuked."),
2975 }
2976 wipe_unit(punit, ULR_NUKE, pplayer);
2978
2979
2980 if (pcity) {
2981 struct player *owner = city_owner(pcity);
2982 char city_name[MAX_LEN_LINK];
2983
2985
2987 _("%s was nuked by %s."),
2988 city_name,
2989 pplayer == owner
2990 ? _("yourself")
2991 : nation_plural_for_player(pplayer));
2992
2993 if (owner != pplayer) {
2994 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2995 _("You nuked %s."),
2996 city_name);
2997 }
2998
2999 pop_loss = round((game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100.0);
3000 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
3001 /* Send city size reduction to everyone seeing it */
3002 send_city_info(NULL, pcity);
3003 } else {
3004 /* City was destroyed */
3006 _("%s was destroyed by the nuke."),
3007 city_name);
3008 if (owner != pplayer) {
3009 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3010 _("Your nuke destroyed %s."),
3011 city_name);
3012 }
3013 }
3014 }
3015
3016 if (fc_rand(2) == 1) {
3017 struct extra_type *pextra;
3018
3019 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
3020 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
3021 tile_add_extra(ptile, pextra);
3022 update_tile_knowledge(ptile);
3023 }
3024 }
3025}
3026
3027/**********************************************************************/
3036 const struct unit_type *act_utype,
3037 struct player *pplayer, struct tile *ptile)
3038{
3041 &(const struct req_context) {
3042 .player = pplayer,
3043 /* City: Wait for users before choosing
3044 * home city or target tile city */
3045 .tile = ptile,
3046 .unittype = act_utype,
3047 .action = paction,
3048 },
3049 NULL,
3051
3053 do_nuke_tile(pplayer, ptile1, paction);
3055
3056 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
3057 API_TYPE_PLAYER, pplayer);
3059 _("The %s detonated a nuke!"),
3060 nation_plural_for_player(pplayer));
3061}
3062
3063/**********************************************************************/
3067bool do_airline(struct unit *punit, struct city *pdest_city,
3068 const struct action *paction)
3069{
3071
3074 _("%s transported successfully."),
3075 unit_link(punit));
3076
3079 /* Can only airlift to allied and domestic cities */
3080 FALSE, FALSE,
3081 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3083
3084 /* Update airlift fields. */
3086 psrc_city->airlift--;
3088 }
3090 pdest_city->airlift--;
3092 }
3093
3094 return TRUE;
3095}
3096
3097/**********************************************************************/
3100void do_explore(struct unit *punit)
3101{
3102 switch (manage_auto_explorer(punit)) {
3103 case MR_DEATH:
3104 /* don't use punit! */
3105 return;
3106 case MR_NOT_ALLOWED:
3107 /* Needed for something else */
3108 return;
3109 case MR_OK:
3110 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3111 * but don't count on this. See PR#39792.
3112 */
3114 break;
3115 }
3116
3118 default:
3120
3121 /* FIXME: When the manage_auto_explorer() call changes the activity from
3122 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3123 * alone. We reset it here. See PR#12931. */
3125 break;
3126 }
3127
3128 send_unit_info(NULL, punit); /* Probably duplicate */
3129}
3130
3131/**********************************************************************/
3136bool do_paradrop(struct unit *punit, struct tile *ptile,
3137 const struct action *paction)
3138{
3139 struct player *pplayer = unit_owner(punit);
3140 struct player *tgt_player = tile_owner(ptile);
3141 const struct unit_type *act_utype = unit_type_get(punit);
3142 const struct city *pcity;
3143
3144 /* Hard requirements */
3145 /* FIXME: hard requirements belong in common/actions's
3146 * is_action_possible() and the explanation texts belong in
3147 * server/unithand's action not enabled system (expl_act_not_enabl(),
3148 * ane_kind, explain_why_no_action_enabled(), etc)
3149 */
3150 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3151 /* Only take in account values from player map. */
3152 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3153
3154 if (NULL == plrtile->site) {
3155 bv_extras fbv;
3156
3157 dbv_to_bv(fbv.vec, &(plrtile->extras));
3158
3160 &fbv)) {
3161 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3162 _("This unit cannot paradrop into %s."),
3164 return FALSE;
3165 }
3166 }
3167
3168 if (NULL != plrtile->site
3169 && plrtile->owner != NULL
3170 && !pplayers_allied(pplayer, plrtile->owner)
3172 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3173 /* TRANS: Paratroopers ... Paradrop Unit */
3174 _("%s cannot conquer a city with \"%s\"."),
3177 return FALSE;
3178 }
3179
3180 if (NULL != plrtile->site
3181 && plrtile->owner != NULL
3182 && (pplayers_non_attack(pplayer, plrtile->owner)
3183 || (player_diplstate_get(pplayer, plrtile->owner)->type
3184 == DS_ALLIANCE)
3185 || (player_diplstate_get(pplayer, plrtile->owner)->type
3186 == DS_TEAM))
3188 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3189 _("Cannot attack unless you declare war first."));
3190 return FALSE;
3191 }
3192 }
3193
3194
3195 /* Kill the unit when the landing goes wrong. */
3196
3197 /* Safe terrain, really? Not transformed since player last saw it. */
3198 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3199 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3200 || !unit_could_load_at(punit, ptile))) {
3201 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3202 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3203 _("Your %s paradropped into the %s and was lost."),
3206 pplayer->score.units_lost++;
3208 return TRUE;
3209 }
3210
3211 pcity = tile_city(ptile);
3212
3213 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3215 || is_non_allied_unit_tile(ptile, pplayer,
3217 struct player *main_victim = NULL;
3218 struct player *secondary_victim = NULL;
3220
3221 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3222 unit_make_contact(punit, ptile, pplayer);
3223 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3224 _("Your %s was killed by enemy units at the "
3225 "paradrop destination."),
3227 /* TODO: Should defender score.units_killed get increased too?
3228 * What if there's units of several allied players? Should the
3229 * city owner or owner of the first/random unit get the kill? */
3230 pplayer->score.units_lost++;
3231
3232 if (pcity != NULL) {
3233 struct player *owner = city_owner(pcity);
3234
3235 if (!pplayers_at_war(pplayer, owner)) {
3237 } else {
3239 }
3240
3242 } else {
3244 }
3245
3246 if (main_victim == NULL) {
3247 unit_list_iterate(ptile->units, tgt) {
3248 struct player *owner = unit_owner(tgt);
3249
3250 if (!pplayers_at_war(pplayer, owner)) {
3252 break;
3253 } else if (secondary_victim == NULL) {
3255 }
3257
3258 if (main_victim == NULL) {
3259 /* There's no victim with whom the attacker isn't in war,
3260 * fallback to one with whom there's already a war. */
3262 }
3263 }
3264
3266 main_victim, ptile,
3267 victim_link);
3268
3270 return TRUE;
3271 }
3272
3273 /* All ok */
3275 if (unit_move(punit, ptile,
3276 /* Done by Action_Success_Actor_Move_Cost */
3277 0,
3278 NULL, BV_ISSET(paction->sub_results,
3282 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3283 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3284 /* Ensure we finished on valid state. */
3287 }
3288
3289 /* May cause an incident */
3291 ptile, tile_link(ptile));
3292
3293 return TRUE;
3294}
3295
3296/**********************************************************************/
3300static bool hut_get_limited(struct unit *punit)
3301{
3302 bool ok = TRUE;
3303 int hut_chance = fc_rand(12);
3304 struct player *pplayer = unit_owner(punit);
3305 /* 1 in 12 to get barbarians */
3306 if (hut_chance != 0) {
3307 int cred = 25;
3309 PL_("You found %d gold.",
3310 "You found %d gold.", cred), cred);
3311 pplayer->economic.gold += cred;
3314 notify_player(pplayer, unit_tile(punit),
3316 _("An abandoned village is here."));
3317 } else {
3319 _("Your %s has been killed by barbarians!"),
3322 ok = FALSE;
3323 }
3324 return ok;
3325}
3326
3327/**********************************************************************/
3331static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3332{
3333 struct player *pplayer = unit_owner(punit);
3334 int id = punit->id;
3335 struct tile *ptile = unit_tile(punit);
3336 bool hut = FALSE;
3337 const struct req_context context = {
3338 .player = pplayer,
3339 .tile = ptile,
3340 };
3341
3343 if (tile_has_extra(ptile, pextra)
3345 &(const struct req_context) {
3346 .player = tile_owner(ptile),
3347 },
3348 &pextra->rmreqs,
3350 ) {
3351 hut = TRUE;
3352 /* FIXME: are all enter-removes extras worth counting? */
3353 pplayer->server.huts++;
3354
3355 destroy_extra(ptile, pextra);
3357
3358 /* FIXME: enable different classes
3359 * to behave differently with different huts */
3360 if (frighten_hut) {
3361 script_server_signal_emit("hut_frighten", punit,
3362 extra_rule_name(pextra));
3363 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3364 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3366 } else {
3367 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3368 }
3369
3370 /* We need punit for the callbacks, can't continue if the unit died */
3371 if (!unit_is_alive(id)) {
3372 break;
3373 }
3374 }
3376
3377 if (hut) {
3378 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3379 }
3380 return;
3381}
3382
3383/**********************************************************************/
3387{
3388 bv_player can_see_unit;
3389
3392
3393 BV_CLR_ALL(can_see_unit);
3394 players_iterate(pplayer) {
3395 if (can_player_see_unit(pplayer, punit)) {
3396 BV_SET(can_see_unit, player_index(pplayer));
3397 }
3399
3401
3402 players_iterate(pplayer) {
3403 if (BV_ISSET(can_see_unit, player_index(pplayer))
3404 && !can_player_see_unit(pplayer, punit)) {
3405 unit_goes_out_of_sight(pplayer, punit);
3406 }
3408
3411}
3412
3413/**********************************************************************/
3417 struct unit *ptrans,
3418 bool force)
3419{
3420 bool had_cargo;
3421
3424
3426
3428
3429 if (!had_cargo) {
3430 /* Transport's loaded status changed */
3432 }
3433}
3434
3435/**********************************************************************/
3439{
3440 struct unit *ptrans;
3441
3443
3445
3447
3449
3452}
3453
3454/**********************************************************************/
3458static void autoattack_prob_free(struct autoattack_prob *prob)
3459{
3460 free(prob);
3461}
3462
3463/**********************************************************************/
3472static int compare_units(const struct autoattack_prob *const *p1,
3473 const struct autoattack_prob *const *q1)
3474{
3475 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3476 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3477
3478 /* Sort by transport depth first. This makes sure that no transport
3479 * attacks before its cargo does -- cargo sorts earlier in the list. */
3480 {
3481 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3482
3483 /* Walk the transport stacks in parallel, so as to bail out as soon as
3484 * one of them is empty (avoid walking deep stacks more often than
3485 * necessary). */
3486 while (p1trans && q1trans) {
3489 }
3490 if (!p1trans && q1trans) {
3491 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3492 * earlier in the list (p1 > q1). */
3493 return 1;
3494 } else if (p1trans && !q1trans) {
3495 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3496 return -1;
3497 }
3498 /* else same depth, so move on to checking win chance: */
3499 }
3500
3501 /* Put the units with the highest probability of success first. The up
3502 * side of this is that units with bonuses against the victim attacks
3503 * before other units. The downside is that strong units can be led
3504 * away by sacrificial units. */
3505 return (-1
3506 /* Assume the worst. */
3507 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3508}
3509
3510/**********************************************************************/
3515{
3516 struct autoattack_prob_list *autoattack;
3517 int moves = punit->moves_left;
3518 int sanity1 = punit->id;
3519 struct civ_map *nmap = &(wld.map);
3520
3521 if (!game.server.autoattack) {
3522 return TRUE;
3523 }
3524
3526
3527 /* Kludge to prevent attack power from dropping to zero during calc */
3529
3530 adjc_iterate(nmap, unit_tile(punit), ptile) {
3531 /* First add all eligible units to a autoattack list */
3532 unit_list_iterate(ptile->units, penemy) {
3534 struct tile *tgt_tile = unit_tile(punit);
3535
3536 fc_assert_action(tgt_tile, continue);
3537
3538 probability->prob =
3542 punit, NULL);
3543
3544 if (action_prob_possible(probability->prob)) {
3545 probability->unit_id = penemy->id;
3547 } else {
3549 }
3552
3553 /* Sort the potential attackers from highest to lowest success
3554 * probability. */
3555 if (autoattack_prob_list_size(autoattack) >= 2) {
3557 }
3558
3560 int sanity2 = penemy->id;
3561 struct tile *ptile = unit_tile(penemy);
3562 struct unit *enemy_defender = get_defender(nmap, punit, ptile, NULL);
3563 double punitwin, penemywin;
3564 double threshold = 0.25;
3565 struct tile *tgt_tile = unit_tile(punit);
3566
3568
3569 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3570 /* Don't leave city defenseless */
3571 threshold = 0.90;
3572 }
3573
3574 if (NULL != enemy_defender) {
3576 } else {
3577 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3578 punitwin = 1.0;
3579 }
3580
3581 /* Previous attacks may have changed the odds. Recalculate. */
3582 peprob->prob =
3586 punit, NULL);
3587
3588 if (!action_prob_possible(peprob->prob)) {
3589 /* No longer legal. */
3590 continue;
3591 }
3592
3593 /* Assume the worst. */
3595
3596 if ((penemywin > 1.0 - punitwin
3598 && penemywin > threshold) {
3599
3600#ifdef REALLY_DEBUG_THIS
3601 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3604 1.0 - punitwin, threshold);
3605#endif
3606
3611 } else {
3612#ifdef REALLY_DEBUG_THIS
3613 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3616 1.0 - punitwin, threshold);
3617#endif
3618 continue;
3619 }
3620
3623 }
3626 } else {
3627 autoattack_prob_list_destroy(autoattack);
3628 return FALSE; /* moving unit dead */
3629 }
3631
3632 autoattack_prob_list_destroy(autoattack);
3634 /* We could have lost movement in combat */
3637 return TRUE;
3638 } else {
3639 return FALSE;
3640 }
3641}
3642
3643/**********************************************************************/
3646static void cancel_orders(struct unit *punit, char *dbg_msg)
3647{
3650 log_debug("%s", dbg_msg);
3651}
3652
3653/**********************************************************************/
3658{
3659 bool alone_in_city;
3660
3661 if (NULL != tile_city(unit_tile(punit))) {
3662 int count = 0;
3663
3665 /* Consider only units not transported. */
3666 if (!unit_transported(aunit)) {
3667 count++;
3668 }
3670
3671 alone_in_city = (1 == count);
3672 } else {
3674 }
3675
3676 /* There may be sentried units with a sightrange > 3, but we don't
3677 wake them up if the punit is farther away than 3. */
3678 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3679 unit_list_iterate(ptile->units, penemy) {
3681 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3682
3684 && penemy->activity == ACTIVITY_SENTRY
3685 && radius_sq >= distance_sq
3686 /* If the unit moved on a city, and the unit is alone, consider
3687 * it is visible. */
3688 && (alone_in_city
3690 /* on board transport; don't awaken */
3694 }
3697
3698 /* Wakeup patrolling units we bump into.
3699 We do not wakeup units further away than 3 squares... */
3700 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3701 unit_list_iterate(ptile->units, ppatrol) {
3702 if (punit != ppatrol
3704 && ppatrol->orders.vigilant) {
3706 cancel_orders(ppatrol, " stopping because of nearby enemy");
3709 _("Orders for %s aborted after enemy movement was "
3710 "spotted."),
3712 }
3713 }
3716}
3717
3718/**********************************************************************/
3728 struct tile *src_tile,
3729 struct tile *dst_tile,
3730 bool passenger,
3732{
3733 struct city *fromcity = tile_city(src_tile);
3734 struct city *tocity = tile_city(dst_tile);
3735 struct city *homecity_start_pos = NULL;
3736 struct city *homecity_end_pos = NULL;
3742 const struct unit_type *type_end_pos = type_start_pos;
3745 int saved_id = punit->id;
3746 bool alive = TRUE;
3747 const struct civ_map *nmap = &(wld.map);
3748
3750 if (!passenger) {
3751 /* The unit that does the move may conquer. */
3753 }
3754
3755 /* Run for passengers too. A passenger may have been killed when its
3756 * transport conquered a city. (unit_conquer_city() can cause Lua code
3757 * to run) */
3758
3760 if (alive) {
3761 /* In case script has changed something about unit */
3765 }
3766 }
3767
3768 if (homecity_id_start_pos != 0) {
3770 }
3773 } else {
3775 }
3776
3777 /* We only do refreshes for non-AI players to now make sure the AI turns
3778 doesn't take too long. Perhaps we should make a special refresh_city
3779 functions that only refreshed happines. */
3780
3781 /* might have changed owners or may be destroyed */
3783
3784 if (tocity) { /* entering a city */
3785 if (tocity->owner == pplayer_end_pos) {
3789 }
3790 }
3791 if (homecity_start_pos) {
3793 }
3794 }
3795
3796 if (fromcity) { /* leaving a city */
3797 if (homecity_start_pos) {
3799 }
3801 && fromcity->owner == pplayer_start_pos
3805 }
3806 }
3807
3808 /* Entering/leaving a fortress or friendly territory */
3810 bool friendly_end = FALSE;
3811
3814 } else {
3816 type_end_pos);
3817
3818 if (max_friendliness_range >= 0
3821 } else {
3824
3825 if (max_friendliness_range >= 0
3828 }
3829 }
3830 }
3831
3832 if (friendly_end) {
3835 }
3836 }
3837
3841 }
3848 }
3849
3851 sync_cities();
3852
3853 return alive;
3854}
3855
3856/**********************************************************************/
3860static void check_unit_activity(struct unit *punit)
3861{
3862 switch (punit->activity) {
3863 case ACTIVITY_IDLE:
3864 case ACTIVITY_SENTRY:
3865 case ACTIVITY_EXPLORE:
3866 case ACTIVITY_GOTO:
3867 break;
3868 case ACTIVITY_CLEAN:
3869 case ACTIVITY_MINE:
3870 case ACTIVITY_IRRIGATE:
3871 case ACTIVITY_CULTIVATE:
3872 case ACTIVITY_PLANT:
3873 case ACTIVITY_FORTIFIED:
3874 case ACTIVITY_PILLAGE:
3875 case ACTIVITY_TRANSFORM:
3877 case ACTIVITY_BASE:
3878 case ACTIVITY_GEN_ROAD:
3879 case ACTIVITY_CONVERT:
3880 case ACTIVITY_LAST:
3882 break;
3883 };
3884}
3885
3886/**********************************************************************/
3890 const struct tile *psrctile,
3891 const struct tile *pdesttile)
3892{
3893 struct unit_move_data *pdata;
3894 struct player *powner = unit_owner(punit);
3895
3896 if (punit->server.moving) {
3897 /* Recursive moving (probably due to a script). */
3899 pdata->ref_count++;
3900 fc_assert_msg(pdata->punit == punit,
3901 "Unit number %d (%p) was going to die, but "
3902 "server attempts to move it.",
3903 punit->id, punit);
3904 fc_assert_msg(pdata->old_vision == NULL,
3905 "Unit number %d (%p) has done an incomplete move.",
3906 punit->id, punit);
3907 } else {
3908 pdata = fc_malloc(sizeof(*pdata));
3909 pdata->ref_count = 1;
3910 pdata->punit = punit;
3912 BV_CLR_ALL(pdata->can_see_unit);
3913 }
3914 pdata->powner = powner;
3915 BV_CLR_ALL(pdata->can_see_move);
3916 pdata->old_vision = punit->server.vision;
3917
3918 return pdata;
3919}
3920
3921/**********************************************************************/
3925 const struct tile *psrctile,
3926 struct tile *pdesttile)
3927{
3928 struct vision *new_vision;
3929 struct unit *punit = pdata->punit;
3931 const v_radius_t radius_sq
3935
3936 /* Remove unit from the source tile. */
3938
3939#ifndef FREECIV_NDEBUG
3940 bool success =
3941#endif
3944
3945 /* Set new tile. */
3948
3949 if (unit_transported(punit)) {
3950 /* Silently free orders since they won't be applicable anymore. */
3952 }
3953
3954 /* Check unit activity. */
3958
3959 /* We first unfog the destination, then send the move,
3960 * and then fog the old territory. This means that the player
3961 * gets a chance to see the newly explored territory while the
3962 * client moves the unit, and both areas are visible during the
3963 * move */
3964
3965 /* Enhance vision if unit steps into a fortress */
3968 vision_change_sight(new_vision, radius_sq);
3970}
3971
3972/**********************************************************************/
3976{
3978 fc_assert_ret(pdata->ref_count > 0);
3979 fc_assert_msg(pdata->old_vision == NULL,
3980 "Unit number %d (%p) has done an incomplete move.",
3981 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3982
3983 pdata->ref_count--;
3984 if (pdata->ref_count == 0) {
3985 if (pdata->punit != NULL) {
3986 fc_assert(pdata->punit->server.moving == pdata);
3987 pdata->punit->server.moving = NULL;
3988 }
3989 free(pdata);
3990 }
3991}
3992
3993/**********************************************************************/
3997 const struct tile *psrctile,
3998 struct tile *pdesttile,
3999 bool adj)
4000{
4003 struct unit_move_data *pdata;
4004
4005 /* Make new data for 'punit'. */
4008
4009 /* Add all contained units. */
4011 struct unit_move_data *cargo_data;
4012
4016
4017 /* Determine the players able to see the move(s), now that the player
4018 * vision has been increased. */
4019 if (adj) {
4020 /* Main unit for adjacent move: the move is visible for every player
4021 * able to see on the matching unit layer. */
4022 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
4023
4027 BV_SET(pdata->can_see_unit, player_index(oplayer));
4028 BV_SET(pdata->can_see_move, player_index(oplayer));
4029 }
4031 }
4032
4034
4036
4037 if (adj && pmove_data->punit == punit) {
4038 /* If positions are adjacent, we have already handled 'punit'. See
4039 * above. */
4040 continue;
4041 }
4042
4044 if ((adj
4046 pmove_data != pdata))
4048 pmove_data != pdata)) {
4049 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4050 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4051 }
4053 pmove_data != pdata)) {
4054 /* The unit was seen with its source tile even if it was
4055 * teleported. */
4056 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4057 }
4060
4061 return plist;
4062}
4063
4064/**********************************************************************/
4075bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
4076 struct unit *embark_to, bool find_embark_target,
4078 bool enter_hut, bool frighten_hut)
4079{
4080 struct player *pplayer;
4081 struct tile *psrctile;
4082 struct city *psrccity;
4083 struct city *pdestcity;
4084 struct unit *ptransporter;
4087 struct unit_move_data_list *plist;
4088 struct unit_move_data *pdata;
4089 int saved_id;
4090 bool unit_lives;
4091 bool adj;
4092 enum direction8 facing;
4093
4094 /* Some checks. */
4097
4098 pplayer = unit_owner(punit);
4099 saved_id = punit->id;
4102
4104
4105 /* Unload the unit if on a transport. */
4107 if (ptransporter != NULL) {
4108 /* Unload unit _before_ setting the new tile! */
4110 /* Send updated information to anyone watching that transporter
4111 * was unloading cargo. */
4113 }
4114
4115 /* Wakup units next to us before we move. */
4117
4118 /* Make info packets at 'psrctile'. */
4119 if (adj) {
4120 /* If tiles are adjacent, we will show the move to users able
4121 * to see it. */
4124 }
4125
4126 /* Set unit orientation */
4127 if (adj) {
4128 /* Only change orientation when moving to adjacent tile */
4129 punit->facing = facing;
4130 }
4131
4133
4134 /* Move magic. */
4135 punit->moved = TRUE;
4136 punit->moves_left = MAX(0, punit->moves_left - move_cost);
4137 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
4138 /* The next order may not require any remaining move fragments. */
4140 }
4141
4142 /* No longer relevant. */
4145
4147 /* The unit can perform an action to the city at the destination tile.
4148 * A long distance move (like an airlift) doesn't ask what action to
4149 * perform before moving. Ask now. */
4150
4153 }
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
4191 /* Notifications of the move to the clients. */
4192 if (adj) {
4193 /* Special case: 'punit' is moving to adjacent position. Then we show
4194 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4195
4196 /* Make info packets at 'pdesttile'. */
4199
4202
4203 if (aplayer == NULL) {
4204 if (pconn->observer) {
4205 /* Global observers see all... */
4208 }
4209 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4210 if (aplayer == pplayer) {
4213 } else {
4216 }
4217 }
4219 }
4220
4221 /* Other moves. */
4223 if (adj && pmove_data == pdata) {
4224 /* If positions are adjacent, we have already shown 'punit' move.
4225 * See above. */
4226 continue;
4227 }
4228
4229 /* Make info packets at 'pdesttile'. */
4233
4236
4237 if (aplayer == NULL) {
4238 if (pconn->observer) {
4239 /* Global observers see all... */
4241 }
4242 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4243 if (aplayer == pmove_data->powner) {
4245 } else {
4247 }
4248 }
4251
4252 /* Clear old vision. */
4254 if (pmove_data->old_vision != NULL) {
4255 vision_clear_sight(pmove_data->old_vision);
4256 vision_free(pmove_data->old_vision);
4257 pmove_data->old_vision = NULL;
4258 }
4260
4261 /* Move consequences. */
4263 struct unit *aunit = pmove_data->punit;
4264
4265 if (aunit != NULL
4266 && unit_owner(aunit) == pmove_data->powner
4267 && unit_tile(aunit) == pdesttile) {
4269 pdata != pmove_data,
4271 }
4273
4274 unit_lives = (pdata->punit == punit);
4275
4276 /* Wakeup units and make contact. */
4277 if (unit_lives) {
4279 }
4281
4282 if (unit_lives) {
4283 /* Special checks for ground units in the ocean. */
4285 if (embark_to != NULL) {
4287 } else if (find_embark_target) {
4288 /* TODO: Consider to stop supporting find_embark_target and make all
4289 * callers that wants auto loading set embark_to. */
4291 } else {
4293 }
4294 if (ptransporter) {
4296
4297 /* Set activity to sentry if boarding a ship. */
4298 if (is_human(pplayer)
4303 }
4304
4306 }
4307 }
4308 }
4309
4310 /* Remove units going out of sight. */
4312 struct unit *aunit = pmove_data->punit;
4313
4314 if (aunit == NULL) {
4315 continue; /* Died! */
4316 }
4317
4319 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4322 }
4325
4326 /* Inform the owner's client about actor unit arrival. Can, depending on
4327 * the client settings, cause the client to start the process that makes
4328 * the action selection dialog pop up. */
4330 if (pdestcity != NULL) {
4331 /* Arrival in a city counts. */
4332
4334 struct unit *ptrans;
4335 bool ok;
4336 struct unit *act_unit;
4337 struct player *act_player;
4338
4339 act_unit = pmove_data->punit;
4341
4342 if (act_unit == NULL
4343 || !unit_is_alive(act_unit->id)) {
4344 /* The unit died before reaching this point. */
4345 continue;
4346 }
4347
4348 if (unit_tile(act_unit) != pdesttile) {
4349 /* The unit didn't arrive at the destination tile. */
4350 continue;
4351 }
4352
4353 if (!is_human(act_player)) {
4354 /* Only humans need reminders. */
4355 continue;
4356 }
4357
4358 if (!unit_transported(act_unit)) {
4359 /* Don't show the action selection dialog again. Non transported
4360 * units are handled before they move to the tile. */
4361 continue;
4362 }
4363
4364 /* Open action dialog only if 'act_unit' and all its transporters
4365 * (recursively) don't have orders. */
4367 /* The unit it self has orders. */
4368 continue;
4369 }
4370
4373 if (NULL == ptrans) {
4374 /* No (recursive) transport has orders. */
4375 ok = TRUE;
4376 break;
4377 } else if (unit_has_orders(ptrans)) {
4378 /* A unit transporting the unit has orders */
4379 ok = FALSE;
4380 break;
4381 }
4382 }
4383
4384 if (!ok) {
4385 /* A unit transporting act_unit has orders. */
4386 continue;
4387 }
4388
4390 /* There is a valid target. */
4391
4392 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4393 act_unit->action_decision_tile = pdesttile;
4394
4395 /* Let the client know that this unit wants the player to decide
4396 * what to do. */
4398 }
4400 }
4401
4403 /* Check cities at source and destination. */
4405 if (psrccity != NULL) {
4407 }
4408 if (pdestcity != NULL) {
4410 }
4411
4412 if (unit_lives) {
4413 /* Let the scripts run ... */
4416 }
4417
4418 if (unit_lives) {
4419 /* Autoattack. */
4421 }
4422
4423 if (unit_lives && (enter_hut || frighten_hut)) {
4424 /* Is there a hut? */
4428 }
4429
4431
4432 if (unit_lives) {
4433 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4434 }
4435
4436 return unit_lives;
4437}
4438
4439/**********************************************************************/
4443 struct tile *ptile)
4444{
4445 struct player *owner = unit_owner(punit);
4446
4447 return (is_non_allied_unit_tile(ptile, owner,
4449 || is_non_allied_city_tile(ptile, owner));
4450}
4451
4452/**********************************************************************/
4459{
4460 bool cancel = FALSE;
4461 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4462 struct player *pplayer = unit_owner(punit);
4463
4464 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4465 struct unit *penemy = tile_non_allied_unit(ptile, pplayer,
4467 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4468
4469 if ((penemy && can_player_see_unit(pplayer, penemy))
4471 && pdcity->occupied)) {
4472 cancel = TRUE;
4473 break;
4474 }
4476
4477 return cancel;
4478}
4479
4480/**********************************************************************/
4488static inline bool player_is_watching(struct unit *punit, const bool fresh)
4489{
4490 /* The player just sent the orders to the unit. The unit has moves left.
4491 * It is therefore safe to assume that the player already is paying
4492 * attention to the unit. */
4493 return fresh && punit->moves_left > 0;
4494}
4495
4496/**********************************************************************/
4515bool execute_orders(struct unit *punit, const bool fresh)
4516{
4517 struct act_prob prob;
4518 bool performed;
4519 const char *name;
4520 bool res, last_order;
4521 int unitid = punit->id;
4522 struct player *pplayer = unit_owner(punit);
4523 int moves_made = 0;
4524 const struct civ_map *nmap = &(wld.map);
4525
4527
4528 if (punit->activity != ACTIVITY_IDLE) {
4529 /* Unit's in the middle of an activity; wait for it to finish. */
4531 return TRUE;
4532 }
4533
4534 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4535
4536 /* Any time the orders are canceled we should give the player a message. */
4537
4538 while (TRUE) {
4539 struct unit_order order;
4540
4541 struct action *oaction;
4542
4543 struct tile *dst_tile;
4544 struct city *tgt_city;
4545 struct unit *tgt_unit;
4546 int tgt_id;
4547 int sub_tgt_id;
4548 struct extra_type *pextra;
4549
4550 if (punit->done_moving) {
4551 log_debug(" stopping because we're done this turn");
4552 return TRUE;
4553 }
4554
4556 /* "Patrol" orders are stopped if an enemy is near. */
4557 cancel_orders(punit, " stopping because of nearby enemy");
4559 _("Orders for %s aborted as there are units nearby."),
4560 unit_link(punit));
4561 return TRUE;
4562 }
4563
4564 if (moves_made == punit->orders.length) {
4565 /* For repeating orders, don't repeat more than once per turn. */
4566 log_debug(" stopping because we ran a round");
4569 return TRUE;
4570 }
4571 moves_made++;
4572
4573 order = punit->orders.list[punit->orders.index];
4574
4575 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4576 * this far. */
4578 || action_id_exists(order.action)),
4579 continue);
4580
4581 switch (order.order) {
4582 case ORDER_MOVE:
4583 case ORDER_ACTION_MOVE:
4584 case ORDER_FULL_MP:
4585 if (0 == punit->moves_left) {
4586 log_debug(" stopping because of no more move points");
4587 return TRUE;
4588 }
4589 break;
4592 log_debug(" stopping. Not enough move points this turn");
4593 return TRUE;
4594 }
4595 break;
4596 case ORDER_ACTIVITY:
4597 case ORDER_LAST:
4598 /* Those actions don't require moves left. */
4599 break;
4600 }
4601
4603 && punit->orders.index + 1 == punit->orders.length);
4604
4605 if (last_order) {
4606 /* Clear the orders before we engage in the move. That way any
4607 * has_orders checks will yield FALSE and this will be treated as
4608 * a normal move. This is important: for instance a caravan goto
4609 * will popup the caravan dialog on the last move only. */
4611 }
4612
4613 /* Advance the orders one step forward. This is needed because any
4614 * updates sent to the client as a result of the action should include
4615 * the new index value. Note that we have to send_unit_info() somewhere
4616 * after this point so that the client is properly updated. */
4617 punit->orders.index++;
4618
4619 switch (order.order) {
4620 case ORDER_FULL_MP:
4622 /* If the unit doesn't have full MP then it just waits until the
4623 * next turn. We assume that the next turn it will have full MP
4624 * (there's no check for that). */
4626 log_debug(" waiting this turn");
4628 }
4629 break;
4630 case ORDER_ACTIVITY:
4631 {
4632 enum unit_activity activity = order.activity;
4633
4634 fc_assert(activity == ACTIVITY_SENTRY);
4635
4636 if (can_unit_do_activity(nmap, punit, activity)) {
4638 set_unit_activity(punit, activity, order.action);
4640
4641 break;
4642 }
4643 }
4644
4645 cancel_orders(punit, " orders canceled because of failed activity");
4647 _("Orders for %s aborted since they "
4648 "give an invalid activity."),
4649 unit_link(punit));
4650 return TRUE;
4651 case ORDER_MOVE:
4652 case ORDER_ACTION_MOVE:
4653 /* Move unit */
4654 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4655 cancel_orders(punit, " move order sent us to invalid location");
4657 _("Orders for %s aborted since they "
4658 "give an invalid location."),
4659 unit_link(punit));
4660 return TRUE;
4661 }
4662
4663 if (order.order != ORDER_ACTION_MOVE
4665 /* Plain move required: no attack, trade route etc. */
4666 cancel_orders(punit, " orders canceled because of enemy");
4668 _("Orders for %s aborted as there "
4669 "are units in the way."),
4670 unit_link(punit));
4671 return TRUE;
4672 }
4673
4674 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4676 order.order != ORDER_ACTION_MOVE);
4677 if (!player_unit_by_number(pplayer, unitid)) {
4678 log_debug(" unit died while moving.");
4679 /* A player notification should already have been sent. */
4680 return FALSE;
4681 }
4682
4683 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4684 /* Movement succeeded but unit didn't move. */
4685 log_debug(" orders resulted in combat.");
4687 return TRUE;
4688 }
4689
4690 if (!res) {
4691 fc_assert(0 <= punit->moves_left);
4692
4693 /* Movement failed (ZOC, etc.) */
4694 cancel_orders(punit, " attempt to move failed.");
4695
4697 /* The final move "failed" because the unit needs to ask the
4698 * player what action it should take.
4699 *
4700 * The action decision request notifies the player. Its
4701 * location at the unit's last order makes it clear to the
4702 * player who the decision is for. ("The Spy I sent to Berlin
4703 * has arrived.")
4704 *
4705 * A notification message is therefore redundant. */
4706 && !(last_order
4709 /* The player may have missed this. No one else will announce it
4710 * in a satisfying manner. Inform the player. */
4711 notify_player(pplayer, unit_tile(punit),
4713 _("Orders for %s aborted because of failed move."),
4714 unit_link(punit));
4715 }
4716
4717 return TRUE;
4718 }
4719 break;
4722
4723 /* Checked in unit_order_list_is_sane() */
4724 fc_assert_action(oaction != NULL, continue);
4725
4726 log_debug(" orders: doing action %s", action_rule_name(oaction));
4727
4728 dst_tile = index_to_tile(&(wld.map), order.target);
4729
4730 if (dst_tile == NULL) {
4731 /* Could be at the edge of the map while trying to target a tile
4732 * outside of it. */
4733
4734 cancel_orders(punit, " target location doesn't exist");
4736 order.action, dst_tile, NULL, NULL);
4737
4738 return TRUE;
4739 }
4740
4741 /* Get the target city from the target tile. */
4743
4744 if (tgt_city == NULL
4746 /* This action targets a city but no city target was found. */
4747
4748 cancel_orders(punit, " perform action vs city with no city");
4750 order.action, dst_tile, tgt_city, NULL);
4751
4752 return TRUE;
4753 }
4754
4755 /* Get a target unit at the target tile. */
4757
4758 if (tgt_unit == NULL
4760 /* This action targets a unit but no target unit was found. */
4761
4762 cancel_orders(punit, " perform action vs unit with no unit");
4764 order.action, dst_tile, tgt_city, tgt_unit);
4765
4766 return TRUE;
4767 }
4768
4769 /* Server side sub target assignment */
4770 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4771 && order.sub_target == NO_TARGET) {
4772 /* Try to find a sub target. */
4774 } else {
4775 /* The client should have specified a sub target if needed */
4776 sub_tgt_id = order.sub_target;
4777 }
4778
4779 /* Get a target extra at the target tile */
4780 pextra = (sub_tgt_id == NO_TARGET ?
4781 NULL :
4782 extra_by_number(sub_tgt_id));
4783
4785 && pextra != NULL
4786 && actres_creates_extra(oaction->result, pextra)
4787 && tile_has_extra(dst_tile, pextra)) {
4788 /* Already there. Move on to the next order. */
4789 break;
4790 }
4791
4793 && pextra != NULL
4794 && actres_removes_extra(oaction->result, pextra)
4795 && !tile_has_extra(dst_tile, pextra)) {
4796 /* Already not there. Move on to the next order. */
4797 break;
4798 }
4799
4800 /* No target selected. */
4801 tgt_id = -1;
4802
4803 /* Assume impossible until told otherwise. */
4804 prob = ACTPROB_IMPOSSIBLE;
4805
4806 switch (action_id_get_target_kind(order.action)) {
4807 case ATK_UNITS:
4808 prob = action_prob_vs_stack(punit, order.action,
4809 dst_tile);
4810 tgt_id = dst_tile->index;
4811 break;
4812 case ATK_TILE:
4813 prob = action_prob_vs_tile(punit, order.action,
4814 dst_tile, pextra);
4815 tgt_id = dst_tile->index;
4816 break;
4817 case ATK_EXTRAS:
4818 prob = action_prob_vs_extras(punit, order.action,
4819 dst_tile, pextra);
4820 tgt_id = dst_tile->index;
4821 break;
4822 case ATK_CITY:
4823 prob = action_prob_vs_city(nmap, punit, order.action,
4824 tgt_city);
4825 tgt_id = tgt_city->id;
4826 break;
4827 case ATK_UNIT:
4828 prob = action_prob_vs_unit(nmap, punit, order.action,
4829 tgt_unit);
4830
4831 tgt_id = tgt_unit->id;
4832 break;
4833 case ATK_SELF:
4834 prob = action_prob_self(punit, order.action);
4835
4836 tgt_id = unitid;
4837 break;
4838 case ATK_COUNT:
4839 log_error("Invalid action target kind");
4840
4841 /* The check below will abort and cancel the orders because prob
4842 * was initialized to impossible above this switch statement. */
4843
4844 break;
4845 }
4846
4847 if (!action_prob_possible(prob)) {
4848 /* The player has enough information to know that this action is
4849 * against the rules. Don't risk any punishment by trying to
4850 * perform it. */
4851
4852 cancel_orders(punit, " illegal action");
4854 _("%s could not do %s to %s."),
4858
4859 /* Try to explain what rule made it illegal. */
4861 order.action, dst_tile, tgt_city, tgt_unit);
4862
4863 return TRUE;
4864 }
4865
4867 /* This action needs a name. */
4869 } else {
4870 /* This action doesn't need a name. */
4871 name = "";
4872 }
4873
4875 unitid,
4876 tgt_id,
4877 sub_tgt_id,
4878 name,
4879 order.action,
4881
4882 if (!player_unit_by_number(pplayer, unitid)) {
4883 /* The unit "died" while performing the action. */
4884 return FALSE;
4885 }
4886
4887 if (!performed) {
4888 /* The action wasn't performed as ordered. */
4889
4890 cancel_orders(punit, " failed action");
4892 _("Orders for %s aborted because "
4893 "doing %s to %s failed."),
4897
4898 return TRUE;
4899 }
4900
4901 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4903 /* Done at turn change. */
4906 break;
4907 }
4908
4909 break;
4910 case ORDER_LAST:
4911 /* Should be caught when loading the unit orders from the savegame or
4912 * when receiving the unit orders from the client. */
4913 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4914 cancel_orders(punit, " invalid order!");
4916 _("Your %s has invalid orders."),
4917 unit_link(punit));
4918 return TRUE;
4919 }
4920
4921 if (last_order) {
4923 log_debug(" stopping because orders are complete");
4924 return TRUE;
4925 }
4926
4927 if (punit->orders.index == punit->orders.length) {
4929 /* Start over. */
4930 log_debug(" repeating orders.");
4931 punit->orders.index = 0;
4932 }
4933 } /* end while */
4934}
4935
4936/**********************************************************************/
4943static int get_unit_vision_base(const struct unit *punit,
4944 enum vision_layer vlayer,
4945 const int base)
4946{
4947 switch (vlayer) {
4948 case V_MAIN:
4949 return MAX(0, base);
4950 case V_INVIS:
4951 case V_SUBSURFACE:
4952 return CLIP(0, base, 2);
4953 case V_COUNT:
4954 break;
4955 }
4956
4957 log_error("Unsupported vision layer variant: %d.", vlayer);
4958
4959 return 0;
4960}
4961
4962/**********************************************************************/
4965static int unit_vision_range_modifiers(const struct unit *punit,
4966 const struct tile *ptile)
4967{
4968 const struct unit_type *utype = unit_type_get(punit);
4969
4970 return (utype->vision_radius_sq
4972 &(const struct req_context) {
4973 .player = unit_owner(punit),
4974 .tile = ptile,
4975 .unittype = utype,
4976 .unit = punit,
4977 },
4979}
4980
4981/**********************************************************************/
4988int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
4989 enum vision_layer vlayer)
4990{
4993}
4994
4995/**********************************************************************/
5002{
5003 struct vision *uvision = punit->server.vision;
5004 const struct tile *utile = unit_tile(punit);
5005 int mod = unit_vision_range_modifiers(punit, utile);
5006 const v_radius_t radius_sq
5010
5011 vision_change_sight(uvision, radius_sq);
5013}
5014
5015/**********************************************************************/
5024
5025/**********************************************************************/
5030{
5031 time_t dt;
5032
5033 if (!punit) {
5034 return FALSE;
5035 }
5036
5037 if (game.server.unitwaittime <= 0) {
5038 return TRUE;
5039 }
5040
5041 if (punit->server.action_turn != game.info.turn - 1) {
5042 return TRUE;
5043 }
5044
5046 if (dt < game.server.unitwaittime) {
5047 char buf[64];
5050 ftc_server, _("Your unit may not act for another %s "
5051 "this turn. See /help unitwaittime."), buf);
5052 return FALSE;
5053 }
5054
5055 return TRUE;
5056}
5057
5058/**********************************************************************/
5063{
5064 if (!punit) {
5065 return;
5066 }
5067
5070}
5071
5072/**********************************************************************/
5078{
5079 /* check if there is enemy nearby */
5080 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
5082 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
5083 return FALSE;
5084 }
5085 }
5087
5088 return TRUE;
5089}
5090
5091/**********************************************************************/
5094void random_movements(struct player *pplayer)
5095{
5096 const struct civ_map *nmap = &(wld.map);
5097
5098 game.server.random_move_time = pplayer;
5099
5102 bool moved = TRUE;
5103 struct tile *curtile = unit_tile(punit);
5104 int id = punit->id;
5105
5106 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
5107 /*
5108 * List of all 8 directions
5109 */
5110 enum direction8 dirs[8] = {
5113 };
5114 int n;
5115
5116 moved = FALSE;
5117
5118 for (n = 8; n > 0 && !moved; n--) {
5119 enum direction8 choice = (enum direction8) fc_rand(n);
5120 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
5121
5122 if (dest != NULL) {
5124 dest))) {
5125 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
5127 moved = TRUE;
5128 break;
5129 }
5130 }
5131
5132 if (!moved) {
5134 NULL)) {
5135 if (unit_perform_action(pplayer, id, tile_index(dest),
5137 ACT_REQ_RULES)) {
5138 moved = TRUE;
5139 }
5141 punit, dest, NULL)) {
5142 if (unit_perform_action(pplayer, id, tile_index(dest),
5144 ACT_REQ_RULES)) {
5145 moved = TRUE;
5146 }
5148 punit, dest, NULL)) {
5149 if (unit_perform_action(pplayer, id, tile_index(dest),
5151 ACT_REQ_RULES)) {
5152 moved = TRUE;
5153 }
5154 }
5155 }
5156 }
5157
5158 if (!moved) {
5159 /* Choice was bad, so replace it with the last direction
5160 * in the list. On the next iteration, one fewer choice
5161 * will remain. */
5162 dirs[choice] = dirs[n - 1];
5163 }
5164 }
5165 }
5166 }
5168
5170}
5171
5172/**********************************************************************/
5177void unit_make_contact(const struct unit *punit,
5178 struct tile *ptile, struct player *pplayer) {
5179 fc_assert_ret(punit != nullptr);
5180
5182 return; /* Flagless unit can't make contact */
5183 }
5184
5185 maybe_make_contact(ptile ? ptile : unit_tile(punit),
5186 pplayer ? pplayer : unit_owner(punit));
5187}
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:5522
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1225
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Definition actions.c:4717
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5044
const char * action_name_translation(const struct action *paction)
Definition actions.c:1205
const char * action_rule_name(const struct action *action)
Definition actions.c:1191
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1094
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4562
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:3293
struct act_prob action_prob_vs_stack(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:4478
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:4203
struct act_prob action_prob_vs_extras(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4646
bool action_id_exists(const action_id act_id)
Definition actions.c:1043
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5104
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:3442
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:4286
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5155
static struct action * action_by_number(action_id act_id)
Definition actions.h:390
#define action_has_result(_act_, _res_)
Definition actions.h:175
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:431
#define ACTPROB_IMPOSSIBLE
Definition actions.h:665
#define action_id_get_target_kind(act_id)
Definition actions.h:407
#define action_id_has_result_safe(act_id, result)
Definition actions.h:420
#define ACTION_NONE
Definition actions.h:55
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:806
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:785
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
void dbv_to_bv(unsigned char *dest, const struct dbv *src)
Definition bitvector.c:235
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool city_exists_within_max_city_map(const struct tile *ptile, bool may_be_on_center)
Definition city.c:2108
bool is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile, int distance)
Definition city.c:2088
const char * city_name_get(const struct city *pcity)
Definition city.c:1133
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:763
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:727
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:739
#define output_type_iterate(output)
Definition city.h:836
#define city_owner(_pcity_)
Definition city.h:563
#define city_list_iterate_end
Definition city.h:510
#define output_type_iterate_end
Definition city.h:842
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3317
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:453
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2351
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:851
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2203
void sync_cities(void)
Definition citytools.c:3326
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1981
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3140
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:761
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:992
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:715
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1023
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:770
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:613
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:839
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:74
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:2938
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2665
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2695
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
int get_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:358
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:353
@ RPT_CERTAIN
Definition fc_types.h:678
@ AUT_NONE
Definition fc_types.h:374
@ HB_DISABLED
Definition fc_types.h:1271
#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:851
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:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:211
#define log_test
Definition log.h:136
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:647
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:673
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:462
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:950
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:375
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:1343
#define adjc_iterate_end
Definition map.h:419
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:377
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:414
#define square_iterate_end
Definition map.h:380
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:279
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:387
#define circle_iterate_end
Definition map.h:390
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2538
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2626
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1924
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2225
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2561
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2729
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:927
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:871
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1446
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:2000
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1389
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2526
#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:289
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:318
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
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:912
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:341
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:490
@ 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:292
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:239
unit_info_use
Definition packets.h: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:539
#define players_iterate(_pplayer)
Definition player.h:534
#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:3219
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2362
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1146
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1593
void player_loot_player(struct player *pvictor, struct player *pvictim)
Definition plrhand.c: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:1965
#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:320
int id
Definition city.h:326
struct tile * tile
Definition city.h:322
struct unit_list * units_supported
Definition city.h:406
int unitwaittime
Definition game.h:198
struct player * random_move_time
Definition game.h:276
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:132
int killunhomed
Definition game.h:154
struct civ_game::@31::@35 server
int ransom_gold
Definition game.h:175
bool autoattack
Definition game.h:131
int timeoutaddenemymove
Definition game.h:208
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_economic economic
Definition player.h:284
struct player_score score
Definition player.h:283
struct player::@70::@72 server
const struct player * player
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
bv_player can_see_unit
Definition unittools.c:95
struct player * powner
Definition unittools.c:94
bv_player can_see_move
Definition unittools.c:96
struct unit * punit
Definition unittools.c:93
struct vision * old_vision
Definition unittools.c:97
enum unit_activity activity
Definition unit.h: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:529
enum vision_layer vlayer
Definition unittype.h:576
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
struct unit::@80 orders
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
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::@81::@84 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:189
#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:111
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:121
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#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:1821
void free_unit_orders(struct unit *punit)
Definition unit.c:1807
bool unit_is_alive(int id)
Definition unit.c:2291
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:550
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2428
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1275
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2499
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2448
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2221
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:866
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1662
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:893
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1767
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1285
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1115
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:2026
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2483
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:776
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2509
bool unit_has_orders(const struct unit *punit)
Definition unit.c:205
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1950
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2073
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:590
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.c:1336
bool can_unit_do_activity_targeted(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, struct extra_type *target)
Definition unit.c:932
#define unit_tile(_pu)
Definition unit.h:397
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:420
#define unit_cargo_iterate_end
Definition unit.h:575
@ 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:408
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:572
#define CHECK_UNIT(punit)
Definition unit.h:273
#define unit_owner(_pu)
Definition unit.h:396
@ UU_OK
Definition unit.h:62
#define unit_home(_pu_)
Definition unit.h:394
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:433
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:2514
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unithand.c:6613
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:3337
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5679
#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:356
void unit_did_action(struct unit *punit)
Definition unittools.c:5062
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3458
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2644
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:3067
void unit_make_contact(const struct unit *punit, struct tile *ptile, struct player *pplayer)
Definition unittools.c:5177
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1162
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:2152
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:3996
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4515
static void unit_convert(struct unit *punit)
Definition unittools.c:775
void update_unit_activities(struct player *pplayer)
Definition unittools.c:667
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1306
#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:1554
void random_movements(struct player *pplayer)
Definition unittools.c:5094
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:289
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1795
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1417
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1489
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1920
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1452
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4442
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:401
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1402
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:3035
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3975
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1772
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3331
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2734
#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:2865
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:658
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3657
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:715
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:3416
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3514
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:699
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:677
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:1114
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2878
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1944
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1371
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3860
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:631
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:425
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3889
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1714
void notify_unit_experience(struct unit *punit)
Definition unittools.c:744
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:2815
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:1666
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1476
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:1633
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1911
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1786
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4988
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:219
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5001
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:1606
void do_explore(struct unit *punit)
Definition unittools.c:3100
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3386
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:5029
#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:2140
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:689
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3136
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4488
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4943
void player_restore_units(struct player *pplayer)
Definition unittools.c:478
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1531
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4965
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:3438
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1522
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:237
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3646
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:5077
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:735
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:831
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2200
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1188
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2950
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3300
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1083
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3472
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:3727
void unit_get_goods(struct unit *punit)
Definition unittools.c:1617
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2922
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4458
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:4075
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3924
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:5018
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2267
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1226
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:1569
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, bool consider_reg_impr_req)
Definition unittype.c:1968
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2253
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2567
int num_role_units(int role)
Definition unittype.c:2203
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1927
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1703
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2498
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2583
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
#define utype_class(_t_)
Definition unittype.h:756
#define utype_fuel(ptype)
Definition unittype.h:843
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define U_LAST
Definition unittype.h:40
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
void vision_free(struct vision *vision)
Definition vision.c:50
#define ASSERT_VISION(v)
Definition vision.h:98
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition vision.h:96
#define vision_site_owner(v)
Definition vision.h:128
short int v_radius_t[V_COUNT]
Definition vision.h:83