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
713 if (punit->server.scout_vision != nullptr) {
716 punit->server.scout_vision = nullptr;
717 }
718
719 send_unit_info(nullptr, punit);
721}
722
723/**********************************************************************/
727static int total_activity(struct tile *ptile, enum unit_activity act,
728 struct extra_type *tgt)
729{
730 int total = 0;
732
733 unit_list_iterate(ptile->units, punit) {
734 if (punit->activity == act
735 && (!tgt_matters || punit->activity_target == tgt)) {
736 total += punit->activity_count;
737 }
739
740 return total;
741}
742
743/**********************************************************************/
747static bool total_activity_done(struct tile *ptile, enum unit_activity act,
748 struct extra_type *tgt)
749{
750 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
751}
752
753/**********************************************************************/
757{
758 const struct veteran_level *vlevel;
759 const struct veteran_system *vsystem;
760
761 if (!punit) {
762 return;
763 }
764
766 fc_assert_ret(vsystem != nullptr);
768
770 fc_assert_ret(vlevel != nullptr);
771
774 /* TRANS: Your <unit> became ... rank of <veteran level>. */
775 _("Your %s became more experienced and achieved the rank "
776 "of %s."),
778}
779
780/**********************************************************************/
783static void unit_convert(struct unit *punit)
784{
785 const struct unit_type *to_type;
786 const struct unit_type *from_type;
787
789 to_type = from_type->converted_to;
790
791 if (unit_can_convert(&(wld.map), punit)) {
795 _("%s converted to %s."),
798 } else {
801 _("%s cannot be converted."),
803 }
804}
805
806/**********************************************************************/
810{
811 if (unit_has_orders(punit)) {
814 _("Orders for %s aborted because activity "
815 "is no longer available."),
818 }
819
821 send_unit_info(nullptr, punit);
822}
823
824/**********************************************************************/
835
836/**********************************************************************/
847
848/**********************************************************************/
862
863/**********************************************************************/
867static void update_unit_activity(struct unit *punit)
868{
869 struct player *pplayer = unit_owner(punit);
871 enum unit_activity activity = punit->activity;
872 struct tile *ptile = unit_tile(punit);
873 const struct unit_type *act_utype = unit_type_get(punit);
874
875 switch (activity) {
876 case ACTIVITY_IDLE:
877 case ACTIVITY_EXPLORE:
879 case ACTIVITY_SENTRY:
880 case ACTIVITY_GOTO:
881 case ACTIVITY_LAST:
882 /* We don't need the activity_count for the above */
883 break;
884
886 case ACTIVITY_CONVERT:
888 break;
889
890 case ACTIVITY_CLEAN:
891 case ACTIVITY_MINE:
893 case ACTIVITY_PILLAGE:
895 case ACTIVITY_PLANT:
897 case ACTIVITY_BASE:
900
901 /* Worker may become veteran when doing something useful */
904 }
905 break;
906 };
907
909
910 switch (activity) {
911 case ACTIVITY_EXPLORE:
912 /* Not accumulating activity - will be handled more like movement
913 * after the TC */
915 case ACTIVITY_IDLE:
917 case ACTIVITY_SENTRY:
918 case ACTIVITY_GOTO:
920 case ACTIVITY_CONVERT:
921 case ACTIVITY_LAST:
922 /* No default, ensure all handled */
923 break;
924
925 case ACTIVITY_PILLAGE:
930
932
933 /* Change vision if effects have changed. */
935 }
936 break;
937
938 case ACTIVITY_CLEAN:
939 /* TODO: Remove this fallback target setting when target always correctly
940 * set */
941 {
942 struct extra_type *pextra;
943
944 if (punit->activity_target == nullptr) {
945 pextra = prev_extra_in_tile(ptile, ERM_CLEAN,
946 nullptr, punit);
947 if (pextra != nullptr) {
948 punit->activity_target = pextra;
949 }
950 } else {
952 pextra = punit->activity_target;
953 } else {
954 pextra = nullptr;
955 }
956 }
957
958 if (pextra != nullptr) {
959 if (total_activity_done(ptile, ACTIVITY_CLEAN, pextra)) {
960 destroy_extra(ptile, pextra);
962 }
963 }
964 }
965 break;
966
967 case ACTIVITY_BASE:
968 {
973 }
974 }
975 break;
976
978 {
983 }
984 }
985 break;
986
988 case ACTIVITY_MINE:
990 case ACTIVITY_PLANT:
992 if (total_activity_done(ptile, activity, punit->activity_target)) {
993 struct terrain *old = tile_terrain(ptile);
994
995 /* The function below could change the terrain. Therefore, we have to
996 * check the terrain (which will also do a sanity check for the tile). */
997 tile_apply_activity(ptile, activity, punit->activity_target);
1000 }
1001 break;
1002 }
1003
1004 if (unit_activity_done) {
1006
1007 update_tile_knowledge(ptile);
1008
1009 unit_list_iterate(ptile->units, punit2) {
1010 if (punit2->activity == activity
1011 && punit2->activity_target == act_tgt) {
1012 /* This unit was helping with the work just finished.
1013 * Mark it idle (already finished) so its "current"
1014 * activity is not considered illegal
1015 * in tile_change_side_effects() . */
1017 }
1019
1021 }
1022
1023 if (activity == ACTIVITY_FORTIFYING) {
1026 punit, ptile, punit->activity_target)) {
1029 }
1030 }
1031
1032 if (activity == ACTIVITY_CONVERT) {
1035 punit, ptile, punit->activity_target)) {
1039 }
1040 }
1041
1042 if (unit_activity_done) {
1043 if (activity == ACTIVITY_PILLAGE) {
1044 /* Casus Belli for when the action is completed. */
1045 /* TODO: is it more logical to put Casus_Belli_Success here, change
1046 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1047 * trigger it when an activity successfully has began? */
1050 act_utype,
1054 }
1055 }
1056}
1057
1058/**********************************************************************/
1066
1067/**********************************************************************/
1072{
1073 switch (activity) {
1074 case ACTIVITY_PILLAGE:
1075 /* Can be set server side. */
1076 return FALSE;
1077 default:
1078 return activity_requires_target(activity);
1079 }
1080}
1081
1082/**********************************************************************/
1092 enum unit_activity *activity,
1093 enum gen_action action,
1094 struct extra_type **target)
1095{
1096 const struct civ_map *nmap = &(wld.map);
1097
1098 if (*activity == ACTIVITY_PILLAGE
1099 && *target == nullptr) {
1100 struct tile *ptile = unit_tile(punit);
1101 struct extra_type *tgt;
1102 bv_extras extras = *tile_extras(ptile);
1103
1104 while ((tgt = get_preferred_pillage(extras))) {
1105
1106 BV_CLR(extras, extra_index(tgt));
1107
1109 tgt)) {
1110 *target = tgt;
1111 return;
1112 }
1113 }
1114
1115 /* Nothing we can pillage here. */
1116 *activity = ACTIVITY_IDLE;
1117 }
1118}
1119
1120/**********************************************************************/
1125 struct player *powner,
1126 struct unit_type *u_type,
1127 int sq_radius,
1128 struct tile **dst_tile)
1129{
1130 int bestvalue = 0;
1131 struct civ_map *nmap = &(wld.map);
1132
1133 /* coords of best tile in arg pointers */
1135 int value;
1136
1137 if (!is_native_tile(u_type, ptile)) {
1138 continue;
1139 }
1140
1141 if (tile_city(ptile) != nullptr) {
1142 continue;
1143 }
1144
1145 if (0 < unit_list_size(ptile->units)) {
1146 continue;
1147 }
1148
1149 /* City may not have changed hands yet; see place_partisans(). */
1150 value = get_virtual_defense_power(nmap, nullptr, u_type, powner,
1151 ptile, FALSE, 0);
1152 value *= 10;
1153
1154 if (tile_continent(ptile) != tile_continent(pcenter)) {
1155 value /= 2;
1156 }
1157
1158 value -= fc_rand(value/3);
1159
1160 if (value > bestvalue) {
1161 *dst_tile = ptile;
1162 bestvalue = value;
1163 }
1165
1166 return bestvalue > 0;
1167}
1168
1169/**********************************************************************/
1172void place_partisans(struct tile *pcenter, struct player *powner,
1173 int count, int sq_radius)
1174{
1175 struct tile *ptile = nullptr;
1177 const struct civ_map *nmap = &(wld.map);
1178
1179 while (count-- > 0
1181 sq_radius, &ptile)) {
1182 struct unit *punit;
1184
1185 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1187 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1188 punit->action = action;
1189 }
1190
1191 (void) place_unit(punit, powner, nullptr, nullptr, FALSE);
1192 }
1193}
1194
1195/**********************************************************************/
1201 int move_cost, bool verbose)
1202{
1203 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1204
1205 if (city_owner(pcity) == unit_owner(punit)) {
1206 log_verbose("Teleported %s %s from (%d,%d) to %s",
1209 if (verbose) {
1212 _("Teleported your %s to %s."),
1214 city_link(pcity));
1215 }
1216
1217 /* Silently free orders since they won't be applicable anymore. */
1219
1220 if (move_cost == -1) {
1221 move_cost = punit->moves_left;
1222 }
1223 unit_move(punit, dst_tile, move_cost,
1224 nullptr, FALSE, FALSE, FALSE, FALSE, FALSE);
1225
1226 return TRUE;
1227 }
1228 return FALSE;
1229}
1230
1231/**********************************************************************/
1238void bounce_unit(struct unit *punit, bool verbose)
1239{
1240 struct player *pplayer;
1241 struct tile *punit_tile;
1242 int count = 0;
1243
1244 /* I assume that there are no topologies that have more than
1245 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1246 const int DIST = 2;
1247 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1248
1249 if (!punit) {
1250 return;
1251 }
1252
1253 pplayer = unit_owner(punit);
1255
1256 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1257 if (count >= ARRAY_SIZE(tiles)) {
1258 break;
1259 }
1260
1261 if (ptile == punit_tile) {
1262 continue;
1263 }
1264
1265 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1266 && !is_non_allied_city_tile(ptile, pplayer)
1267 && !is_non_allied_unit_tile(ptile, pplayer,
1269 tiles[count++] = ptile;
1270 }
1272
1273 if (count > 0) {
1274 struct tile *ptile = tiles[fc_rand(count)];
1275
1276 if (verbose) {
1277 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1278 /* TRANS: A unit is moved to resolve stack conflicts. */
1279 _("Moved your %s."),
1280 unit_link(punit));
1281 }
1282
1283 /* TODO: Should a unit be able to bounce to a transport like is done
1284 * below? What if the unit can't legally enter the transport, say
1285 * because the transport is Unreachable and the unit doesn't have it in
1286 * its embarks field or because "Transport Embark" isn't enabled? Kept
1287 * like it was to preserve the old rules for now. -- Sveinung */
1288 unit_move(punit, ptile, 0, nullptr, TRUE, FALSE, FALSE, FALSE, FALSE);
1289 return;
1290 }
1291
1292 /* Didn't find a place to bounce the unit, going to disband it.
1293 * Try to bounce transported units. */
1295 struct unit_list *pcargo_units;
1296
1299 bounce_unit(pcargo, verbose);
1301 }
1302
1303 if (verbose) {
1305 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1306 _("Disbanded your %s."),
1308 }
1309
1311}
1312
1313/**********************************************************************/
1318static void throw_units_from_illegal_cities(struct player *pplayer,
1319 bool verbose)
1320{
1321 struct tile *ptile;
1322 struct city *pcity;
1323 struct unit *ptrans;
1324 struct unit_list *pcargo_units;
1325
1326 /* Unload undesired units from transports, if possible. */
1327 unit_list_iterate(pplayer->units, punit) {
1328 ptile = unit_tile(punit);
1329 pcity = tile_city(ptile);
1330 if (pcity != nullptr
1331 && !pplayers_allied(city_owner(pcity), pplayer)
1335 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1336 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1338 }
1339 }
1341 }
1343
1344 /* Bounce units except transported ones which will be bounced with their
1345 * transport. */
1347 ptile = unit_tile(punit);
1348 pcity = tile_city(ptile);
1349 if (pcity != nullptr
1350 && !pplayers_allied(city_owner(pcity), pplayer)) {
1352 if (ptrans == nullptr || pplayer != unit_owner(ptrans)) {
1353 bounce_unit(punit, verbose);
1354 }
1355 }
1357
1358#ifdef FREECIV_DEBUG
1359 /* Sanity check. */
1360 unit_list_iterate(pplayer->units, punit) {
1361 ptile = unit_tile(punit);
1362 pcity = tile_city(ptile);
1363 fc_assert_msg(pcity == nullptr
1364 || pplayers_allied(city_owner(pcity), pplayer),
1365 "Failed to throw %s %d from %s %d (%d, %d)",
1367 punit->id,
1369 pcity->id,
1370 TILE_XY(ptile));
1372#endif /* FREECIV_DEBUG */
1373}
1374
1375/**********************************************************************/
1383static void resolve_stack_conflicts(struct player *pplayer,
1384 struct player *aplayer, bool verbose)
1385{
1387 struct tile *ptile = unit_tile(punit);
1388
1389 /* Can pass FALSE 'everyone_non_allied' since no flagless
1390 * unit could be stacked there to begin with. */
1391 if (is_non_allied_unit_tile(ptile, pplayer, FALSE)) {
1393 if (unit_owner(aunit) == pplayer
1394 || unit_owner(aunit) == aplayer
1395 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1396 bounce_unit(aunit, verbose);
1397 }
1399 }
1401}
1402
1403/**********************************************************************/
1414void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1415 bool verbose)
1416{
1417 throw_units_from_illegal_cities(pplayer, verbose);
1419
1420 resolve_stack_conflicts(pplayer, aplayer, verbose);
1421 resolve_stack_conflicts(aplayer, pplayer, verbose);
1422}
1423
1424/**********************************************************************/
1429struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1430 const struct player *aplayer)
1431{
1432 struct unit_list *seen_units = unit_list_new();
1433
1434 /* Anybody's units inside ally's cities */
1435 city_list_iterate(aplayer->cities, pcity) {
1437 if (can_player_see_unit(pplayer, punit)) {
1439 }
1442
1443 /* Ally's own units inside transports */
1445 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1447 }
1449
1450 /* Make sure the same unit is not added in multiple phases
1451 * (unit within transport in a city) */
1453
1454 return seen_units;
1455}
1456
1457/**********************************************************************/
1464void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1465 const struct unit_list *seen_units)
1466{
1468 /* We need to hide units previously seen by the client. */
1469 if (!can_player_see_unit(pplayer, punit)) {
1470 unit_goes_out_of_sight(pplayer, punit);
1471 }
1473
1474 city_list_iterate(aplayer->cities, pcity) {
1475 /* The player used to know what units were in these cities. Now that
1476 * they don't, they need to get a new short city packet updating the
1477 * occupied status. */
1478 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1479 send_city_info(pplayer, pcity);
1480 }
1482}
1483
1484/**********************************************************************/
1488void give_allied_visibility(struct player *pplayer,
1489 struct player *aplayer)
1490{
1492 if (can_player_see_unit(pplayer, punit)) {
1493 send_unit_info(pplayer->connections, punit);
1494 }
1496}
1497
1498/**********************************************************************/
1501static bool is_refuel_tile(const struct tile *ptile,
1502 const struct player *pplayer,
1503 const struct unit *punit)
1504{
1505 const struct unit_type *utype;
1506 const struct unit_class *pclass;
1507
1508 if (is_allied_city_tile(ptile, pplayer)) {
1509 return TRUE;
1510 }
1511
1512 utype = unit_type_get(punit);
1513 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1514 return TRUE;
1515 }
1516
1517 pclass = utype_class(utype);
1518 if (pclass->cache.refuel_extras != nullptr) {
1519 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1520
1521 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1522 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1523 return TRUE;
1524 }
1526 }
1527
1528 return FALSE;
1529}
1530
1531/**********************************************************************/
1535{
1536 return unit_transported(punit) /* Carrier */
1538}
1539
1540/**********************************************************************/
1543bool is_refuel_point(const struct tile *ptile,
1544 const struct player *pplayer,
1545 const struct unit *punit)
1546{
1547 if (is_non_allied_unit_tile(ptile, pplayer,
1549 return FALSE;
1550 }
1551
1552 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1553}
1554
1555/**********************************************************************/
1566void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1567 int vet_loss)
1568{
1569 struct player *pplayer = unit_owner(punit);
1570 const struct unit_type *old_type = punit->utype;
1572 int old_hp = unit_type_get(punit)->hp;
1573 int lvls;
1574
1575 punit->utype = to_unit;
1576
1577 /* New type may not have the same veteran system, and we may want to
1578 * knock some levels off. */
1581 /* Keeping the old behavior, so first clip top, then reduce */
1583
1584 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1585 * and don't kill the unit. unit_move_rate() is used to take into account
1586 * global effects like Magellan's Expedition. */
1587 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1588 if (old_mr == 0) {
1590 } else {
1592 }
1593
1595
1599 }
1600
1601 /* Update unit upkeep */
1603
1605
1607
1608 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1610
1611 send_unit_info(nullptr, punit);
1613}
1614
1615/**********************************************************************/
1618struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1619 const struct unit_type *type, int veteran_level,
1620 int homecity_id, int moves_left)
1621{
1622 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1623 moves_left, -1, nullptr);
1624}
1625
1626/**********************************************************************/
1630{
1631 if (punit->homecity != 0) {
1633
1634 if (home != nullptr && game.info.goods_selection == GSM_LEAVING) {
1636 }
1637 }
1638}
1639
1640/**********************************************************************/
1645struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1646 const struct unit_type *type, int veteran_level,
1647 int homecity_id, int moves_left, int hp_left,
1648 struct unit *ptrans)
1649{
1650 struct unit *punit
1651 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1654 ? nullptr : game_city_by_number(homecity_id);
1655 bool could_place;
1656
1657 fc_assert_ret_val(punit, nullptr);
1660 if (!could_place) {
1662 punit = nullptr;
1663 }
1664
1665 return punit;
1666}
1667
1668/**********************************************************************/
1678struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1679 const struct unit_type *type,
1680 int veteran_level, int homecity_id,
1681 int moves_left, int hp_left)
1682{
1683 struct unit *punit;
1684
1685 fc_assert_ret_val(ptile != nullptr, nullptr);
1686 punit = unit_virtual_create(pplayer, nullptr, type, veteran_level);
1687 unit_tile_set(punit, ptile);
1688
1690 punit->homecity = 0; /* None */
1691 } else {
1693 }
1694
1695 if (hp_left >= 0) {
1696 /* Override default full HP */
1697 punit->hp = hp_left;
1698 }
1699
1700 if (moves_left >= 0) {
1701 int mr = unit_move_rate(punit);
1702
1703 /* Override default full MP */
1704 /* FIXME: there are valid situations when a unit have mp
1705 * over its move rate. Here, keeping the old behavior. */
1707 /* Assume that if moves_left < 0 then the unit is "fresh",
1708 * and not moved; else the unit has had something happen
1709 * to it (eg, bribed) which we treat as equivalent to moved.
1710 * (Otherwise could pass moved arg too...) --dwp */
1711 punit->moved = TRUE;
1712 }
1713
1714 return punit;
1715}
1716
1717/**********************************************************************/
1726bool place_unit(struct unit *punit, struct player *pplayer,
1727 struct city *pcity, struct unit *ptrans, bool force)
1728{
1729 struct tile *ptile;
1730
1731 fc_assert_ret_val(pplayer, FALSE);
1733 ptile = punit->tile;
1734 fc_assert_ret_val(ptile, FALSE);
1735
1736 /* Register unit */
1739
1740 if (ptrans) {
1741 /* Set transporter for unit. */
1743 }
1744
1746 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1747 FALSE);
1748
1749 unit_list_prepend(pplayer->units, punit);
1750 unit_list_prepend(ptile->units, punit);
1751 unit_make_contact(punit, ptile, nullptr);
1754 fc_assert(city_owner(pcity) == pplayer);
1755 unit_list_prepend(pcity->units_supported, punit);
1756 /* update unit upkeep */
1758 /* Refresh the unit's homecity. */
1760 send_city_info(pplayer, pcity);
1761 }
1762
1763 punit->server.vision = vision_new(pplayer, ptile);
1765
1767
1768 send_unit_info(nullptr, punit);
1770
1771 /* The unit may have changed the available tiles in nearby cities. */
1773 sync_cities();
1774
1775 CALL_FUNC_EACH_AI(unit_created, punit);
1776 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1777
1778 return TRUE;
1779}
1780
1781/**********************************************************************/
1785 void (*callback)(struct unit *punit))
1786{
1787 /* Tried to overwrite another call back. If this assertion is triggered
1788 * in a case where two call back are needed it may be time to support
1789 * more than one unit removal call back at a time. */
1791
1793}
1794
1795/**********************************************************************/
1799{
1800 punit->server.removal_callback = nullptr;
1801}
1802
1803/**********************************************************************/
1807static void server_remove_unit_full(struct unit *punit, bool transported,
1809{
1810 struct packet_unit_remove packet;
1811 struct tile *ptile = unit_tile(punit);
1812 struct city *pcity = tile_city(ptile);
1814 struct unit *ptrans;
1815 struct player *pplayer = unit_owner(punit);
1816
1817 /* The unit is doomed. */
1819
1820#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1821 unit_list_iterate(ptile->units, pcargo) {
1824#endif /* FREECIV_DEBUG */
1825
1826 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1827 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1828
1829 /* Save transporter for updating below. */
1831 /* Unload unit. */
1833
1834 /* Since settlers plot in new cities in the minimap before they
1835 are built, so that no two settlers head towards the same city
1836 spot, we need to ensure this reservation is cleared should
1837 the settler disappear on the way. */
1838 adv_unit_new_task(punit, AUT_NONE, nullptr);
1839
1840 /* Clear the vision before sending unit remove. Else, we might duplicate
1841 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1842 if (punit->server.vision != nullptr) {
1845 punit->server.vision = nullptr;
1846 }
1847 if (punit->server.scout_vision != nullptr) {
1850 punit->server.scout_vision = nullptr;
1851 }
1852
1853 packet.unit_id = punit->id;
1854 /* Send to onlookers. */
1857 transported)) {
1858 lsend_packet_unit_remove(aplayer->connections, &packet);
1859 }
1861 /* Send to global observers. */
1865 }
1867
1868 if (punit->server.moving != nullptr) {
1869 /* Do not care of this unit for running moves. */
1870 punit->server.moving->punit = nullptr;
1871 }
1872
1873 if (punit->server.removal_callback != nullptr) {
1874 /* Run the unit removal call back. */
1876 }
1877
1878 /* check if this unit had UTYF_GAMELOSS flag */
1880 && ULR_EDITOR != reason) {
1882 _("Unable to defend %s, %s has lost the game."),
1884 player_name(pplayer));
1885 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1886 _("Losing %s meant losing the game! "
1887 "Be more careful next time!"),
1888 unit_link(punit));
1890 }
1891
1894
1897 punit = nullptr;
1898
1899 if (ptrans != nullptr) {
1900 /* Update the occupy info. */
1901 send_unit_info(nullptr, ptrans);
1902 }
1903
1904 /* This unit may have blocked tiles of adjacent cities. Update them. */
1906 sync_cities();
1907
1908 if (phomecity) {
1911 }
1912
1913 if (pcity && pcity != phomecity) {
1916 }
1917
1918 if (pcity && unit_list_size(ptile->units) == 0) {
1919 /* The last unit in the city was killed: update the occupied flag. */
1920 send_city_info(nullptr, pcity);
1921 }
1922}
1923
1924/**********************************************************************/
1933
1934/**********************************************************************/
1937static void unit_lost_with_transport(const struct player *pplayer,
1938 struct unit *pcargo,
1939 const struct unit_type *ptransport,
1940 struct player *killer)
1941{
1943 _("%s lost when %s was lost."),
1946 /* Unit is not transported any more at this point, but it has jumped
1947 * off the transport and drowns outside. So it must be removed from
1948 * all clients.
1949 * However, we don't know if given client has received ANY updates
1950 * about the swimming unit, and we can't remove it if it's not there
1951 * in the first place -> we send it once here just to be sure it's
1952 * there. */
1953 send_unit_info(nullptr, pcargo);
1955}
1956
1957/**********************************************************************/
1961static void wipe_unit_full(struct unit *punit, bool transported,
1963 struct player *killer)
1964{
1965 struct tile *ptile = unit_tile(punit);
1966 struct player *pplayer = unit_owner(punit);
1967 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1968 struct unit_list *helpless = unit_list_new();
1969 struct unit_list *imperiled = unit_list_new();
1970 struct unit_list *unsaved = unit_list_new();
1972 struct city *pexclcity;
1973 struct civ_map *nmap = &(wld.map);
1974
1975 if (killer != nullptr
1978 player_loot_player(killer, pplayer);
1979 }
1980
1981 /* The unit is doomed. */
1983
1984 /* If a unit is being lost due to loss of its city, ensure that we don't
1985 * try to teleport any of its cargo to that city (which may not yet
1986 * have changed hands or disappeared). (It is assumed that the unit's
1987 * home city is always the one that is being lost/transferred/etc.) */
1988 if (reason == ULR_CITY_LOST) {
1990 } else {
1991 pexclcity = nullptr;
1992 }
1993
1994 /* Remove unit itself from its transport */
1995 if (ptrans != nullptr) {
1997 send_unit_info(nullptr, ptrans);
1998 }
1999
2000 /* First pull all units off of the transporter. */
2002 /* Use iterate_safe as unloaded units will be removed from the list
2003 * while iterating. */
2005 bool healthy = FALSE;
2006
2007 if (!can_unit_unload(pcargo, punit)) {
2009 } else {
2010 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
2012 } else {
2013 /* These units do not need to be saved. */
2014 healthy = TRUE;
2015 }
2016 }
2017
2018 /* Could use unit_transport_unload_send() here, but that would
2019 * call send_unit_info() for the transporter unnecessarily.
2020 * Note that this means that unit might to get seen briefly
2021 * by clients other than owner's, for example as a result of
2022 * update of homecity common to this cargo and some other
2023 * destroyed unit. */
2025 if (pcargo->activity == ACTIVITY_SENTRY) {
2026 /* Activate sentried units - like planes on a disbanded carrier.
2027 * Note this will activate ground units even if they just change
2028 * transporter. */
2030 }
2031
2032 /* Unit info for unhealthy units will be sent when they are
2033 * assigned new transport or removed. */
2034 if (healthy) {
2035 send_unit_info(nullptr, pcargo);
2036 }
2038 }
2039
2040 /* Now remove the unit. */
2041 server_remove_unit_full(punit, transported, reason);
2042
2043 switch (reason) {
2044 case ULR_KILLED:
2045 case ULR_EXECUTED:
2046 case ULR_SDI:
2047 case ULR_NUKE:
2048 case ULR_BRIBED:
2049 case ULR_CAPTURED:
2050 case ULR_CAUGHT:
2051 case ULR_ELIMINATED:
2052 case ULR_TRANSPORT_LOST:
2053 if (killer != nullptr) {
2054 killer->score.units_killed++;
2055 }
2056 pplayer->score.units_lost++;
2057 break;
2058 case ULR_BARB_UNLEASH:
2059 case ULR_CITY_LOST:
2060 case ULR_STARVED:
2061 case ULR_UPKEEP:
2062 case ULR_NONNATIVE_TERR:
2063 case ULR_ARMISTICE:
2064 case ULR_HP_LOSS:
2065 case ULR_FUEL:
2066 case ULR_STACK_CONFLICT:
2067 case ULR_SOLD:
2068 pplayer->score.units_lost++;
2069 break;
2070 case ULR_RETIRED:
2071 case ULR_DISBANDED:
2072 case ULR_USED:
2073 case ULR_DETONATED:
2074 case ULR_MISSILE:
2075 pplayer->score.units_used++;
2076 break;
2077 case ULR_EDITOR:
2078 case ULR_PLAYER_DIED:
2079 break;
2080 }
2081
2082 /* First, sort out helpless cargo. */
2083 if (unit_list_size(helpless) > 0) {
2084 struct unit_list *remaining = unit_list_new();
2085
2086 /* Grant priority to gameloss units and units with the EvacuateFirst
2087 * unit type flag. */
2094 pexclcity)) {
2096 }
2097 } else {
2098 unit_list_prepend(remaining, pcargo);
2099 }
2101
2102 /* Handle non-priority units. */
2103 unit_list_iterate_safe(remaining, pcargo) {
2106 }
2108
2109 unit_list_destroy(remaining);
2110 }
2112
2113 /* Then, save any imperiled cargo. */
2114 if (unit_list_size(imperiled) > 0) {
2115 struct unit_list *remaining = unit_list_new();
2116
2117 /* Grant priority to gameloss units and units with the EvacuateFirst
2118 * unit type flag. */
2125 pexclcity)) {
2127 }
2128 } else {
2129 unit_list_prepend(remaining, pcargo);
2130 }
2132
2133 /* Handle non-priority units. */
2134 unit_list_iterate_safe(remaining, pcargo) {
2137 }
2139
2140 unit_list_destroy(remaining);
2141 }
2143
2144 /* Finally, kill off the unsaved units. */
2145 if (unit_list_size(unsaved) > 0) {
2149 }
2151}
2152
2153/**********************************************************************/
2162
2163/**********************************************************************/
2169static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2170 bool helpless, bool teleporting,
2171 const struct city *pexclcity)
2172{
2173 struct tile *ptile = unit_tile(punit);
2174 struct player *pplayer = unit_owner(punit);
2176
2177 /* Helpless units cannot board a transport in their current state. */
2178 if (!helpless
2179 && ptransport != nullptr) {
2181 send_unit_info(nullptr, punit);
2182 return TRUE;
2183 } else {
2184 /* Only units that cannot find transport are considered for teleport. */
2185 if (teleporting) {
2186 struct city *pcity = find_closest_city(ptile, pexclcity,
2190 if (pcity != nullptr) {
2191 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2192
2194
2196 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2197 _("%s escaped the destruction of %s, and fled to %s."),
2198 tplink,
2200 city_link(pcity));
2201 return TRUE;
2202 }
2203 }
2204 }
2205 }
2206
2207 /* The unit could not use transport on the tile, and could not teleport. */
2208 return FALSE;
2209}
2210
2211/**********************************************************************/
2217struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2219{
2220 struct unit *gained_unit;
2221 int id = 0;
2222
2223#ifndef FREECIV_NDEBUG
2224 bool placed;
2225#endif
2226
2229
2230 /* Convert the unit to your cause. It's supposed that the original unit
2231 * is on a valid tile and is not transported. */
2235 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2236
2237 /* Owner changes, nationality not. */
2238 gained_unit->nationality = punit->nationality;
2239
2240 /* Copy some more unit fields */
2241 gained_unit->fuel = punit->fuel;
2242 gained_unit->paradropped = punit->paradropped;
2243 gained_unit->birth_turn = punit->birth_turn;
2244 gained_unit->current_form_turn = punit->current_form_turn;
2245
2246 /* Fog is lifted in the placing algorithm. */
2247#ifndef FREECIV_NDEBUG
2248 placed =
2249#endif
2250 place_unit(gained_unit, pplayer,
2252 nullptr, FALSE);
2253
2255
2256 id = gained_unit->id;
2257
2258 /* Update unit upkeep in the new homecity */
2259 if (homecity > 0) {
2261 }
2262
2263 /* Be sure to wipe the converted unit! */
2264 /* Old homecity upkeep is updated in process */
2265#ifndef FREECIV_NDEBUG
2266 uco_wipe:
2267#endif
2268
2269 wipe_unit(punit, reason, nullptr);
2270
2271 if (!unit_is_alive(id)) {
2272 /* Destroyed by a script */
2273 return nullptr;
2274 }
2275
2276 return gained_unit; /* Returns the replacement. */
2277}
2278
2279/**********************************************************************/
2284void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2285{
2287 struct player *pvictim = unit_owner(punit);
2288 struct player *pvictor = unit_owner(pkiller);
2289 struct tile *deftile = unit_tile(punit);
2290 int unitcount = 0;
2291 bool escaped;
2294 const struct civ_map *nmap = &(wld.map);
2295
2298
2299 /* The unit is doomed. */
2301
2303 if ((flagless_killer
2307 unitcount++;
2308 }
2310
2311 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2312 if (vet) {
2314 }
2316 } else { /* Unitcount > 1 */
2317 int i;
2318 int slots = player_slot_count();
2319 int num_killed[slots];
2320 int num_escaped[slots];
2321 struct unit *other_killed[slots];
2322
2323 fc_assert(unitcount > 1);
2324
2325 /* Initialize */
2326 for (i = 0; i < slots; i++) {
2327 num_killed[i] = 0;
2328 other_killed[i] = nullptr;
2329 num_escaped[i] = 0;
2330 }
2331
2332 /* Count killed units */
2334 struct player *vplayer = unit_owner(vunit);
2335
2338 escaped = FALSE;
2339
2342 && vunit->hp > 0
2343 && vunit->moves_left > pkiller->moves_left
2344 && fc_rand(2)) {
2345 int curr_def_bonus;
2346 int def_bonus = 0;
2347 struct tile *dsttile = nullptr;
2348 int move_cost;
2349
2350 fc_assert(vunit->hp > 0);
2351
2353 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2354 && tile_city(ptile2) == nullptr) {
2355 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2356 if (pkiller->moves_left <= vunit->moves_left - move_cost
2358 || unit_list_size(ptile2->units)) == 0) {
2360 vunit->utype);
2361 if (def_bonus <= curr_def_bonus) {
2363 dsttile = ptile2;
2364 }
2365 }
2366 }
2368
2369 if (dsttile != nullptr) {
2372 nullptr, nullptr, dsttile,
2374 nullptr, nullptr)
2375 != nullptr);
2376
2377 if (escaped) {
2379 unitcount--;
2380 }
2381 }
2382 }
2383
2384 if (!escaped) {
2386
2387 if (vunit != punit) {
2390 }
2391 }
2392 }
2394
2395 /* Inform the destroyer again if more than one unit was killed */
2396 if (unitcount > 1) {
2397 if (flagless_victim) {
2399 /* TRANS: "... Cannon ... Destroyer ...." */
2400 PL_("Your attacking %s succeeded against %s "
2401 "(and %d other unit)!",
2402 "Your attacking %s succeeded against %s "
2403 "(and %d other units)!", unitcount - 1),
2405 punit_link,
2406 unitcount - 1);
2407 } else {
2409 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2410 PL_("Your attacking %s succeeded against the %s %s "
2411 "(and %d other unit)!",
2412 "Your attacking %s succeeded against the %s %s "
2413 "(and %d other units)!", unitcount - 1),
2416 punit_link,
2417 unitcount - 1);
2418 }
2419 }
2420
2421 if (vet) {
2423 }
2424
2425 /* Inform the owners: this only tells about owned units that were killed.
2426 * there may have been 20 units who died but if only 2 belonged to the
2427 * particular player they'll only learn about those.
2428 *
2429 * Also if a large number of units die you don't find out what type
2430 * they all are. */
2431 for (i = 0; i < slots; i++) {
2432 if (num_killed[i] == 1) {
2433 if (i == player_index(pvictim)) {
2434 fc_assert(other_killed[i] == nullptr);
2435
2436 if (flagless_killer) {
2439 /* TRANS: "Cannon ... Destroyer." */
2440 _("%s lost to an attack by %s."),
2441 punit_link,
2442 pkiller_link);
2443 } else {
2446 /* TRANS: "Cannon ... the Polish Destroyer." */
2447 _("%s lost to an attack by the %s %s."),
2448 punit_link,
2450 pkiller_link);
2451 }
2452 } else {
2454
2455 if (flagless_victim) {
2456 if (flagless_killer) {
2459 /* TRANS: "Cannon lost when Destroyer
2460 * attacked Musketeers." */
2461 _("%s lost when %s attacked %s."),
2464 punit_link);
2465 } else {
2468 /* TRANS: "Cannon lost when the Polish Destroyer
2469 * attacked Musketeers." */
2470 _("%s lost when the %s %s attacked %s."),
2474 punit_link);
2475 }
2476 } else {
2477 if (flagless_killer) {
2480 /* TRANS: "Cannon lost when Destroyer
2481 * attacked the German Musketeers." */
2482 _("%s lost when %s attacked the %s %s."),
2486 punit_link);
2487 } else {
2490 /* TRANS: "Cannon lost when the Polish Destroyer
2491 * attacked the German Musketeers." */
2492 _("%s lost when the %s %s attacked the %s %s."),
2497 punit_link);
2498 }
2499 }
2500 }
2501 } else if (num_killed[i] > 1) {
2502 if (i == player_index(pvictim)) {
2503 int others = num_killed[i] - 1;
2504
2505 if (others == 1) {
2506 if (flagless_killer) {
2509 /* TRANS: "Musketeers (and Cannon) lost to an
2510 * attack from Destroyer." */
2511 _("%s (and %s) lost to an attack from %s."),
2512 punit_link,
2514 pkiller_link);
2515 } else {
2518 /* TRANS: "Musketeers (and Cannon) lost to an
2519 * attack from the Polish Destroyer." */
2520 _("%s (and %s) lost to an attack from the %s %s."),
2521 punit_link,
2524 pkiller_link);
2525 }
2526 } else {
2527 if (flagless_killer) {
2530 /* TRANS: "Musketeers and 3 other units lost to
2531 * an attack from Destroyer."
2532 * (only happens with at least 2 other units) */
2533 PL_("%s and %d other unit lost to an attack "
2534 "from %s.",
2535 "%s and %d other units lost to an attack "
2536 "from %s.", others),
2537 punit_link,
2538 others,
2539 pkiller_link);
2540 } else {
2543 /* TRANS: "Musketeers and 3 other units lost to
2544 * an attack from the Polish Destroyer."
2545 * (only happens with at least 2 other units) */
2546 PL_("%s and %d other unit lost to an attack "
2547 "from the %s %s.",
2548 "%s and %d other units lost to an attack "
2549 "from the %s %s.", others),
2550 punit_link,
2551 others,
2553 pkiller_link);
2554 }
2555 }
2556 } else {
2557 if (flagless_victim) {
2558 if (flagless_killer) {
2561 /* TRANS: "2 units lost when Destroyer
2562 * attacked Musketeers."
2563 * (only happens with at least 2 other units) */
2564 PL_("%d unit lost when %s attacked %s.",
2565 "%d units lost when %s attacked %s.",
2566 num_killed[i]),
2567 num_killed[i],
2569 punit_link);
2570 } else {
2573 /* TRANS: "2 units lost when the Polish Destroyer
2574 * attacked Musketeers."
2575 * (only happens with at least 2 other units) */
2576 PL_("%d unit lost when the %s %s attacked %s.",
2577 "%d units lost when the %s %s attacked %s.",
2578 num_killed[i]),
2579 num_killed[i],
2582 punit_link);
2583 }
2584 } else {
2585 if (flagless_killer) {
2588 /* TRANS: "2 units lost when Destroyer
2589 * attacked the German Musketeers."
2590 * (only happens with at least 2 other units) */
2591 PL_("%d unit lost when %s attacked the %s %s.",
2592 "%d units lost when %s attacked the %s %s.",
2593 num_killed[i]),
2594 num_killed[i],
2597 punit_link);
2598 } else {
2601 /* TRANS: "2 units lost when the Polish Destroyer
2602 * attacked the German Musketeers."
2603 * (only happens with at least 2 other units) */
2604 PL_("%d unit lost when the %s %s attacked the %s %s.",
2605 "%d units lost when the %s %s attacked the %s %s.",
2606 num_killed[i]),
2607 num_killed[i],
2611 punit_link);
2612 }
2613 }
2614 }
2615 }
2616 }
2617
2618 /* Inform the owner of the units that escaped.
2619 * 'deftile' is the original tile they defended at, not where
2620 * they escaped to, as there might be multiple different tiles
2621 * different units escaped to. */
2622 for (i = 0; i < slots; i++) {
2623 if (0 < num_escaped[i]) {
2624 if (flagless_killer) {
2627 PL_("%d unit escaped from attack by %s",
2628 "%d units escaped from attack by %s",
2629 num_escaped[i]),
2630 num_escaped[i],
2631 pkiller_link);
2632 } else {
2635 PL_("%d unit escaped from attack by %s %s",
2636 "%d units escaped from attack by %s %s",
2637 num_escaped[i]),
2638 num_escaped[i],
2640 pkiller_link);
2641 }
2642 }
2643 }
2644
2645 /* Remove the units - note the logic of which units actually die
2646 * must be mimicked exactly in at least one place up above. */
2647 punit = nullptr; /* Wiped during following iteration so unsafe to use */
2648
2653 }
2655 }
2656}
2657
2658/**********************************************************************/
2661void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2662{
2663 struct player *pvictim = unit_owner(punit);
2666 struct tile *deftile = unit_tile(punit);
2667 int unitcount, ransom;
2668
2669 /* The unit is doomed. */
2671
2674
2675 if (pvictim->economic.gold < ransom) {
2676 ransom = pvictim->economic.gold;
2677 }
2678
2680 PL_("%d Barbarian leader captured.",
2681 "%d Barbarian leaders captured.",
2682 unitcount),
2683 unitcount);
2685 PL_("%d gold ransom paid.",
2686 "%d gold ransom paid.",
2687 ransom),
2688 ransom);
2689 pvictor->economic.gold += ransom;
2690 pvictim->economic.gold -= ransom;
2691 send_player_info_c(pvictor, nullptr); /* Let me see my new gold :-) */
2692
2693 if (vet) {
2695 }
2696
2699
2700 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2702 } else {
2703 int i;
2704 int slots = player_slot_count();
2705 int num_collected[slots];
2706
2707 fc_assert(unitcount > 1);
2708
2709 /* Initialize */
2710 for (i = 0; i < slots; i++) {
2711 num_collected[i] = 0;
2712 }
2713
2714 /* Count captured units */
2716 struct player *vplayer = unit_owner(vunit);
2717
2720
2721 for (i = 0; i < slots; i++) {
2722 if (num_collected[i] == 1) {
2725 _("%s %s collected ransom of %s."),
2728 } else if (num_collected[i] > 1) {
2731 PL_("%s %s collected ransom of %s and %d other unit.",
2732 "%s %s collected ransom of %s and %d other units.",
2733 num_collected[i] - 1),
2736 punit_link,
2737 num_collected[i] - 1);
2738 }
2739 }
2740
2744 }
2745}
2746
2747/**********************************************************************/
2751void package_unit(struct unit *punit, struct packet_unit_info *packet)
2752{
2753 packet->id = punit->id;
2754 packet->owner = player_number(unit_owner(punit));
2756 packet->tile = tile_index(unit_tile(punit));
2757 packet->facing = punit->facing;
2758 packet->homecity = punit->homecity;
2760 packet->upkeep[o] = punit->upkeep[o];
2762 packet->veteran = punit->veteran;
2764 packet->movesleft = punit->moves_left;
2765 packet->hp = punit->hp;
2766 packet->activity = punit->activity;
2768
2769 if (punit->activity_target != nullptr) {
2771 } else {
2772 packet->activity_tgt = EXTRA_NONE;
2773 }
2774
2775 packet->changed_from = punit->changed_from;
2777
2778 if (punit->changed_from_target != nullptr) {
2780 } else {
2781 packet->changed_from_tgt = EXTRA_NONE;
2782 }
2783
2785 packet->fuel = punit->fuel;
2786 packet->goto_tile = (punit->goto_tile != nullptr
2787 ? tile_index(punit->goto_tile) : -1);
2788 packet->paradropped = punit->paradropped;
2789 packet->done_moving = punit->done_moving;
2790 packet->stay = punit->stay;
2791 packet->birth_turn = punit->birth_turn;
2793 if (!unit_transported(punit)) {
2794 packet->transported = FALSE;
2795 packet->transported_by = 0;
2796 } else {
2797 packet->transported = TRUE;
2799 }
2800 if (punit->carrying != nullptr) {
2801 packet->carrying = goods_index(punit->carrying);
2802 } else {
2803 packet->carrying = -1;
2804 }
2805 packet->occupied = (get_transporter_occupancy(punit) > 0);
2806 packet->battlegroup = punit->battlegroup;
2807 packet->has_orders = punit->has_orders;
2808 if (punit->has_orders) {
2809 packet->orders_length = punit->orders.length;
2810 packet->orders_index = punit->orders.index;
2811 packet->orders_repeat = punit->orders.repeat;
2813 memcpy(packet->orders, punit->orders.list,
2814 punit->orders.length * sizeof(struct unit_order));
2815 } else {
2816 packet->orders_length = packet->orders_index = 0;
2817 packet->orders_repeat = packet->orders_vigilant = FALSE;
2818 /* No need to initialize array. */
2819 }
2820
2825}
2826
2827/**********************************************************************/
2833 struct packet_unit_short_info *packet,
2834 enum unit_info_use packet_use, int info_city_id)
2835{
2836 packet->packet_use = packet_use;
2837 packet->info_city_id = info_city_id;
2838
2839 packet->id = punit->id;
2840
2842 packet->owner = OWNER_NONE;
2843 } else {
2844 packet->owner = player_number(unit_owner(punit));
2845 }
2846
2847 packet->tile = tile_index(unit_tile(punit));
2848 packet->facing = punit->facing;
2849 packet->veteran = punit->veteran;
2851 packet->hp = punit->hp;
2852 packet->occupied = (get_transporter_occupancy(punit) > 0);
2854 || punit->activity == ACTIVITY_GOTO) {
2855 packet->activity = ACTIVITY_IDLE;
2856 } else {
2857 packet->activity = punit->activity;
2858 }
2859
2860 if (punit->activity_target == nullptr) {
2861 packet->activity_tgt = EXTRA_NONE;
2862 } else {
2864 }
2865
2866 /* Transported_by information is sent to the client even for units that
2867 * aren't fully known. Note that for non-allied players, any transported
2868 * unit can't be seen at all. For allied players we have to know if
2869 * transporters have room in them so that we can load units properly. */
2870 if (!unit_transported(punit)) {
2871 packet->transported = FALSE;
2872 packet->transported_by = 0;
2873 } else {
2874 packet->transported = TRUE;
2876 }
2877}
2878
2879/**********************************************************************/
2882void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2883{
2885 if (punit->server.moving != nullptr) {
2886 /* Update status of 'pplayer' vision for 'punit'. */
2888 }
2889}
2890
2891/**********************************************************************/
2895void send_unit_info(struct conn_list *dest, struct unit *punit)
2896{
2897 const struct player *powner;
2898 struct packet_unit_info info;
2900 struct unit_move_data *pdata;
2901
2902 if (dest == nullptr) {
2903 dest = game.est_connections;
2904 }
2905
2907
2909 package_unit(punit, &info);
2912
2913 conn_list_iterate(dest, pconn) {
2914 struct player *pplayer = conn_get_player(pconn);
2915
2916 /* Be careful to consider all cases where pplayer is nullptr... */
2917 if (pplayer == nullptr) {
2918 if (pconn->observer) {
2920 }
2921 } else if (pplayer == powner) {
2923 if (pdata != nullptr) {
2924 BV_SET(pdata->can_see_unit, player_index(pplayer));
2925 }
2926 } else if (can_player_see_unit(pplayer, punit)) {
2928 if (pdata != nullptr) {
2929 BV_SET(pdata->can_see_unit, player_index(pplayer));
2930 }
2931 }
2933}
2934
2935/**********************************************************************/
2940{
2941 conn_list_do_buffer(dest);
2942 conn_list_iterate(dest, pconn) {
2943 struct player *pplayer = pconn->playing;
2944
2945 if (pplayer == nullptr && !pconn->observer) {
2946 continue;
2947 }
2948
2951 send_unit_info(dest, punit);
2954 }
2957 flush_packets();
2958}
2959
2960/**********************************************************************/
2967static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2968 const struct action *paction)
2969{
2970 struct city *pcity = nullptr;
2971 int pop_loss;
2972
2973 pcity = tile_city(ptile);
2974
2976
2977 /* unit in a city may survive */
2979 continue;
2980 }
2982 _("Your %s was nuked by %s."),
2984 pplayer == unit_owner(punit)
2985 ? _("yourself")
2986 : nation_plural_for_player(pplayer));
2987 if (unit_owner(punit) != pplayer) {
2988 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2989 _("The %s %s was nuked."),
2992 }
2993 wipe_unit(punit, ULR_NUKE, pplayer);
2995
2996
2997 if (pcity) {
2998 struct player *owner = city_owner(pcity);
2999 char city_name[MAX_LEN_LINK];
3000
3002
3004 _("%s was nuked by %s."),
3005 city_name,
3006 pplayer == owner
3007 ? _("yourself")
3008 : nation_plural_for_player(pplayer));
3009
3010 if (owner != pplayer) {
3011 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3012 _("You nuked %s."),
3013 city_name);
3014 }
3015
3017 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
3018 /* Send city size reduction to everyone seeing it */
3019 send_city_info(nullptr, pcity);
3020 } else {
3021 /* City was destroyed */
3023 _("%s was destroyed by the nuke."),
3024 city_name);
3025 if (owner != pplayer) {
3026 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3027 _("Your nuke destroyed %s."),
3028 city_name);
3029 }
3030 }
3031 }
3032
3033 if (fc_rand(2) == 1) {
3034 struct extra_type *pextra;
3035
3036 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
3037 if (pextra != nullptr && !tile_has_extra(ptile, pextra)) {
3038 tile_add_extra(ptile, pextra);
3039 update_tile_knowledge(ptile);
3040 }
3041 }
3042}
3043
3044/**********************************************************************/
3053 const struct unit_type *act_utype,
3054 struct player *pplayer, struct tile *ptile)
3055{
3057 = get_target_bonus_effects(nullptr,
3058 &(const struct req_context) {
3059 .player = pplayer,
3060 /* City: Wait for users before choosing
3061 * home city or target tile city */
3062 .tile = ptile,
3063 .unittype = act_utype,
3064 .action = paction,
3065 },
3066 nullptr,
3068
3070 do_nuke_tile(pplayer, ptile1, paction);
3072
3073 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
3074 API_TYPE_PLAYER, pplayer);
3075 notify_conn(nullptr, ptile, E_NUKE, ftc_server,
3076 _("The %s detonated a nuke!"),
3077 nation_plural_for_player(pplayer));
3078}
3079
3080/**********************************************************************/
3084bool do_airline(struct unit *punit, struct city *pdest_city,
3085 const struct action *paction)
3086{
3088
3091 _("%s transported successfully."),
3092 unit_link(punit));
3093
3095 nullptr, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
3096 /* Can only airlift to allied and domestic cities */
3097 FALSE, FALSE,
3098 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3100
3101 /* Update airlift fields. */
3103 psrc_city->airlift--;
3105 }
3107 pdest_city->airlift--;
3109 }
3110
3111 return TRUE;
3112}
3113
3114/**********************************************************************/
3117void do_explore(struct unit *punit)
3118{
3119 switch (manage_auto_explorer(punit)) {
3120 case MR_DEATH:
3121 /* don't use punit! */
3122 return;
3123 case MR_NOT_ALLOWED:
3124 /* Needed for something else */
3125 return;
3126 case MR_OK:
3127 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3128 * but don't count on this. See PR#39792.
3129 */
3131 break;
3132 }
3133
3135 default:
3137
3138 /* FIXME: When the manage_auto_explorer() call changes the activity from
3139 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3140 * alone. We reset it here. See PR#12931. */
3142 break;
3143 }
3144
3145 send_unit_info(nullptr, punit); /* Probably duplicate */
3146}
3147
3148/**********************************************************************/
3153bool do_paradrop(struct unit *punit, struct tile *ptile,
3154 const struct action *paction)
3155{
3156 struct player *pplayer = unit_owner(punit);
3157 struct player *tgt_player = tile_owner(ptile);
3158 const struct unit_type *act_utype = unit_type_get(punit);
3159 const struct city *pcity;
3160
3161 /* Hard requirements */
3162 /* FIXME: hard requirements belong in common/actions's
3163 * is_action_possible() and the explanation texts belong in
3164 * server/unithand's action not enabled system (expl_act_not_enabl(),
3165 * ane_kind, explain_why_no_action_enabled(), etc)
3166 */
3167 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3168 /* Only take in account values from player map. */
3169 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3170
3171 if (plrtile->site == nullptr) {
3172 bv_extras fbv;
3173
3174 dbv_to_bv(fbv.vec, &(plrtile->extras));
3175
3177 &fbv)) {
3178 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3179 _("This unit cannot paradrop into %s."),
3181 return FALSE;
3182 }
3183 }
3184
3185 if (plrtile->site != nullptr
3186 && plrtile->owner != nullptr
3187 && !pplayers_allied(pplayer, plrtile->owner)
3189 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3190 /* TRANS: Paratroopers ... Paradrop Unit */
3191 _("%s cannot conquer a city with \"%s\"."),
3194 return FALSE;
3195 }
3196
3197 if (plrtile->site != nullptr
3198 && plrtile->owner != nullptr
3199 && (pplayers_non_attack(pplayer, plrtile->owner)
3200 || (player_diplstate_get(pplayer, plrtile->owner)->type
3201 == DS_ALLIANCE)
3202 || (player_diplstate_get(pplayer, plrtile->owner)->type
3203 == DS_TEAM))
3205 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3206 _("Cannot attack unless you declare war first."));
3207 return FALSE;
3208 }
3209 }
3210
3211
3212 /* Kill the unit when the landing goes wrong. */
3213
3214 /* Safe terrain, really? Not transformed since player last saw it. */
3215 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3216 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3217 || !unit_could_load_at(punit, ptile))) {
3218 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3219 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3220 _("Your %s paradropped into the %s and was lost."),
3223 pplayer->score.units_lost++;
3225 return TRUE;
3226 }
3227
3228 pcity = tile_city(ptile);
3229
3230 if ((pcity != nullptr && !pplayers_allied(pplayer, city_owner(pcity))
3232 || is_non_allied_unit_tile(ptile, pplayer,
3234 struct player *main_victim = nullptr;
3235 struct player *secondary_victim = nullptr;
3237
3238 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3239 unit_make_contact(punit, ptile, pplayer);
3240 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3241 _("Your %s was killed by enemy units at the "
3242 "paradrop destination."),
3244 /* TODO: Should defender score.units_killed get increased too?
3245 * What if there's units of several allied players? Should the
3246 * city owner or owner of the first/random unit get the kill? */
3247 pplayer->score.units_lost++;
3248
3249 if (pcity != nullptr) {
3250 struct player *owner = city_owner(pcity);
3251
3252 if (!pplayers_at_war(pplayer, owner)) {
3254 } else {
3256 }
3257
3259 } else {
3261 }
3262
3263 if (main_victim == nullptr) {
3264 unit_list_iterate(ptile->units, tgt) {
3265 struct player *owner = unit_owner(tgt);
3266
3267 if (!pplayers_at_war(pplayer, owner)) {
3269 break;
3270 } else if (secondary_victim == nullptr) {
3272 }
3274
3275 if (main_victim == nullptr) {
3276 /* There's no victim with whom the attacker isn't in war,
3277 * fallback to one with whom there's already a war. */
3279 }
3280 }
3281
3283 main_victim, ptile,
3284 victim_link);
3285
3287 return TRUE;
3288 }
3289
3290 /* All ok */
3292 if (unit_move(punit, ptile,
3293 /* Done by Action_Success_Actor_Move_Cost */
3294 0,
3295 nullptr, BV_ISSET(paction->sub_results,
3299 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3300 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3301 /* Ensure we finished on valid state. */
3304 }
3305
3306 /* May cause an incident */
3308 ptile, tile_link(ptile));
3309
3310 return TRUE;
3311}
3312
3313/**********************************************************************/
3317static bool hut_get_limited(struct unit *punit)
3318{
3319 bool ok = TRUE;
3320 int hut_chance = fc_rand(12);
3321 struct player *pplayer = unit_owner(punit);
3322 const struct civ_map *nmap = &(wld.map);
3323
3324 /* 1 in 12 to get barbarians */
3325 if (hut_chance != 0) {
3326 int cred = 25;
3327
3329 PL_("You found %d gold.",
3330 "You found %d gold.", cred), cred);
3331 pplayer->economic.gold += cred;
3334 notify_player(pplayer, unit_tile(punit),
3336 _("An abandoned village is here."));
3337 } else {
3339 _("Your %s has been killed by barbarians!"),
3341 wipe_unit(punit, ULR_BARB_UNLEASH, nullptr);
3342 ok = FALSE;
3343 }
3344
3345 return ok;
3346}
3347
3348/**********************************************************************/
3352static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3353{
3354 struct player *pplayer = unit_owner(punit);
3355 int id = punit->id;
3356 struct tile *ptile = unit_tile(punit);
3357 bool hut = FALSE;
3358 const struct req_context context = {
3359 .player = pplayer,
3360 .tile = ptile,
3361 };
3362
3364 if (tile_has_extra(ptile, pextra)
3366 &(const struct req_context) {
3367 .player = tile_owner(ptile),
3368 },
3369 &pextra->rmreqs,
3371 ) {
3372 hut = TRUE;
3373 /* FIXME: are all enter-removes extras worth counting? */
3374 pplayer->server.huts++;
3375
3376 destroy_extra(ptile, pextra);
3378
3379 /* FIXME: enable different classes
3380 * to behave differently with different huts */
3381 if (frighten_hut) {
3382 script_server_signal_emit("hut_frighten", punit,
3383 extra_rule_name(pextra));
3384 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3385 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3387 } else {
3388 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3389 }
3390
3391 /* We need punit for the callbacks, can't continue if the unit died */
3392 if (!unit_is_alive(id)) {
3393 break;
3394 }
3395 }
3397
3398 if (hut) {
3399 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3400 }
3401 return;
3402}
3403
3404/**********************************************************************/
3408{
3409 bv_player can_see_unit;
3410
3411 fc_assert_ret(punit != nullptr);
3412 fc_assert_ret(ptrans != nullptr);
3413
3414 BV_CLR_ALL(can_see_unit);
3415 players_iterate(pplayer) {
3416 if (can_player_see_unit(pplayer, punit)) {
3417 BV_SET(can_see_unit, player_index(pplayer));
3418 }
3420
3422
3423 players_iterate(pplayer) {
3424 if (BV_ISSET(can_see_unit, player_index(pplayer))
3425 && !can_player_see_unit(pplayer, punit)) {
3426 unit_goes_out_of_sight(pplayer, punit);
3427 }
3429
3430 send_unit_info(nullptr, punit);
3431 send_unit_info(nullptr, ptrans);
3432}
3433
3434/**********************************************************************/
3438 struct unit *ptrans,
3439 bool force)
3440{
3441 bool had_cargo;
3442
3443 fc_assert_ret(punit != nullptr);
3444 fc_assert_ret(ptrans != nullptr);
3445
3447
3449
3450 if (!had_cargo) {
3451 /* Transport's loaded status changed */
3452 send_unit_info(nullptr, ptrans);
3453 }
3454}
3455
3456/**********************************************************************/
3460{
3461 struct unit *ptrans;
3462
3464
3466
3468
3470
3471 send_unit_info(nullptr, punit);
3472 send_unit_info(nullptr, ptrans);
3473}
3474
3475/**********************************************************************/
3479static void autoattack_prob_free(struct autoattack_prob *prob)
3480{
3481 free(prob);
3482}
3483
3484/**********************************************************************/
3493static int compare_units(const struct autoattack_prob *const *p1,
3494 const struct autoattack_prob *const *q1)
3495{
3496 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3497 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3498
3499 /* Sort by transport depth first. This makes sure that no transport
3500 * attacks before its cargo does -- cargo sorts earlier in the list. */
3501 {
3502 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3503
3504 /* Walk the transport stacks in parallel, so as to bail out as soon as
3505 * one of them is empty (avoid walking deep stacks more often than
3506 * necessary). */
3507 while (p1trans && q1trans) {
3510 }
3511 if (!p1trans && q1trans) {
3512 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3513 * earlier in the list (p1 > q1). */
3514 return 1;
3515 } else if (p1trans && !q1trans) {
3516 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3517 return -1;
3518 }
3519 /* else same depth, so move on to checking win chance: */
3520 }
3521
3522 /* Put the units with the highest probability of success first. The up
3523 * side of this is that units with bonuses against the victim attacks
3524 * before other units. The downside is that strong units can be led
3525 * away by sacrificial units. */
3526 return (-1
3527 /* Assume the worst. */
3528 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3529}
3530
3531/**********************************************************************/
3536{
3537 struct autoattack_prob_list *autoattack;
3538 int moves = punit->moves_left;
3539 int sanity1 = punit->id;
3540 struct civ_map *nmap = &(wld.map);
3541
3542 if (!game.server.autoattack) {
3543 return TRUE;
3544 }
3545
3547
3548 /* Kludge to prevent attack power from dropping to zero during calc */
3550
3551 adjc_iterate(nmap, unit_tile(punit), ptile) {
3552 /* First add all eligible units to a autoattack list */
3553 unit_list_iterate(ptile->units, penemy) {
3555 struct tile *tgt_tile = unit_tile(punit);
3556
3557 fc_assert_action(tgt_tile, continue);
3558
3559 probability->prob =
3561 penemy, unit_owner(punit), nullptr, nullptr,
3563 punit, nullptr);
3564
3565 if (action_prob_possible(probability->prob)) {
3566 probability->unit_id = penemy->id;
3568 } else {
3570 }
3573
3574 /* Sort the potential attackers from highest to lowest success
3575 * probability. */
3576 if (autoattack_prob_list_size(autoattack) >= 2) {
3578 }
3579
3581 int sanity2 = penemy->id;
3582 struct tile *ptile = unit_tile(penemy);
3583 struct unit *enemy_defender = get_defender(nmap, punit, ptile, nullptr);
3584 double punitwin, penemywin;
3585 double threshold = 0.25;
3586 struct tile *tgt_tile = unit_tile(punit);
3587
3589
3590 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3591 /* Don't leave city defenseless */
3592 threshold = 0.90;
3593 }
3594
3595 if (enemy_defender != nullptr) {
3597 } else {
3598 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3599 punitwin = 1.0;
3600 }
3601
3602 /* Previous attacks may have changed the odds. Recalculate. */
3603 peprob->prob =
3605 penemy, unit_owner(punit), nullptr, nullptr,
3607 punit, nullptr);
3608
3609 if (!action_prob_possible(peprob->prob)) {
3610 /* No longer legal. */
3611 continue;
3612 }
3613
3614 /* Assume the worst. */
3616
3617 if ((penemywin > 1.0 - punitwin
3619 && penemywin > threshold) {
3620
3621#ifdef REALLY_DEBUG_THIS
3622 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3625 1.0 - punitwin, threshold);
3626#endif
3627
3630 penemy, unit_owner(punit), nullptr, nullptr,
3631 tgt_tile, tile_city(tgt_tile), punit, nullptr);
3632 } else {
3633#ifdef REALLY_DEBUG_THIS
3634 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3637 1.0 - punitwin, threshold);
3638#endif
3639 continue;
3640 }
3641
3643 send_unit_info(nullptr, penemy);
3644 }
3646 send_unit_info(nullptr, punit);
3647 } else {
3648 autoattack_prob_list_destroy(autoattack);
3649 return FALSE; /* moving unit dead */
3650 }
3652
3653 autoattack_prob_list_destroy(autoattack);
3655 /* We could have lost movement in combat */
3657 send_unit_info(nullptr, punit);
3658 return TRUE;
3659 } else {
3660 return FALSE;
3661 }
3662}
3663
3664/**********************************************************************/
3667static void cancel_orders(struct unit *punit, char *dbg_msg)
3668{
3670 send_unit_info(nullptr, punit);
3671 log_debug("%s", dbg_msg);
3672}
3673
3674/**********************************************************************/
3679{
3680 bool alone_in_city;
3681
3682 if (tile_city(unit_tile(punit)) != nullptr) {
3683 int count = 0;
3684
3686 /* Consider only units not transported. */
3687 if (!unit_transported(aunit)) {
3688 count++;
3689 }
3691
3692 alone_in_city = (1 == count);
3693 } else {
3695 }
3696
3697 /* There may be sentried units with a sightrange > 3, but we don't
3698 wake them up if the punit is farther away than 3. */
3699 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3700 unit_list_iterate(ptile->units, penemy) {
3701 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3702 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3703
3705 && penemy->activity == ACTIVITY_SENTRY
3706 && radius_sq >= distance_sq
3707 /* If the unit moved on a city, and the unit is alone, consider
3708 * it is visible. */
3709 && (alone_in_city
3711 /* On board transport; don't awaken */
3714 send_unit_info(nullptr, penemy);
3715 }
3718
3719 /* Wakeup patrolling units we bump into.
3720 We do not wakeup units further away than 3 squares... */
3721 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3722 unit_list_iterate(ptile->units, ppatrol) {
3723 if (punit != ppatrol
3725 && ppatrol->orders.vigilant) {
3727 cancel_orders(ppatrol, " stopping because of nearby enemy");
3730 _("Orders for %s aborted after enemy movement was "
3731 "spotted."),
3733 }
3734 }
3737}
3738
3739/**********************************************************************/
3749 struct tile *src_tile,
3750 struct tile *dst_tile,
3751 bool passenger,
3753{
3754 struct city *fromcity = tile_city(src_tile);
3755 struct city *tocity = tile_city(dst_tile);
3756 struct city *homecity_start_pos = nullptr;
3757 struct city *homecity_end_pos = nullptr;
3763 const struct unit_type *type_end_pos = type_start_pos;
3766 int saved_id = punit->id;
3767 bool alive = TRUE;
3768 const struct civ_map *nmap = &(wld.map);
3769
3771 if (!passenger) {
3772 /* The unit that does the move may conquer. */
3774 }
3775
3776 /* Run for passengers too. A passenger may have been killed when its
3777 * transport conquered a city. (unit_conquer_city() can cause Lua code
3778 * to run) */
3779
3781 if (alive) {
3782 /* In case script has changed something about unit */
3786 }
3787 }
3788
3789 if (homecity_id_start_pos != 0) {
3791 }
3794 } else {
3796 }
3797
3798 /* We only do refreshes for non-AI players to now make sure the AI turns
3799 doesn't take too long. Perhaps we should make a special refresh_city
3800 functions that only refreshed happines. */
3801
3802 /* might have changed owners or may be destroyed */
3804
3805 if (tocity) { /* entering a city */
3806 if (tocity->owner == pplayer_end_pos) {
3810 }
3811 }
3812 if (homecity_start_pos) {
3814 }
3815 }
3816
3817 if (fromcity) { /* leaving a city */
3818 if (homecity_start_pos) {
3820 }
3822 && fromcity->owner == pplayer_start_pos
3826 }
3827 }
3828
3829 /* Entering/leaving a fortress or friendly territory */
3831 bool friendly_end = FALSE;
3832
3835 } else {
3837 type_end_pos);
3838
3839 if (max_friendliness_range >= 0
3842 } else {
3845
3846 if (max_friendliness_range >= 0
3849 }
3850 }
3851 }
3852
3853 if (friendly_end) {
3856 }
3857 }
3858
3862 }
3869 }
3870
3872 sync_cities();
3873
3874 return alive;
3875}
3876
3877/**********************************************************************/
3881static void check_unit_activity(struct unit *punit)
3882{
3883 switch (punit->activity) {
3884 case ACTIVITY_IDLE:
3885 case ACTIVITY_SENTRY:
3886 case ACTIVITY_EXPLORE:
3887 case ACTIVITY_GOTO:
3888 break;
3889 case ACTIVITY_CLEAN:
3890 case ACTIVITY_MINE:
3891 case ACTIVITY_IRRIGATE:
3892 case ACTIVITY_CULTIVATE:
3893 case ACTIVITY_PLANT:
3894 case ACTIVITY_FORTIFIED:
3895 case ACTIVITY_PILLAGE:
3896 case ACTIVITY_TRANSFORM:
3898 case ACTIVITY_BASE:
3899 case ACTIVITY_GEN_ROAD:
3900 case ACTIVITY_CONVERT:
3901 case ACTIVITY_LAST:
3903 break;
3904 };
3905}
3906
3907/**********************************************************************/
3911 const struct tile *psrctile,
3912 const struct tile *pdesttile)
3913{
3914 struct unit_move_data *pdata;
3915 struct player *powner = unit_owner(punit);
3916
3917 if (punit->server.moving) {
3918 /* Recursive moving (probably due to a script). */
3920 pdata->ref_count++;
3921 fc_assert_msg(pdata->punit == punit,
3922 "Unit number %d (%p) was going to die, but "
3923 "server attempts to move it.",
3924 punit->id, punit);
3925 fc_assert_msg(pdata->old_vision == nullptr,
3926 "Unit number %d (%p) has done an incomplete move.",
3927 punit->id, punit);
3928 } else {
3929 pdata = fc_malloc(sizeof(*pdata));
3930 pdata->ref_count = 1;
3931 pdata->punit = punit;
3933 BV_CLR_ALL(pdata->can_see_unit);
3934 }
3935 pdata->powner = powner;
3936 BV_CLR_ALL(pdata->can_see_move);
3937 pdata->old_vision = punit->server.vision;
3938
3939 return pdata;
3940}
3941
3942/**********************************************************************/
3946 const struct tile *psrctile,
3947 struct tile *pdesttile)
3948{
3949 struct vision *new_vision;
3950 struct unit *punit = pdata->punit;
3952 const v_radius_t radius_sq
3956
3957 /* Remove unit from the source tile. */
3959
3960#ifndef FREECIV_NDEBUG
3961 bool success =
3962#endif
3965
3966 /* Set new tile. */
3969
3970 if (unit_transported(punit)) {
3971 /* Silently free orders since they won't be applicable anymore. */
3973 }
3974
3975 /* Check unit activity. */
3979
3980 /* We first unfog the destination, then send the move,
3981 * and then fog the old territory. This means that the player
3982 * gets a chance to see the newly explored territory while the
3983 * client moves the unit, and both areas are visible during the
3984 * move */
3985
3986 /* Enhance vision if unit steps into a fortress */
3989 vision_change_sight(new_vision, radius_sq);
3991}
3992
3993/**********************************************************************/
3997{
3998 fc_assert_ret(pdata != nullptr);
3999 fc_assert_ret(pdata->ref_count > 0);
4000 fc_assert_msg(pdata->old_vision == nullptr,
4001 "Unit number %d (%p) has done an incomplete move.",
4002 pdata->punit != nullptr ? pdata->punit->id : -1, pdata->punit);
4003
4004 pdata->ref_count--;
4005 if (pdata->ref_count == 0) {
4006 if (pdata->punit != nullptr) {
4007 fc_assert(pdata->punit->server.moving == pdata);
4008 pdata->punit->server.moving = nullptr;
4009 }
4010 free(pdata);
4011 }
4012}
4013
4014/**********************************************************************/
4018 const struct tile *psrctile,
4019 struct tile *pdesttile,
4020 bool adj)
4021{
4024 struct unit_move_data *pdata;
4025
4026 /* Make new data for 'punit'. */
4029
4030 /* Add all contained units. */
4032 struct unit_move_data *cargo_data;
4033
4037
4038 /* Determine the players able to see the move(s), now that the player
4039 * vision has been increased. */
4040 if (adj) {
4041 /* Main unit for adjacent move: the move is visible for every player
4042 * able to see on the matching unit layer. */
4043 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
4044
4048 BV_SET(pdata->can_see_unit, player_index(oplayer));
4049 BV_SET(pdata->can_see_move, player_index(oplayer));
4050 }
4052 }
4053
4055
4057
4058 if (adj && pmove_data->punit == punit) {
4059 /* If positions are adjacent, we have already handled 'punit'. See
4060 * above. */
4061 continue;
4062 }
4063
4065 if ((adj
4067 pmove_data != pdata))
4069 pmove_data != pdata)) {
4070 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4071 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4072 }
4074 pmove_data != pdata)) {
4075 /* The unit was seen with its source tile even if it was
4076 * teleported. */
4077 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4078 }
4081
4082 return plist;
4083}
4084
4085/**********************************************************************/
4096bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
4097 struct unit *embark_to, bool find_embark_target,
4099 bool enter_hut, bool frighten_hut)
4100{
4101 struct player *pplayer;
4102 struct tile *psrctile;
4103 struct city *psrccity;
4104 struct city *pdestcity;
4105 struct unit *ptransporter;
4108 struct unit_move_data_list *plist;
4109 struct unit_move_data *pdata;
4110 int saved_id;
4111 bool unit_lives;
4112 bool adj;
4113 enum direction8 facing;
4115
4116 /* Some checks. */
4117 fc_assert_ret_val(punit != nullptr, FALSE);
4118 fc_assert_ret_val(pdesttile != nullptr, FALSE);
4119
4120 pplayer = unit_owner(punit);
4121 saved_id = punit->id;
4124
4126
4127 /* Unload the unit if on a transport. */
4129 if (ptransporter != nullptr) {
4130 /* Unload unit _before_ setting the new tile! */
4132 /* Send updated information to anyone watching that transporter
4133 * was unloading cargo. */
4134 send_unit_info(nullptr, ptransporter);
4135 }
4136
4137 /* Wakup units next to us before we move. */
4139
4140 /* Make info packets at 'psrctile'. */
4141 if (adj) {
4142 /* If tiles are adjacent, we will show the move to users able
4143 * to see it. */
4146 }
4147
4148 /* Set unit orientation */
4149 if (adj) {
4150 /* Only change orientation when moving to adjacent tile */
4151 punit->facing = facing;
4152 }
4153
4155
4156 /* Move magic. */
4157 punit->moved = TRUE;
4158 punit->moves_left = MAX(0, punit->moves_left - move_cost);
4159 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
4160 /* The next order may not require any remaining move fragments. */
4162 }
4163
4164 /* No longer relevant. */
4165 punit->action_decision_tile = nullptr;
4167
4168 /* Claim ownership of fortress? */
4171 /* Yes. We claim *all* bases if there's *any* claimable base(s).
4172 * Even if original unit cannot claim other kind of bases, the
4173 * first claimed base will have influence over other bases,
4174 * or something like that. */
4175 tile_claim_bases(pdesttile, pplayer);
4176 }
4177
4179 fc_assert(pdata->punit == punit);
4180
4181 /* Check timeout settings. */
4184
4185 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4186 * if they are ever seen. */
4188 /* Increase the timeout if an enemy unit moves and the
4189 * timeoutaddenemymove setting is in use. */
4190 if (penemy->is_connected
4191 && pplayer != penemy
4192 && pplayers_at_war(pplayer, penemy)
4193 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4195 break;
4196 }
4198
4201 }
4202 }
4203
4205 /* The unit can perform an action to the city at the destination tile.
4206 * A long distance move (like an airlift) doesn't ask what action to
4207 * perform before moving. Ask now. */
4208
4211 }
4212
4213 /* Notifications of the move to the clients. */
4214 if (adj) {
4215 /* Special case: 'punit' is moving to adjacent position. Then we show
4216 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4217
4218 /* Make info packets at 'pdesttile'. */
4221
4224
4225 if (aplayer == nullptr) {
4226 if (pconn->observer) {
4227 /* Global observers see all... */
4230 }
4231 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4232 if (aplayer == pplayer) {
4235 } else {
4238 }
4239 }
4241 }
4242
4243 /* Other moves. */
4245 if (adj && pmove_data == pdata) {
4246 /* If positions are adjacent, we have already shown 'punit' move.
4247 * See above. */
4248 continue;
4249 }
4250
4251 /* Make info packets at 'pdesttile'. */
4255
4258
4259 if (aplayer == nullptr) {
4260 if (pconn->observer) {
4261 /* Global observers see all... */
4263 }
4264 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4265 if (aplayer == pmove_data->powner) {
4267 } else {
4269 }
4270 }
4273
4274 /* Clear old vision. */
4276 if (pmove_data->old_vision != nullptr) {
4277 vision_clear_sight(pmove_data->old_vision);
4278 vision_free(pmove_data->old_vision);
4279 pmove_data->old_vision = nullptr;
4280 }
4282
4283 /* Move consequences. */
4285 struct unit *aunit = pmove_data->punit;
4286
4287 if (aunit != nullptr
4288 && unit_owner(aunit) == pmove_data->powner
4289 && unit_tile(aunit) == pdesttile) {
4291 pdata != pmove_data,
4293 }
4295
4296 unit_lives = (pdata->punit == punit);
4297
4298 /* Wakeup units and make contact. */
4299 if (unit_lives) {
4301 }
4302
4303 /* Do not pass 'punit' to unit_make_contact(), as it
4304 * might refer to a dead unit.
4305 * Flagless units do not make contact. */
4306 if (!flagless) {
4307 unit_make_contact(nullptr, pdesttile, pplayer);
4308 }
4309
4310 if (unit_lives) {
4311 /* Special checks for ground units in the ocean. */
4313 if (embark_to != nullptr) {
4315 } else if (find_embark_target) {
4316 /* TODO: Consider to stop supporting find_embark_target and make all
4317 * callers that wants auto loading set embark_to. */
4319 } else {
4320 ptransporter = nullptr;
4321 }
4322 if (ptransporter) {
4324
4325 /* Set activity to sentry if boarding a ship. */
4326 if (is_human(pplayer)
4331 }
4332
4333 send_unit_info(nullptr, punit);
4334 }
4335 }
4336 }
4337
4338 /* Remove units going out of sight. */
4340 struct unit *aunit = pmove_data->punit;
4341
4342 if (aunit == nullptr) {
4343 continue; /* Died! */
4344 }
4345
4347 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4350 }
4353
4354 /* Inform the owner's client about actor unit arrival. Can, depending on
4355 * the client settings, cause the client to start the process that makes
4356 * the action selection dialog pop up. */
4358 if (pdestcity != nullptr) {
4359 /* Arrival in a city counts. */
4360
4362 struct unit *ptrans;
4363 bool ok;
4364 struct unit *act_unit;
4365 struct player *act_player;
4366
4367 act_unit = pmove_data->punit;
4369
4370 if (act_unit == nullptr
4371 || !unit_is_alive(act_unit->id)) {
4372 /* The unit died before reaching this point. */
4373 continue;
4374 }
4375
4376 if (unit_tile(act_unit) != pdesttile) {
4377 /* The unit didn't arrive at the destination tile. */
4378 continue;
4379 }
4380
4381 if (!is_human(act_player)) {
4382 /* Only humans need reminders. */
4383 continue;
4384 }
4385
4386 if (!unit_transported(act_unit)) {
4387 /* Don't show the action selection dialog again. Non transported
4388 * units are handled before they move to the tile. */
4389 continue;
4390 }
4391
4392 /* Open action dialog only if 'act_unit' and all its transporters
4393 * (recursively) don't have orders. */
4395 /* The unit it self has orders. */
4396 continue;
4397 }
4398
4401 if (ptrans == nullptr) {
4402 /* No (recursive) transport has orders. */
4403 ok = TRUE;
4404 break;
4405 } else if (unit_has_orders(ptrans)) {
4406 /* A unit transporting the unit has orders */
4407 ok = FALSE;
4408 break;
4409 }
4410 }
4411
4412 if (!ok) {
4413 /* A unit transporting act_unit has orders. */
4414 continue;
4415 }
4416
4418 /* There is a valid target. */
4419
4420 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4421 act_unit->action_decision_tile = pdesttile;
4422
4423 /* Let the client know that this unit wants the player to decide
4424 * what to do. */
4426 }
4428 }
4429
4431 /* Check cities at source and destination. */
4433 if (psrccity != nullptr) {
4435 }
4436 if (pdestcity != nullptr) {
4438 }
4439
4440 if (unit_lives) {
4441 /* Let the scripts run ... */
4444 }
4445
4446 if (unit_lives) {
4447 /* Autoattack. */
4449 }
4450
4451 if (unit_lives && (enter_hut || frighten_hut)) {
4452 /* Is there a hut? */
4456 }
4457
4459
4460 if (unit_lives) {
4461 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4462 }
4463
4464 return unit_lives;
4465}
4466
4467/**********************************************************************/
4471 struct tile *ptile)
4472{
4473 struct player *owner = unit_owner(punit);
4474
4475 return (is_non_allied_unit_tile(ptile, owner,
4477 || is_non_allied_city_tile(ptile, owner));
4478}
4479
4480/**********************************************************************/
4487{
4488 bool cancel = FALSE;
4489 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4490 struct player *pplayer = unit_owner(punit);
4491
4492 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4493 struct unit *penemy = tile_non_allied_unit(ptile, pplayer,
4495 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4496
4497 if ((penemy && can_player_see_unit(pplayer, penemy))
4499 && pdcity->occupied)) {
4500 cancel = TRUE;
4501 break;
4502 }
4504
4505 return cancel;
4506}
4507
4508/**********************************************************************/
4516static inline bool player_is_watching(struct unit *punit, const bool fresh)
4517{
4518 /* The player just sent the orders to the unit. The unit has moves left.
4519 * It is therefore safe to assume that the player already is paying
4520 * attention to the unit. */
4521 return fresh && punit->moves_left > 0;
4522}
4523
4524/**********************************************************************/
4543bool execute_orders(struct unit *punit, const bool fresh)
4544{
4545 struct act_prob prob;
4546 bool performed;
4547 const char *name;
4548 bool res, last_order;
4549 int unitid = punit->id;
4550 struct player *pplayer = unit_owner(punit);
4551 int moves_made = 0;
4552 const struct civ_map *nmap = &(wld.map);
4553
4555
4556 if (punit->activity != ACTIVITY_IDLE) {
4557 /* Unit's in the middle of an activity; wait for it to finish. */
4559 return TRUE;
4560 }
4561
4562 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4563
4564 /* Any time the orders are canceled we should give the player a message. */
4565
4566 while (TRUE) {
4567 struct unit_order order;
4568
4569 struct action *oaction;
4570
4571 struct tile *dst_tile;
4572 struct city *tgt_city;
4573 struct unit *tgt_unit;
4574 int tgt_id;
4575 int sub_tgt_id;
4576 struct extra_type *pextra;
4577
4578 if (punit->done_moving) {
4579 log_debug(" stopping because we're done this turn");
4580 return TRUE;
4581 }
4582
4584 /* "Patrol" orders are stopped if an enemy is near. */
4585 cancel_orders(punit, " stopping because of nearby enemy");
4587 _("Orders for %s aborted as there are units nearby."),
4588 unit_link(punit));
4589 return TRUE;
4590 }
4591
4592 if (moves_made == punit->orders.length) {
4593 /* For repeating orders, don't repeat more than once per turn. */
4594 log_debug(" stopping because we ran a round");
4596 send_unit_info(nullptr, punit);
4597 return TRUE;
4598 }
4599 moves_made++;
4600
4601 order = punit->orders.list[punit->orders.index];
4602
4603 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4604 * this far. */
4606 || action_id_exists(order.action)),
4607 continue);
4608
4609 switch (order.order) {
4610 case ORDER_MOVE:
4611 case ORDER_ACTION_MOVE:
4612 case ORDER_FULL_MP:
4613 if (0 == punit->moves_left) {
4614 log_debug(" stopping because of no more move points");
4615 return TRUE;
4616 }
4617 break;
4620 log_debug(" stopping. Not enough move points this turn");
4621 return TRUE;
4622 }
4623 break;
4624 case ORDER_ACTIVITY:
4625 case ORDER_LAST:
4626 /* Those actions don't require moves left. */
4627 break;
4628 }
4629
4631 && punit->orders.index + 1 == punit->orders.length);
4632
4633 if (last_order) {
4634 /* Clear the orders before we engage in the move. That way any
4635 * has_orders checks will yield FALSE and this will be treated as
4636 * a normal move. This is important: for instance a caravan goto
4637 * will popup the caravan dialog on the last move only. */
4639 }
4640
4641 /* Advance the orders one step forward. This is needed because any
4642 * updates sent to the client as a result of the action should include
4643 * the new index value. Note that we have to send_unit_info() somewhere
4644 * after this point so that the client is properly updated. */
4645 punit->orders.index++;
4646
4647 switch (order.order) {
4648 case ORDER_FULL_MP:
4650 /* If the unit doesn't have full MP then it just waits until the
4651 * next turn. We assume that the next turn it will have full MP
4652 * (there's no check for that). */
4654 log_debug(" waiting this turn");
4655 send_unit_info(nullptr, punit);
4656 }
4657 break;
4658 case ORDER_ACTIVITY:
4659 {
4660 enum unit_activity activity = order.activity;
4661
4662 fc_assert(activity == ACTIVITY_SENTRY);
4663
4664 if (can_unit_do_activity(nmap, punit, activity, order.action)) {
4666 set_unit_activity(punit, activity, order.action);
4667 send_unit_info(nullptr, punit);
4668
4669 break;
4670 }
4671 }
4672
4673 cancel_orders(punit, " orders canceled because of failed activity");
4675 _("Orders for %s aborted since they "
4676 "give an invalid activity."),
4677 unit_link(punit));
4678 return TRUE;
4679 case ORDER_MOVE:
4680 case ORDER_ACTION_MOVE:
4681 /* Move unit */
4682 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4683 cancel_orders(punit, " move order sent us to invalid location");
4685 _("Orders for %s aborted since they "
4686 "give an invalid location."),
4687 unit_link(punit));
4688 return TRUE;
4689 }
4690
4691 if (order.order != ORDER_ACTION_MOVE
4693 /* Plain move required: no attack, trade route etc. */
4694 cancel_orders(punit, " orders canceled because of enemy");
4696 _("Orders for %s aborted as there "
4697 "are units in the way."),
4698 unit_link(punit));
4699 return TRUE;
4700 }
4701
4702 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4704 order.order != ORDER_ACTION_MOVE);
4705 if (!player_unit_by_number(pplayer, unitid)) {
4706 log_debug(" unit died while moving.");
4707 /* A player notification should already have been sent. */
4708 return FALSE;
4709 }
4710
4711 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4712 /* Movement succeeded but unit didn't move. */
4713 log_debug(" orders resulted in combat.");
4714 send_unit_info(nullptr, punit);
4715 return TRUE;
4716 }
4717
4718 if (!res) {
4719 fc_assert(0 <= punit->moves_left);
4720
4721 /* Movement failed (ZOC, etc.) */
4722 cancel_orders(punit, " attempt to move failed.");
4723
4725 /* The final move "failed" because the unit needs to ask the
4726 * player what action it should take.
4727 *
4728 * The action decision request notifies the player. Its
4729 * location at the unit's last order makes it clear to the
4730 * player who the decision is for. ("The Spy I sent to Berlin
4731 * has arrived.")
4732 *
4733 * A notification message is therefore redundant. */
4734 && !(last_order
4737 /* The player may have missed this. No one else will announce it
4738 * in a satisfying manner. Inform the player. */
4739 notify_player(pplayer, unit_tile(punit),
4741 _("Orders for %s aborted because of failed move."),
4742 unit_link(punit));
4743 }
4744
4745 return TRUE;
4746 }
4747 break;
4750
4751 /* Checked in unit_order_list_is_sane() */
4752 fc_assert_action(oaction != nullptr, continue);
4753
4754 log_debug(" orders: doing action %s", action_rule_name(oaction));
4755
4756 dst_tile = index_to_tile(&(wld.map), order.target);
4757
4758 if (dst_tile == nullptr) {
4759 /* Could be at the edge of the map while trying to target a tile
4760 * outside of it. */
4761
4762 cancel_orders(punit, " target location doesn't exist");
4764 order.action, dst_tile, nullptr, nullptr);
4765
4766 return TRUE;
4767 }
4768
4769 /* Get the target city from the target tile. */
4771
4772 if (tgt_city == nullptr
4774 /* This action targets a city but no city target was found. */
4775
4776 cancel_orders(punit, " perform action vs city with no city");
4778 order.action, dst_tile, tgt_city, nullptr);
4779
4780 return TRUE;
4781 }
4782
4783 /* Get a target unit at the target tile. */
4785
4786 if (tgt_unit == nullptr
4788 /* This action targets a unit but no target unit was found. */
4789
4790 cancel_orders(punit, " perform action vs unit with no unit");
4792 order.action, dst_tile, tgt_city, tgt_unit);
4793
4794 return TRUE;
4795 }
4796
4797 /* Server side sub target assignment */
4798 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4799 && order.sub_target == NO_TARGET) {
4800 /* Try to find a sub target. */
4802 } else {
4803 /* The client should have specified a sub target if needed */
4804 sub_tgt_id = order.sub_target;
4805 }
4806
4807 /* Get a target extra at the target tile */
4808 pextra = (sub_tgt_id == NO_TARGET ?
4809 nullptr :
4810 extra_by_number(sub_tgt_id));
4811
4813 && pextra != nullptr
4814 && actres_creates_extra(oaction->result, pextra)
4815 && tile_has_extra(dst_tile, pextra)) {
4816 /* Already there. Move on to the next order. */
4817 break;
4818 }
4819
4821 && pextra != nullptr
4822 && actres_removes_extra(oaction->result, pextra)
4823 && !tile_has_extra(dst_tile, pextra)) {
4824 /* Already not there. Move on to the next order. */
4825 break;
4826 }
4827
4828 /* No target selected. */
4829 tgt_id = -1;
4830
4831 /* Assume impossible until told otherwise. */
4832 prob = ACTPROB_IMPOSSIBLE;
4833
4834 switch (action_id_get_target_kind(order.action)) {
4835 case ATK_STACK:
4836 prob = action_prob_vs_stack(nmap, punit, order.action,
4837 dst_tile);
4838 tgt_id = dst_tile->index;
4839 break;
4840 case ATK_TILE:
4841 prob = action_prob_vs_tile(nmap, punit, order.action,
4842 dst_tile, pextra);
4843 tgt_id = dst_tile->index;
4844 break;
4845 case ATK_EXTRAS:
4846 prob = action_prob_vs_extras(nmap, punit, order.action,
4847 dst_tile, pextra);
4848 tgt_id = dst_tile->index;
4849 break;
4850 case ATK_CITY:
4851 prob = action_prob_vs_city(nmap, punit, order.action,
4852 tgt_city);
4853 tgt_id = tgt_city->id;
4854 break;
4855 case ATK_UNIT:
4856 prob = action_prob_vs_unit(nmap, punit, order.action,
4857 tgt_unit);
4858
4859 tgt_id = tgt_unit->id;
4860 break;
4861 case ATK_SELF:
4862 prob = action_prob_self(nmap, punit, order.action);
4863
4864 tgt_id = unitid;
4865 break;
4866 case ATK_COUNT:
4867 log_error("Invalid action target kind");
4868
4869 /* The check below will abort and cancel the orders because prob
4870 * was initialized to impossible above this switch statement. */
4871
4872 break;
4873 }
4874
4875 if (!action_prob_possible(prob)) {
4876 /* The player has enough information to know that this action is
4877 * against the rules. Don't risk any punishment by trying to
4878 * perform it. */
4879
4880 cancel_orders(punit, " illegal action");
4882 _("%s could not do %s to %s."),
4886
4887 /* Try to explain what rule made it illegal. */
4889 order.action, dst_tile, tgt_city, tgt_unit);
4890
4891 return TRUE;
4892 }
4893
4895 /* This action needs a name. */
4897 } else {
4898 /* This action doesn't need a name. */
4899 name = "";
4900 }
4901
4903 unitid,
4904 tgt_id,
4905 sub_tgt_id,
4906 name,
4907 order.action,
4909
4910 if (!player_unit_by_number(pplayer, unitid)) {
4911 /* The unit "died" while performing the action. */
4912 return FALSE;
4913 }
4914
4915 if (!performed) {
4916 /* The action wasn't performed as ordered. */
4917
4918 cancel_orders(punit, " failed action");
4920 _("Orders for %s aborted because "
4921 "doing %s to %s failed."),
4925
4926 return TRUE;
4927 }
4928
4929 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4931 /* Done at turn change. */
4933 send_unit_info(nullptr, punit);
4934 break;
4935 }
4936
4937 break;
4938 case ORDER_LAST:
4939 /* Should be caught when loading the unit orders from the savegame or
4940 * when receiving the unit orders from the client. */
4941 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4942 cancel_orders(punit, " invalid order!");
4944 _("Your %s has invalid orders."),
4945 unit_link(punit));
4946 return TRUE;
4947 }
4948
4949 if (last_order) {
4951 log_debug(" stopping because orders are complete");
4952 return TRUE;
4953 }
4954
4955 if (punit->orders.index == punit->orders.length) {
4957 /* Start over. */
4958 log_debug(" repeating orders.");
4959 punit->orders.index = 0;
4960 }
4961 } /* end while */
4962}
4963
4964/**********************************************************************/
4971static int get_unit_vision_base(const struct unit *punit,
4972 enum vision_layer vlayer,
4973 const int base)
4974{
4975 switch (vlayer) {
4976 case V_MAIN:
4977 return MAX(0, base);
4978 case V_INVIS:
4979 case V_SUBSURFACE:
4980 return CLIP(0, base, 2);
4981 case V_COUNT:
4982 break;
4983 }
4984
4985 log_error("Unsupported vision layer variant: %d.", vlayer);
4986
4987 return 0;
4988}
4989
4990/**********************************************************************/
4993static int unit_vision_range_modifiers(const struct unit *punit,
4994 const struct tile *ptile)
4995{
4996 const struct unit_type *utype = unit_type_get(punit);
4997
4998 return (utype->vision_radius_sq
4999 + get_target_bonus_effects(nullptr,
5000 &(const struct req_context) {
5001 .player = unit_owner(punit),
5002 .tile = ptile,
5003 .unittype = utype,
5004 .unit = punit,
5005 },
5006 nullptr, EFT_UNIT_VISION_RADIUS_SQ));
5007}
5008
5009/**********************************************************************/
5016int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
5017 enum vision_layer vlayer)
5018{
5021}
5022
5023/**********************************************************************/
5030{
5031 struct vision *uvision = punit->server.vision;
5032 const struct tile *utile = unit_tile(punit);
5033 int mod = unit_vision_range_modifiers(punit, utile);
5034 const v_radius_t radius_sq
5038
5039 vision_change_sight(uvision, radius_sq);
5041}
5042
5043/**********************************************************************/
5052
5053/**********************************************************************/
5058{
5059 time_t dt;
5060
5061 if (!punit) {
5062 return FALSE;
5063 }
5064
5065 if (game.server.unitwaittime <= 0) {
5066 return TRUE;
5067 }
5068
5069 if (punit->server.action_turn != game.info.turn - 1) {
5070 return TRUE;
5071 }
5072
5073 dt = time(nullptr) - punit->server.action_timestamp;
5074 if (dt < game.server.unitwaittime) {
5075 char buf[64];
5078 ftc_server, _("Your unit may not act for another %s "
5079 "this turn. See /help unitwaittime."), buf);
5080 return FALSE;
5081 }
5082
5083 return TRUE;
5084}
5085
5086/**********************************************************************/
5091{
5092 if (!punit) {
5093 return;
5094 }
5095
5096 punit->server.action_timestamp = time(nullptr);
5098}
5099
5100/**********************************************************************/
5106{
5107 /* check if there is enemy nearby */
5108 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
5110 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
5111 return FALSE;
5112 }
5113 }
5115
5116 return TRUE;
5117}
5118
5119/**********************************************************************/
5122void random_movements(struct player *pplayer)
5123{
5124 struct civ_map *nmap = &(wld.map);
5125
5126 game.server.random_move_time = pplayer;
5127
5130 bool moved = TRUE;
5131 struct tile *curtile = unit_tile(punit);
5132 int id = punit->id;
5133
5134 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
5135 /*
5136 * List of all 8 directions
5137 */
5138 enum direction8 dirs[8] = {
5141 };
5142 int n;
5143
5144 moved = FALSE;
5145
5146 for (n = 8; n > 0 && !moved; n--) {
5147 enum direction8 choice = (enum direction8) fc_rand(n);
5148 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
5149
5150 if (dest != nullptr) {
5151 enum gen_action act
5153
5154 if (act != ACTION_NONE) {
5155 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
5156 "", act, ACT_REQ_RULES)) {
5157 moved = TRUE;
5158 break;
5159 }
5160 }
5161
5162 if (!moved) {
5164 nullptr)) {
5165 if (unit_perform_action(pplayer, id, tile_index(dest),
5167 ACT_REQ_RULES)) {
5168 moved = TRUE;
5169 }
5171 punit, dest, nullptr)) {
5172 if (unit_perform_action(pplayer, id, tile_index(dest),
5174 ACT_REQ_RULES)) {
5175 moved = TRUE;
5176 }
5178 punit, dest, nullptr)) {
5179 if (unit_perform_action(pplayer, id, tile_index(dest),
5181 ACT_REQ_RULES)) {
5182 moved = TRUE;
5183 }
5184 }
5185 }
5186 }
5187
5188 if (!moved) {
5189 /* Choice was bad, so replace it with the last direction
5190 * in the list. On the next iteration, one fewer choice
5191 * will remain. */
5192 dirs[choice] = dirs[n - 1];
5193 }
5194 }
5195 }
5196 }
5198
5199 game.server.random_move_time = nullptr;
5200}
5201
5202/**********************************************************************/
5207void unit_make_contact(const struct unit *punit,
5208 struct tile *ptile, struct player *pplayer)
5209{
5210 fc_assert_ret(punit != nullptr
5211 || (ptile != nullptr && pplayer != nullptr));
5212
5213 if (punit != nullptr && unit_has_type_flag(punit, UTYF_FLAGLESS)) {
5214 return; /* Flagless unit can't make contact */
5215 }
5216
5217 maybe_make_contact(ptile != nullptr ? ptile : unit_tile(punit),
5218 pplayer != nullptr ? pplayer : unit_owner(punit));
5219}
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:5800
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:5322
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:4843
enum gen_action select_actres_action_unit_on_stack(struct civ_map *nmap, enum action_result actres, struct unit *punit, struct tile *ptile)
Definition actions.c:7566
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:3346
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:4926
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:4996
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:4485
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:5382
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:4760
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:3495
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:4568
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5433
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:818
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:797
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:49
#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:2159
const char * city_name_get(const struct city *pcity)
Definition city.c:1157
bool city_exists_within_max_city_map(const struct civ_map *nmap, const struct tile *ptile, bool may_be_on_center)
Definition city.c:2179
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:778
#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:742
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:754
#define output_type_iterate(output)
Definition city.h:853
#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:859
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3351
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:2374
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:2226
void sync_cities(void)
Definition citytools.c:3360
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1998
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3174
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:3210
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2829
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2889
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
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:77
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:2492
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2580
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1929
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2187
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2515
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2683
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:927
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:871
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1447
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:2005
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1390
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2480
#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:842
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:3225
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2371
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:2109
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:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:101
enum direction8 dir
Definition unit.h:103
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
int vision_radius_sq
Definition unittype.h:529
enum vision_layer vlayer
Definition unittype.h:576
Definition unit.h:139
time_t action_timestamp
Definition unit.h:248
int length
Definition unit.h:197
int upkeep[O_LAST]
Definition unit.h:149
bool has_orders
Definition unit.h:195
enum action_decision action_decision_want
Definition unit.h:204
int battlegroup
Definition unit.h:193
enum unit_activity activity
Definition unit.h:158
int moves_left
Definition unit.h:151
int id
Definition unit.h:146
enum gen_action action
Definition unit.h:159
struct unit::@83 orders
bool moved
Definition unit.h:175
int index
Definition unit.h:197
struct vision * vision
Definition unit.h:246
bool vigilant
Definition unit.h:199
int hp
Definition unit.h:152
int fuel
Definition unit.h:154
struct extra_type * changed_from_target
Definition unit.h:172
int current_form_turn
Definition unit.h:210
bool stay
Definition unit.h:207
enum direction8 facing
Definition unit.h:143
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:141
struct extra_type * activity_target
Definition unit.h:166
int activity_count
Definition unit.h:164
struct unit_order * list
Definition unit.h:200
struct vision * scout_vision
Definition unit.h:247
enum unit_activity changed_from
Definition unit.h:170
struct player * nationality
Definition unit.h:145
bool repeat
Definition unit.h:198
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:147
bool paradropped
Definition unit.h:176
bool done_moving
Definition unit.h:183
int birth_turn
Definition unit.h:209
struct goods_type * carrying
Definition unit.h:188
struct tile * goto_tile
Definition unit.h:156
struct tile * action_decision_tile
Definition unit.h:205
const struct unit_type * utype
Definition unit.h:140
int veteran
Definition unit.h:153
int changed_from_count
Definition unit.h:171
bool dying
Definition unit.h:253
enum server_side_agent ssa_controller
Definition unit.h:174
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:1841
void free_unit_orders(struct unit *punit)
Definition unit.c:1827
bool unit_is_alive(int id)
Definition unit.c:2307
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:2462
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1299
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2526
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2479
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2237
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:2943
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:1787
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:2042
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2512
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:2534
bool unit_has_orders(const struct unit *punit)
Definition unit.c:221
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1968
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2089
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:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h: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:61
#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:2531
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unithand.c:6714
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:3374
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5764
#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:5090
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3479
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2661
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:3084
void unit_make_contact(const struct unit *punit, struct tile *ptile, struct player *pplayer)
Definition unittools.c:5207
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1172
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:2169
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:4017
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4543
static void unit_convert(struct unit *punit)
Definition unittools.c:783
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:1318
#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:1566
void random_movements(struct player *pplayer)
Definition unittools.c:5122
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:1807
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1429
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1501
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1937
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1464
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4470
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:1414
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:3052
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3996
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1784
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3352
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2751
#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:2882
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:3678
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:727
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:827
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3437
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3535
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:1124
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2895
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1961
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1383
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3881
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:3910
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1726
void notify_unit_experience(struct unit *punit)
Definition unittools.c:756
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:809
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:2832
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:1678
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1488
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1062
#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:1645
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1928
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1798
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:5016
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:220
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5029
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:1618
void do_explore(struct unit *punit)
Definition unittools.c:3117
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3407
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:5057
#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:2157
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:3153
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4516
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4971
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:1543
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4993
static void update_unit_activity(struct unit *punit)
Definition unittools.c:867
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3459
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1534
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:3667
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:5105
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:747
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:839
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, enum gen_action action, struct extra_type **target)
Definition unittools.c:1091
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2217
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1200
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2967
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3317
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3493
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:854
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:3748
void unit_get_goods(struct unit *punit)
Definition unittools.c:1629
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2939
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4486
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:4096
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3945
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:5046
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2284
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1238
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1071
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