Freeciv-3.4
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 nullptr if the unit is not moving). */
93 struct unit *punit; /* nullptr 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_ == nullptr) { \
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 RPT_CERTAIN, TRUE)) {
193 players++;
194 }
196
197 if (players > minplayers) {
198 which[num++] = iunit;
199 }
200 }
201 }
202 if (num == 0) {
203 for (i = 0; i < num_role_units(role); i++) {
204 which[num++] = get_role_unit(role, i);
205 }
206 }
207
208 /* Ruleset code should ensure there is at least one unit for each
209 * possibly-required role, or check before calling this function. */
210 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
211 role, role_tech);
212
213 return which[fc_rand(num)];
214}
215
216/**********************************************************************/
224
225/**********************************************************************/
240 bool worker)
241{
242 const struct veteran_system *vsystem;
243 const struct veteran_level *vlevel;
244 int chance;
245 const struct civ_map *nmap = &(wld.map);
246
247 fc_assert_ret_val(punit != nullptr, FALSE);
248
250 fc_assert_ret_val(vsystem != nullptr, FALSE);
252
254 fc_assert_ret_val(vlevel != nullptr, FALSE);
255
256 if (punit->veteran + 1 >= vsystem->levels
258 return FALSE;
259 } else if (!worker) {
261
262 /* The modification is tacked on as a multiplier to the base chance.
263 * For example with a base chance of 50% for green units and a modifier
264 * of +50% the end chance is 75%. */
265 chance = vlevel->base_raise_chance * mod / 100;
268
269 chance = vlevel->work_raise_chance * mod / 100;
270 } else {
271 /* No battle and no work done. */
272 return FALSE;
273 }
274
275 if (fc_rand(100) < chance) {
276 punit->veteran++;
277 return TRUE;
278 }
279
280 return FALSE;
281}
282
283/**********************************************************************/
293bool unit_versus_unit(struct unit *attacker, struct unit *defender,
294 int *att_hp, int *def_hp, int *att_vet, int *def_vet,
295 const struct action *paction)
296{
297 int attackpower = get_total_attack_power(attacker, defender, paction);
298 int defensepower = get_total_defense_power(attacker, defender);
300 struct player *plr1 = unit_owner(attacker);
301 struct player *plr2 = unit_owner(defender);
302 struct civ_map *nmap = &(wld.map);
303 int max_rounds;
304 int rounds;
305 int att_strength;
306 int def_strength;
307
308 *att_hp = attacker->hp;
309 *def_hp = defender->hp;
310 get_modified_firepower(nmap, attacker, defender,
312
313 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
314 "defense firepower:%d", attackpower, defensepower,
316
319
322
323 /* In a combat between equal strength units the values are 50% / 50%.
324 * -> scaling that to 100% by doubling, to match scale of chances
325 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
328
329 if (attackpower == 0) {
330 *att_hp = 0;
331 } else if (defensepower == 0) {
332 *def_hp = 0;
333 }
335 for (rounds = 0;
336 *att_hp > 0 && *def_hp > 0
338 rounds++) {
340 *def_hp -= attack_firepower;
341 } else {
342 *att_hp -= defense_firepower;
343 }
344 }
345 if (*att_hp < 0) {
346 *att_hp = 0;
347 }
348 if (*def_hp < 0) {
349 *def_hp = 0;
350 }
351
352 return attackpower <= 0 || defensepower <= 0;
353}
354
355/**********************************************************************/
361void unit_bombs_unit(struct unit *attacker, struct unit *defender,
362 int *att_hp, int *def_hp,
363 const struct action *paction)
364{
365 int i;
366 int rate = unit_bombard_rate(attacker);
367 int attackpower = get_total_attack_power(attacker, defender, paction);
368 int defensepower = get_total_defense_power(attacker, defender);
370 struct player *plr1 = unit_owner(attacker);
371 struct player *plr2 = unit_owner(defender);
372 struct civ_map *nmap = &(wld.map);
373
374 *att_hp = attacker->hp;
375 *def_hp = defender->hp;
376 get_modified_firepower(nmap, attacker, defender,
378
379 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
380 "defense firepower:%d", attackpower, defensepower,
382
385
386 for (i = 0; i < rate; i++) {
388 *def_hp -= attack_firepower;
389 }
390 }
391
392 if (*def_hp <= 0) {
393 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
394 /* Don't kill the target. */
395 *def_hp = 1;
396 } else {
397 *def_hp = 0;
398 }
399 }
400}
401
402/**********************************************************************/
406void combat_veterans(struct unit *attacker, struct unit *defender,
407 bool powerless, int att_vet, int def_vet)
408{
410 if (attacker->hp <= 0 || defender->hp <= 0
413 att_vet = 100;
414 def_vet = 100;
415 }
416 if (attacker->hp > 0) {
417 maybe_make_veteran(attacker, att_vet);
418 }
419 if (defender->hp > 0) {
420 maybe_make_veteran(defender, def_vet);
421 }
422 }
423 }
424}
425
426/**********************************************************************/
430static void do_upgrade_effects(struct player *pplayer)
431{
433 struct unit_list *candidates;
434
435 if (upgrades <= 0) {
436 return;
437 }
439
440 unit_list_iterate(pplayer->units, punit) {
441 /* We have to be careful not to strand units at sea, for example by
442 * upgrading a frigate to an ironclad while it was carrying a unit. */
443 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
444 unit_list_prepend(candidates, punit); /* Potential candidate :) */
445 }
447
448 while (upgrades > 0 && unit_list_size(candidates) > 0) {
449 /* Upgrade one unit. The unit is chosen at random from the list of
450 * available candidates. */
453 const struct unit_type *type_from = unit_type_get(punit);
454 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
455
458 _("%s was upgraded for free to %s."),
462 upgrades--;
463 }
464
466}
467
468/**********************************************************************/
483void player_restore_units(struct player *pplayer)
484{
485 const struct civ_map *nmap = &(wld.map);
486
487 /* 1) get Leonardo out of the way first: */
488 do_upgrade_effects(pplayer);
489
491
492 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
494
495 /* 3) Check that unit has hitpoints */
496 if (punit->hp <= 0) {
497 /* This should usually only happen for heli units, but if any other
498 * units get 0 hp somehow, catch them too. --dwp */
499 /* if 'game.server.killunhomed' is activated unhomed units are slowly
500 * killed; notify player here */
501 if (!punit->homecity && 0 < game.server.killunhomed) {
503 ftc_server, _("Your %s has run out of hit points "
504 "because it was not supported by a city."),
506 } else {
508 _("Your %s has run out of hit points."),
510 }
511
512 wipe_unit(punit, ULR_HP_LOSS, nullptr);
513 continue; /* Continue iterating... */
514 }
515
516 /* 4) Rescue planes if needed */
518 /* Shall we emergency return home on the last vapors? */
519
520 /* I think this is strongly against the spirit of client goto.
521 * The problem is (again) that here we know too much. -- Zamar */
522
523 if (punit->fuel <= 1
525 struct unit *carrier;
526
528 if (carrier) {
530 } else {
531 struct pf_map *pfm;
532 struct pf_parameter parameter;
533 bool alive = TRUE;
534
535 pft_fill_unit_parameter(&parameter, nmap, punit);
536 parameter.omniscience = !has_handicap(pplayer, H_MAP);
537 pfm = pf_map_new(&parameter);
538
539 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
540 if (move_cost > punit->moves_left) {
541 /* Too far */
542 break;
543 }
544
545 if (is_refuel_point(ptile, pplayer, punit)) {
546 struct pf_path *path;
547 int id = punit->id;
548
549 /* Client orders may be running for this unit - if so
550 * we free them before engaging goto. */
552
553 path = pf_map_path(pfm, ptile);
554
555 alive = adv_follow_path(punit, path, ptile);
556
557 if (!alive) {
558 log_error("rescue plane: unit %d died enroute!", id);
559 } else if (!same_pos(unit_tile(punit), ptile)) {
560 /* Enemy units probably blocked our route
561 * FIXME: We should try find alternative route around
562 * the enemy unit instead of just giving up and crashing. */
563 log_debug("rescue plane: unit %d could not move to "
564 "refuel point!", punit->id);
565 }
566
567 if (alive) {
568 /* Clear activity. Unit info will be sent in the end of
569 * the function. */
572 punit->goto_tile = nullptr;
573
576 if (carrier) {
578 }
579 }
580
581 notify_player(pplayer, unit_tile(punit),
583 _("Your %s has returned to refuel."),
585 }
586 pf_path_destroy(path);
587 break;
588 }
591
592 if (!alive) {
593 /* Unit died trying to move to refuel point. */
594 return;
595 }
596 }
597 }
598
599 /* 5) Update fuel */
600 punit->fuel--;
601
602 /* 6) Automatically refuel air units in cities, airbases, and
603 * transporters (carriers). */
606 }
607 }
609
610 /* 7) Check if there are air units without fuel */
612 const struct unit_type *utype = unit_type_get(punit);
613
614 if (punit->fuel <= 0 && utype_fuel(utype)) {
615 /* Notifications sent from the lua script when unit wiped. */
616 wipe_unit(punit, ULR_FUEL, nullptr);
617 }
619
620 /* Send all updates. */
621 unit_list_iterate(pplayer->units, punit) {
622 send_unit_info(nullptr, punit);
624}
625
626/**********************************************************************/
637{
638 bool was_lower;
639 const struct unit_type *utype = unit_type_get(punit);
640
641 was_lower = (punit->hp < utype->hp);
642
644
645 fc_assert(punit->hp >= 0);
646 fc_assert(punit->hp <= utype->hp);
647
648 if (punit->hp == utype->hp) {
651 }
652 }
653
654 punit->moved = FALSE;
656}
657
658/**********************************************************************/
663static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
664{
667}
668
669/**********************************************************************/
678
679/**********************************************************************/
682void execute_unit_orders(struct player *pplayer)
683{
685 if (unit_has_orders(punit)) {
687 }
689}
690
691/**********************************************************************/
694void unit_tc_effect_refresh(struct player *pplayer)
695{
696 unit_list_iterate(pplayer->units, punit) {
699}
700
701/**********************************************************************/
705{
706 /* Remember activities only after all knock-on effects of unit activities
707 * on other units have been resolved */
708 unit_list_iterate(pplayer->units, punit) {
712 send_unit_info(nullptr, punit);
714}
715
716/**********************************************************************/
720static int total_activity(struct tile *ptile, enum unit_activity act,
721 struct extra_type *tgt)
722{
723 int total = 0;
725
726 unit_list_iterate(ptile->units, punit) {
727 if (punit->activity == act
728 && (!tgt_matters || punit->activity_target == tgt)) {
729 total += punit->activity_count;
730 }
732
733 return total;
734}
735
736/**********************************************************************/
740static bool total_activity_done(struct tile *ptile, enum unit_activity act,
741 struct extra_type *tgt)
742{
743 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
744}
745
746/**********************************************************************/
750{
751 const struct veteran_level *vlevel;
752 const struct veteran_system *vsystem;
753
754 if (!punit) {
755 return;
756 }
757
759 fc_assert_ret(vsystem != nullptr);
761
763 fc_assert_ret(vlevel != nullptr);
764
767 /* TRANS: Your <unit> became ... rank of <veteran level>. */
768 _("Your %s became more experienced and achieved the rank "
769 "of %s."),
771}
772
773/**********************************************************************/
776static void unit_convert(struct unit *punit)
777{
778 const struct unit_type *to_type;
779 const struct unit_type *from_type;
780
782 to_type = from_type->converted_to;
783
784 if (unit_can_convert(&(wld.map), punit)) {
788 _("%s converted to %s."),
791 } else {
794 _("%s cannot be converted."),
796 }
797}
798
799/**********************************************************************/
803{
804 if (unit_has_orders(punit)) {
807 _("Orders for %s aborted because activity "
808 "is no longer available."),
811 }
812
814 send_unit_info(nullptr, punit);
815}
816
817/**********************************************************************/
828
829/**********************************************************************/
840
841/**********************************************************************/
855
856/**********************************************************************/
860static void update_unit_activity(struct unit *punit)
861{
862 struct player *pplayer = unit_owner(punit);
864 enum unit_activity activity = punit->activity;
865 struct tile *ptile = unit_tile(punit);
866 const struct unit_type *act_utype = unit_type_get(punit);
867
868 switch (activity) {
869 case ACTIVITY_IDLE:
870 case ACTIVITY_EXPLORE:
872 case ACTIVITY_SENTRY:
873 case ACTIVITY_GOTO:
874 case ACTIVITY_LAST:
875 /* We don't need the activity_count for the above */
876 break;
877
879 case ACTIVITY_CONVERT:
881 break;
882
883 case ACTIVITY_CLEAN:
884 case ACTIVITY_MINE:
886 case ACTIVITY_PILLAGE:
888 case ACTIVITY_PLANT:
890 case ACTIVITY_BASE:
893
894 /* Worker may become veteran when doing something useful */
897 }
898 break;
899 };
900
902
903 switch (activity) {
904 case ACTIVITY_EXPLORE:
905 /* Not accumulating activity - will be handled more like movement
906 * after the TC */
908 case ACTIVITY_IDLE:
910 case ACTIVITY_SENTRY:
911 case ACTIVITY_GOTO:
913 case ACTIVITY_CONVERT:
914 case ACTIVITY_LAST:
915 /* No default, ensure all handled */
916 break;
917
918 case ACTIVITY_PILLAGE:
923
925
926 /* Change vision if effects have changed. */
928 }
929 break;
930
931 case ACTIVITY_CLEAN:
932 /* TODO: Remove this fallback target setting when target always correctly
933 * set */
934 {
935 struct extra_type *pextra;
936
937 if (punit->activity_target == nullptr) {
938 pextra = prev_extra_in_tile(ptile, ERM_CLEAN,
939 nullptr, punit);
940 if (pextra != nullptr) {
941 punit->activity_target = pextra;
942 }
943 } else {
945 pextra = punit->activity_target;
946 } else {
947 pextra = nullptr;
948 }
949 }
950
951 if (pextra != nullptr) {
952 if (total_activity_done(ptile, ACTIVITY_CLEAN, pextra)) {
953 destroy_extra(ptile, pextra);
955 }
956 }
957 }
958 break;
959
960 case ACTIVITY_BASE:
961 {
966 }
967 }
968 break;
969
971 {
976 }
977 }
978 break;
979
981 case ACTIVITY_MINE:
983 case ACTIVITY_PLANT:
985 if (total_activity_done(ptile, activity, punit->activity_target)) {
986 struct terrain *old = tile_terrain(ptile);
987
988 /* The function below could change the terrain. Therefore, we have to
989 * check the terrain (which will also do a sanity check for the tile). */
990 tile_apply_activity(ptile, activity, punit->activity_target);
993 }
994 break;
995 }
996
997 if (unit_activity_done) {
999
1000 update_tile_knowledge(ptile);
1001
1002 unit_list_iterate(ptile->units, punit2) {
1003 if (punit2->activity == activity
1004 && punit2->activity_target == act_tgt) {
1005 /* This unit was helping with the work just finished.
1006 * Mark it idle (already finished) so its "current"
1007 * activity is not considered illegal
1008 * in tile_change_side_effects() . */
1010 }
1012
1014 }
1015
1016 if (activity == ACTIVITY_FORTIFYING) {
1019 punit, ptile, punit->activity_target)) {
1022 }
1023 }
1024
1025 if (activity == ACTIVITY_CONVERT) {
1028 punit, ptile, punit->activity_target)) {
1032 }
1033 }
1034
1035 if (unit_activity_done) {
1036 if (activity == ACTIVITY_PILLAGE) {
1037 /* Casus Belli for when the action is completed. */
1038 /* TODO: is it more logical to put Casus_Belli_Success here, change
1039 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1040 * trigger it when an activity successfully has began? */
1043 act_utype,
1047 }
1048 }
1049}
1050
1051/**********************************************************************/
1059
1060/**********************************************************************/
1065{
1066 switch (activity) {
1067 case ACTIVITY_PILLAGE:
1068 /* Can be set server side. */
1069 return FALSE;
1070 default:
1071 return activity_requires_target(activity);
1072 }
1073}
1074
1075/**********************************************************************/
1085 enum unit_activity *activity,
1086 enum gen_action action,
1087 struct extra_type **target)
1088{
1089 const struct civ_map *nmap = &(wld.map);
1090
1091 if (*activity == ACTIVITY_PILLAGE
1092 && *target == nullptr) {
1093 struct tile *ptile = unit_tile(punit);
1094 struct extra_type *tgt;
1095 bv_extras extras = *tile_extras(ptile);
1096
1097 while ((tgt = get_preferred_pillage(extras))) {
1098
1099 BV_CLR(extras, extra_index(tgt));
1100
1102 tgt)) {
1103 *target = tgt;
1104 return;
1105 }
1106 }
1107
1108 /* Nothing we can pillage here. */
1109 *activity = ACTIVITY_IDLE;
1110 }
1111}
1112
1113/**********************************************************************/
1118 struct player *powner,
1119 struct unit_type *u_type,
1120 int sq_radius,
1121 struct tile **dst_tile)
1122{
1123 int bestvalue = 0;
1124 struct civ_map *nmap = &(wld.map);
1125
1126 /* coords of best tile in arg pointers */
1128 int value;
1129
1130 if (!is_native_tile(u_type, ptile)) {
1131 continue;
1132 }
1133
1134 if (tile_city(ptile) != nullptr) {
1135 continue;
1136 }
1137
1138 if (0 < unit_list_size(ptile->units)) {
1139 continue;
1140 }
1141
1142 /* City may not have changed hands yet; see place_partisans(). */
1143 value = get_virtual_defense_power(nmap, nullptr, u_type, powner,
1144 ptile, FALSE, 0);
1145 value *= 10;
1146
1147 if (tile_continent(ptile) != tile_continent(pcenter)) {
1148 value /= 2;
1149 }
1150
1151 value -= fc_rand(value/3);
1152
1153 if (value > bestvalue) {
1154 *dst_tile = ptile;
1155 bestvalue = value;
1156 }
1158
1159 return bestvalue > 0;
1160}
1161
1162/**********************************************************************/
1165void place_partisans(struct tile *pcenter, struct player *powner,
1166 int count, int sq_radius)
1167{
1168 struct tile *ptile = nullptr;
1170 const struct civ_map *nmap = &(wld.map);
1171
1172 while (count-- > 0
1174 sq_radius, &ptile)) {
1175 struct unit *punit;
1177
1178 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1180 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1181 punit->action = action;
1182 }
1183
1184 (void) place_unit(punit, powner, nullptr, nullptr, FALSE);
1185 }
1186}
1187
1188/**********************************************************************/
1194 int move_cost, bool verbose)
1195{
1196 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1197
1198 if (city_owner(pcity) == unit_owner(punit)) {
1199 log_verbose("Teleported %s %s from (%d,%d) to %s",
1202 if (verbose) {
1205 _("Teleported your %s to %s."),
1207 city_link(pcity));
1208 }
1209
1210 /* Silently free orders since they won't be applicable anymore. */
1212
1213 if (move_cost == -1) {
1214 move_cost = punit->moves_left;
1215 }
1216 unit_move(punit, dst_tile, move_cost,
1217 nullptr, FALSE, FALSE, FALSE, FALSE, FALSE);
1218
1219 return TRUE;
1220 }
1221 return FALSE;
1222}
1223
1224/**********************************************************************/
1231void bounce_unit(struct unit *punit, bool verbose)
1232{
1233 struct player *pplayer;
1234 struct tile *punit_tile;
1235 int count = 0;
1236
1237 /* I assume that there are no topologies that have more than
1238 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1239 const int DIST = 2;
1240 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1241
1242 if (!punit) {
1243 return;
1244 }
1245
1246 pplayer = unit_owner(punit);
1248
1249 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1250 if (count >= ARRAY_SIZE(tiles)) {
1251 break;
1252 }
1253
1254 if (ptile == punit_tile) {
1255 continue;
1256 }
1257
1258 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1259 && !is_non_allied_city_tile(ptile, pplayer)
1260 && !is_non_allied_unit_tile(ptile, pplayer,
1262 tiles[count++] = ptile;
1263 }
1265
1266 if (count > 0) {
1267 struct tile *ptile = tiles[fc_rand(count)];
1268
1269 if (verbose) {
1270 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1271 /* TRANS: A unit is moved to resolve stack conflicts. */
1272 _("Moved your %s."),
1273 unit_link(punit));
1274 }
1275
1276 /* TODO: Should a unit be able to bounce to a transport like is done
1277 * below? What if the unit can't legally enter the transport, say
1278 * because the transport is Unreachable and the unit doesn't have it in
1279 * its embarks field or because "Transport Embark" isn't enabled? Kept
1280 * like it was to preserve the old rules for now. -- Sveinung */
1281 unit_move(punit, ptile, 0, nullptr, TRUE, FALSE, FALSE, FALSE, FALSE);
1282 return;
1283 }
1284
1285 /* Didn't find a place to bounce the unit, going to disband it.
1286 * Try to bounce transported units. */
1288 struct unit_list *pcargo_units;
1289
1292 bounce_unit(pcargo, verbose);
1294 }
1295
1296 if (verbose) {
1298 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1299 _("Disbanded your %s."),
1301 }
1302
1304}
1305
1306/**********************************************************************/
1311static void throw_units_from_illegal_cities(struct player *pplayer,
1312 bool verbose)
1313{
1314 struct tile *ptile;
1315 struct city *pcity;
1316 struct unit *ptrans;
1317 struct unit_list *pcargo_units;
1318
1319 /* Unload undesired units from transports, if possible. */
1320 unit_list_iterate(pplayer->units, punit) {
1321 ptile = unit_tile(punit);
1322 pcity = tile_city(ptile);
1323 if (pcity != nullptr
1324 && !pplayers_allied(city_owner(pcity), pplayer)
1328 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1329 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1331 }
1332 }
1334 }
1336
1337 /* Bounce units except transported ones which will be bounced with their
1338 * transport. */
1340 ptile = unit_tile(punit);
1341 pcity = tile_city(ptile);
1342 if (pcity != nullptr
1343 && !pplayers_allied(city_owner(pcity), pplayer)) {
1345 if (ptrans == nullptr || pplayer != unit_owner(ptrans)) {
1346 bounce_unit(punit, verbose);
1347 }
1348 }
1350
1351#ifdef FREECIV_DEBUG
1352 /* Sanity check. */
1353 unit_list_iterate(pplayer->units, punit) {
1354 ptile = unit_tile(punit);
1355 pcity = tile_city(ptile);
1356 fc_assert_msg(pcity == nullptr
1357 || pplayers_allied(city_owner(pcity), pplayer),
1358 "Failed to throw %s %d from %s %d (%d, %d)",
1360 punit->id,
1362 pcity->id,
1363 TILE_XY(ptile));
1365#endif /* FREECIV_DEBUG */
1366}
1367
1368/**********************************************************************/
1376static void resolve_stack_conflicts(struct player *pplayer,
1377 struct player *aplayer, bool verbose)
1378{
1380 struct tile *ptile = unit_tile(punit);
1381
1382 /* Can pass FALSE 'everyone_non_allied' since no flagless
1383 * unit could be stacked there to begin with. */
1384 if (is_non_allied_unit_tile(ptile, pplayer, FALSE)) {
1386 if (unit_owner(aunit) == pplayer
1387 || unit_owner(aunit) == aplayer
1388 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1389 bounce_unit(aunit, verbose);
1390 }
1392 }
1394}
1395
1396/**********************************************************************/
1407void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1408 bool verbose)
1409{
1410 throw_units_from_illegal_cities(pplayer, verbose);
1412
1413 resolve_stack_conflicts(pplayer, aplayer, verbose);
1414 resolve_stack_conflicts(aplayer, pplayer, verbose);
1415}
1416
1417/**********************************************************************/
1422struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1423 const struct player *aplayer)
1424{
1425 struct unit_list *seen_units = unit_list_new();
1426
1427 /* Anybody's units inside ally's cities */
1428 city_list_iterate(aplayer->cities, pcity) {
1430 if (can_player_see_unit(pplayer, punit)) {
1432 }
1435
1436 /* Ally's own units inside transports */
1438 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1440 }
1442
1443 /* Make sure the same unit is not added in multiple phases
1444 * (unit within transport in a city) */
1446
1447 return seen_units;
1448}
1449
1450/**********************************************************************/
1457void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1458 const struct unit_list *seen_units)
1459{
1461 /* We need to hide units previously seen by the client. */
1462 if (!can_player_see_unit(pplayer, punit)) {
1463 unit_goes_out_of_sight(pplayer, punit);
1464 }
1466
1467 city_list_iterate(aplayer->cities, pcity) {
1468 /* The player used to know what units were in these cities. Now that
1469 * they don't, they need to get a new short city packet updating the
1470 * occupied status. */
1471 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1472 send_city_info(pplayer, pcity);
1473 }
1475}
1476
1477/**********************************************************************/
1481void give_allied_visibility(struct player *pplayer,
1482 struct player *aplayer)
1483{
1485 if (can_player_see_unit(pplayer, punit)) {
1486 send_unit_info(pplayer->connections, punit);
1487 }
1489}
1490
1491/**********************************************************************/
1494static bool is_refuel_tile(const struct tile *ptile,
1495 const struct player *pplayer,
1496 const struct unit *punit)
1497{
1498 const struct unit_type *utype;
1499 const struct unit_class *pclass;
1500
1501 if (is_allied_city_tile(ptile, pplayer)) {
1502 return TRUE;
1503 }
1504
1505 utype = unit_type_get(punit);
1506 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1507 return TRUE;
1508 }
1509
1510 pclass = utype_class(utype);
1511 if (pclass->cache.refuel_extras != nullptr) {
1512 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1513
1514 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1515 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1516 return TRUE;
1517 }
1519 }
1520
1521 return FALSE;
1522}
1523
1524/**********************************************************************/
1528{
1529 return unit_transported(punit) /* Carrier */
1531}
1532
1533/**********************************************************************/
1536bool is_refuel_point(const struct tile *ptile,
1537 const struct player *pplayer,
1538 const struct unit *punit)
1539{
1540 if (is_non_allied_unit_tile(ptile, pplayer,
1542 return FALSE;
1543 }
1544
1545 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1546}
1547
1548/**********************************************************************/
1559void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1560 int vet_loss)
1561{
1562 struct player *pplayer = unit_owner(punit);
1563 const struct unit_type *old_type = punit->utype;
1565 int old_hp = unit_type_get(punit)->hp;
1566 int lvls;
1567
1568 punit->utype = to_unit;
1569
1570 /* New type may not have the same veteran system, and we may want to
1571 * knock some levels off. */
1574 /* Keeping the old behavior, so first clip top, then reduce */
1576
1577 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1578 * and don't kill the unit. unit_move_rate() is used to take into account
1579 * global effects like Magellan's Expedition. */
1580 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1581 if (old_mr == 0) {
1583 } else {
1585 }
1586
1588
1592 }
1593
1594 /* Update unit upkeep */
1596
1598
1600
1601 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1603
1604 send_unit_info(nullptr, punit);
1606}
1607
1608/**********************************************************************/
1611struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1612 const struct unit_type *type, int veteran_level,
1613 int homecity_id, int moves_left)
1614{
1615 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1616 moves_left, -1, nullptr);
1617}
1618
1619/**********************************************************************/
1623{
1624 if (punit->homecity != 0) {
1626
1627 if (home != nullptr && game.info.goods_selection == GSM_LEAVING) {
1629 }
1630 }
1631}
1632
1633/**********************************************************************/
1638struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1639 const struct unit_type *type, int veteran_level,
1640 int homecity_id, int moves_left, int hp_left,
1641 struct unit *ptrans)
1642{
1643 struct unit *punit
1644 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1647 ? nullptr : game_city_by_number(homecity_id);
1648 bool could_place;
1649
1650 fc_assert_ret_val(punit, nullptr);
1653 if (!could_place) {
1655 punit = nullptr;
1656 }
1657
1658 return punit;
1659}
1660
1661/**********************************************************************/
1671struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1672 const struct unit_type *type,
1673 int veteran_level, int homecity_id,
1674 int moves_left, int hp_left)
1675{
1676 struct unit *punit;
1677
1678 fc_assert_ret_val(ptile != nullptr, nullptr);
1679 punit = unit_virtual_create(pplayer, nullptr, type, veteran_level);
1680 unit_tile_set(punit, ptile);
1681
1683 punit->homecity = 0; /* None */
1684 } else {
1686 }
1687
1688 if (hp_left >= 0) {
1689 /* Override default full HP */
1690 punit->hp = hp_left;
1691 }
1692
1693 if (moves_left >= 0) {
1694 int mr = unit_move_rate(punit);
1695
1696 /* Override default full MP */
1697 /* FIXME: there are valid situations when a unit have mp
1698 * over its move rate. Here, keeping the old behavior. */
1700 /* Assume that if moves_left < 0 then the unit is "fresh",
1701 * and not moved; else the unit has had something happen
1702 * to it (eg, bribed) which we treat as equivalent to moved.
1703 * (Otherwise could pass moved arg too...) --dwp */
1704 punit->moved = TRUE;
1705 }
1706
1707 return punit;
1708}
1709
1710/**********************************************************************/
1719bool place_unit(struct unit *punit, struct player *pplayer,
1720 struct city *pcity, struct unit *ptrans, bool force)
1721{
1722 struct tile *ptile;
1723
1724 fc_assert_ret_val(pplayer, FALSE);
1726 ptile = punit->tile;
1727 fc_assert_ret_val(ptile, FALSE);
1728
1729 /* Register unit */
1732
1733 if (ptrans) {
1734 /* Set transporter for unit. */
1736 }
1737
1739 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1740 FALSE);
1741
1742 unit_list_prepend(pplayer->units, punit);
1743 unit_list_prepend(ptile->units, punit);
1744 unit_make_contact(punit, ptile, nullptr);
1747 fc_assert(city_owner(pcity) == pplayer);
1748 unit_list_prepend(pcity->units_supported, punit);
1749 /* update unit upkeep */
1751 /* Refresh the unit's homecity. */
1753 send_city_info(pplayer, pcity);
1754 }
1755
1756 punit->server.vision = vision_new(pplayer, ptile);
1758
1760
1761 send_unit_info(nullptr, punit);
1763
1764 /* The unit may have changed the available tiles in nearby cities. */
1766 sync_cities();
1767
1768 CALL_FUNC_EACH_AI(unit_created, punit);
1769 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1770
1771 return TRUE;
1772}
1773
1774/**********************************************************************/
1778 void (*callback)(struct unit *punit))
1779{
1780 /* Tried to overwrite another call back. If this assertion is triggered
1781 * in a case where two call back are needed it may be time to support
1782 * more than one unit removal call back at a time. */
1784
1786}
1787
1788/**********************************************************************/
1792{
1793 punit->server.removal_callback = nullptr;
1794}
1795
1796/**********************************************************************/
1800static void server_remove_unit_full(struct unit *punit, bool transported,
1802{
1803 struct packet_unit_remove packet;
1804 struct tile *ptile = unit_tile(punit);
1805 struct city *pcity = tile_city(ptile);
1807 struct unit *ptrans;
1808 struct player *pplayer = unit_owner(punit);
1809
1810 /* The unit is doomed. */
1812
1813#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1814 unit_list_iterate(ptile->units, pcargo) {
1817#endif /* FREECIV_DEBUG */
1818
1819 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1820 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1821
1822 /* Save transporter for updating below. */
1824 /* Unload unit. */
1826
1827 /* Since settlers plot in new cities in the minimap before they
1828 are built, so that no two settlers head towards the same city
1829 spot, we need to ensure this reservation is cleared should
1830 the settler disappear on the way. */
1831 adv_unit_new_task(punit, AUT_NONE, nullptr);
1832
1833 /* Clear the vision before sending unit remove. Else, we might duplicate
1834 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1835 if (punit->server.vision != nullptr) {
1838 punit->server.vision = nullptr;
1839 }
1840
1841 packet.unit_id = punit->id;
1842 /* Send to onlookers. */
1845 transported)) {
1846 lsend_packet_unit_remove(aplayer->connections, &packet);
1847 }
1849 /* Send to global observers. */
1853 }
1855
1856 if (punit->server.moving != nullptr) {
1857 /* Do not care of this unit for running moves. */
1858 punit->server.moving->punit = nullptr;
1859 }
1860
1861 if (punit->server.removal_callback != nullptr) {
1862 /* Run the unit removal call back. */
1864 }
1865
1866 /* check if this unit had UTYF_GAMELOSS flag */
1868 && ULR_EDITOR != reason) {
1870 _("Unable to defend %s, %s has lost the game."),
1872 player_name(pplayer));
1873 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1874 _("Losing %s meant losing the game! "
1875 "Be more careful next time!"),
1876 unit_link(punit));
1878 }
1879
1882
1885 punit = nullptr;
1886
1887 if (ptrans != nullptr) {
1888 /* Update the occupy info. */
1889 send_unit_info(nullptr, ptrans);
1890 }
1891
1892 /* This unit may have blocked tiles of adjacent cities. Update them. */
1894 sync_cities();
1895
1896 if (phomecity) {
1899 }
1900
1901 if (pcity && pcity != phomecity) {
1904 }
1905
1906 if (pcity && unit_list_size(ptile->units) == 0) {
1907 /* The last unit in the city was killed: update the occupied flag. */
1908 send_city_info(nullptr, pcity);
1909 }
1910}
1911
1912/**********************************************************************/
1921
1922/**********************************************************************/
1925static void unit_lost_with_transport(const struct player *pplayer,
1926 struct unit *pcargo,
1927 const struct unit_type *ptransport,
1928 struct player *killer)
1929{
1931 _("%s lost when %s was lost."),
1934 /* Unit is not transported any more at this point, but it has jumped
1935 * off the transport and drowns outside. So it must be removed from
1936 * all clients.
1937 * However, we don't know if given client has received ANY updates
1938 * about the swimming unit, and we can't remove it if it's not there
1939 * in the first place -> we send it once here just to be sure it's
1940 * there. */
1941 send_unit_info(nullptr, pcargo);
1943}
1944
1945/**********************************************************************/
1949static void wipe_unit_full(struct unit *punit, bool transported,
1951 struct player *killer)
1952{
1953 struct tile *ptile = unit_tile(punit);
1954 struct player *pplayer = unit_owner(punit);
1955 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1956 struct unit_list *helpless = unit_list_new();
1957 struct unit_list *imperiled = unit_list_new();
1958 struct unit_list *unsaved = unit_list_new();
1960 struct city *pexclcity;
1961 struct civ_map *nmap = &(wld.map);
1962
1963 if (killer != nullptr
1966 player_loot_player(killer, pplayer);
1967 }
1968
1969 /* The unit is doomed. */
1971
1972 /* If a unit is being lost due to loss of its city, ensure that we don't
1973 * try to teleport any of its cargo to that city (which may not yet
1974 * have changed hands or disappeared). (It is assumed that the unit's
1975 * home city is always the one that is being lost/transferred/etc.) */
1976 if (reason == ULR_CITY_LOST) {
1978 } else {
1979 pexclcity = nullptr;
1980 }
1981
1982 /* Remove unit itself from its transport */
1983 if (ptrans != nullptr) {
1985 send_unit_info(nullptr, ptrans);
1986 }
1987
1988 /* First pull all units off of the transporter. */
1990 /* Use iterate_safe as unloaded units will be removed from the list
1991 * while iterating. */
1993 bool healthy = FALSE;
1994
1995 if (!can_unit_unload(pcargo, punit)) {
1997 } else {
1998 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
2000 } else {
2001 /* These units do not need to be saved. */
2002 healthy = TRUE;
2003 }
2004 }
2005
2006 /* Could use unit_transport_unload_send() here, but that would
2007 * call send_unit_info() for the transporter unnecessarily.
2008 * Note that this means that unit might to get seen briefly
2009 * by clients other than owner's, for example as a result of
2010 * update of homecity common to this cargo and some other
2011 * destroyed unit. */
2013 if (pcargo->activity == ACTIVITY_SENTRY) {
2014 /* Activate sentried units - like planes on a disbanded carrier.
2015 * Note this will activate ground units even if they just change
2016 * transporter. */
2018 }
2019
2020 /* Unit info for unhealthy units will be sent when they are
2021 * assigned new transport or removed. */
2022 if (healthy) {
2023 send_unit_info(nullptr, pcargo);
2024 }
2026 }
2027
2028 /* Now remove the unit. */
2029 server_remove_unit_full(punit, transported, reason);
2030
2031 switch (reason) {
2032 case ULR_KILLED:
2033 case ULR_EXECUTED:
2034 case ULR_SDI:
2035 case ULR_NUKE:
2036 case ULR_BRIBED:
2037 case ULR_CAPTURED:
2038 case ULR_CAUGHT:
2039 case ULR_ELIMINATED:
2040 case ULR_TRANSPORT_LOST:
2041 if (killer != nullptr) {
2042 killer->score.units_killed++;
2043 }
2044 pplayer->score.units_lost++;
2045 break;
2046 case ULR_BARB_UNLEASH:
2047 case ULR_CITY_LOST:
2048 case ULR_STARVED:
2049 case ULR_UPKEEP:
2050 case ULR_NONNATIVE_TERR:
2051 case ULR_ARMISTICE:
2052 case ULR_HP_LOSS:
2053 case ULR_FUEL:
2054 case ULR_STACK_CONFLICT:
2055 case ULR_SOLD:
2056 pplayer->score.units_lost++;
2057 break;
2058 case ULR_RETIRED:
2059 case ULR_DISBANDED:
2060 case ULR_USED:
2061 case ULR_DETONATED:
2062 case ULR_MISSILE:
2063 pplayer->score.units_used++;
2064 break;
2065 case ULR_EDITOR:
2066 case ULR_PLAYER_DIED:
2067 break;
2068 }
2069
2070 /* First, sort out helpless cargo. */
2071 if (unit_list_size(helpless) > 0) {
2072 struct unit_list *remaining = unit_list_new();
2073
2074 /* Grant priority to gameloss units and units with the EvacuateFirst
2075 * unit type flag. */
2082 pexclcity)) {
2084 }
2085 } else {
2086 unit_list_prepend(remaining, pcargo);
2087 }
2089
2090 /* Handle non-priority units. */
2091 unit_list_iterate_safe(remaining, pcargo) {
2094 }
2096
2097 unit_list_destroy(remaining);
2098 }
2100
2101 /* Then, save any imperiled cargo. */
2102 if (unit_list_size(imperiled) > 0) {
2103 struct unit_list *remaining = unit_list_new();
2104
2105 /* Grant priority to gameloss units and units with the EvacuateFirst
2106 * unit type flag. */
2113 pexclcity)) {
2115 }
2116 } else {
2117 unit_list_prepend(remaining, pcargo);
2118 }
2120
2121 /* Handle non-priority units. */
2122 unit_list_iterate_safe(remaining, pcargo) {
2125 }
2127
2128 unit_list_destroy(remaining);
2129 }
2131
2132 /* Finally, kill off the unsaved units. */
2133 if (unit_list_size(unsaved) > 0) {
2137 }
2139}
2140
2141/**********************************************************************/
2150
2151/**********************************************************************/
2157static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2158 bool helpless, bool teleporting,
2159 const struct city *pexclcity)
2160{
2161 struct tile *ptile = unit_tile(punit);
2162 struct player *pplayer = unit_owner(punit);
2164
2165 /* Helpless units cannot board a transport in their current state. */
2166 if (!helpless
2167 && ptransport != nullptr) {
2169 send_unit_info(nullptr, punit);
2170 return TRUE;
2171 } else {
2172 /* Only units that cannot find transport are considered for teleport. */
2173 if (teleporting) {
2174 struct city *pcity = find_closest_city(ptile, pexclcity,
2178 if (pcity != nullptr) {
2179 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2180
2182
2184 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2185 _("%s escaped the destruction of %s, and fled to %s."),
2186 tplink,
2188 city_link(pcity));
2189 return TRUE;
2190 }
2191 }
2192 }
2193 }
2194
2195 /* The unit could not use transport on the tile, and could not teleport. */
2196 return FALSE;
2197}
2198
2199/**********************************************************************/
2205struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2207{
2208 struct unit *gained_unit;
2209 int id = 0;
2210
2211#ifndef FREECIV_NDEBUG
2212 bool placed;
2213#endif
2214
2217
2218 /* Convert the unit to your cause. It's supposed that the original unit
2219 * is on a valid tile and is not transported. */
2223 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2224
2225 /* Owner changes, nationality not. */
2226 gained_unit->nationality = punit->nationality;
2227
2228 /* Copy some more unit fields */
2229 gained_unit->fuel = punit->fuel;
2230 gained_unit->paradropped = punit->paradropped;
2231 gained_unit->birth_turn = punit->birth_turn;
2232 gained_unit->current_form_turn = punit->current_form_turn;
2233
2234 /* Fog is lifted in the placing algorithm. */
2235#ifndef FREECIV_NDEBUG
2236 placed =
2237#endif
2238 place_unit(gained_unit, pplayer,
2240 nullptr, FALSE);
2241
2243
2244 id = gained_unit->id;
2245
2246 /* Update unit upkeep in the new homecity */
2247 if (homecity > 0) {
2249 }
2250
2251 /* Be sure to wipe the converted unit! */
2252 /* Old homecity upkeep is updated in process */
2253#ifndef FREECIV_NDEBUG
2254 uco_wipe:
2255#endif
2256
2257 wipe_unit(punit, reason, nullptr);
2258
2259 if (!unit_is_alive(id)) {
2260 /* Destroyed by a script */
2261 return nullptr;
2262 }
2263
2264 return gained_unit; /* Returns the replacement. */
2265}
2266
2267/**********************************************************************/
2272void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2273{
2275 struct player *pvictim = unit_owner(punit);
2276 struct player *pvictor = unit_owner(pkiller);
2277 struct tile *deftile = unit_tile(punit);
2278 int unitcount = 0;
2279 bool escaped;
2282 const struct civ_map *nmap = &(wld.map);
2283
2286
2287 /* The unit is doomed. */
2289
2291 if ((flagless_killer
2295 unitcount++;
2296 }
2298
2299 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2300 if (vet) {
2302 }
2304 } else { /* Unitcount > 1 */
2305 int i;
2306 int slots = player_slot_count();
2307 int num_killed[slots];
2308 int num_escaped[slots];
2309 struct unit *other_killed[slots];
2310
2311 fc_assert(unitcount > 1);
2312
2313 /* Initialize */
2314 for (i = 0; i < slots; i++) {
2315 num_killed[i] = 0;
2316 other_killed[i] = nullptr;
2317 num_escaped[i] = 0;
2318 }
2319
2320 /* Count killed units */
2322 struct player *vplayer = unit_owner(vunit);
2323
2326 escaped = FALSE;
2327
2330 && vunit->hp > 0
2331 && vunit->moves_left > pkiller->moves_left
2332 && fc_rand(2)) {
2333 int curr_def_bonus;
2334 int def_bonus = 0;
2335 struct tile *dsttile = nullptr;
2336 int move_cost;
2337
2338 fc_assert(vunit->hp > 0);
2339
2341 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2342 && tile_city(ptile2) == nullptr) {
2343 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2344 if (pkiller->moves_left <= vunit->moves_left - move_cost
2346 || unit_list_size(ptile2->units)) == 0) {
2348 vunit->utype);
2349 if (def_bonus <= curr_def_bonus) {
2351 dsttile = ptile2;
2352 }
2353 }
2354 }
2356
2357 if (dsttile != nullptr) {
2360 nullptr, nullptr, dsttile,
2362 nullptr, nullptr)
2363 != nullptr);
2364
2365 if (escaped) {
2367 unitcount--;
2368 }
2369 }
2370 }
2371
2372 if (!escaped) {
2374
2375 if (vunit != punit) {
2378 }
2379 }
2380 }
2382
2383 /* Inform the destroyer again if more than one unit was killed */
2384 if (unitcount > 1) {
2385 if (flagless_victim) {
2387 /* TRANS: "... Cannon ... Destroyer ...." */
2388 PL_("Your attacking %s succeeded against %s "
2389 "(and %d other unit)!",
2390 "Your attacking %s succeeded against %s "
2391 "(and %d other units)!", unitcount - 1),
2393 punit_link,
2394 unitcount - 1);
2395 } else {
2397 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2398 PL_("Your attacking %s succeeded against the %s %s "
2399 "(and %d other unit)!",
2400 "Your attacking %s succeeded against the %s %s "
2401 "(and %d other units)!", unitcount - 1),
2404 punit_link,
2405 unitcount - 1);
2406 }
2407 }
2408
2409 if (vet) {
2411 }
2412
2413 /* Inform the owners: this only tells about owned units that were killed.
2414 * there may have been 20 units who died but if only 2 belonged to the
2415 * particular player they'll only learn about those.
2416 *
2417 * Also if a large number of units die you don't find out what type
2418 * they all are. */
2419 for (i = 0; i < slots; i++) {
2420 if (num_killed[i] == 1) {
2421 if (i == player_index(pvictim)) {
2422 fc_assert(other_killed[i] == nullptr);
2423
2424 if (flagless_killer) {
2427 /* TRANS: "Cannon ... Destroyer." */
2428 _("%s lost to an attack by %s."),
2429 punit_link,
2430 pkiller_link);
2431 } else {
2434 /* TRANS: "Cannon ... the Polish Destroyer." */
2435 _("%s lost to an attack by the %s %s."),
2436 punit_link,
2438 pkiller_link);
2439 }
2440 } else {
2442
2443 if (flagless_victim) {
2444 if (flagless_killer) {
2447 /* TRANS: "Cannon lost when Destroyer
2448 * attacked Musketeers." */
2449 _("%s lost when %s attacked %s."),
2452 punit_link);
2453 } else {
2456 /* TRANS: "Cannon lost when the Polish Destroyer
2457 * attacked Musketeers." */
2458 _("%s lost when the %s %s attacked %s."),
2462 punit_link);
2463 }
2464 } else {
2465 if (flagless_killer) {
2468 /* TRANS: "Cannon lost when Destroyer
2469 * attacked the German Musketeers." */
2470 _("%s lost when %s attacked the %s %s."),
2474 punit_link);
2475 } else {
2478 /* TRANS: "Cannon lost when the Polish Destroyer
2479 * attacked the German Musketeers." */
2480 _("%s lost when the %s %s attacked the %s %s."),
2485 punit_link);
2486 }
2487 }
2488 }
2489 } else if (num_killed[i] > 1) {
2490 if (i == player_index(pvictim)) {
2491 int others = num_killed[i] - 1;
2492
2493 if (others == 1) {
2494 if (flagless_killer) {
2497 /* TRANS: "Musketeers (and Cannon) lost to an
2498 * attack from Destroyer." */
2499 _("%s (and %s) lost to an attack from %s."),
2500 punit_link,
2502 pkiller_link);
2503 } else {
2506 /* TRANS: "Musketeers (and Cannon) lost to an
2507 * attack from the Polish Destroyer." */
2508 _("%s (and %s) lost to an attack from the %s %s."),
2509 punit_link,
2512 pkiller_link);
2513 }
2514 } else {
2515 if (flagless_killer) {
2518 /* TRANS: "Musketeers and 3 other units lost to
2519 * an attack from Destroyer."
2520 * (only happens with at least 2 other units) */
2521 PL_("%s and %d other unit lost to an attack "
2522 "from %s.",
2523 "%s and %d other units lost to an attack "
2524 "from %s.", others),
2525 punit_link,
2526 others,
2527 pkiller_link);
2528 } else {
2531 /* TRANS: "Musketeers and 3 other units lost to
2532 * an attack from the Polish Destroyer."
2533 * (only happens with at least 2 other units) */
2534 PL_("%s and %d other unit lost to an attack "
2535 "from the %s %s.",
2536 "%s and %d other units lost to an attack "
2537 "from the %s %s.", others),
2538 punit_link,
2539 others,
2541 pkiller_link);
2542 }
2543 }
2544 } else {
2545 if (flagless_victim) {
2546 if (flagless_killer) {
2549 /* TRANS: "2 units lost when Destroyer
2550 * attacked Musketeers."
2551 * (only happens with at least 2 other units) */
2552 PL_("%d unit lost when %s attacked %s.",
2553 "%d units lost when %s attacked %s.",
2554 num_killed[i]),
2555 num_killed[i],
2557 punit_link);
2558 } else {
2561 /* TRANS: "2 units lost when the Polish Destroyer
2562 * attacked Musketeers."
2563 * (only happens with at least 2 other units) */
2564 PL_("%d unit lost when the %s %s attacked %s.",
2565 "%d units lost when the %s %s attacked %s.",
2566 num_killed[i]),
2567 num_killed[i],
2570 punit_link);
2571 }
2572 } else {
2573 if (flagless_killer) {
2576 /* TRANS: "2 units lost when Destroyer
2577 * attacked the German Musketeers."
2578 * (only happens with at least 2 other units) */
2579 PL_("%d unit lost when %s attacked the %s %s.",
2580 "%d units lost when %s attacked the %s %s.",
2581 num_killed[i]),
2582 num_killed[i],
2585 punit_link);
2586 } else {
2589 /* TRANS: "2 units lost when the Polish Destroyer
2590 * attacked the German Musketeers."
2591 * (only happens with at least 2 other units) */
2592 PL_("%d unit lost when the %s %s attacked the %s %s.",
2593 "%d units lost when the %s %s attacked the %s %s.",
2594 num_killed[i]),
2595 num_killed[i],
2599 punit_link);
2600 }
2601 }
2602 }
2603 }
2604 }
2605
2606 /* Inform the owner of the units that escaped.
2607 * 'deftile' is the original tile they defended at, not where
2608 * they escaped to, as there might be multiple different tiles
2609 * different units escaped to. */
2610 for (i = 0; i < slots; i++) {
2611 if (0 < num_escaped[i]) {
2612 if (flagless_killer) {
2615 PL_("%d unit escaped from attack by %s",
2616 "%d units escaped from attack by %s",
2617 num_escaped[i]),
2618 num_escaped[i],
2619 pkiller_link);
2620 } else {
2623 PL_("%d unit escaped from attack by %s %s",
2624 "%d units escaped from attack by %s %s",
2625 num_escaped[i]),
2626 num_escaped[i],
2628 pkiller_link);
2629 }
2630 }
2631 }
2632
2633 /* Remove the units - note the logic of which units actually die
2634 * must be mimiced exactly in at least one place up above. */
2635 punit = nullptr; /* Wiped during following iteration so unsafe to use */
2636
2641 }
2643 }
2644}
2645
2646/**********************************************************************/
2649void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2650{
2651 struct player *pvictim = unit_owner(punit);
2654 struct tile *deftile = unit_tile(punit);
2655 int unitcount, ransom;
2656
2657 /* The unit is doomed. */
2659
2662
2663 if (pvictim->economic.gold < ransom) {
2664 ransom = pvictim->economic.gold;
2665 }
2666
2668 PL_("%d Barbarian leader captured.",
2669 "%d Barbarian leaders captured.",
2670 unitcount),
2671 unitcount);
2673 PL_("%d gold ransom paid.",
2674 "%d gold ransom paid.",
2675 ransom),
2676 ransom);
2677 pvictor->economic.gold += ransom;
2678 pvictim->economic.gold -= ransom;
2679 send_player_info_c(pvictor, nullptr); /* Let me see my new gold :-) */
2680
2681 if (vet) {
2683 }
2684
2687
2688 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2690 } else {
2691 int i;
2692 int slots = player_slot_count();
2693 int num_collected[slots];
2694
2695 fc_assert(unitcount > 1);
2696
2697 /* Initialize */
2698 for (i = 0; i < slots; i++) {
2699 num_collected[i] = 0;
2700 }
2701
2702 /* Count captured units */
2704 struct player *vplayer = unit_owner(vunit);
2705
2708
2709 for (i = 0; i < slots; i++) {
2710 if (num_collected[i] == 1) {
2713 _("%s %s collected ransom of %s."),
2716 } else if (num_collected[i] > 1) {
2719 PL_("%s %s collected ransom of %s and %d other unit.",
2720 "%s %s collected ransom of %s and %d other units.",
2721 num_collected[i] - 1),
2724 punit_link,
2725 num_collected[i] - 1);
2726 }
2727 }
2728
2732 }
2733}
2734
2735/**********************************************************************/
2739void package_unit(struct unit *punit, struct packet_unit_info *packet)
2740{
2741 packet->id = punit->id;
2742 packet->owner = player_number(unit_owner(punit));
2744 packet->tile = tile_index(unit_tile(punit));
2745 packet->facing = punit->facing;
2746 packet->homecity = punit->homecity;
2748 packet->upkeep[o] = punit->upkeep[o];
2750 packet->veteran = punit->veteran;
2752 packet->movesleft = punit->moves_left;
2753 packet->hp = punit->hp;
2754 packet->activity = punit->activity;
2756
2757 if (punit->activity_target != nullptr) {
2759 } else {
2760 packet->activity_tgt = EXTRA_NONE;
2761 }
2762
2763 packet->changed_from = punit->changed_from;
2765
2766 if (punit->changed_from_target != nullptr) {
2768 } else {
2769 packet->changed_from_tgt = EXTRA_NONE;
2770 }
2771
2773 packet->fuel = punit->fuel;
2774 packet->goto_tile = (punit->goto_tile != nullptr
2775 ? tile_index(punit->goto_tile) : -1);
2776 packet->paradropped = punit->paradropped;
2777 packet->done_moving = punit->done_moving;
2778 packet->stay = punit->stay;
2779 packet->birth_turn = punit->birth_turn;
2781 if (!unit_transported(punit)) {
2782 packet->transported = FALSE;
2783 packet->transported_by = 0;
2784 } else {
2785 packet->transported = TRUE;
2787 }
2788 if (punit->carrying != nullptr) {
2789 packet->carrying = goods_index(punit->carrying);
2790 } else {
2791 packet->carrying = -1;
2792 }
2793 packet->occupied = (get_transporter_occupancy(punit) > 0);
2794 packet->battlegroup = punit->battlegroup;
2795 packet->has_orders = punit->has_orders;
2796 if (punit->has_orders) {
2797 packet->orders_length = punit->orders.length;
2798 packet->orders_index = punit->orders.index;
2799 packet->orders_repeat = punit->orders.repeat;
2801 memcpy(packet->orders, punit->orders.list,
2802 punit->orders.length * sizeof(struct unit_order));
2803 } else {
2804 packet->orders_length = packet->orders_index = 0;
2805 packet->orders_repeat = packet->orders_vigilant = FALSE;
2806 /* No need to initialize array. */
2807 }
2808
2813}
2814
2815/**********************************************************************/
2821 struct packet_unit_short_info *packet,
2822 enum unit_info_use packet_use, int info_city_id)
2823{
2824 packet->packet_use = packet_use;
2825 packet->info_city_id = info_city_id;
2826
2827 packet->id = punit->id;
2828
2830 packet->owner = OWNER_NONE;
2831 } else {
2832 packet->owner = player_number(unit_owner(punit));
2833 }
2834
2835 packet->tile = tile_index(unit_tile(punit));
2836 packet->facing = punit->facing;
2837 packet->veteran = punit->veteran;
2839 packet->hp = punit->hp;
2840 packet->occupied = (get_transporter_occupancy(punit) > 0);
2842 || punit->activity == ACTIVITY_GOTO) {
2843 packet->activity = ACTIVITY_IDLE;
2844 } else {
2845 packet->activity = punit->activity;
2846 }
2847
2848 if (punit->activity_target == nullptr) {
2849 packet->activity_tgt = EXTRA_NONE;
2850 } else {
2852 }
2853
2854 /* Transported_by information is sent to the client even for units that
2855 * aren't fully known. Note that for non-allied players, any transported
2856 * unit can't be seen at all. For allied players we have to know if
2857 * transporters have room in them so that we can load units properly. */
2858 if (!unit_transported(punit)) {
2859 packet->transported = FALSE;
2860 packet->transported_by = 0;
2861 } else {
2862 packet->transported = TRUE;
2864 }
2865}
2866
2867/**********************************************************************/
2870void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2871{
2873 if (punit->server.moving != nullptr) {
2874 /* Update status of 'pplayer' vision for 'punit'. */
2876 }
2877}
2878
2879/**********************************************************************/
2883void send_unit_info(struct conn_list *dest, struct unit *punit)
2884{
2885 const struct player *powner;
2886 struct packet_unit_info info;
2888 struct unit_move_data *pdata;
2889
2890 if (dest == nullptr) {
2891 dest = game.est_connections;
2892 }
2893
2895
2897 package_unit(punit, &info);
2900
2901 conn_list_iterate(dest, pconn) {
2902 struct player *pplayer = conn_get_player(pconn);
2903
2904 /* Be careful to consider all cases where pplayer is nullptr... */
2905 if (pplayer == nullptr) {
2906 if (pconn->observer) {
2908 }
2909 } else if (pplayer == powner) {
2911 if (pdata != nullptr) {
2912 BV_SET(pdata->can_see_unit, player_index(pplayer));
2913 }
2914 } else if (can_player_see_unit(pplayer, punit)) {
2916 if (pdata != nullptr) {
2917 BV_SET(pdata->can_see_unit, player_index(pplayer));
2918 }
2919 }
2921}
2922
2923/**********************************************************************/
2928{
2929 conn_list_do_buffer(dest);
2930 conn_list_iterate(dest, pconn) {
2931 struct player *pplayer = pconn->playing;
2932
2933 if (pplayer == nullptr && !pconn->observer) {
2934 continue;
2935 }
2936
2939 send_unit_info(dest, punit);
2942 }
2945 flush_packets();
2946}
2947
2948/**********************************************************************/
2955static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2956 const struct action *paction)
2957{
2958 struct city *pcity = nullptr;
2959 int pop_loss;
2960
2961 pcity = tile_city(ptile);
2962
2964
2965 /* unit in a city may survive */
2967 continue;
2968 }
2970 _("Your %s was nuked by %s."),
2972 pplayer == unit_owner(punit)
2973 ? _("yourself")
2974 : nation_plural_for_player(pplayer));
2975 if (unit_owner(punit) != pplayer) {
2976 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2977 _("The %s %s was nuked."),
2980 }
2981 wipe_unit(punit, ULR_NUKE, pplayer);
2983
2984
2985 if (pcity) {
2986 struct player *owner = city_owner(pcity);
2987 char city_name[MAX_LEN_LINK];
2988
2990
2992 _("%s was nuked by %s."),
2993 city_name,
2994 pplayer == owner
2995 ? _("yourself")
2996 : nation_plural_for_player(pplayer));
2997
2998 if (owner != pplayer) {
2999 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3000 _("You nuked %s."),
3001 city_name);
3002 }
3003
3005 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
3006 /* Send city size reduction to everyone seeing it */
3007 send_city_info(nullptr, pcity);
3008 } else {
3009 /* City was destroyed */
3011 _("%s was destroyed by the nuke."),
3012 city_name);
3013 if (owner != pplayer) {
3014 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3015 _("Your nuke destroyed %s."),
3016 city_name);
3017 }
3018 }
3019 }
3020
3021 if (fc_rand(2) == 1) {
3022 struct extra_type *pextra;
3023
3024 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
3025 if (pextra != nullptr && !tile_has_extra(ptile, pextra)) {
3026 tile_add_extra(ptile, pextra);
3027 update_tile_knowledge(ptile);
3028 }
3029 }
3030}
3031
3032/**********************************************************************/
3041 const struct unit_type *act_utype,
3042 struct player *pplayer, struct tile *ptile)
3043{
3045 = get_target_bonus_effects(nullptr,
3046 &(const struct req_context) {
3047 .player = pplayer,
3048 /* City: Wait for users before choosing
3049 * home city or target tile city */
3050 .tile = ptile,
3051 .unittype = act_utype,
3052 .action = paction,
3053 },
3054 nullptr,
3056
3058 do_nuke_tile(pplayer, ptile1, paction);
3060
3061 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
3062 API_TYPE_PLAYER, pplayer);
3063 notify_conn(nullptr, ptile, E_NUKE, ftc_server,
3064 _("The %s detonated a nuke!"),
3065 nation_plural_for_player(pplayer));
3066}
3067
3068/**********************************************************************/
3072bool do_airline(struct unit *punit, struct city *pdest_city,
3073 const struct action *paction)
3074{
3076
3079 _("%s transported successfully."),
3080 unit_link(punit));
3081
3083 nullptr, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
3084 /* Can only airlift to allied and domestic cities */
3085 FALSE, FALSE,
3086 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3088
3089 /* Update airlift fields. */
3091 psrc_city->airlift--;
3093 }
3095 pdest_city->airlift--;
3097 }
3098
3099 return TRUE;
3100}
3101
3102/**********************************************************************/
3105void do_explore(struct unit *punit)
3106{
3107 switch (manage_auto_explorer(punit)) {
3108 case MR_DEATH:
3109 /* don't use punit! */
3110 return;
3111 case MR_NOT_ALLOWED:
3112 /* Needed for something else */
3113 return;
3114 case MR_OK:
3115 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3116 * but don't count on this. See PR#39792.
3117 */
3119 break;
3120 }
3121
3123 default:
3125
3126 /* FIXME: When the manage_auto_explorer() call changes the activity from
3127 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3128 * alone. We reset it here. See PR#12931. */
3130 break;
3131 }
3132
3133 send_unit_info(nullptr, punit); /* Probably duplicate */
3134}
3135
3136/**********************************************************************/
3141bool do_paradrop(struct unit *punit, struct tile *ptile,
3142 const struct action *paction)
3143{
3144 struct player *pplayer = unit_owner(punit);
3145 struct player *tgt_player = tile_owner(ptile);
3146 const struct unit_type *act_utype = unit_type_get(punit);
3147 const struct city *pcity;
3148
3149 /* Hard requirements */
3150 /* FIXME: hard requirements belong in common/actions's
3151 * is_action_possible() and the explanation texts belong in
3152 * server/unithand's action not enabled system (expl_act_not_enabl(),
3153 * ane_kind, explain_why_no_action_enabled(), etc)
3154 */
3155 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3156 /* Only take in account values from player map. */
3157 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3158
3159 if (plrtile->site == nullptr) {
3160 bv_extras fbv;
3161
3162 dbv_to_bv(fbv.vec, &(plrtile->extras));
3163
3165 &fbv)) {
3166 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3167 _("This unit cannot paradrop into %s."),
3169 return FALSE;
3170 }
3171 }
3172
3173 if (plrtile->site != nullptr
3174 && plrtile->owner != nullptr
3175 && !pplayers_allied(pplayer, plrtile->owner)
3177 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3178 /* TRANS: Paratroopers ... Paradrop Unit */
3179 _("%s cannot conquer a city with \"%s\"."),
3182 return FALSE;
3183 }
3184
3185 if (plrtile->site != nullptr
3186 && plrtile->owner != nullptr
3187 && (pplayers_non_attack(pplayer, plrtile->owner)
3188 || (player_diplstate_get(pplayer, plrtile->owner)->type
3189 == DS_ALLIANCE)
3190 || (player_diplstate_get(pplayer, plrtile->owner)->type
3191 == DS_TEAM))
3193 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3194 _("Cannot attack unless you declare war first."));
3195 return FALSE;
3196 }
3197 }
3198
3199
3200 /* Kill the unit when the landing goes wrong. */
3201
3202 /* Safe terrain, really? Not transformed since player last saw it. */
3203 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3204 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3205 || !unit_could_load_at(punit, ptile))) {
3206 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3207 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3208 _("Your %s paradropped into the %s and was lost."),
3211 pplayer->score.units_lost++;
3213 return TRUE;
3214 }
3215
3216 pcity = tile_city(ptile);
3217
3218 if ((pcity != nullptr && !pplayers_allied(pplayer, city_owner(pcity))
3220 || is_non_allied_unit_tile(ptile, pplayer,
3222 struct player *main_victim = nullptr;
3223 struct player *secondary_victim = nullptr;
3225
3226 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3227 unit_make_contact(punit, ptile, pplayer);
3228 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3229 _("Your %s was killed by enemy units at the "
3230 "paradrop destination."),
3232 /* TODO: Should defender score.units_killed get increased too?
3233 * What if there's units of several allied players? Should the
3234 * city owner or owner of the first/random unit get the kill? */
3235 pplayer->score.units_lost++;
3236
3237 if (pcity != nullptr) {
3238 struct player *owner = city_owner(pcity);
3239
3240 if (!pplayers_at_war(pplayer, owner)) {
3242 } else {
3244 }
3245
3247 } else {
3249 }
3250
3251 if (main_victim == nullptr) {
3252 unit_list_iterate(ptile->units, tgt) {
3253 struct player *owner = unit_owner(tgt);
3254
3255 if (!pplayers_at_war(pplayer, owner)) {
3257 break;
3258 } else if (secondary_victim == nullptr) {
3260 }
3262
3263 if (main_victim == nullptr) {
3264 /* There's no victim with whom the attacker isn't in war,
3265 * fallback to one with whom there's already a war. */
3267 }
3268 }
3269
3271 main_victim, ptile,
3272 victim_link);
3273
3275 return TRUE;
3276 }
3277
3278 /* All ok */
3280 if (unit_move(punit, ptile,
3281 /* Done by Action_Success_Actor_Move_Cost */
3282 0,
3283 nullptr, BV_ISSET(paction->sub_results,
3287 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3288 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3289 /* Ensure we finished on valid state. */
3292 }
3293
3294 /* May cause an incident */
3296 ptile, tile_link(ptile));
3297
3298 return TRUE;
3299}
3300
3301/**********************************************************************/
3305static bool hut_get_limited(struct unit *punit)
3306{
3307 bool ok = TRUE;
3308 int hut_chance = fc_rand(12);
3309 struct player *pplayer = unit_owner(punit);
3310 const struct civ_map *nmap = &(wld.map);
3311
3312 /* 1 in 12 to get barbarians */
3313 if (hut_chance != 0) {
3314 int cred = 25;
3315
3317 PL_("You found %d gold.",
3318 "You found %d gold.", cred), cred);
3319 pplayer->economic.gold += cred;
3322 notify_player(pplayer, unit_tile(punit),
3324 _("An abandoned village is here."));
3325 } else {
3327 _("Your %s has been killed by barbarians!"),
3329 wipe_unit(punit, ULR_BARB_UNLEASH, nullptr);
3330 ok = FALSE;
3331 }
3332
3333 return ok;
3334}
3335
3336/**********************************************************************/
3340static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3341{
3342 struct player *pplayer = unit_owner(punit);
3343 int id = punit->id;
3344 struct tile *ptile = unit_tile(punit);
3345 bool hut = FALSE;
3346 const struct req_context context = {
3347 .player = pplayer,
3348 .tile = ptile,
3349 };
3350
3352 if (tile_has_extra(ptile, pextra)
3354 &(const struct req_context) {
3355 .player = tile_owner(ptile),
3356 },
3357 &pextra->rmreqs,
3359 ) {
3360 hut = TRUE;
3361 /* FIXME: are all enter-removes extras worth counting? */
3362 pplayer->server.huts++;
3363
3364 destroy_extra(ptile, pextra);
3366
3367 /* FIXME: enable different classes
3368 * to behave differently with different huts */
3369 if (frighten_hut) {
3370 script_server_signal_emit("hut_frighten", punit,
3371 extra_rule_name(pextra));
3372 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3373 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3375 } else {
3376 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3377 }
3378
3379 /* We need punit for the callbacks, can't continue if the unit died */
3380 if (!unit_is_alive(id)) {
3381 break;
3382 }
3383 }
3385
3386 if (hut) {
3387 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3388 }
3389 return;
3390}
3391
3392/**********************************************************************/
3396{
3397 bv_player can_see_unit;
3398
3399 fc_assert_ret(punit != nullptr);
3400 fc_assert_ret(ptrans != nullptr);
3401
3402 BV_CLR_ALL(can_see_unit);
3403 players_iterate(pplayer) {
3404 if (can_player_see_unit(pplayer, punit)) {
3405 BV_SET(can_see_unit, player_index(pplayer));
3406 }
3408
3410
3411 players_iterate(pplayer) {
3412 if (BV_ISSET(can_see_unit, player_index(pplayer))
3413 && !can_player_see_unit(pplayer, punit)) {
3414 unit_goes_out_of_sight(pplayer, punit);
3415 }
3417
3418 send_unit_info(nullptr, punit);
3419 send_unit_info(nullptr, ptrans);
3420}
3421
3422/**********************************************************************/
3426 struct unit *ptrans,
3427 bool force)
3428{
3429 bool had_cargo;
3430
3431 fc_assert_ret(punit != nullptr);
3432 fc_assert_ret(ptrans != nullptr);
3433
3435
3437
3438 if (!had_cargo) {
3439 /* Transport's loaded status changed */
3440 send_unit_info(nullptr, ptrans);
3441 }
3442}
3443
3444/**********************************************************************/
3448{
3449 struct unit *ptrans;
3450
3452
3454
3456
3458
3459 send_unit_info(nullptr, punit);
3460 send_unit_info(nullptr, ptrans);
3461}
3462
3463/**********************************************************************/
3467static void autoattack_prob_free(struct autoattack_prob *prob)
3468{
3469 free(prob);
3470}
3471
3472/**********************************************************************/
3481static int compare_units(const struct autoattack_prob *const *p1,
3482 const struct autoattack_prob *const *q1)
3483{
3484 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3485 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3486
3487 /* Sort by transport depth first. This makes sure that no transport
3488 * attacks before its cargo does -- cargo sorts earlier in the list. */
3489 {
3490 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3491
3492 /* Walk the transport stacks in parallel, so as to bail out as soon as
3493 * one of them is empty (avoid walking deep stacks more often than
3494 * necessary). */
3495 while (p1trans && q1trans) {
3498 }
3499 if (!p1trans && q1trans) {
3500 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3501 * earlier in the list (p1 > q1). */
3502 return 1;
3503 } else if (p1trans && !q1trans) {
3504 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3505 return -1;
3506 }
3507 /* else same depth, so move on to checking win chance: */
3508 }
3509
3510 /* Put the units with the highest probability of success first. The up
3511 * side of this is that units with bonuses against the victim attacks
3512 * before other units. The downside is that strong units can be led
3513 * away by sacrificial units. */
3514 return (-1
3515 /* Assume the worst. */
3516 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3517}
3518
3519/**********************************************************************/
3524{
3525 struct autoattack_prob_list *autoattack;
3526 int moves = punit->moves_left;
3527 int sanity1 = punit->id;
3528 struct civ_map *nmap = &(wld.map);
3529
3530 if (!game.server.autoattack) {
3531 return TRUE;
3532 }
3533
3535
3536 /* Kludge to prevent attack power from dropping to zero during calc */
3538
3539 adjc_iterate(nmap, unit_tile(punit), ptile) {
3540 /* First add all eligible units to a autoattack list */
3541 unit_list_iterate(ptile->units, penemy) {
3543 struct tile *tgt_tile = unit_tile(punit);
3544
3545 fc_assert_action(tgt_tile, continue);
3546
3547 probability->prob =
3549 penemy, unit_owner(punit), nullptr, nullptr,
3551 punit, nullptr);
3552
3553 if (action_prob_possible(probability->prob)) {
3554 probability->unit_id = penemy->id;
3556 } else {
3558 }
3561
3562 /* Sort the potential attackers from highest to lowest success
3563 * probability. */
3564 if (autoattack_prob_list_size(autoattack) >= 2) {
3566 }
3567
3569 int sanity2 = penemy->id;
3570 struct tile *ptile = unit_tile(penemy);
3571 struct unit *enemy_defender = get_defender(nmap, punit, ptile, nullptr);
3572 double punitwin, penemywin;
3573 double threshold = 0.25;
3574 struct tile *tgt_tile = unit_tile(punit);
3575
3577
3578 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3579 /* Don't leave city defenseless */
3580 threshold = 0.90;
3581 }
3582
3583 if (enemy_defender != nullptr) {
3585 } else {
3586 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3587 punitwin = 1.0;
3588 }
3589
3590 /* Previous attacks may have changed the odds. Recalculate. */
3591 peprob->prob =
3593 penemy, unit_owner(punit), nullptr, nullptr,
3595 punit, nullptr);
3596
3597 if (!action_prob_possible(peprob->prob)) {
3598 /* No longer legal. */
3599 continue;
3600 }
3601
3602 /* Assume the worst. */
3604
3605 if ((penemywin > 1.0 - punitwin
3607 && penemywin > threshold) {
3608
3609#ifdef REALLY_DEBUG_THIS
3610 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3613 1.0 - punitwin, threshold);
3614#endif
3615
3618 penemy, unit_owner(punit), nullptr, nullptr,
3619 tgt_tile, tile_city(tgt_tile), punit, nullptr);
3620 } else {
3621#ifdef REALLY_DEBUG_THIS
3622 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3625 1.0 - punitwin, threshold);
3626#endif
3627 continue;
3628 }
3629
3631 send_unit_info(nullptr, penemy);
3632 }
3634 send_unit_info(nullptr, punit);
3635 } else {
3636 autoattack_prob_list_destroy(autoattack);
3637 return FALSE; /* moving unit dead */
3638 }
3640
3641 autoattack_prob_list_destroy(autoattack);
3643 /* We could have lost movement in combat */
3645 send_unit_info(nullptr, punit);
3646 return TRUE;
3647 } else {
3648 return FALSE;
3649 }
3650}
3651
3652/**********************************************************************/
3655static void cancel_orders(struct unit *punit, char *dbg_msg)
3656{
3658 send_unit_info(nullptr, punit);
3659 log_debug("%s", dbg_msg);
3660}
3661
3662/**********************************************************************/
3667{
3668 bool alone_in_city;
3669
3670 if (tile_city(unit_tile(punit)) != nullptr) {
3671 int count = 0;
3672
3674 /* Consider only units not transported. */
3675 if (!unit_transported(aunit)) {
3676 count++;
3677 }
3679
3680 alone_in_city = (1 == count);
3681 } else {
3683 }
3684
3685 /* There may be sentried units with a sightrange > 3, but we don't
3686 wake them up if the punit is farther away than 3. */
3687 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3688 unit_list_iterate(ptile->units, penemy) {
3689 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3690 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3691
3693 && penemy->activity == ACTIVITY_SENTRY
3694 && radius_sq >= distance_sq
3695 /* If the unit moved on a city, and the unit is alone, consider
3696 * it is visible. */
3697 && (alone_in_city
3699 /* On board transport; don't awaken */
3702 send_unit_info(nullptr, penemy);
3703 }
3706
3707 /* Wakeup patrolling units we bump into.
3708 We do not wakeup units further away than 3 squares... */
3709 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3710 unit_list_iterate(ptile->units, ppatrol) {
3711 if (punit != ppatrol
3713 && ppatrol->orders.vigilant) {
3715 cancel_orders(ppatrol, " stopping because of nearby enemy");
3718 _("Orders for %s aborted after enemy movement was "
3719 "spotted."),
3721 }
3722 }
3725}
3726
3727/**********************************************************************/
3737 struct tile *src_tile,
3738 struct tile *dst_tile,
3739 bool passenger,
3741{
3742 struct city *fromcity = tile_city(src_tile);
3743 struct city *tocity = tile_city(dst_tile);
3744 struct city *homecity_start_pos = nullptr;
3745 struct city *homecity_end_pos = nullptr;
3751 const struct unit_type *type_end_pos = type_start_pos;
3754 int saved_id = punit->id;
3755 bool alive = TRUE;
3756 const struct civ_map *nmap = &(wld.map);
3757
3759 if (!passenger) {
3760 /* The unit that does the move may conquer. */
3762 }
3763
3764 /* Run for passengers too. A passenger may have been killed when its
3765 * transport conquered a city. (unit_conquer_city() can cause Lua code
3766 * to run) */
3767
3769 if (alive) {
3770 /* In case script has changed something about unit */
3774 }
3775 }
3776
3777 if (homecity_id_start_pos != 0) {
3779 }
3782 } else {
3784 }
3785
3786 /* We only do refreshes for non-AI players to now make sure the AI turns
3787 doesn't take too long. Perhaps we should make a special refresh_city
3788 functions that only refreshed happines. */
3789
3790 /* might have changed owners or may be destroyed */
3792
3793 if (tocity) { /* entering a city */
3794 if (tocity->owner == pplayer_end_pos) {
3798 }
3799 }
3800 if (homecity_start_pos) {
3802 }
3803 }
3804
3805 if (fromcity) { /* leaving a city */
3806 if (homecity_start_pos) {
3808 }
3810 && fromcity->owner == pplayer_start_pos
3814 }
3815 }
3816
3817 /* Entering/leaving a fortress or friendly territory */
3819 bool friendly_end = FALSE;
3820
3823 } else {
3825 type_end_pos);
3826
3827 if (max_friendliness_range >= 0
3830 } else {
3833
3834 if (max_friendliness_range >= 0
3837 }
3838 }
3839 }
3840
3841 if (friendly_end) {
3844 }
3845 }
3846
3850 }
3857 }
3858
3860 sync_cities();
3861
3862 return alive;
3863}
3864
3865/**********************************************************************/
3869static void check_unit_activity(struct unit *punit)
3870{
3871 switch (punit->activity) {
3872 case ACTIVITY_IDLE:
3873 case ACTIVITY_SENTRY:
3874 case ACTIVITY_EXPLORE:
3875 case ACTIVITY_GOTO:
3876 break;
3877 case ACTIVITY_CLEAN:
3878 case ACTIVITY_MINE:
3879 case ACTIVITY_IRRIGATE:
3880 case ACTIVITY_CULTIVATE:
3881 case ACTIVITY_PLANT:
3882 case ACTIVITY_FORTIFIED:
3883 case ACTIVITY_PILLAGE:
3884 case ACTIVITY_TRANSFORM:
3886 case ACTIVITY_BASE:
3887 case ACTIVITY_GEN_ROAD:
3888 case ACTIVITY_CONVERT:
3889 case ACTIVITY_LAST:
3891 break;
3892 };
3893}
3894
3895/**********************************************************************/
3899 const struct tile *psrctile,
3900 const struct tile *pdesttile)
3901{
3902 struct unit_move_data *pdata;
3903 struct player *powner = unit_owner(punit);
3904
3905 if (punit->server.moving) {
3906 /* Recursive moving (probably due to a script). */
3908 pdata->ref_count++;
3909 fc_assert_msg(pdata->punit == punit,
3910 "Unit number %d (%p) was going to die, but "
3911 "server attempts to move it.",
3912 punit->id, punit);
3913 fc_assert_msg(pdata->old_vision == nullptr,
3914 "Unit number %d (%p) has done an incomplete move.",
3915 punit->id, punit);
3916 } else {
3917 pdata = fc_malloc(sizeof(*pdata));
3918 pdata->ref_count = 1;
3919 pdata->punit = punit;
3921 BV_CLR_ALL(pdata->can_see_unit);
3922 }
3923 pdata->powner = powner;
3924 BV_CLR_ALL(pdata->can_see_move);
3925 pdata->old_vision = punit->server.vision;
3926
3927 return pdata;
3928}
3929
3930/**********************************************************************/
3934 const struct tile *psrctile,
3935 struct tile *pdesttile)
3936{
3937 struct vision *new_vision;
3938 struct unit *punit = pdata->punit;
3940 const v_radius_t radius_sq
3944
3945 /* Remove unit from the source tile. */
3947
3948#ifndef FREECIV_NDEBUG
3949 bool success =
3950#endif
3953
3954 /* Set new tile. */
3957
3958 if (unit_transported(punit)) {
3959 /* Silently free orders since they won't be applicable anymore. */
3961 }
3962
3963 /* Check unit activity. */
3967
3968 /* We first unfog the destination, then send the move,
3969 * and then fog the old territory. This means that the player
3970 * gets a chance to see the newly explored territory while the
3971 * client moves the unit, and both areas are visible during the
3972 * move */
3973
3974 /* Enhance vision if unit steps into a fortress */
3977 vision_change_sight(new_vision, radius_sq);
3979}
3980
3981/**********************************************************************/
3985{
3986 fc_assert_ret(pdata != nullptr);
3987 fc_assert_ret(pdata->ref_count > 0);
3988 fc_assert_msg(pdata->old_vision == nullptr,
3989 "Unit number %d (%p) has done an incomplete move.",
3990 pdata->punit != nullptr ? pdata->punit->id : -1, pdata->punit);
3991
3992 pdata->ref_count--;
3993 if (pdata->ref_count == 0) {
3994 if (pdata->punit != nullptr) {
3995 fc_assert(pdata->punit->server.moving == pdata);
3996 pdata->punit->server.moving = nullptr;
3997 }
3998 free(pdata);
3999 }
4000}
4001
4002/**********************************************************************/
4006 const struct tile *psrctile,
4007 struct tile *pdesttile,
4008 bool adj)
4009{
4012 struct unit_move_data *pdata;
4013
4014 /* Make new data for 'punit'. */
4017
4018 /* Add all contained units. */
4020 struct unit_move_data *cargo_data;
4021
4025
4026 /* Determine the players able to see the move(s), now that the player
4027 * vision has been increased. */
4028 if (adj) {
4029 /* Main unit for adjacent move: the move is visible for every player
4030 * able to see on the matching unit layer. */
4031 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
4032
4036 BV_SET(pdata->can_see_unit, player_index(oplayer));
4037 BV_SET(pdata->can_see_move, player_index(oplayer));
4038 }
4040 }
4041
4043
4045
4046 if (adj && pmove_data->punit == punit) {
4047 /* If positions are adjacent, we have already handled 'punit'. See
4048 * above. */
4049 continue;
4050 }
4051
4053 if ((adj
4055 pmove_data != pdata))
4057 pmove_data != pdata)) {
4058 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4059 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4060 }
4062 pmove_data != pdata)) {
4063 /* The unit was seen with its source tile even if it was
4064 * teleported. */
4065 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4066 }
4069
4070 return plist;
4071}
4072
4073/**********************************************************************/
4084bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
4085 struct unit *embark_to, bool find_embark_target,
4087 bool enter_hut, bool frighten_hut)
4088{
4089 struct player *pplayer;
4090 struct tile *psrctile;
4091 struct city *psrccity;
4092 struct city *pdestcity;
4093 struct unit *ptransporter;
4096 struct unit_move_data_list *plist;
4097 struct unit_move_data *pdata;
4098 int saved_id;
4099 bool unit_lives;
4100 bool adj;
4101 enum direction8 facing;
4103
4104 /* Some checks. */
4105 fc_assert_ret_val(punit != nullptr, FALSE);
4106 fc_assert_ret_val(pdesttile != nullptr, FALSE);
4107
4108 pplayer = unit_owner(punit);
4109 saved_id = punit->id;
4112
4114
4115 /* Unload the unit if on a transport. */
4117 if (ptransporter != nullptr) {
4118 /* Unload unit _before_ setting the new tile! */
4120 /* Send updated information to anyone watching that transporter
4121 * was unloading cargo. */
4122 send_unit_info(nullptr, ptransporter);
4123 }
4124
4125 /* Wakup units next to us before we move. */
4127
4128 /* Make info packets at 'psrctile'. */
4129 if (adj) {
4130 /* If tiles are adjacent, we will show the move to users able
4131 * to see it. */
4134 }
4135
4136 /* Set unit orientation */
4137 if (adj) {
4138 /* Only change orientation when moving to adjacent tile */
4139 punit->facing = facing;
4140 }
4141
4143
4144 /* Move magic. */
4145 punit->moved = TRUE;
4146 punit->moves_left = MAX(0, punit->moves_left - move_cost);
4147 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
4148 /* The next order may not require any remaining move fragments. */
4150 }
4151
4152 /* No longer relevant. */
4153 punit->action_decision_tile = nullptr;
4155
4156 /* Claim ownership of fortress? */
4159 /* Yes. We claim *all* bases if there's *any* claimable base(s).
4160 * Even if original unit cannot claim other kind of bases, the
4161 * first claimed base will have influence over other bases,
4162 * or something like that. */
4163 tile_claim_bases(pdesttile, pplayer);
4164 }
4165
4167 fc_assert(pdata->punit == punit);
4168
4169 /* Check timeout settings. */
4172
4173 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4174 * if they are ever seen. */
4176 /* Increase the timeout if an enemy unit moves and the
4177 * timeoutaddenemymove setting is in use. */
4178 if (penemy->is_connected
4179 && pplayer != penemy
4180 && pplayers_at_war(pplayer, penemy)
4181 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4183 break;
4184 }
4186
4189 }
4190 }
4191
4193 /* The unit can perform an action to the city at the destination tile.
4194 * A long distance move (like an airlift) doesn't ask what action to
4195 * perform before moving. Ask now. */
4196
4199 }
4200
4201 /* Notifications of the move to the clients. */
4202 if (adj) {
4203 /* Special case: 'punit' is moving to adjacent position. Then we show
4204 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4205
4206 /* Make info packets at 'pdesttile'. */
4209
4212
4213 if (aplayer == nullptr) {
4214 if (pconn->observer) {
4215 /* Global observers see all... */
4218 }
4219 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4220 if (aplayer == pplayer) {
4223 } else {
4226 }
4227 }
4229 }
4230
4231 /* Other moves. */
4233 if (adj && pmove_data == pdata) {
4234 /* If positions are adjacent, we have already shown 'punit' move.
4235 * See above. */
4236 continue;
4237 }
4238
4239 /* Make info packets at 'pdesttile'. */
4243
4246
4247 if (aplayer == nullptr) {
4248 if (pconn->observer) {
4249 /* Global observers see all... */
4251 }
4252 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4253 if (aplayer == pmove_data->powner) {
4255 } else {
4257 }
4258 }
4261
4262 /* Clear old vision. */
4264 if (pmove_data->old_vision != nullptr) {
4265 vision_clear_sight(pmove_data->old_vision);
4266 vision_free(pmove_data->old_vision);
4267 pmove_data->old_vision = nullptr;
4268 }
4270
4271 /* Move consequences. */
4273 struct unit *aunit = pmove_data->punit;
4274
4275 if (aunit != nullptr
4276 && unit_owner(aunit) == pmove_data->powner
4277 && unit_tile(aunit) == pdesttile) {
4279 pdata != pmove_data,
4281 }
4283
4284 unit_lives = (pdata->punit == punit);
4285
4286 /* Wakeup units and make contact. */
4287 if (unit_lives) {
4289 }
4290
4291 /* Do not pass 'punit' to unit_make_contact(), as it
4292 * might refer to a dead unit.
4293 * Flagless units do not make contact. */
4294 if (!flagless) {
4295 unit_make_contact(nullptr, pdesttile, pplayer);
4296 }
4297
4298 if (unit_lives) {
4299 /* Special checks for ground units in the ocean. */
4301 if (embark_to != nullptr) {
4303 } else if (find_embark_target) {
4304 /* TODO: Consider to stop supporting find_embark_target and make all
4305 * callers that wants auto loading set embark_to. */
4307 } else {
4308 ptransporter = nullptr;
4309 }
4310 if (ptransporter) {
4312
4313 /* Set activity to sentry if boarding a ship. */
4314 if (is_human(pplayer)
4319 }
4320
4321 send_unit_info(nullptr, punit);
4322 }
4323 }
4324 }
4325
4326 /* Remove units going out of sight. */
4328 struct unit *aunit = pmove_data->punit;
4329
4330 if (aunit == nullptr) {
4331 continue; /* Died! */
4332 }
4333
4335 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4338 }
4341
4342 /* Inform the owner's client about actor unit arrival. Can, depending on
4343 * the client settings, cause the client to start the process that makes
4344 * the action selection dialog pop up. */
4346 if (pdestcity != nullptr) {
4347 /* Arrival in a city counts. */
4348
4350 struct unit *ptrans;
4351 bool ok;
4352 struct unit *act_unit;
4353 struct player *act_player;
4354
4355 act_unit = pmove_data->punit;
4357
4358 if (act_unit == nullptr
4359 || !unit_is_alive(act_unit->id)) {
4360 /* The unit died before reaching this point. */
4361 continue;
4362 }
4363
4364 if (unit_tile(act_unit) != pdesttile) {
4365 /* The unit didn't arrive at the destination tile. */
4366 continue;
4367 }
4368
4369 if (!is_human(act_player)) {
4370 /* Only humans need reminders. */
4371 continue;
4372 }
4373
4374 if (!unit_transported(act_unit)) {
4375 /* Don't show the action selection dialog again. Non transported
4376 * units are handled before they move to the tile. */
4377 continue;
4378 }
4379
4380 /* Open action dialog only if 'act_unit' and all its transporters
4381 * (recursively) don't have orders. */
4383 /* The unit it self has orders. */
4384 continue;
4385 }
4386
4389 if (ptrans == nullptr) {
4390 /* No (recursive) transport has orders. */
4391 ok = TRUE;
4392 break;
4393 } else if (unit_has_orders(ptrans)) {
4394 /* A unit transporting the unit has orders */
4395 ok = FALSE;
4396 break;
4397 }
4398 }
4399
4400 if (!ok) {
4401 /* A unit transporting act_unit has orders. */
4402 continue;
4403 }
4404
4406 /* There is a valid target. */
4407
4408 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4409 act_unit->action_decision_tile = pdesttile;
4410
4411 /* Let the client know that this unit wants the player to decide
4412 * what to do. */
4414 }
4416 }
4417
4419 /* Check cities at source and destination. */
4421 if (psrccity != nullptr) {
4423 }
4424 if (pdestcity != nullptr) {
4426 }
4427
4428 if (unit_lives) {
4429 /* Let the scripts run ... */
4432 }
4433
4434 if (unit_lives) {
4435 /* Autoattack. */
4437 }
4438
4439 if (unit_lives && (enter_hut || frighten_hut)) {
4440 /* Is there a hut? */
4444 }
4445
4447
4448 if (unit_lives) {
4449 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4450 }
4451
4452 return unit_lives;
4453}
4454
4455/**********************************************************************/
4459 struct tile *ptile)
4460{
4461 struct player *owner = unit_owner(punit);
4462
4463 return (is_non_allied_unit_tile(ptile, owner,
4465 || is_non_allied_city_tile(ptile, owner));
4466}
4467
4468/**********************************************************************/
4475{
4476 bool cancel = FALSE;
4477 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4478 struct player *pplayer = unit_owner(punit);
4479
4480 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4481 struct unit *penemy = tile_non_allied_unit(ptile, pplayer,
4483 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4484
4485 if ((penemy && can_player_see_unit(pplayer, penemy))
4487 && pdcity->occupied)) {
4488 cancel = TRUE;
4489 break;
4490 }
4492
4493 return cancel;
4494}
4495
4496/**********************************************************************/
4504static inline bool player_is_watching(struct unit *punit, const bool fresh)
4505{
4506 /* The player just sent the orders to the unit. The unit has moves left.
4507 * It is therefore safe to assume that the player already is paying
4508 * attention to the unit. */
4509 return fresh && punit->moves_left > 0;
4510}
4511
4512/**********************************************************************/
4531bool execute_orders(struct unit *punit, const bool fresh)
4532{
4533 struct act_prob prob;
4534 bool performed;
4535 const char *name;
4536 bool res, last_order;
4537 int unitid = punit->id;
4538 struct player *pplayer = unit_owner(punit);
4539 int moves_made = 0;
4540 const struct civ_map *nmap = &(wld.map);
4541
4543
4544 if (punit->activity != ACTIVITY_IDLE) {
4545 /* Unit's in the middle of an activity; wait for it to finish. */
4547 return TRUE;
4548 }
4549
4550 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4551
4552 /* Any time the orders are canceled we should give the player a message. */
4553
4554 while (TRUE) {
4555 struct unit_order order;
4556
4557 struct action *oaction;
4558
4559 struct tile *dst_tile;
4560 struct city *tgt_city;
4561 struct unit *tgt_unit;
4562 int tgt_id;
4563 int sub_tgt_id;
4564 struct extra_type *pextra;
4565
4566 if (punit->done_moving) {
4567 log_debug(" stopping because we're done this turn");
4568 return TRUE;
4569 }
4570
4572 /* "Patrol" orders are stopped if an enemy is near. */
4573 cancel_orders(punit, " stopping because of nearby enemy");
4575 _("Orders for %s aborted as there are units nearby."),
4576 unit_link(punit));
4577 return TRUE;
4578 }
4579
4580 if (moves_made == punit->orders.length) {
4581 /* For repeating orders, don't repeat more than once per turn. */
4582 log_debug(" stopping because we ran a round");
4584 send_unit_info(nullptr, punit);
4585 return TRUE;
4586 }
4587 moves_made++;
4588
4589 order = punit->orders.list[punit->orders.index];
4590
4591 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4592 * this far. */
4594 || action_id_exists(order.action)),
4595 continue);
4596
4597 switch (order.order) {
4598 case ORDER_MOVE:
4599 case ORDER_ACTION_MOVE:
4600 case ORDER_FULL_MP:
4601 if (0 == punit->moves_left) {
4602 log_debug(" stopping because of no more move points");
4603 return TRUE;
4604 }
4605 break;
4608 log_debug(" stopping. Not enough move points this turn");
4609 return TRUE;
4610 }
4611 break;
4612 case ORDER_ACTIVITY:
4613 case ORDER_LAST:
4614 /* Those actions don't require moves left. */
4615 break;
4616 }
4617
4619 && punit->orders.index + 1 == punit->orders.length);
4620
4621 if (last_order) {
4622 /* Clear the orders before we engage in the move. That way any
4623 * has_orders checks will yield FALSE and this will be treated as
4624 * a normal move. This is important: for instance a caravan goto
4625 * will popup the caravan dialog on the last move only. */
4627 }
4628
4629 /* Advance the orders one step forward. This is needed because any
4630 * updates sent to the client as a result of the action should include
4631 * the new index value. Note that we have to send_unit_info() somewhere
4632 * after this point so that the client is properly updated. */
4633 punit->orders.index++;
4634
4635 switch (order.order) {
4636 case ORDER_FULL_MP:
4638 /* If the unit doesn't have full MP then it just waits until the
4639 * next turn. We assume that the next turn it will have full MP
4640 * (there's no check for that). */
4642 log_debug(" waiting this turn");
4643 send_unit_info(nullptr, punit);
4644 }
4645 break;
4646 case ORDER_ACTIVITY:
4647 {
4648 enum unit_activity activity = order.activity;
4649
4650 fc_assert(activity == ACTIVITY_SENTRY);
4651
4652 if (can_unit_do_activity(nmap, punit, activity, order.action)) {
4654 set_unit_activity(punit, activity, order.action);
4655 send_unit_info(nullptr, punit);
4656
4657 break;
4658 }
4659 }
4660
4661 cancel_orders(punit, " orders canceled because of failed activity");
4663 _("Orders for %s aborted since they "
4664 "give an invalid activity."),
4665 unit_link(punit));
4666 return TRUE;
4667 case ORDER_MOVE:
4668 case ORDER_ACTION_MOVE:
4669 /* Move unit */
4670 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4671 cancel_orders(punit, " move order sent us to invalid location");
4673 _("Orders for %s aborted since they "
4674 "give an invalid location."),
4675 unit_link(punit));
4676 return TRUE;
4677 }
4678
4679 if (order.order != ORDER_ACTION_MOVE
4681 /* Plain move required: no attack, trade route etc. */
4682 cancel_orders(punit, " orders canceled because of enemy");
4684 _("Orders for %s aborted as there "
4685 "are units in the way."),
4686 unit_link(punit));
4687 return TRUE;
4688 }
4689
4690 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4692 order.order != ORDER_ACTION_MOVE);
4693 if (!player_unit_by_number(pplayer, unitid)) {
4694 log_debug(" unit died while moving.");
4695 /* A player notification should already have been sent. */
4696 return FALSE;
4697 }
4698
4699 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4700 /* Movement succeeded but unit didn't move. */
4701 log_debug(" orders resulted in combat.");
4702 send_unit_info(nullptr, punit);
4703 return TRUE;
4704 }
4705
4706 if (!res) {
4707 fc_assert(0 <= punit->moves_left);
4708
4709 /* Movement failed (ZOC, etc.) */
4710 cancel_orders(punit, " attempt to move failed.");
4711
4713 /* The final move "failed" because the unit needs to ask the
4714 * player what action it should take.
4715 *
4716 * The action decision request notifies the player. Its
4717 * location at the unit's last order makes it clear to the
4718 * player who the decision is for. ("The Spy I sent to Berlin
4719 * has arrived.")
4720 *
4721 * A notification message is therefore redundant. */
4722 && !(last_order
4725 /* The player may have missed this. No one else will announce it
4726 * in a satisfying manner. Inform the player. */
4727 notify_player(pplayer, unit_tile(punit),
4729 _("Orders for %s aborted because of failed move."),
4730 unit_link(punit));
4731 }
4732
4733 return TRUE;
4734 }
4735 break;
4738
4739 /* Checked in unit_order_list_is_sane() */
4740 fc_assert_action(oaction != nullptr, continue);
4741
4742 log_debug(" orders: doing action %s", action_rule_name(oaction));
4743
4744 dst_tile = index_to_tile(&(wld.map), order.target);
4745
4746 if (dst_tile == nullptr) {
4747 /* Could be at the edge of the map while trying to target a tile
4748 * outside of it. */
4749
4750 cancel_orders(punit, " target location doesn't exist");
4752 order.action, dst_tile, nullptr, nullptr);
4753
4754 return TRUE;
4755 }
4756
4757 /* Get the target city from the target tile. */
4759
4760 if (tgt_city == nullptr
4762 /* This action targets a city but no city target was found. */
4763
4764 cancel_orders(punit, " perform action vs city with no city");
4766 order.action, dst_tile, tgt_city, nullptr);
4767
4768 return TRUE;
4769 }
4770
4771 /* Get a target unit at the target tile. */
4773
4774 if (tgt_unit == nullptr
4776 /* This action targets a unit but no target unit was found. */
4777
4778 cancel_orders(punit, " perform action vs unit with no unit");
4780 order.action, dst_tile, tgt_city, tgt_unit);
4781
4782 return TRUE;
4783 }
4784
4785 /* Server side sub target assignment */
4786 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4787 && order.sub_target == NO_TARGET) {
4788 /* Try to find a sub target. */
4790 } else {
4791 /* The client should have specified a sub target if needed */
4792 sub_tgt_id = order.sub_target;
4793 }
4794
4795 /* Get a target extra at the target tile */
4796 pextra = (sub_tgt_id == NO_TARGET ?
4797 nullptr :
4798 extra_by_number(sub_tgt_id));
4799
4801 && pextra != nullptr
4802 && actres_creates_extra(oaction->result, pextra)
4803 && tile_has_extra(dst_tile, pextra)) {
4804 /* Already there. Move on to the next order. */
4805 break;
4806 }
4807
4809 && pextra != nullptr
4810 && actres_removes_extra(oaction->result, pextra)
4811 && !tile_has_extra(dst_tile, pextra)) {
4812 /* Already not there. Move on to the next order. */
4813 break;
4814 }
4815
4816 /* No target selected. */
4817 tgt_id = -1;
4818
4819 /* Assume impossible until told otherwise. */
4820 prob = ACTPROB_IMPOSSIBLE;
4821
4822 switch (action_id_get_target_kind(order.action)) {
4823 case ATK_STACK:
4824 prob = action_prob_vs_stack(nmap, punit, order.action,
4825 dst_tile);
4826 tgt_id = dst_tile->index;
4827 break;
4828 case ATK_TILE:
4829 prob = action_prob_vs_tile(nmap, punit, order.action,
4830 dst_tile, pextra);
4831 tgt_id = dst_tile->index;
4832 break;
4833 case ATK_EXTRAS:
4834 prob = action_prob_vs_extras(nmap, punit, order.action,
4835 dst_tile, pextra);
4836 tgt_id = dst_tile->index;
4837 break;
4838 case ATK_CITY:
4839 prob = action_prob_vs_city(nmap, punit, order.action,
4840 tgt_city);
4841 tgt_id = tgt_city->id;
4842 break;
4843 case ATK_UNIT:
4844 prob = action_prob_vs_unit(nmap, punit, order.action,
4845 tgt_unit);
4846
4847 tgt_id = tgt_unit->id;
4848 break;
4849 case ATK_SELF:
4850 prob = action_prob_self(nmap, punit, order.action);
4851
4852 tgt_id = unitid;
4853 break;
4854 case ATK_COUNT:
4855 log_error("Invalid action target kind");
4856
4857 /* The check below will abort and cancel the orders because prob
4858 * was initialized to impossible above this switch statement. */
4859
4860 break;
4861 }
4862
4863 if (!action_prob_possible(prob)) {
4864 /* The player has enough information to know that this action is
4865 * against the rules. Don't risk any punishment by trying to
4866 * perform it. */
4867
4868 cancel_orders(punit, " illegal action");
4870 _("%s could not do %s to %s."),
4874
4875 /* Try to explain what rule made it illegal. */
4877 order.action, dst_tile, tgt_city, tgt_unit);
4878
4879 return TRUE;
4880 }
4881
4883 /* This action needs a name. */
4885 } else {
4886 /* This action doesn't need a name. */
4887 name = "";
4888 }
4889
4891 unitid,
4892 tgt_id,
4893 sub_tgt_id,
4894 name,
4895 order.action,
4897
4898 if (!player_unit_by_number(pplayer, unitid)) {
4899 /* The unit "died" while performing the action. */
4900 return FALSE;
4901 }
4902
4903 if (!performed) {
4904 /* The action wasn't performed as ordered. */
4905
4906 cancel_orders(punit, " failed action");
4908 _("Orders for %s aborted because "
4909 "doing %s to %s failed."),
4913
4914 return TRUE;
4915 }
4916
4917 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4919 /* Done at turn change. */
4921 send_unit_info(nullptr, punit);
4922 break;
4923 }
4924
4925 break;
4926 case ORDER_LAST:
4927 /* Should be caught when loading the unit orders from the savegame or
4928 * when receiving the unit orders from the client. */
4929 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4930 cancel_orders(punit, " invalid order!");
4932 _("Your %s has invalid orders."),
4933 unit_link(punit));
4934 return TRUE;
4935 }
4936
4937 if (last_order) {
4939 log_debug(" stopping because orders are complete");
4940 return TRUE;
4941 }
4942
4943 if (punit->orders.index == punit->orders.length) {
4945 /* Start over. */
4946 log_debug(" repeating orders.");
4947 punit->orders.index = 0;
4948 }
4949 } /* end while */
4950}
4951
4952/**********************************************************************/
4959static int get_unit_vision_base(const struct unit *punit,
4960 enum vision_layer vlayer,
4961 const int base)
4962{
4963 switch (vlayer) {
4964 case V_MAIN:
4965 return MAX(0, base);
4966 case V_INVIS:
4967 case V_SUBSURFACE:
4968 return CLIP(0, base, 2);
4969 case V_COUNT:
4970 break;
4971 }
4972
4973 log_error("Unsupported vision layer variant: %d.", vlayer);
4974
4975 return 0;
4976}
4977
4978/**********************************************************************/
4981static int unit_vision_range_modifiers(const struct unit *punit,
4982 const struct tile *ptile)
4983{
4984 const struct unit_type *utype = unit_type_get(punit);
4985
4986 return (utype->vision_radius_sq
4987 + get_target_bonus_effects(nullptr,
4988 &(const struct req_context) {
4989 .player = unit_owner(punit),
4990 .tile = ptile,
4991 .unittype = utype,
4992 .unit = punit,
4993 },
4994 nullptr, EFT_UNIT_VISION_RADIUS_SQ));
4995}
4996
4997/**********************************************************************/
5004int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
5005 enum vision_layer vlayer)
5006{
5009}
5010
5011/**********************************************************************/
5018{
5019 struct vision *uvision = punit->server.vision;
5020 const struct tile *utile = unit_tile(punit);
5021 int mod = unit_vision_range_modifiers(punit, utile);
5022 const v_radius_t radius_sq
5026
5027 vision_change_sight(uvision, radius_sq);
5029}
5030
5031/**********************************************************************/
5040
5041/**********************************************************************/
5046{
5047 time_t dt;
5048
5049 if (!punit) {
5050 return FALSE;
5051 }
5052
5053 if (game.server.unitwaittime <= 0) {
5054 return TRUE;
5055 }
5056
5057 if (punit->server.action_turn != game.info.turn - 1) {
5058 return TRUE;
5059 }
5060
5061 dt = time(nullptr) - punit->server.action_timestamp;
5062 if (dt < game.server.unitwaittime) {
5063 char buf[64];
5066 ftc_server, _("Your unit may not act for another %s "
5067 "this turn. See /help unitwaittime."), buf);
5068 return FALSE;
5069 }
5070
5071 return TRUE;
5072}
5073
5074/**********************************************************************/
5079{
5080 if (!punit) {
5081 return;
5082 }
5083
5084 punit->server.action_timestamp = time(nullptr);
5086}
5087
5088/**********************************************************************/
5094{
5095 /* check if there is enemy nearby */
5096 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
5098 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
5099 return FALSE;
5100 }
5101 }
5103
5104 return TRUE;
5105}
5106
5107/**********************************************************************/
5110void random_movements(struct player *pplayer)
5111{
5112 const struct civ_map *nmap = &(wld.map);
5113
5114 game.server.random_move_time = pplayer;
5115
5118 bool moved = TRUE;
5119 struct tile *curtile = unit_tile(punit);
5120 int id = punit->id;
5121
5122 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
5123 /*
5124 * List of all 8 directions
5125 */
5126 enum direction8 dirs[8] = {
5129 };
5130 int n;
5131
5132 moved = FALSE;
5133
5134 for (n = 8; n > 0 && !moved; n--) {
5135 enum direction8 choice = (enum direction8) fc_rand(n);
5136 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
5137
5138 if (dest != nullptr) {
5140 dest))) {
5141 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
5143 moved = TRUE;
5144 break;
5145 }
5146 }
5147
5148 if (!moved) {
5150 nullptr)) {
5151 if (unit_perform_action(pplayer, id, tile_index(dest),
5153 ACT_REQ_RULES)) {
5154 moved = TRUE;
5155 }
5157 punit, dest, nullptr)) {
5158 if (unit_perform_action(pplayer, id, tile_index(dest),
5160 ACT_REQ_RULES)) {
5161 moved = TRUE;
5162 }
5164 punit, dest, nullptr)) {
5165 if (unit_perform_action(pplayer, id, tile_index(dest),
5167 ACT_REQ_RULES)) {
5168 moved = TRUE;
5169 }
5170 }
5171 }
5172 }
5173
5174 if (!moved) {
5175 /* Choice was bad, so replace it with the last direction
5176 * in the list. On the next iteration, one fewer choice
5177 * will remain. */
5178 dirs[choice] = dirs[n - 1];
5179 }
5180 }
5181 }
5182 }
5184
5185 game.server.random_move_time = nullptr;
5186}
5187
5188/**********************************************************************/
5193void unit_make_contact(const struct unit *punit,
5194 struct tile *ptile, struct player *pplayer)
5195{
5196 fc_assert_ret(punit != nullptr
5197 || (ptile != nullptr && pplayer != nullptr));
5198
5199 if (punit != nullptr && unit_has_type_flag(punit, UTYF_FLAGLESS)) {
5200 return; /* Flagless unit can't make contact */
5201 }
5202
5203 maybe_make_contact(ptile != nullptr ? ptile : unit_tile(punit),
5204 pplayer != nullptr ? pplayer : unit_owner(punit));
5205}
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:5795
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1271
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5317
const char * action_name_translation(const struct action *paction)
Definition actions.c:1251
struct act_prob action_prob_vs_tile(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4838
const char * action_rule_name(const struct action *action)
Definition actions.c:1237
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1140
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:3344
struct act_prob action_prob_vs_extras(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4921
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:4991
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:4480
bool action_id_exists(const action_id act_id)
Definition actions.c:1089
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5377
struct act_prob action_prob_vs_stack(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:4755
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:3493
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:4563
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5428
static struct action * action_by_number(action_id act_id)
Definition actions.h:400
#define action_has_result(_act_, _res_)
Definition actions.h:184
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:441
#define ACTPROB_IMPOSSIBLE
Definition actions.h:717
#define action_id_get_target_kind(act_id)
Definition actions.h:417
#define action_id_has_result_safe(act_id, result)
Definition actions.h:430
#define ACTION_NONE
Definition actions.h:59
void action_consequence_complete(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
void action_consequence_caught(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct act_prob action_auto_perf_unit_prob(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
const struct action * action_auto_perf_unit_do(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
void action_consequence_success(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
bool actres_removes_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:811
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:790
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:390
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:380
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
void dbv_to_bv(unsigned char *dest, const struct dbv *src)
Definition bitvector.c:227
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile, int distance)
Definition city.c:2147
const char * city_name_get(const struct city *pcity)
Definition city.c:1155
bool city_exists_within_max_city_map(const struct civ_map *nmap, const struct tile *ptile, bool may_be_on_center)
Definition city.c:2167
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:776
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:565
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:740
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:752
#define output_type_iterate(output)
Definition city.h:851
#define city_owner(_pcity_)
Definition city.h:564
#define city_list_iterate_end
Definition city.h:510
#define output_type_iterate_end
Definition city.h:857
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3345
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:458
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2368
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Definition citytools.c:856
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2220
void sync_cities(void)
Definition citytools.c:3354
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1992
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3168
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:764
bool city_refresh(struct city *pcity)
Definition cityturn.c:159
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:480
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:86
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:994
int get_virtual_defense_power(const struct civ_map *nmap, const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, struct tile *ptile, bool fortified, int veteran)
Definition combat.c:717
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1025
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:772
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:615
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:841
void get_modified_firepower(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, int *att_fp, int *def_fp)
Definition combat.c:411
char * incite_cost
Definition comments.c:77
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:765
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:368
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:358
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:755
#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:2977
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2692
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2722
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:1071
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:215
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:210
@ RPT_CERTAIN
Definition fc_types.h:516
@ AUT_NONE
Definition fc_types.h:231
@ HB_DISABLED
Definition fc_types.h:986
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:94
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
const char * tile_link(const struct tile *ptile)
const struct ft_color ftc_server
const char * city_link(const struct city *pcity)
const char * unit_link(const struct unit *punit)
const char * unit_tile_link(const struct unit *punit)
#define MAX_LEN_LINK
struct civ_game game
Definition game.c:62
int current_turn_timeout(void)
Definition game.c:858
struct world wld
Definition game.c:63
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:123
struct unit * game_unit_by_number(int id)
Definition game.c:115
struct city * game_city_by_number(int id)
Definition game.c:106
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1039
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
@ H_LIMITEDHUTS
Definition handicaps.h:20
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:212
#define log_test
Definition log.h:137
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
int 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)
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:712
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1085
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
bool base_get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile, enum direction8 *dir)
Definition map.c:1478
#define adjc_iterate_end
Definition map.h:439
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:397
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:434
#define square_iterate_end
Definition map.h:400
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:299
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:407
#define circle_iterate_end
Definition map.h:410
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2489
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2577
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1926
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2184
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2512
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2680
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:925
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:869
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1444
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:2002
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1387
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2477
#define map_get_player_site(_ptile_, _pplayer_)
Definition maphand.h:93
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:278
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:362
int unit_move_rate(const struct unit *punit)
Definition movement.c:89
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:962
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:373
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:522
@ MR_OK
Definition movement.h:35
@ MR_NOT_ALLOWED
Definition movement.h:53
@ MR_DEATH
Definition movement.h:36
static mpqt_worker * worker
Definition mpgui_qt.cpp:55
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:461
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:291
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:238
unit_info_use
Definition packets.h:66
@ UNIT_INFO_IDENTITY
Definition packets.h:67
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:1217
struct player * player_by_number(const int player_id)
Definition player.c:837
bool can_player_see_unit_at(const struct player *pplayer, const struct unit *punit, const struct tile *ptile, bool is_transported)
Definition player.c:1025
int player_slot_count(void)
Definition player.c:415
int player_number(const struct player *pplayer)
Definition player.c:826
const char * player_name(const struct player *pplayer)
Definition player.c:885
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1095
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1376
int player_index(const struct player *pplayer)
Definition player.c:818
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:325
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
struct player_slot * slots
Definition player.c:51
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1451
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define OWNER_NONE
Definition player.h:50
static bool is_barbarian(const struct player *pplayer)
Definition player.h:499
#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:3220
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2366
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1148
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1595
void player_loot_player(struct player *pvictor, struct player *pvictim)
Definition plrhand.c:410
#define phase_players_iterate(pplayer)
Definition plrhand.h:113
#define phase_players_iterate_end
Definition plrhand.h:118
#define fc_rand(_size)
Definition rand.h:56
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
void script_server_signal_emit(const char *signal_name,...)
void script_server_remove_exported_object(void *object)
void flush_packets(void)
Definition sernet.c:376
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1977
#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:2105
struct act_prob prob
Definition unittools.c:115
Definition city.h:318
int unitwaittime
Definition game.h:205
struct player * random_move_time
Definition game.h:283
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:139
int killunhomed
Definition game.h:161
int ransom_gold
Definition game.h:182
struct civ_game::@32::@36 server
bool autoattack
Definition game.h:138
int timeoutaddenemymove
Definition game.h:215
enum gameloss_style gameloss_style
enum goods_selection_method goods_selection
enum happyborders_type happyborders
int nuke_defender_survival_chance_pct
bool only_real_fight_makes_veteran
enum airlifting_style airlifting_style
bool only_killing_makes_veteran
bool combat_odds_scaled_veterancy
enum action_decision action_decision_want
enum unit_activity activity
struct unit_order orders[MAX_LEN_ROUTE]
Unit_type_id type
enum unit_activity changed_from
enum direction8 facing
int upkeep[O_LAST]
enum server_side_agent ssa_controller
enum direction8 facing
enum diplstate_type type
Definition player.h:199
int units_used
Definition player.h:108
int units_lost
Definition player.h:106
struct unit_list * units
Definition player.h:282
struct conn_list * connections
Definition player.h:298
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
struct player::@73::@75 server
struct player_economic economic
Definition player.h:284
struct player_score score
Definition player.h:283
const struct player * player
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
bv_player can_see_unit
Definition unittools.c:95
struct player * powner
Definition unittools.c:94
bv_player can_see_move
Definition unittools.c:96
struct unit * punit
Definition unittools.c:93
struct vision * old_vision
Definition unittools.c:97
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
int vision_radius_sq
Definition unittype.h: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
enum action_decision action_decision_want
Definition unit.h:205
int battlegroup
Definition unit.h:194
enum unit_activity activity
Definition unit.h:159
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
enum gen_action action
Definition unit.h:160
struct unit::@83 orders
bool moved
Definition unit.h:176
int index
Definition unit.h:198
struct vision * vision
Definition unit.h:247
bool vigilant
Definition unit.h:200
int hp
Definition unit.h:153
int fuel
Definition unit.h:155
struct extra_type * changed_from_target
Definition unit.h:173
int current_form_turn
Definition unit.h:211
bool stay
Definition unit.h:208
enum direction8 facing
Definition unit.h:144
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:142
struct extra_type * activity_target
Definition unit.h:167
int activity_count
Definition unit.h:165
struct unit_order * list
Definition unit.h:201
enum unit_activity changed_from
Definition unit.h:171
struct player * nationality
Definition unit.h:146
bool repeat
Definition unit.h:199
void(* removal_callback)(struct unit *punit)
Definition unit.h:256
struct unit_move_data * moving
Definition unit.h:250
int action_turn
Definition unit.h:249
int homecity
Definition unit.h:148
bool paradropped
Definition unit.h:177
bool done_moving
Definition unit.h:184
int birth_turn
Definition unit.h:210
struct goods_type * carrying
Definition unit.h:189
struct tile * goto_tile
Definition unit.h:157
struct tile * action_decision_tile
Definition unit.h:206
const struct unit_type * utype
Definition unit.h:141
int veteran
Definition unit.h:154
int changed_from_count
Definition unit.h:172
bool dying
Definition unit.h:253
enum server_side_agent ssa_controller
Definition unit.h:175
struct civ_map map
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define nullptr
Definition support.h:55
#define fc__fallthrough
Definition support.h:119
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:240
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:553
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:956
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:216
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:682
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:234
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:419
int tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:197
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:89
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
#define tile_owner(_tile)
Definition tile.h:97
struct goods_type * goods_from_city_to_unit(const struct city *src, const struct unit *punit)
Goods_type_id goods_index(const struct goods_type *pgood)
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1840
void free_unit_orders(struct unit *punit)
Definition unit.c:1826
bool unit_is_alive(int id)
Definition unit.c:2306
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:567
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2461
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1299
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2525
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2478
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2236
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:882
enum gen_action activity_default_action(enum unit_activity act)
Definition unit.c:2942
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, enum gen_action action)
Definition unit.c:912
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1682
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1786
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1308
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1139
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:2041
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2511
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:793
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2533
bool unit_has_orders(const struct unit *punit)
Definition unit.c:221
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1967
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2088
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:607
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.c:1358
bool can_unit_do_activity_targeted(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, enum gen_action action, struct extra_type *target)
Definition unit.c:953
#define unit_tile(_pu)
Definition unit.h:408
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:433
#define unit_cargo_iterate_end
Definition unit.h:602
@ 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:421
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:599
#define CHECK_UNIT(punit)
Definition unit.h:273
#define unit_owner(_pu)
Definition unit.h:407
@ UU_OK
Definition unit.h:62
#define unit_home(_pu_)
Definition unit.h:405
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:446
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:2527
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unithand.c:6708
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:3370
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5758
#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:361
void unit_did_action(struct unit *punit)
Definition unittools.c:5078
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3467
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2649
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:3072
void unit_make_contact(const struct unit *punit, struct tile *ptile, struct player *pplayer)
Definition unittools.c:5193
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1165
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:2157
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:4005
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4531
static void unit_convert(struct unit *punit)
Definition unittools.c:776
void update_unit_activities(struct player *pplayer)
Definition unittools.c:672
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1311
#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:1559
void random_movements(struct player *pplayer)
Definition unittools.c:5110
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:293
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1800
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1422
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1494
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1925
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1457
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4458
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:406
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1407
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:3040
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3984
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1777
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3340
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2739
#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:2870
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:663
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3666
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:720
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:820
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3425
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3523
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:704
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:682
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:1117
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2883
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1949
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1376
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3869
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:636
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:430
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3898
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1719
void notify_unit_experience(struct unit *punit)
Definition unittools.c:749
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:802
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:2820
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:1671
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1481
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1055
#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:1638
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1916
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1791
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:5004
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:220
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5017
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:1611
void do_explore(struct unit *punit)
Definition unittools.c:3105
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3395
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:5045
#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:2145
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:694
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3141
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4504
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4959
void player_restore_units(struct player *pplayer)
Definition unittools.c:483
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1536
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4981
static void update_unit_activity(struct unit *punit)
Definition unittools.c:860
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3447
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1527
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:239
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3655
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:5093
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:740
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:832
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1084
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2205
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1193
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2955
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3305
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3481
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:847
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:3736
void unit_get_goods(struct unit *punit)
Definition unittools.c:1622
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2927
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4474
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:4084
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3933
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:5034
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2272
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1231
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1064
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1595
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2284
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1613
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2604
int num_role_units(int role)
Definition unittype.c:2234
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1954
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1729
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2535
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:215
const struct veteran_level * vsystem_veteran_level(const struct veteran_system *vsystem, int level)
Definition unittype.c:2622
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:102
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, const enum req_problem_type prob_type, bool consider_reg_impr_req)
Definition unittype.c:1995
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
#define utype_class(_t_)
Definition unittype.h:756
#define utype_fuel(ptype)
Definition unittype.h:849
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:97
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition vision.h:95
#define vision_site_owner(v)
Definition vision.h:128
short int v_radius_t[V_COUNT]
Definition vision.h:82