Freeciv-3.3
Loading...
Searching...
No Matches
unittools.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22/* utility */
23#include "bitvector.h"
24#include "fcintl.h"
25#include "log.h"
26#include "mem.h"
27#include "rand.h"
28#include "shared.h"
29#include "support.h"
30
31/* common */
32#include "base.h"
33#include "city.h"
34#include "combat.h"
35#include "events.h"
36#include "game.h"
37#include "government.h"
38#include "idex.h"
39#include "map.h"
40#include "movement.h"
41#include "packets.h"
42#include "player.h"
43#include "research.h"
44#include "terrain.h"
45#include "unit.h"
46#include "unitlist.h"
47#include "unittype.h"
48
49/* common/scriptcore */
50#include "luascript_signal.h"
51#include "luascript_types.h"
52
53/* aicore */
54#include "path_finding.h"
55#include "pf_tools.h"
56
57/* server/scripting */
58#include "script_server.h"
59
60/* server */
61#include "actiontools.h"
62#include "aiiface.h"
63#include "barbarian.h"
64#include "citytools.h"
65#include "cityturn.h"
66#include "diplhand.h"
67#include "gamehand.h"
68#include "maphand.h"
69#include "notify.h"
70#include "plrhand.h"
71#include "sanitycheck.h"
72#include "sernet.h"
73#include "srv_main.h"
74#include "techtools.h"
75#include "unithand.h"
76
77/* server/advisors */
78#include "advgoto.h"
79#include "autoexplorer.h"
80#include "autoworkers.h"
81
82/* ai */
83#include "handicaps.h"
84
85#include "unittools.h"
86
87
88/* Tools for controlling the client vision of every unit when a unit
89 * moves + script effects. See unit_move(). You can access this data with
90 * punit->server.moving; it may be NULL if the unit is not moving). */
93 struct unit *punit; /* NULL for invalidating. */
94 struct player *powner;
98};
99
100#define SPECLIST_TAG unit_move_data
101#include "speclist.h"
102#define unit_move_data_list_iterate(_plist, _pdata) \
103 TYPED_LIST_ITERATE(struct unit_move_data, _plist, _pdata)
104#define unit_move_data_list_iterate_end LIST_ITERATE_END
105#define unit_move_data_list_iterate_rev(_plist, _pdata) \
106 TYPED_LIST_ITERATE_REV(struct unit_move_data, _plist, _pdata)
107#define unit_move_data_list_iterate_rev_end LIST_ITERATE_REV_END
108
109/* This data structure lets the auto attack code cache each potential
110 * attacker unit's probability of success against the target unit during
111 * the checks if the unit can do autoattack. It is then reused when the
112 * list of potential attackers is sorted by probability of success. */
116};
117
118#define SPECLIST_TAG autoattack_prob
119#define SPECLIST_TYPE struct autoattack_prob
120#include "speclist.h"
121
122#define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, \
123 _unit_) \
124 TYPED_LIST_ITERATE(struct autoattack_prob, autoattack_prob_list, _aap_) \
125 struct unit *_unit_ = game_unit_by_number(_aap_->unit_id); \
126 \
127 if (_unit_ == NULL) { \
128 continue; \
129 }
130
131#define autoattack_prob_list_iterate_safe_end LIST_ITERATE_END
132
133static void unit_restore_hitpoints(struct unit *punit);
134static void unit_restore_movepoints(struct player *pplayer, struct unit *punit);
135static void update_unit_activity(struct unit *punit);
136static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
137 bool helpless, bool teleporting,
138 const struct city *pexclcity);
139static void wakeup_neighbor_sentries(struct unit *punit);
140static void do_upgrade_effects(struct player *pplayer);
141
142static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
143
144static bool maybe_become_veteran_real(struct unit *punit, int base_chance,
145 bool worker);
146
147static void unit_transport_load_tp_status(struct unit *punit,
148 struct unit *ptrans,
149 bool force);
150
151static void wipe_unit_full(struct unit *punit, bool transported,
153 struct player *killer);
154
155static int get_unit_vision_base(const struct unit *punit,
156 enum vision_layer vlayer,
157 const int base);
158static int unit_vision_range_modifiers(const struct unit *punit,
159 const struct tile *ptile);
160
161/**********************************************************************/
177{
178 struct unit_type *which[U_LAST];
179 int i, num = 0;
180
181 if (role_tech != -1) {
182 for (i = 0; i < num_role_units(role_tech); i++) {
184 const int minplayers = 2;
185 int players = 0;
186
187 /* Note, if there's only one player in the game this check will always
188 * fail. */
189 players_iterate(pplayer) {
190 if (!is_barbarian(pplayer)
192 players++;
193 }
195
196 if (players > minplayers) {
197 which[num++] = iunit;
198 }
199 }
200 }
201 if (num == 0) {
202 for (i = 0; i < num_role_units(role); i++) {
203 which[num++] = get_role_unit(role, i);
204 }
205 }
206
207 /* Ruleset code should ensure there is at least one unit for each
208 * possibly-required role, or check before calling this function. */
209 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
210 role, role_tech);
211
212 return which[fc_rand(num)];
213}
214
215/**********************************************************************/
223
224/**********************************************************************/
239 bool worker)
240{
241 const struct veteran_system *vsystem;
242 const struct veteran_level *vlevel;
243 int chance;
244 const struct civ_map *nmap = &(wld.map);
245
247
251
254
255 if (punit->veteran + 1 >= vsystem->levels
257 return FALSE;
258 } else if (!worker) {
260
261 /* The modification is tacked on as a multiplier to the base chance.
262 * For example with a base chance of 50% for green units and a modifier
263 * of +50% the end chance is 75%. */
264 chance = vlevel->base_raise_chance * mod / 100;
267
268 chance = vlevel->work_raise_chance * mod / 100;
269 } else {
270 /* No battle and no work done. */
271 return FALSE;
272 }
273
274 if (fc_rand(100) < chance) {
275 punit->veteran++;
276 return TRUE;
277 }
278
279 return FALSE;
280}
281
282/**********************************************************************/
292bool unit_versus_unit(struct unit *attacker, struct unit *defender,
293 int *att_hp, int *def_hp, int *att_vet, int *def_vet,
294 const struct action *paction)
295{
296 int attackpower = get_total_attack_power(attacker, defender, paction);
297 int defensepower = get_total_defense_power(attacker, defender);
299 struct player *plr1 = unit_owner(attacker);
300 struct player *plr2 = unit_owner(defender);
301 struct civ_map *nmap = &(wld.map);
302 int max_rounds;
303 int rounds;
304 int att_strength;
305 int def_strength;
306
307 *att_hp = attacker->hp;
308 *def_hp = defender->hp;
309 get_modified_firepower(nmap, attacker, defender,
311
312 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
313 "defense firepower:%d", attackpower, defensepower,
315
318
321
322 /* In a combat between equal strength units the values are 50% / 50%.
323 * -> scaling that to 100% by doubling, to match scale of chances
324 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
327
328 if (attackpower == 0) {
329 *att_hp = 0;
330 } else if (defensepower == 0) {
331 *def_hp = 0;
332 }
334 for (rounds = 0;
335 *att_hp > 0 && *def_hp > 0
337 rounds++) {
339 *def_hp -= attack_firepower;
340 } else {
341 *att_hp -= defense_firepower;
342 }
343 }
344 if (*att_hp < 0) {
345 *att_hp = 0;
346 }
347 if (*def_hp < 0) {
348 *def_hp = 0;
349 }
350
351 return attackpower <= 0 || defensepower <= 0;
352}
353
354/**********************************************************************/
359void unit_bombs_unit(struct unit *attacker, struct unit *defender,
360 int *att_hp, int *def_hp,
361 const struct action *paction)
362{
363 int i;
364 int rate = unit_bombard_rate(attacker);
365 int attackpower = get_total_attack_power(attacker, defender, paction);
366 int defensepower = get_total_defense_power(attacker, defender);
368 struct player *plr1 = unit_owner(attacker);
369 struct player *plr2 = unit_owner(defender);
370 struct civ_map *nmap = &(wld.map);
371
372 *att_hp = attacker->hp;
373 *def_hp = defender->hp;
374 get_modified_firepower(nmap, attacker, defender,
376
377 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
378 "defense firepower:%d", attackpower, defensepower,
380
383
384 for (i = 0; i < rate; i++) {
386 *def_hp -= attack_firepower;
387 }
388 }
389
390 if (*def_hp <= 0) {
391 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
392 /* Don't kill the target. */
393 *def_hp = 1;
394 } else {
395 *def_hp = 0;
396 }
397 }
398}
399
400/**********************************************************************/
404void combat_veterans(struct unit *attacker, struct unit *defender,
405 bool powerless, int att_vet, int def_vet)
406{
408 if (attacker->hp <= 0 || defender->hp <= 0
411 att_vet = 100;
412 def_vet = 100;
413 }
414 if (attacker->hp > 0) {
415 maybe_make_veteran(attacker, att_vet);
416 }
417 if (defender->hp > 0) {
418 maybe_make_veteran(defender, def_vet);
419 }
420 }
421 }
422}
423
424/**********************************************************************/
428static void do_upgrade_effects(struct player *pplayer)
429{
431 struct unit_list *candidates;
432
433 if (upgrades <= 0) {
434 return;
435 }
437
438 unit_list_iterate(pplayer->units, punit) {
439 /* We have to be careful not to strand units at sea, for example by
440 * upgrading a frigate to an ironclad while it was carrying a unit. */
441 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
442 unit_list_prepend(candidates, punit); /* Potential candidate :) */
443 }
445
446 while (upgrades > 0 && unit_list_size(candidates) > 0) {
447 /* Upgrade one unit. The unit is chosen at random from the list of
448 * available candidates. */
451 const struct unit_type *type_from = unit_type_get(punit);
452 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
453
456 _("%s was upgraded for free to %s."),
460 upgrades--;
461 }
462
464}
465
466/**********************************************************************/
481void player_restore_units(struct player *pplayer)
482{
483 const struct civ_map *nmap = &(wld.map);
484
485 /* 1) get Leonardo out of the way first: */
486 do_upgrade_effects(pplayer);
487
489
490 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
492
493 /* 3) Check that unit has hitpoints */
494 if (punit->hp <= 0) {
495 /* This should usually only happen for heli units, but if any other
496 * units get 0 hp somehow, catch them too. --dwp */
497 /* if 'game.server.killunhomed' is activated unhomed units are slowly
498 * killed; notify player here */
499 if (!punit->homecity && 0 < game.server.killunhomed) {
501 ftc_server, _("Your %s has run out of hit points "
502 "because it was not supported by a city."),
504 } else {
506 _("Your %s has run out of hit points."),
508 }
509
511 continue; /* Continue iterating... */
512 }
513
514 /* 4) Rescue planes if needed */
516 /* Shall we emergency return home on the last vapors? */
517
518 /* I think this is strongly against the spirit of client goto.
519 * The problem is (again) that here we know too much. -- Zamar */
520
521 if (punit->fuel <= 1
523 struct unit *carrier;
524
526 if (carrier) {
528 } else {
529 struct pf_map *pfm;
530 struct pf_parameter parameter;
531 bool alive = TRUE;
532
533 pft_fill_unit_parameter(&parameter, nmap, punit);
534 parameter.omniscience = !has_handicap(pplayer, H_MAP);
535 pfm = pf_map_new(&parameter);
536
537 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
538 if (move_cost > punit->moves_left) {
539 /* Too far */
540 break;
541 }
542
543 if (is_refuel_point(ptile, pplayer, punit)) {
544 struct pf_path *path;
545 int id = punit->id;
546
547 /* Client orders may be running for this unit - if so
548 * we free them before engaging goto. */
550
551 path = pf_map_path(pfm, ptile);
552
553 alive = adv_follow_path(punit, path, ptile);
554
555 if (!alive) {
556 log_error("rescue plane: unit %d died enroute!", id);
557 } else if (!same_pos(unit_tile(punit), ptile)) {
558 /* Enemy units probably blocked our route
559 * FIXME: We should try find alternative route around
560 * the enemy unit instead of just giving up and crashing. */
561 log_debug("rescue plane: unit %d could not move to "
562 "refuel point!", punit->id);
563 }
564
565 if (alive) {
566 /* Clear activity. Unit info will be sent in the end of
567 * the function. */
571
574 if (carrier) {
576 }
577 }
578
579 notify_player(pplayer, unit_tile(punit),
581 _("Your %s has returned to refuel."),
583 }
584 pf_path_destroy(path);
585 break;
586 }
589
590 if (!alive) {
591 /* Unit died trying to move to refuel point. */
592 return;
593 }
594 }
595 }
596
597 /* 5) Update fuel */
598 punit->fuel--;
599
600 /* 6) Automatically refuel air units in cities, airbases, and
601 * transporters (carriers). */
604 }
605 }
607
608 /* 7) Check if there are air units without fuel */
610 const struct unit_type *utype = unit_type_get(punit);
611
612 if (punit->fuel <= 0 && utype_fuel(utype)) {
613 /* Notifications sent from the lua script when unit wiped. */
615 }
617
618 /* Send all updates. */
619 unit_list_iterate(pplayer->units, punit) {
622}
623
624/**********************************************************************/
635{
636 bool was_lower;
637 const struct unit_type *utype = unit_type_get(punit);
638
639 was_lower = (punit->hp < utype->hp);
640
642
643 fc_assert(punit->hp >= 0);
644 fc_assert(punit->hp <= utype->hp);
645
646 if (punit->hp == utype->hp) {
649 }
650 }
651
652 punit->moved = FALSE;
654}
655
656/**********************************************************************/
661static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
662{
665}
666
667/**********************************************************************/
676
677/**********************************************************************/
680void execute_unit_orders(struct player *pplayer)
681{
683 if (unit_has_orders(punit)) {
685 }
687}
688
689/**********************************************************************/
692void unit_tc_effect_refresh(struct player *pplayer)
693{
694 unit_list_iterate(pplayer->units, punit) {
697}
698
699/**********************************************************************/
703{
704 /* Remember activities only after all knock-on effects of unit activities
705 * on other units have been resolved */
706 unit_list_iterate(pplayer->units, punit) {
712}
713
714/**********************************************************************/
718static int total_activity(struct tile *ptile, enum unit_activity act,
719 struct extra_type *tgt)
720{
721 int total = 0;
723
724 unit_list_iterate(ptile->units, punit) {
725 if (punit->activity == act
726 && (!tgt_matters || punit->activity_target == tgt)) {
727 total += punit->activity_count;
728 }
730
731 return total;
732}
733
734/**********************************************************************/
738static bool total_activity_done(struct tile *ptile, enum unit_activity act,
739 struct extra_type *tgt)
740{
741 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
742}
743
744/**********************************************************************/
748{
749 const struct veteran_level *vlevel;
750 const struct veteran_system *vsystem;
751
752 if (!punit) {
753 return;
754 }
755
759
762
765 /* TRANS: Your <unit> became ... rank of <veteran level>. */
766 _("Your %s became more experienced and achieved the rank "
767 "of %s."),
769}
770
771/**********************************************************************/
774static void unit_convert(struct unit *punit)
775{
776 const struct unit_type *to_type;
777 const struct unit_type *from_type;
778
780 to_type = from_type->converted_to;
781
782 if (unit_can_convert(&(wld.map), punit)) {
786 _("%s converted to %s."),
789 } else {
792 _("%s cannot be converted."),
794 }
795}
796
797/**********************************************************************/
801{
802 if (unit_has_orders(punit)) {
805 _("Orders for %s aborted because activity "
806 "is no longer available."),
809 }
810
813}
814
815/**********************************************************************/
826
827/**********************************************************************/
838
839/**********************************************************************/
853
854/**********************************************************************/
858static void update_unit_activity(struct unit *punit)
859{
860 struct player *pplayer = unit_owner(punit);
862 enum unit_activity activity = punit->activity;
863 struct tile *ptile = unit_tile(punit);
864 const struct unit_type *act_utype = unit_type_get(punit);
865
866 switch (activity) {
867 case ACTIVITY_IDLE:
868 case ACTIVITY_EXPLORE:
870 case ACTIVITY_SENTRY:
871 case ACTIVITY_GOTO:
872 case ACTIVITY_LAST:
873 /* We don't need the activity_count for the above */
874 break;
875
877 case ACTIVITY_CONVERT:
879 break;
880
881 case ACTIVITY_CLEAN:
882 case ACTIVITY_MINE:
884 case ACTIVITY_PILLAGE:
886 case ACTIVITY_PLANT:
888 case ACTIVITY_BASE:
891
892 /* Worker may become veteran when doing something useful */
895 }
896 break;
897 };
898
900
901 switch (activity) {
902 case ACTIVITY_EXPLORE:
903 /* Not accumulating activity - will be handled more like movement
904 * after the TC */
906 case ACTIVITY_IDLE:
908 case ACTIVITY_SENTRY:
909 case ACTIVITY_GOTO:
911 case ACTIVITY_CONVERT:
912 case ACTIVITY_LAST:
913 /* No default, ensure all handled */
914 break;
915
916 case ACTIVITY_PILLAGE:
921
923
924 /* Change vision if effects have changed. */
926 }
927 break;
928
929 case ACTIVITY_CLEAN:
930 /* TODO: Remove this fallback target setting when target always correctly
931 * set */
932 {
933 struct extra_type *pextra;
934
935 if (punit->activity_target == NULL) {
936 pextra = prev_extra_in_tile(ptile, ERM_CLEAN,
937 NULL, punit);
938 if (pextra != NULL) {
939 punit->activity_target = pextra;
940 }
941 } else {
943 pextra = punit->activity_target;
944 } else {
945 pextra = NULL;
946 }
947 }
948
949 if (pextra != NULL) {
950 if (total_activity_done(ptile, ACTIVITY_CLEAN, pextra)) {
951 destroy_extra(ptile, pextra);
953 }
954 }
955 }
956 break;
957
958 case ACTIVITY_BASE:
959 {
964 }
965 }
966 break;
967
969 {
974 }
975 }
976 break;
977
979 case ACTIVITY_MINE:
981 case ACTIVITY_PLANT:
983 if (total_activity_done(ptile, activity, punit->activity_target)) {
984 struct terrain *old = tile_terrain(ptile);
985
986 /* The function below could change the terrain. Therefore, we have to
987 * check the terrain (which will also do a sanity check for the tile). */
988 tile_apply_activity(ptile, activity, punit->activity_target);
991 }
992 break;
993 }
994
995 if (unit_activity_done) {
997
999
1000 unit_list_iterate(ptile->units, punit2) {
1001 if (punit2->activity == activity
1002 && punit2->activity_target == act_tgt) {
1003 /* This unit was helping with the work just finished.
1004 * Mark it idle (already finished) so its "current"
1005 * activity is not considered illegal
1006 * in tile_change_side_effects() . */
1008 }
1010
1012 }
1013
1014 if (activity == ACTIVITY_FORTIFYING) {
1017 punit, ptile, punit->activity_target)) {
1020 }
1021 }
1022
1023 if (activity == ACTIVITY_CONVERT) {
1026 punit, ptile, punit->activity_target)) {
1030 }
1031 }
1032
1033 if (unit_activity_done) {
1034 if (activity == ACTIVITY_PILLAGE) {
1035 /* Casus Belli for when the action is completed. */
1036 /* TODO: is it more logical to put Casus_Belli_Success here, change
1037 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1038 * trigger it when an activity successfully has began? */
1041 act_utype,
1045 }
1046 }
1047}
1048
1049/**********************************************************************/
1057
1058/**********************************************************************/
1063{
1064 switch (activity) {
1065 case ACTIVITY_PILLAGE:
1066 /* Can be set server side. */
1067 return FALSE;
1068 default:
1069 return activity_requires_target(activity);
1070 }
1071}
1072
1073/**********************************************************************/
1083 enum unit_activity *activity,
1084 struct extra_type **target)
1085{
1086 const struct civ_map *nmap = &(wld.map);
1087
1088 if (*activity == ACTIVITY_PILLAGE
1089 && *target == NULL) {
1090 struct tile *ptile = unit_tile(punit);
1091 struct extra_type *tgt;
1092 bv_extras extras = *tile_extras(ptile);
1093
1094 while ((tgt = get_preferred_pillage(extras))) {
1095
1096 BV_CLR(extras, extra_index(tgt));
1097
1098 if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
1099 *target = tgt;
1100 return;
1101 }
1102 }
1103
1104 /* Nothing we can pillage here. */
1105 *activity = ACTIVITY_IDLE;
1106 }
1107}
1108
1109/**********************************************************************/
1114 struct player *powner,
1115 struct unit_type *u_type,
1116 int sq_radius,
1117 struct tile **dst_tile)
1118{
1119 int bestvalue = 0;
1120 struct civ_map *nmap = &(wld.map);
1121
1122 /* coords of best tile in arg pointers */
1124 int value;
1125
1126 if (!is_native_tile(u_type, ptile)) {
1127 continue;
1128 }
1129
1130 if (NULL != tile_city(ptile)) {
1131 continue;
1132 }
1133
1134 if (0 < unit_list_size(ptile->units)) {
1135 continue;
1136 }
1137
1138 /* City may not have changed hands yet; see place_partisans(). */
1139 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1140 ptile, FALSE, 0);
1141 value *= 10;
1142
1143 if (tile_continent(ptile) != tile_continent(pcenter)) {
1144 value /= 2;
1145 }
1146
1147 value -= fc_rand(value/3);
1148
1149 if (value > bestvalue) {
1150 *dst_tile = ptile;
1151 bestvalue = value;
1152 }
1154
1155 return bestvalue > 0;
1156}
1157
1158/**********************************************************************/
1161void place_partisans(struct tile *pcenter, struct player *powner,
1162 int count, int sq_radius)
1163{
1164 struct tile *ptile = NULL;
1166 const struct civ_map *nmap = &(wld.map);
1167
1168 while (count-- > 0
1170 sq_radius, &ptile)) {
1171 struct unit *punit;
1172
1173 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1175 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1176 }
1177
1178 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1179 }
1180}
1181
1182/**********************************************************************/
1188 int move_cost, bool verbose)
1189{
1190 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1191
1192 if (city_owner(pcity) == unit_owner(punit)) {
1193 log_verbose("Teleported %s %s from (%d,%d) to %s",
1196 if (verbose) {
1199 _("Teleported your %s to %s."),
1201 city_link(pcity));
1202 }
1203
1204 /* Silently free orders since they won't be applicable anymore. */
1206
1207 if (move_cost == -1) {
1208 move_cost = punit->moves_left;
1209 }
1210 unit_move(punit, dst_tile, move_cost,
1212
1213 return TRUE;
1214 }
1215 return FALSE;
1216}
1217
1218/**********************************************************************/
1225void bounce_unit(struct unit *punit, bool verbose)
1226{
1227 struct player *pplayer;
1228 struct tile *punit_tile;
1229 int count = 0;
1230
1231 /* I assume that there are no topologies that have more than
1232 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1233 const int DIST = 2;
1234 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1235
1236 if (!punit) {
1237 return;
1238 }
1239
1240 pplayer = unit_owner(punit);
1242
1243 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1244 if (count >= ARRAY_SIZE(tiles)) {
1245 break;
1246 }
1247
1248 if (ptile == punit_tile) {
1249 continue;
1250 }
1251
1252 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1253 && !is_non_allied_city_tile(ptile, pplayer)
1254 && !is_non_allied_unit_tile(ptile, pplayer,
1256 tiles[count++] = ptile;
1257 }
1259
1260 if (count > 0) {
1261 struct tile *ptile = tiles[fc_rand(count)];
1262
1263 if (verbose) {
1264 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1265 /* TRANS: A unit is moved to resolve stack conflicts. */
1266 _("Moved your %s."),
1267 unit_link(punit));
1268 }
1269
1270 /* TODO: should a unit be able to bounce to a transport like is done
1271 * below? What if the unit can't legally enter the transport, say
1272 * because the transport is Unreachable and the unit doesn't have it in
1273 * its embarks field or because "Transport Embark" isn't enabled? Kept
1274 * like it was to preserve the old rules for now. -- Sveinung */
1275 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1276 return;
1277 }
1278
1279 /* Didn't find a place to bounce the unit, going to disband it.
1280 * Try to bounce transported units. */
1282 struct unit_list *pcargo_units;
1283
1286 bounce_unit(pcargo, verbose);
1288 }
1289
1290 if (verbose) {
1292 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1293 _("Disbanded your %s."),
1295 }
1296
1298}
1299
1300/**********************************************************************/
1305static void throw_units_from_illegal_cities(struct player *pplayer,
1306 bool verbose)
1307{
1308 struct tile *ptile;
1309 struct city *pcity;
1310 struct unit *ptrans;
1311 struct unit_list *pcargo_units;
1312
1313 /* Unload undesired units from transports, if possible. */
1314 unit_list_iterate(pplayer->units, punit) {
1315 ptile = unit_tile(punit);
1316 pcity = tile_city(ptile);
1317 if (NULL != pcity
1318 && !pplayers_allied(city_owner(pcity), pplayer)
1322 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1323 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1325 }
1326 }
1328 }
1330
1331 /* Bounce units except transported ones which will be bounced with their
1332 * transport. */
1334 ptile = unit_tile(punit);
1335 pcity = tile_city(ptile);
1336 if (NULL != pcity
1337 && !pplayers_allied(city_owner(pcity), pplayer)) {
1339 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1340 bounce_unit(punit, verbose);
1341 }
1342 }
1344
1345#ifdef FREECIV_DEBUG
1346 /* Sanity check. */
1347 unit_list_iterate(pplayer->units, punit) {
1348 ptile = unit_tile(punit);
1349 pcity = tile_city(ptile);
1351 || pplayers_allied(city_owner(pcity), pplayer),
1352 "Failed to throw %s %d from %s %d (%d, %d)",
1354 punit->id,
1356 pcity->id,
1357 TILE_XY(ptile));
1359#endif /* FREECIV_DEBUG */
1360}
1361
1362/**********************************************************************/
1370static void resolve_stack_conflicts(struct player *pplayer,
1371 struct player *aplayer, bool verbose)
1372{
1374 struct tile *ptile = unit_tile(punit);
1375
1376 /* Can pass FALSE 'everyone_non_allied' since no flagless
1377 * unit could be stacked there to begin with. */
1378 if (is_non_allied_unit_tile(ptile, pplayer, FALSE)) {
1380 if (unit_owner(aunit) == pplayer
1381 || unit_owner(aunit) == aplayer
1382 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1383 bounce_unit(aunit, verbose);
1384 }
1386 }
1388}
1389
1390/**********************************************************************/
1401void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1402 bool verbose)
1403{
1404 throw_units_from_illegal_cities(pplayer, verbose);
1406
1407 resolve_stack_conflicts(pplayer, aplayer, verbose);
1408 resolve_stack_conflicts(aplayer, pplayer, verbose);
1409}
1410
1411/**********************************************************************/
1416struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1417 const struct player *aplayer)
1418{
1419 struct unit_list *seen_units = unit_list_new();
1420
1421 /* Anybody's units inside ally's cities */
1422 city_list_iterate(aplayer->cities, pcity) {
1424 if (can_player_see_unit(pplayer, punit)) {
1426 }
1429
1430 /* Ally's own units inside transports */
1432 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1434 }
1436
1437 /* Make sure the same unit is not added in multiple phases
1438 * (unit within transport in a city) */
1440
1441 return seen_units;
1442}
1443
1444/**********************************************************************/
1451void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1452 const struct unit_list *seen_units)
1453{
1455 /* We need to hide units previously seen by the client. */
1456 if (!can_player_see_unit(pplayer, punit)) {
1457 unit_goes_out_of_sight(pplayer, punit);
1458 }
1460
1461 city_list_iterate(aplayer->cities, pcity) {
1462 /* The player used to know what units were in these cities. Now that
1463 * they don't, they need to get a new short city packet updating the
1464 * occupied status. */
1465 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1466 send_city_info(pplayer, pcity);
1467 }
1469}
1470
1471/**********************************************************************/
1475void give_allied_visibility(struct player *pplayer,
1476 struct player *aplayer)
1477{
1479 if (can_player_see_unit(pplayer, punit)) {
1480 send_unit_info(pplayer->connections, punit);
1481 }
1483}
1484
1485/**********************************************************************/
1488static bool is_refuel_tile(const struct tile *ptile,
1489 const struct player *pplayer,
1490 const struct unit *punit)
1491{
1492 const struct unit_type *utype;
1493 const struct unit_class *pclass;
1494
1495 if (is_allied_city_tile(ptile, pplayer)) {
1496 return TRUE;
1497 }
1498
1499 utype = unit_type_get(punit);
1500 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1501 return TRUE;
1502 }
1503
1504 pclass = utype_class(utype);
1505 if (NULL != pclass->cache.refuel_extras) {
1506 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1507
1508 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1509 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1510 return TRUE;
1511 }
1513 }
1514
1515 return FALSE;
1516}
1517
1518/**********************************************************************/
1522{
1523 return unit_transported(punit) /* Carrier */
1525}
1526
1527/**********************************************************************/
1530bool is_refuel_point(const struct tile *ptile,
1531 const struct player *pplayer,
1532 const struct unit *punit)
1533{
1534 if (is_non_allied_unit_tile(ptile, pplayer,
1536 return FALSE;
1537 }
1538
1539 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1540}
1541
1542/**********************************************************************/
1553void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1554 int vet_loss)
1555{
1556 struct player *pplayer = unit_owner(punit);
1557 const struct unit_type *old_type = punit->utype;
1559 int old_hp = unit_type_get(punit)->hp;
1560 int lvls;
1561
1562 punit->utype = to_unit;
1563
1564 /* New type may not have the same veteran system, and we may want to
1565 * knock some levels off. */
1568 /* Keeping the old behaviour, so first clip top, then reduce */
1570
1571 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1572 * and don't kill the unit. unit_move_rate() is used to take into account
1573 * global effects like Magellan's Expedition. */
1574 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1575 if (old_mr == 0) {
1577 } else {
1579 }
1580
1582
1586 }
1587
1588 /* Update unit upkeep */
1590
1592
1594
1595 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1597
1600}
1601
1602/**********************************************************************/
1605struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1606 const struct unit_type *type, int veteran_level,
1607 int homecity_id, int moves_left)
1608{
1609 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1610 moves_left, -1, NULL);
1611}
1612
1613/**********************************************************************/
1617{
1618 if (punit->homecity != 0) {
1620
1623 }
1624 }
1625}
1626
1627/**********************************************************************/
1632struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1633 const struct unit_type *type, int veteran_level,
1634 int homecity_id, int moves_left, int hp_left,
1635 struct unit *ptrans)
1636{
1637 struct unit *punit
1638 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1642 bool could_place;
1643
1647 if (!could_place) {
1649 punit = NULL;
1650 }
1651
1652 return punit;
1653}
1654
1655/**********************************************************************/
1665struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1666 const struct unit_type *type,
1667 int veteran_level, int homecity_id,
1668 int moves_left, int hp_left)
1669{
1670 struct unit *punit;
1671
1672 fc_assert_ret_val(ptile != NULL, NULL);
1674 unit_tile_set(punit, ptile);
1675
1677 punit->homecity = 0; /* none */
1678 } else {
1680 }
1681
1682 if (hp_left >= 0) {
1683 /* Override default full HP */
1684 punit->hp = hp_left;
1685 }
1686
1687 if (moves_left >= 0) {
1688 int mr = unit_move_rate(punit);
1689
1690 /* Override default full MP */
1691 /* FIXME: there are valid situations when a unit have mp
1692 * over its move rate. Here, keeping the old behavior. */
1694 /* Assume that if moves_left < 0 then the unit is "fresh",
1695 * and not moved; else the unit has had something happen
1696 * to it (eg, bribed) which we treat as equivalent to moved.
1697 * (Otherwise could pass moved arg too...) --dwp */
1698 punit->moved = TRUE;
1699 }
1700
1701 return punit;
1702}
1703
1704/**********************************************************************/
1713bool place_unit(struct unit *punit, struct player *pplayer,
1714 struct city *pcity, struct unit *ptrans, bool force)
1715{
1716 struct tile *ptile;
1717
1718 fc_assert_ret_val(pplayer, FALSE);
1720 ptile = punit->tile;
1721 fc_assert_ret_val(ptile, FALSE);
1722
1723 /* Register unit */
1726
1727 if (ptrans) {
1728 /* Set transporter for unit. */
1730 }
1731
1733 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1734 FALSE);
1735
1736 unit_list_prepend(pplayer->units, punit);
1737 unit_list_prepend(ptile->units, punit);
1738 unit_make_contact(punit, ptile, nullptr);
1741 fc_assert(city_owner(pcity) == pplayer);
1742 unit_list_prepend(pcity->units_supported, punit);
1743 /* update unit upkeep */
1745 /* Refresh the unit's homecity. */
1747 send_city_info(pplayer, pcity);
1748 }
1749
1750 punit->server.vision = vision_new(pplayer, ptile);
1752
1755
1756 /* The unit may have changed the available tiles in nearby cities. */
1758 sync_cities();
1759
1761
1762 CALL_FUNC_EACH_AI(unit_created, punit);
1763 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1764
1765 return TRUE;
1766}
1767
1768/**********************************************************************/
1772 void (*callback)(struct unit *punit))
1773{
1774 /* Tried to overwrite another call back. If this assertion is triggered
1775 * in a case where two call back are needed it may be time to support
1776 * more than one unit removal call back at a time. */
1778
1780}
1781
1782/**********************************************************************/
1789
1790/**********************************************************************/
1794static void server_remove_unit_full(struct unit *punit, bool transported,
1796{
1797 struct packet_unit_remove packet;
1798 struct tile *ptile = unit_tile(punit);
1799 struct city *pcity = tile_city(ptile);
1801 struct unit *ptrans;
1802 struct player *pplayer = unit_owner(punit);
1803
1804 /* The unit is doomed. */
1806
1807#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1808 unit_list_iterate(ptile->units, pcargo) {
1811#endif /* FREECIV_DEBUG */
1812
1813 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1814 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1815
1816 /* Save transporter for updating below. */
1818 /* Unload unit. */
1820
1821 /* Since settlers plot in new cities in the minimap before they
1822 are built, so that no two settlers head towards the same city
1823 spot, we need to ensure this reservation is cleared should
1824 the settler disappear on the way. */
1826
1827 /* Clear the vision before sending unit remove. Else, we might duplicate
1828 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1829 if (punit->server.vision != NULL) {
1833 }
1834
1835 packet.unit_id = punit->id;
1836 /* Send to onlookers. */
1839 transported)) {
1840 lsend_packet_unit_remove(aplayer->connections, &packet);
1841 }
1843 /* Send to global observers. */
1847 }
1849
1850 if (punit->server.moving != NULL) {
1851 /* Do not care of this unit for running moves. */
1853 }
1854
1856 /* Run the unit removal call back. */
1858 }
1859
1860 /* check if this unit had UTYF_GAMELOSS flag */
1862 && ULR_EDITOR != reason) {
1864 _("Unable to defend %s, %s has lost the game."),
1866 player_name(pplayer));
1867 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1868 _("Losing %s meant losing the game! "
1869 "Be more careful next time!"),
1870 unit_link(punit));
1872 }
1873
1876
1879 punit = NULL;
1880
1881 if (NULL != ptrans) {
1882 /* Update the occupy info. */
1884 }
1885
1886 /* This unit may have blocked tiles of adjacent cities. Update them. */
1888 sync_cities();
1889
1890 if (phomecity) {
1893 }
1894
1895 if (pcity && pcity != phomecity) {
1898 }
1899
1900 if (pcity && unit_list_size(ptile->units) == 0) {
1901 /* The last unit in the city was killed: update the occupied flag. */
1903 }
1904}
1905
1906/**********************************************************************/
1915
1916/**********************************************************************/
1919static void unit_lost_with_transport(const struct player *pplayer,
1920 struct unit *pcargo,
1921 const struct unit_type *ptransport,
1922 struct player *killer)
1923{
1925 _("%s lost when %s was lost."),
1928 /* Unit is not transported any more at this point, but it has jumped
1929 * off the transport and drowns outside. So it must be removed from
1930 * all clients.
1931 * However, we don't know if given client has received ANY updates
1932 * about the swimming unit, and we can't remove it if it's not there
1933 * in the first place -> we send it once here just to be sure it's
1934 * there. */
1937}
1938
1939/**********************************************************************/
1943static void wipe_unit_full(struct unit *punit, bool transported,
1945 struct player *killer)
1946{
1947 struct tile *ptile = unit_tile(punit);
1948 struct player *pplayer = unit_owner(punit);
1949 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1950 struct unit_list *helpless = unit_list_new();
1951 struct unit_list *imperiled = unit_list_new();
1952 struct unit_list *unsaved = unit_list_new();
1954 struct city *pexclcity;
1955 struct civ_map *nmap = &(wld.map);
1956
1957 if (killer != NULL
1960 player_loot_player(killer, pplayer);
1961 }
1962
1963 /* The unit is doomed. */
1965
1966 /* If a unit is being lost due to loss of its city, ensure that we don't
1967 * try to teleport any of its cargo to that city (which may not yet
1968 * have changed hands or disappeared). (It is assumed that the unit's
1969 * home city is always the one that is being lost/transferred/etc.) */
1970 if (reason == ULR_CITY_LOST) {
1972 } else {
1973 pexclcity = NULL;
1974 }
1975
1976 /* Remove unit itself from its transport */
1977 if (ptrans != NULL) {
1980 }
1981
1982 /* First pull all units off of the transporter. */
1984 /* Use iterate_safe as unloaded units will be removed from the list
1985 * while iterating. */
1987 bool healthy = FALSE;
1988
1989 if (!can_unit_unload(pcargo, punit)) {
1991 } else {
1992 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
1994 } else {
1995 /* These units do not need to be saved. */
1996 healthy = TRUE;
1997 }
1998 }
1999
2000 /* Could use unit_transport_unload_send() here, but that would
2001 * call send_unit_info() for the transporter unnecessarily.
2002 * Note that this means that unit might to get seen briefly
2003 * by clients other than owner's, for example as a result of
2004 * update of homecity common to this cargo and some other
2005 * destroyed unit. */
2007 if (pcargo->activity == ACTIVITY_SENTRY) {
2008 /* Activate sentried units - like planes on a disbanded carrier.
2009 * Note this will activate ground units even if they just change
2010 * transporter. */
2012 }
2013
2014 /* Unit info for unhealthy units will be sent when they are
2015 * assigned new transport or removed. */
2016 if (healthy) {
2018 }
2020 }
2021
2022 /* Now remove the unit. */
2023 server_remove_unit_full(punit, transported, reason);
2024
2025 switch (reason) {
2026 case ULR_KILLED:
2027 case ULR_EXECUTED:
2028 case ULR_SDI:
2029 case ULR_NUKE:
2030 case ULR_BRIBED:
2031 case ULR_CAPTURED:
2032 case ULR_CAUGHT:
2033 case ULR_ELIMINATED:
2034 case ULR_TRANSPORT_LOST:
2035 if (killer != NULL) {
2036 killer->score.units_killed++;
2037 }
2038 pplayer->score.units_lost++;
2039 break;
2040 case ULR_BARB_UNLEASH:
2041 case ULR_CITY_LOST:
2042 case ULR_STARVED:
2043 case ULR_UPKEEP:
2044 case ULR_NONNATIVE_TERR:
2045 case ULR_ARMISTICE:
2046 case ULR_HP_LOSS:
2047 case ULR_FUEL:
2048 case ULR_STACK_CONFLICT:
2049 case ULR_SOLD:
2050 pplayer->score.units_lost++;
2051 break;
2052 case ULR_RETIRED:
2053 case ULR_DISBANDED:
2054 case ULR_USED:
2055 case ULR_DETONATED:
2056 case ULR_MISSILE:
2057 pplayer->score.units_used++;
2058 break;
2059 case ULR_EDITOR:
2060 case ULR_PLAYER_DIED:
2061 break;
2062 }
2063
2064 /* First, sort out helpless cargo. */
2065 if (unit_list_size(helpless) > 0) {
2066 struct unit_list *remaining = unit_list_new();
2067
2068 /* Grant priority to gameloss units and units with the EvacuateFirst
2069 * unit type flag. */
2076 pexclcity)) {
2078 }
2079 } else {
2080 unit_list_prepend(remaining, pcargo);
2081 }
2083
2084 /* Handle non-priority units. */
2085 unit_list_iterate_safe(remaining, pcargo) {
2088 }
2090
2091 unit_list_destroy(remaining);
2092 }
2094
2095 /* Then, save any imperiled cargo. */
2096 if (unit_list_size(imperiled) > 0) {
2097 struct unit_list *remaining = unit_list_new();
2098
2099 /* Grant priority to gameloss units and units with the EvacuateFirst
2100 * unit type flag. */
2107 pexclcity)) {
2109 }
2110 } else {
2111 unit_list_prepend(remaining, pcargo);
2112 }
2114
2115 /* Handle non-priority units. */
2116 unit_list_iterate_safe(remaining, pcargo) {
2119 }
2121
2122 unit_list_destroy(remaining);
2123 }
2125
2126 /* Finally, kill off the unsaved units. */
2127 if (unit_list_size(unsaved) > 0) {
2131 }
2133}
2134
2135/**********************************************************************/
2144
2145/**********************************************************************/
2151static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2152 bool helpless, bool teleporting,
2153 const struct city *pexclcity)
2154{
2155 struct tile *ptile = unit_tile(punit);
2156 struct player *pplayer = unit_owner(punit);
2158
2159 /* Helpless units cannot board a transport in their current state. */
2160 if (!helpless
2161 && ptransport != NULL) {
2164 return TRUE;
2165 } else {
2166 /* Only units that cannot find transport are considered for teleport. */
2167 if (teleporting) {
2168 struct city *pcity = find_closest_city(ptile, pexclcity,
2172 if (pcity != NULL) {
2173 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2174
2176
2178 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2179 _("%s escaped the destruction of %s, and fled to %s."),
2180 tplink,
2182 city_link(pcity));
2183 return TRUE;
2184 }
2185 }
2186 }
2187 }
2188
2189 /* The unit could not use transport on the tile, and could not teleport. */
2190 return FALSE;
2191}
2192
2193/**********************************************************************/
2199struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2201{
2202 struct unit *gained_unit;
2203 int id = 0;
2204
2205#ifndef FREECIV_NDEBUG
2206 bool placed;
2207#endif
2208
2211
2212 /* Convert the unit to your cause. It's supposed that the original unit
2213 * is on a valid tile and is not transported. */
2217 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2218
2219 /* Owner changes, nationality not. */
2220 gained_unit->nationality = punit->nationality;
2221
2222 /* Copy some more unit fields */
2223 gained_unit->fuel = punit->fuel;
2224 gained_unit->paradropped = punit->paradropped;
2225 gained_unit->birth_turn = punit->birth_turn;
2226 gained_unit->current_form_turn = punit->current_form_turn;
2227
2228 /* Fog is lifted in the placing algorithm. */
2229#ifndef FREECIV_NDEBUG
2230 placed =
2231#endif
2232 place_unit(gained_unit, pplayer,
2234 NULL, FALSE);
2235
2237
2238 id = gained_unit->id;
2239
2240 /* Update unit upkeep in the new homecity */
2241 if (homecity > 0) {
2243 }
2244
2245 /* Be sure to wipe the converted unit! */
2246 /* Old homecity upkeep is updated in process */
2247#ifndef FREECIV_NDEBUG
2248 uco_wipe:
2249#endif
2250
2252
2253 if (!unit_is_alive(id)) {
2254 /* Destroyed by a script */
2255 return NULL;
2256 }
2257
2258 return gained_unit; /* Returns the replacement. */
2259}
2260
2261/**********************************************************************/
2266void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2267{
2269 struct player *pvictim = unit_owner(punit);
2270 struct player *pvictor = unit_owner(pkiller);
2271 struct tile *deftile = unit_tile(punit);
2272 int unitcount = 0;
2273 bool escaped;
2276 const struct civ_map *nmap = &(wld.map);
2277
2280
2281 /* The unit is doomed. */
2283
2285 if ((flagless_killer
2289 unitcount++;
2290 }
2292
2293 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2294 if (vet) {
2296 }
2298 } else { /* Unitcount > 1 */
2299 int i;
2300 int slots = player_slot_count();
2301 int num_killed[slots];
2302 int num_escaped[slots];
2303 struct unit *other_killed[slots];
2304
2305 fc_assert(unitcount > 1);
2306
2307 /* Initialize */
2308 for (i = 0; i < slots; i++) {
2309 num_killed[i] = 0;
2310 other_killed[i] = NULL;
2311 num_escaped[i] = 0;
2312 }
2313
2314 /* Count killed units */
2316 struct player *vplayer = unit_owner(vunit);
2317
2320 escaped = FALSE;
2321
2324 && vunit->hp > 0
2325 && vunit->moves_left > pkiller->moves_left
2326 && fc_rand(2)) {
2327 int curr_def_bonus;
2328 int def_bonus = 0;
2329 struct tile *dsttile = NULL;
2330 int move_cost;
2331
2332 fc_assert(vunit->hp > 0);
2333
2335 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2336 && NULL == tile_city(ptile2)) {
2337 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2338 if (pkiller->moves_left <= vunit->moves_left - move_cost
2340 || unit_list_size(ptile2->units)) == 0) {
2342 vunit->utype);
2343 if (def_bonus <= curr_def_bonus) {
2345 dsttile = ptile2;
2346 }
2347 }
2348 }
2350
2351 if (dsttile != NULL) {
2354 NULL, NULL, dsttile,
2356 NULL, NULL)
2357 != NULL);
2358
2359 if (escaped) {
2361 unitcount--;
2362 }
2363 }
2364 }
2365
2366 if (!escaped) {
2368
2369 if (vunit != punit) {
2372 }
2373 }
2374 }
2376
2377 /* Inform the destroyer again if more than one unit was killed */
2378 if (unitcount > 1) {
2379 if (flagless_victim) {
2381 /* TRANS: "... Cannon ... Destroyer ...." */
2382 PL_("Your attacking %s succeeded against %s "
2383 "(and %d other unit)!",
2384 "Your attacking %s succeeded against %s "
2385 "(and %d other units)!", unitcount - 1),
2387 punit_link,
2388 unitcount - 1);
2389 } else {
2391 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2392 PL_("Your attacking %s succeeded against the %s %s "
2393 "(and %d other unit)!",
2394 "Your attacking %s succeeded against the %s %s "
2395 "(and %d other units)!", unitcount - 1),
2398 punit_link,
2399 unitcount - 1);
2400 }
2401 }
2402
2403 if (vet) {
2405 }
2406
2407 /* Inform the owners: this only tells about owned units that were killed.
2408 * there may have been 20 units who died but if only 2 belonged to the
2409 * particular player they'll only learn about those.
2410 *
2411 * Also if a large number of units die you don't find out what type
2412 * they all are. */
2413 for (i = 0; i < slots; i++) {
2414 if (num_killed[i] == 1) {
2415 if (i == player_index(pvictim)) {
2417
2418 if (flagless_killer) {
2421 /* TRANS: "Cannon ... Destroyer." */
2422 _("%s lost to an attack by %s."),
2423 punit_link,
2424 pkiller_link);
2425 } else {
2428 /* TRANS: "Cannon ... the Polish Destroyer." */
2429 _("%s lost to an attack by the %s %s."),
2430 punit_link,
2432 pkiller_link);
2433 }
2434 } else {
2436
2437 if (flagless_victim) {
2438 if (flagless_killer) {
2441 /* TRANS: "Cannon lost when Destroyer
2442 * attacked Musketeers." */
2443 _("%s lost when %s attacked %s."),
2446 punit_link);
2447 } else {
2450 /* TRANS: "Cannon lost when the Polish Destroyer
2451 * attacked Musketeers." */
2452 _("%s lost when the %s %s attacked %s."),
2456 punit_link);
2457 }
2458 } else {
2459 if (flagless_killer) {
2462 /* TRANS: "Cannon lost when Destroyer
2463 * attacked the German Musketeers." */
2464 _("%s lost when %s attacked the %s %s."),
2468 punit_link);
2469 } else {
2472 /* TRANS: "Cannon lost when the Polish Destroyer
2473 * attacked the German Musketeers." */
2474 _("%s lost when the %s %s attacked the %s %s."),
2479 punit_link);
2480 }
2481 }
2482 }
2483 } else if (num_killed[i] > 1) {
2484 if (i == player_index(pvictim)) {
2485 int others = num_killed[i] - 1;
2486
2487 if (others == 1) {
2488 if (flagless_killer) {
2491 /* TRANS: "Musketeers (and Cannon) lost to an
2492 * attack from Destroyer." */
2493 _("%s (and %s) lost to an attack from %s."),
2494 punit_link,
2496 pkiller_link);
2497 } else {
2500 /* TRANS: "Musketeers (and Cannon) lost to an
2501 * attack from the Polish Destroyer." */
2502 _("%s (and %s) lost to an attack from the %s %s."),
2503 punit_link,
2506 pkiller_link);
2507 }
2508 } else {
2509 if (flagless_killer) {
2512 /* TRANS: "Musketeers and 3 other units lost to
2513 * an attack from Destroyer."
2514 * (only happens with at least 2 other units) */
2515 PL_("%s and %d other unit lost to an attack "
2516 "from %s.",
2517 "%s and %d other units lost to an attack "
2518 "from %s.", others),
2519 punit_link,
2520 others,
2521 pkiller_link);
2522 } else {
2525 /* TRANS: "Musketeers and 3 other units lost to
2526 * an attack from the Polish Destroyer."
2527 * (only happens with at least 2 other units) */
2528 PL_("%s and %d other unit lost to an attack "
2529 "from the %s %s.",
2530 "%s and %d other units lost to an attack "
2531 "from the %s %s.", others),
2532 punit_link,
2533 others,
2535 pkiller_link);
2536 }
2537 }
2538 } else {
2539 if (flagless_victim) {
2540 if (flagless_killer) {
2543 /* TRANS: "2 units lost when Destroyer
2544 * attacked Musketeers."
2545 * (only happens with at least 2 other units) */
2546 PL_("%d unit lost when %s attacked %s.",
2547 "%d units lost when %s attacked %s.",
2548 num_killed[i]),
2549 num_killed[i],
2551 punit_link);
2552 } else {
2555 /* TRANS: "2 units lost when the Polish Destroyer
2556 * attacked Musketeers."
2557 * (only happens with at least 2 other units) */
2558 PL_("%d unit lost when the %s %s attacked %s.",
2559 "%d units lost when the %s %s attacked %s.",
2560 num_killed[i]),
2561 num_killed[i],
2564 punit_link);
2565 }
2566 } else {
2567 if (flagless_killer) {
2570 /* TRANS: "2 units lost when Destroyer
2571 * attacked the German Musketeers."
2572 * (only happens with at least 2 other units) */
2573 PL_("%d unit lost when %s attacked the %s %s.",
2574 "%d units lost when %s attacked the %s %s.",
2575 num_killed[i]),
2576 num_killed[i],
2579 punit_link);
2580 } else {
2583 /* TRANS: "2 units lost when the Polish Destroyer
2584 * attacked the German Musketeers."
2585 * (only happens with at least 2 other units) */
2586 PL_("%d unit lost when the %s %s attacked the %s %s.",
2587 "%d units lost when the %s %s attacked the %s %s.",
2588 num_killed[i]),
2589 num_killed[i],
2593 punit_link);
2594 }
2595 }
2596 }
2597 }
2598 }
2599
2600 /* Inform the owner of the units that escaped.
2601 * 'deftile' is the original tile they defended at, not where
2602 * they escaped to, as there might be multiple different tiles
2603 * different units escaped to. */
2604 for (i = 0; i < slots; i++) {
2605 if (0 < num_escaped[i]) {
2606 if (flagless_killer) {
2609 PL_("%d unit escaped from attack by %s",
2610 "%d units escaped from attack by %s",
2611 num_escaped[i]),
2612 num_escaped[i],
2613 pkiller_link);
2614 } else {
2617 PL_("%d unit escaped from attack by %s %s",
2618 "%d units escaped from attack by %s %s",
2619 num_escaped[i]),
2620 num_escaped[i],
2622 pkiller_link);
2623 }
2624 }
2625 }
2626
2627 /* Remove the units - note the logic of which units actually die
2628 * must be mimiced exactly in at least one place up above. */
2629 punit = NULL; /* Wiped during following iteration so unsafe to use */
2630
2635 }
2637 }
2638}
2639
2640/**********************************************************************/
2643void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2644{
2645 struct player *pvictim = unit_owner(punit);
2648 struct tile *deftile = unit_tile(punit);
2649 int unitcount, ransom;
2650
2651 /* The unit is doomed. */
2653
2656
2657 if (pvictim->economic.gold < ransom) {
2658 ransom = pvictim->economic.gold;
2659 }
2660
2662 PL_("%d Barbarian leader captured.",
2663 "%d Barbarian leaders captured.",
2664 unitcount),
2665 unitcount);
2667 PL_("%d gold ransom paid.",
2668 "%d gold ransom paid.",
2669 ransom),
2670 ransom);
2671 pvictor->economic.gold += ransom;
2672 pvictim->economic.gold -= ransom;
2673 send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */
2674
2675 if (vet) {
2677 }
2678
2681
2682 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2684 } else {
2685 int i;
2686 int slots = player_slot_count();
2687 int num_collected[slots];
2688
2689 fc_assert(unitcount > 1);
2690
2691 /* Initialize */
2692 for (i = 0; i < slots; i++) {
2693 num_collected[i] = 0;
2694 }
2695
2696 /* Count captured units */
2698 struct player *vplayer = unit_owner(vunit);
2699
2702
2703 for (i = 0; i < slots; i++) {
2704 if (num_collected[i] == 1) {
2707 _("%s %s collected ransom of %s."),
2710 } else if (num_collected[i] > 1) {
2713 PL_("%s %s collected ransom of %s and %d other unit.",
2714 "%s %s collected ransom of %s and %d other units.",
2715 num_collected[i] - 1),
2718 punit_link,
2719 num_collected[i] - 1);
2720 }
2721 }
2722
2726 }
2727}
2728
2729/**********************************************************************/
2733void package_unit(struct unit *punit, struct packet_unit_info *packet)
2734{
2735 packet->id = punit->id;
2736 packet->owner = player_number(unit_owner(punit));
2738 packet->tile = tile_index(unit_tile(punit));
2739 packet->facing = punit->facing;
2740 packet->homecity = punit->homecity;
2742 packet->upkeep[o] = punit->upkeep[o];
2744 packet->veteran = punit->veteran;
2746 packet->movesleft = punit->moves_left;
2747 packet->hp = punit->hp;
2748 packet->activity = punit->activity;
2750
2751 if (punit->activity_target != NULL) {
2753 } else {
2754 packet->activity_tgt = EXTRA_NONE;
2755 }
2756
2757 packet->changed_from = punit->changed_from;
2759
2760 if (punit->changed_from_target != NULL) {
2762 } else {
2763 packet->changed_from_tgt = EXTRA_NONE;
2764 }
2765
2767 packet->fuel = punit->fuel;
2768 packet->goto_tile = (NULL != punit->goto_tile
2769 ? tile_index(punit->goto_tile) : -1);
2770 packet->paradropped = punit->paradropped;
2771 packet->done_moving = punit->done_moving;
2772 packet->stay = punit->stay;
2773 packet->birth_turn = punit->birth_turn;
2775 if (!unit_transported(punit)) {
2776 packet->transported = FALSE;
2777 packet->transported_by = 0;
2778 } else {
2779 packet->transported = TRUE;
2781 }
2782 if (punit->carrying != NULL) {
2783 packet->carrying = goods_index(punit->carrying);
2784 } else {
2785 packet->carrying = -1;
2786 }
2787 packet->occupied = (get_transporter_occupancy(punit) > 0);
2788 packet->battlegroup = punit->battlegroup;
2789 packet->has_orders = punit->has_orders;
2790 if (punit->has_orders) {
2791 packet->orders_length = punit->orders.length;
2792 packet->orders_index = punit->orders.index;
2793 packet->orders_repeat = punit->orders.repeat;
2795 memcpy(packet->orders, punit->orders.list,
2796 punit->orders.length * sizeof(struct unit_order));
2797 } else {
2798 packet->orders_length = packet->orders_index = 0;
2799 packet->orders_repeat = packet->orders_vigilant = FALSE;
2800 /* No need to initialize array. */
2801 }
2802
2807}
2808
2809/**********************************************************************/
2815 struct packet_unit_short_info *packet,
2816 enum unit_info_use packet_use, int info_city_id)
2817{
2818 packet->packet_use = packet_use;
2819 packet->info_city_id = info_city_id;
2820
2821 packet->id = punit->id;
2822
2824 packet->owner = OWNER_NONE;
2825 } else {
2826 packet->owner = player_number(unit_owner(punit));
2827 }
2828
2829 packet->tile = tile_index(unit_tile(punit));
2830 packet->facing = punit->facing;
2831 packet->veteran = punit->veteran;
2833 packet->hp = punit->hp;
2834 packet->occupied = (get_transporter_occupancy(punit) > 0);
2836 || punit->activity == ACTIVITY_GOTO) {
2837 packet->activity = ACTIVITY_IDLE;
2838 } else {
2839 packet->activity = punit->activity;
2840 }
2841
2842 if (punit->activity_target == nullptr) {
2843 packet->activity_tgt = EXTRA_NONE;
2844 } else {
2846 }
2847
2848 /* Transported_by information is sent to the client even for units that
2849 * aren't fully known. Note that for non-allied players, any transported
2850 * unit can't be seen at all. For allied players we have to know if
2851 * transporters have room in them so that we can load units properly. */
2852 if (!unit_transported(punit)) {
2853 packet->transported = FALSE;
2854 packet->transported_by = 0;
2855 } else {
2856 packet->transported = TRUE;
2858 }
2859}
2860
2861/**********************************************************************/
2864void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2865{
2867 if (punit->server.moving != NULL) {
2868 /* Update status of 'pplayer' vision for 'punit'. */
2870 }
2871}
2872
2873/**********************************************************************/
2877void send_unit_info(struct conn_list *dest, struct unit *punit)
2878{
2879 const struct player *powner;
2880 struct packet_unit_info info;
2882 struct unit_move_data *pdata;
2883
2884 if (dest == NULL) {
2885 dest = game.est_connections;
2886 }
2887
2889
2891 package_unit(punit, &info);
2894
2895 conn_list_iterate(dest, pconn) {
2896 struct player *pplayer = conn_get_player(pconn);
2897
2898 /* Be careful to consider all cases where pplayer is NULL... */
2899 if (pplayer == NULL) {
2900 if (pconn->observer) {
2902 }
2903 } else if (pplayer == powner) {
2905 if (pdata != NULL) {
2906 BV_SET(pdata->can_see_unit, player_index(pplayer));
2907 }
2908 } else if (can_player_see_unit(pplayer, punit)) {
2910 if (pdata != NULL) {
2911 BV_SET(pdata->can_see_unit, player_index(pplayer));
2912 }
2913 }
2915}
2916
2917/**********************************************************************/
2922{
2923 conn_list_do_buffer(dest);
2924 conn_list_iterate(dest, pconn) {
2925 struct player *pplayer = pconn->playing;
2926
2927 if (NULL == pplayer && !pconn->observer) {
2928 continue;
2929 }
2930
2933 send_unit_info(dest, punit);
2936 }
2939 flush_packets();
2940}
2941
2942/**********************************************************************/
2949static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2950 const struct action *paction)
2951{
2952 struct city *pcity = NULL;
2953 int pop_loss;
2954
2955 pcity = tile_city(ptile);
2956
2958
2959 /* unit in a city may survive */
2961 continue;
2962 }
2964 _("Your %s was nuked by %s."),
2966 pplayer == unit_owner(punit)
2967 ? _("yourself")
2968 : nation_plural_for_player(pplayer));
2969 if (unit_owner(punit) != pplayer) {
2970 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2971 _("The %s %s was nuked."),
2974 }
2975 wipe_unit(punit, ULR_NUKE, pplayer);
2977
2978
2979 if (pcity) {
2980 struct player *owner = city_owner(pcity);
2981 char city_name[MAX_LEN_LINK];
2982
2984
2986 _("%s was nuked by %s."),
2987 city_name,
2988 pplayer == owner
2989 ? _("yourself")
2990 : nation_plural_for_player(pplayer));
2991
2992 if (owner != pplayer) {
2993 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2994 _("You nuked %s."),
2995 city_name);
2996 }
2997
2999 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
3000 /* Send city size reduction to everyone seeing it */
3002 } else {
3003 /* City was destroyed */
3005 _("%s was destroyed by the nuke."),
3006 city_name);
3007 if (owner != pplayer) {
3008 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
3009 _("Your nuke destroyed %s."),
3010 city_name);
3011 }
3012 }
3013 }
3014
3015 if (fc_rand(2) == 1) {
3016 struct extra_type *pextra;
3017
3018 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
3019 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
3020 tile_add_extra(ptile, pextra);
3021 update_tile_knowledge(ptile);
3022 }
3023 }
3024}
3025
3026/**********************************************************************/
3035 const struct unit_type *act_utype,
3036 struct player *pplayer, struct tile *ptile)
3037{
3040 &(const struct req_context) {
3041 .player = pplayer,
3042 /* City: Wait for users before choosing
3043 * home city or target tile city */
3044 .tile = ptile,
3045 .unittype = act_utype,
3046 .action = paction,
3047 },
3048 NULL,
3050
3052 do_nuke_tile(pplayer, ptile1, paction);
3054
3055 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
3056 API_TYPE_PLAYER, pplayer);
3058 _("The %s detonated a nuke!"),
3059 nation_plural_for_player(pplayer));
3060}
3061
3062/**********************************************************************/
3066bool do_airline(struct unit *punit, struct city *pdest_city,
3067 const struct action *paction)
3068{
3070
3073 _("%s transported successfully."),
3074 unit_link(punit));
3075
3078 /* Can only airlift to allied and domestic cities */
3079 FALSE, FALSE,
3080 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3082
3083 /* Update airlift fields. */
3085 psrc_city->airlift--;
3087 }
3089 pdest_city->airlift--;
3091 }
3092
3093 return TRUE;
3094}
3095
3096/**********************************************************************/
3099void do_explore(struct unit *punit)
3100{
3101 switch (manage_auto_explorer(punit)) {
3102 case MR_DEATH:
3103 /* don't use punit! */
3104 return;
3105 case MR_NOT_ALLOWED:
3106 /* Needed for something else */
3107 return;
3108 case MR_OK:
3109 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3110 * but don't count on this. See PR#39792.
3111 */
3113 break;
3114 }
3115
3117 default:
3119
3120 /* FIXME: When the manage_auto_explorer() call changes the activity from
3121 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3122 * alone. We reset it here. See PR#12931. */
3124 break;
3125 }
3126
3127 send_unit_info(NULL, punit); /* Probably duplicate */
3128}
3129
3130/**********************************************************************/
3135bool do_paradrop(struct unit *punit, struct tile *ptile,
3136 const struct action *paction)
3137{
3138 struct player *pplayer = unit_owner(punit);
3139 struct player *tgt_player = tile_owner(ptile);
3140 const struct unit_type *act_utype = unit_type_get(punit);
3141 const struct city *pcity;
3142
3143 /* Hard requirements */
3144 /* FIXME: hard requirements belong in common/actions's
3145 * is_action_possible() and the explanation texts belong in
3146 * server/unithand's action not enabled system (expl_act_not_enabl(),
3147 * ane_kind, explain_why_no_action_enabled(), etc)
3148 */
3149 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3150 /* Only take in account values from player map. */
3151 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3152
3153 if (NULL == plrtile->site) {
3154 bv_extras fbv;
3155
3156 dbv_to_bv(fbv.vec, &(plrtile->extras));
3157
3159 &fbv)) {
3160 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3161 _("This unit cannot paradrop into %s."),
3163 return FALSE;
3164 }
3165 }
3166
3167 if (NULL != plrtile->site
3168 && plrtile->owner != NULL
3169 && !pplayers_allied(pplayer, plrtile->owner)
3171 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3172 /* TRANS: Paratroopers ... Paradrop Unit */
3173 _("%s cannot conquer a city with \"%s\"."),
3176 return FALSE;
3177 }
3178
3179 if (NULL != plrtile->site
3180 && plrtile->owner != NULL
3181 && (pplayers_non_attack(pplayer, plrtile->owner)
3182 || (player_diplstate_get(pplayer, plrtile->owner)->type
3183 == DS_ALLIANCE)
3184 || (player_diplstate_get(pplayer, plrtile->owner)->type
3185 == DS_TEAM))
3187 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3188 _("Cannot attack unless you declare war first."));
3189 return FALSE;
3190 }
3191 }
3192
3193
3194 /* Kill the unit when the landing goes wrong. */
3195
3196 /* Safe terrain, really? Not transformed since player last saw it. */
3197 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3198 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3199 || !unit_could_load_at(punit, ptile))) {
3200 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3201 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3202 _("Your %s paradropped into the %s and was lost."),
3205 pplayer->score.units_lost++;
3207 return TRUE;
3208 }
3209
3210 pcity = tile_city(ptile);
3211
3212 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3214 || is_non_allied_unit_tile(ptile, pplayer,
3216 struct player *main_victim = NULL;
3217 struct player *secondary_victim = NULL;
3219
3220 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3221 unit_make_contact(punit, ptile, pplayer);
3222 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3223 _("Your %s was killed by enemy units at the "
3224 "paradrop destination."),
3226 /* TODO: Should defender score.units_killed get increased too?
3227 * What if there's units of several allied players? Should the
3228 * city owner or owner of the first/random unit get the kill? */
3229 pplayer->score.units_lost++;
3230
3231 if (pcity != NULL) {
3232 struct player *owner = city_owner(pcity);
3233
3234 if (!pplayers_at_war(pplayer, owner)) {
3236 } else {
3238 }
3239
3241 } else {
3243 }
3244
3245 if (main_victim == NULL) {
3246 unit_list_iterate(ptile->units, tgt) {
3247 struct player *owner = unit_owner(tgt);
3248
3249 if (!pplayers_at_war(pplayer, owner)) {
3251 break;
3252 } else if (secondary_victim == NULL) {
3254 }
3256
3257 if (main_victim == NULL) {
3258 /* There's no victim with whom the attacker isn't in war,
3259 * fallback to one with whom there's already a war. */
3261 }
3262 }
3263
3265 main_victim, ptile,
3266 victim_link);
3267
3269 return TRUE;
3270 }
3271
3272 /* All ok */
3274 if (unit_move(punit, ptile,
3275 /* Done by Action_Success_Actor_Move_Cost */
3276 0,
3277 NULL, BV_ISSET(paction->sub_results,
3281 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3282 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3283 /* Ensure we finished on valid state. */
3286 }
3287
3288 /* May cause an incident */
3290 ptile, tile_link(ptile));
3291
3292 return TRUE;
3293}
3294
3295/**********************************************************************/
3299static bool hut_get_limited(struct unit *punit)
3300{
3301 bool ok = TRUE;
3302 int hut_chance = fc_rand(12);
3303 struct player *pplayer = unit_owner(punit);
3304 const struct civ_map *nmap = &(wld.map);
3305
3306 /* 1 in 12 to get barbarians */
3307 if (hut_chance != 0) {
3308 int cred = 25;
3309
3311 PL_("You found %d gold.",
3312 "You found %d gold.", cred), cred);
3313 pplayer->economic.gold += cred;
3316 notify_player(pplayer, unit_tile(punit),
3318 _("An abandoned village is here."));
3319 } else {
3321 _("Your %s has been killed by barbarians!"),
3324 ok = FALSE;
3325 }
3326
3327 return ok;
3328}
3329
3330/**********************************************************************/
3334static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3335{
3336 struct player *pplayer = unit_owner(punit);
3337 int id = punit->id;
3338 struct tile *ptile = unit_tile(punit);
3339 bool hut = FALSE;
3340 const struct req_context context = {
3341 .player = pplayer,
3342 .tile = ptile,
3343 };
3344
3346 if (tile_has_extra(ptile, pextra)
3348 &(const struct req_context) {
3349 .player = tile_owner(ptile),
3350 },
3351 &pextra->rmreqs,
3353 ) {
3354 hut = TRUE;
3355 /* FIXME: are all enter-removes extras worth counting? */
3356 pplayer->server.huts++;
3357
3358 destroy_extra(ptile, pextra);
3360
3361 /* FIXME: enable different classes
3362 * to behave differently with different huts */
3363 if (frighten_hut) {
3364 script_server_signal_emit("hut_frighten", punit,
3365 extra_rule_name(pextra));
3366 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3367 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3369 } else {
3370 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3371 }
3372
3373 /* We need punit for the callbacks, can't continue if the unit died */
3374 if (!unit_is_alive(id)) {
3375 break;
3376 }
3377 }
3379
3380 if (hut) {
3381 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3382 }
3383 return;
3384}
3385
3386/**********************************************************************/
3390{
3391 bv_player can_see_unit;
3392
3395
3396 BV_CLR_ALL(can_see_unit);
3397 players_iterate(pplayer) {
3398 if (can_player_see_unit(pplayer, punit)) {
3399 BV_SET(can_see_unit, player_index(pplayer));
3400 }
3402
3404
3405 players_iterate(pplayer) {
3406 if (BV_ISSET(can_see_unit, player_index(pplayer))
3407 && !can_player_see_unit(pplayer, punit)) {
3408 unit_goes_out_of_sight(pplayer, punit);
3409 }
3411
3414}
3415
3416/**********************************************************************/
3420 struct unit *ptrans,
3421 bool force)
3422{
3423 bool had_cargo;
3424
3427
3429
3431
3432 if (!had_cargo) {
3433 /* Transport's loaded status changed */
3435 }
3436}
3437
3438/**********************************************************************/
3442{
3443 struct unit *ptrans;
3444
3446
3448
3450
3452
3455}
3456
3457/**********************************************************************/
3461static void autoattack_prob_free(struct autoattack_prob *prob)
3462{
3463 free(prob);
3464}
3465
3466/**********************************************************************/
3475static int compare_units(const struct autoattack_prob *const *p1,
3476 const struct autoattack_prob *const *q1)
3477{
3478 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3479 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3480
3481 /* Sort by transport depth first. This makes sure that no transport
3482 * attacks before its cargo does -- cargo sorts earlier in the list. */
3483 {
3484 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3485
3486 /* Walk the transport stacks in parallel, so as to bail out as soon as
3487 * one of them is empty (avoid walking deep stacks more often than
3488 * necessary). */
3489 while (p1trans && q1trans) {
3492 }
3493 if (!p1trans && q1trans) {
3494 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3495 * earlier in the list (p1 > q1). */
3496 return 1;
3497 } else if (p1trans && !q1trans) {
3498 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3499 return -1;
3500 }
3501 /* else same depth, so move on to checking win chance: */
3502 }
3503
3504 /* Put the units with the highest probability of success first. The up
3505 * side of this is that units with bonuses against the victim attacks
3506 * before other units. The downside is that strong units can be led
3507 * away by sacrificial units. */
3508 return (-1
3509 /* Assume the worst. */
3510 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3511}
3512
3513/**********************************************************************/
3518{
3519 struct autoattack_prob_list *autoattack;
3520 int moves = punit->moves_left;
3521 int sanity1 = punit->id;
3522 struct civ_map *nmap = &(wld.map);
3523
3524 if (!game.server.autoattack) {
3525 return TRUE;
3526 }
3527
3529
3530 /* Kludge to prevent attack power from dropping to zero during calc */
3532
3533 adjc_iterate(nmap, unit_tile(punit), ptile) {
3534 /* First add all eligible units to a autoattack list */
3535 unit_list_iterate(ptile->units, penemy) {
3537 struct tile *tgt_tile = unit_tile(punit);
3538
3539 fc_assert_action(tgt_tile, continue);
3540
3541 probability->prob =
3545 punit, NULL);
3546
3547 if (action_prob_possible(probability->prob)) {
3548 probability->unit_id = penemy->id;
3550 } else {
3552 }
3555
3556 /* Sort the potential attackers from highest to lowest success
3557 * probability. */
3558 if (autoattack_prob_list_size(autoattack) >= 2) {
3560 }
3561
3563 int sanity2 = penemy->id;
3564 struct tile *ptile = unit_tile(penemy);
3565 struct unit *enemy_defender = get_defender(nmap, punit, ptile, NULL);
3566 double punitwin, penemywin;
3567 double threshold = 0.25;
3568 struct tile *tgt_tile = unit_tile(punit);
3569
3571
3572 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3573 /* Don't leave city defenseless */
3574 threshold = 0.90;
3575 }
3576
3577 if (NULL != enemy_defender) {
3579 } else {
3580 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3581 punitwin = 1.0;
3582 }
3583
3584 /* Previous attacks may have changed the odds. Recalculate. */
3585 peprob->prob =
3589 punit, NULL);
3590
3591 if (!action_prob_possible(peprob->prob)) {
3592 /* No longer legal. */
3593 continue;
3594 }
3595
3596 /* Assume the worst. */
3598
3599 if ((penemywin > 1.0 - punitwin
3601 && penemywin > threshold) {
3602
3603#ifdef REALLY_DEBUG_THIS
3604 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3607 1.0 - punitwin, threshold);
3608#endif
3609
3614 } else {
3615#ifdef REALLY_DEBUG_THIS
3616 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3619 1.0 - punitwin, threshold);
3620#endif
3621 continue;
3622 }
3623
3626 }
3629 } else {
3630 autoattack_prob_list_destroy(autoattack);
3631 return FALSE; /* moving unit dead */
3632 }
3634
3635 autoattack_prob_list_destroy(autoattack);
3637 /* We could have lost movement in combat */
3640 return TRUE;
3641 } else {
3642 return FALSE;
3643 }
3644}
3645
3646/**********************************************************************/
3649static void cancel_orders(struct unit *punit, char *dbg_msg)
3650{
3653 log_debug("%s", dbg_msg);
3654}
3655
3656/**********************************************************************/
3661{
3662 bool alone_in_city;
3663
3664 if (NULL != tile_city(unit_tile(punit))) {
3665 int count = 0;
3666
3668 /* Consider only units not transported. */
3669 if (!unit_transported(aunit)) {
3670 count++;
3671 }
3673
3674 alone_in_city = (1 == count);
3675 } else {
3677 }
3678
3679 /* There may be sentried units with a sightrange > 3, but we don't
3680 wake them up if the punit is farther away than 3. */
3681 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3682 unit_list_iterate(ptile->units, penemy) {
3683 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3684 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3685
3687 && penemy->activity == ACTIVITY_SENTRY
3688 && radius_sq >= distance_sq
3689 /* If the unit moved on a city, and the unit is alone, consider
3690 * it is visible. */
3691 && (alone_in_city
3693 /* on board transport; don't awaken */
3697 }
3700
3701 /* Wakeup patrolling units we bump into.
3702 We do not wakeup units further away than 3 squares... */
3703 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3704 unit_list_iterate(ptile->units, ppatrol) {
3705 if (punit != ppatrol
3707 && ppatrol->orders.vigilant) {
3709 cancel_orders(ppatrol, " stopping because of nearby enemy");
3712 _("Orders for %s aborted after enemy movement was "
3713 "spotted."),
3715 }
3716 }
3719}
3720
3721/**********************************************************************/
3731 struct tile *src_tile,
3732 struct tile *dst_tile,
3733 bool passenger,
3735{
3736 struct city *fromcity = tile_city(src_tile);
3737 struct city *tocity = tile_city(dst_tile);
3738 struct city *homecity_start_pos = NULL;
3739 struct city *homecity_end_pos = NULL;
3745 const struct unit_type *type_end_pos = type_start_pos;
3748 int saved_id = punit->id;
3749 bool alive = TRUE;
3750 const struct civ_map *nmap = &(wld.map);
3751
3753 if (!passenger) {
3754 /* The unit that does the move may conquer. */
3756 }
3757
3758 /* Run for passengers too. A passenger may have been killed when its
3759 * transport conquered a city. (unit_conquer_city() can cause Lua code
3760 * to run) */
3761
3763 if (alive) {
3764 /* In case script has changed something about unit */
3768 }
3769 }
3770
3771 if (homecity_id_start_pos != 0) {
3773 }
3776 } else {
3778 }
3779
3780 /* We only do refreshes for non-AI players to now make sure the AI turns
3781 doesn't take too long. Perhaps we should make a special refresh_city
3782 functions that only refreshed happines. */
3783
3784 /* might have changed owners or may be destroyed */
3786
3787 if (tocity) { /* entering a city */
3788 if (tocity->owner == pplayer_end_pos) {
3792 }
3793 }
3794 if (homecity_start_pos) {
3796 }
3797 }
3798
3799 if (fromcity) { /* leaving a city */
3800 if (homecity_start_pos) {
3802 }
3804 && fromcity->owner == pplayer_start_pos
3808 }
3809 }
3810
3811 /* Entering/leaving a fortress or friendly territory */
3813 bool friendly_end = FALSE;
3814
3817 } else {
3819 type_end_pos);
3820
3821 if (max_friendliness_range >= 0
3824 } else {
3827
3828 if (max_friendliness_range >= 0
3831 }
3832 }
3833 }
3834
3835 if (friendly_end) {
3838 }
3839 }
3840
3844 }
3851 }
3852
3854 sync_cities();
3855
3856 return alive;
3857}
3858
3859/**********************************************************************/
3863static void check_unit_activity(struct unit *punit)
3864{
3865 switch (punit->activity) {
3866 case ACTIVITY_IDLE:
3867 case ACTIVITY_SENTRY:
3868 case ACTIVITY_EXPLORE:
3869 case ACTIVITY_GOTO:
3870 break;
3871 case ACTIVITY_CLEAN:
3872 case ACTIVITY_MINE:
3873 case ACTIVITY_IRRIGATE:
3874 case ACTIVITY_CULTIVATE:
3875 case ACTIVITY_PLANT:
3876 case ACTIVITY_FORTIFIED:
3877 case ACTIVITY_PILLAGE:
3878 case ACTIVITY_TRANSFORM:
3880 case ACTIVITY_BASE:
3881 case ACTIVITY_GEN_ROAD:
3882 case ACTIVITY_CONVERT:
3883 case ACTIVITY_LAST:
3885 break;
3886 };
3887}
3888
3889/**********************************************************************/
3893 const struct tile *psrctile,
3894 const struct tile *pdesttile)
3895{
3896 struct unit_move_data *pdata;
3897 struct player *powner = unit_owner(punit);
3898
3899 if (punit->server.moving) {
3900 /* Recursive moving (probably due to a script). */
3902 pdata->ref_count++;
3903 fc_assert_msg(pdata->punit == punit,
3904 "Unit number %d (%p) was going to die, but "
3905 "server attempts to move it.",
3906 punit->id, punit);
3907 fc_assert_msg(pdata->old_vision == NULL,
3908 "Unit number %d (%p) has done an incomplete move.",
3909 punit->id, punit);
3910 } else {
3911 pdata = fc_malloc(sizeof(*pdata));
3912 pdata->ref_count = 1;
3913 pdata->punit = punit;
3915 BV_CLR_ALL(pdata->can_see_unit);
3916 }
3917 pdata->powner = powner;
3918 BV_CLR_ALL(pdata->can_see_move);
3919 pdata->old_vision = punit->server.vision;
3920
3921 return pdata;
3922}
3923
3924/**********************************************************************/
3928 const struct tile *psrctile,
3929 struct tile *pdesttile)
3930{
3931 struct vision *new_vision;
3932 struct unit *punit = pdata->punit;
3934 const v_radius_t radius_sq
3938
3939 /* Remove unit from the source tile. */
3941
3942#ifndef FREECIV_NDEBUG
3943 bool success =
3944#endif
3947
3948 /* Set new tile. */
3951
3952 if (unit_transported(punit)) {
3953 /* Silently free orders since they won't be applicable anymore. */
3955 }
3956
3957 /* Check unit activity. */
3961
3962 /* We first unfog the destination, then send the move,
3963 * and then fog the old territory. This means that the player
3964 * gets a chance to see the newly explored territory while the
3965 * client moves the unit, and both areas are visible during the
3966 * move */
3967
3968 /* Enhance vision if unit steps into a fortress */
3971 vision_change_sight(new_vision, radius_sq);
3973}
3974
3975/**********************************************************************/
3979{
3981 fc_assert_ret(pdata->ref_count > 0);
3982 fc_assert_msg(pdata->old_vision == NULL,
3983 "Unit number %d (%p) has done an incomplete move.",
3984 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3985
3986 pdata->ref_count--;
3987 if (pdata->ref_count == 0) {
3988 if (pdata->punit != NULL) {
3989 fc_assert(pdata->punit->server.moving == pdata);
3990 pdata->punit->server.moving = NULL;
3991 }
3992 free(pdata);
3993 }
3994}
3995
3996/**********************************************************************/
4000 const struct tile *psrctile,
4001 struct tile *pdesttile,
4002 bool adj)
4003{
4006 struct unit_move_data *pdata;
4007
4008 /* Make new data for 'punit'. */
4011
4012 /* Add all contained units. */
4014 struct unit_move_data *cargo_data;
4015
4019
4020 /* Determine the players able to see the move(s), now that the player
4021 * vision has been increased. */
4022 if (adj) {
4023 /* Main unit for adjacent move: the move is visible for every player
4024 * able to see on the matching unit layer. */
4025 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
4026
4030 BV_SET(pdata->can_see_unit, player_index(oplayer));
4031 BV_SET(pdata->can_see_move, player_index(oplayer));
4032 }
4034 }
4035
4037
4039
4040 if (adj && pmove_data->punit == punit) {
4041 /* If positions are adjacent, we have already handled 'punit'. See
4042 * above. */
4043 continue;
4044 }
4045
4047 if ((adj
4049 pmove_data != pdata))
4051 pmove_data != pdata)) {
4052 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4053 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4054 }
4056 pmove_data != pdata)) {
4057 /* The unit was seen with its source tile even if it was
4058 * teleported. */
4059 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4060 }
4063
4064 return plist;
4065}
4066
4067/**********************************************************************/
4078bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
4079 struct unit *embark_to, bool find_embark_target,
4081 bool enter_hut, bool frighten_hut)
4082{
4083 struct player *pplayer;
4084 struct tile *psrctile;
4085 struct city *psrccity;
4086 struct city *pdestcity;
4087 struct unit *ptransporter;
4090 struct unit_move_data_list *plist;
4091 struct unit_move_data *pdata;
4092 int saved_id;
4093 bool unit_lives;
4094 bool adj;
4095 enum direction8 facing;
4096
4097 /* Some checks. */
4100
4101 pplayer = unit_owner(punit);
4102 saved_id = punit->id;
4105
4107
4108 /* Unload the unit if on a transport. */
4110 if (ptransporter != NULL) {
4111 /* Unload unit _before_ setting the new tile! */
4113 /* Send updated information to anyone watching that transporter
4114 * was unloading cargo. */
4116 }
4117
4118 /* Wakup units next to us before we move. */
4120
4121 /* Make info packets at 'psrctile'. */
4122 if (adj) {
4123 /* If tiles are adjacent, we will show the move to users able
4124 * to see it. */
4127 }
4128
4129 /* Set unit orientation */
4130 if (adj) {
4131 /* Only change orientation when moving to adjacent tile */
4132 punit->facing = facing;
4133 }
4134
4136
4137 /* Move magic. */
4138 punit->moved = TRUE;
4139 punit->moves_left = MAX(0, punit->moves_left - move_cost);
4140 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
4141 /* The next order may not require any remaining move fragments. */
4143 }
4144
4145 /* No longer relevant. */
4148
4149 /* Claim ownership of fortress? */
4152 /* Yes. We claim *all* bases if there's *any* claimable base(s).
4153 * Even if original unit cannot claim other kind of bases, the
4154 * first claimed base will have influence over other bases,
4155 * or something like that. */
4156 tile_claim_bases(pdesttile, pplayer);
4157 }
4158
4160 fc_assert(pdata->punit == punit);
4161
4162 /* Check timeout settings. */
4165
4166 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4167 * if they are ever seen. */
4169 /* Increase the timeout if an enemy unit moves and the
4170 * timeoutaddenemymove setting is in use. */
4171 if (penemy->is_connected
4172 && pplayer != penemy
4173 && pplayers_at_war(pplayer, penemy)
4174 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4176 break;
4177 }
4179
4182 }
4183 }
4184
4186 /* The unit can perform an action to the city at the destination tile.
4187 * A long distance move (like an airlift) doesn't ask what action to
4188 * perform before moving. Ask now. */
4189
4192 }
4193
4194 /* Notifications of the move to the clients. */
4195 if (adj) {
4196 /* Special case: 'punit' is moving to adjacent position. Then we show
4197 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4198
4199 /* Make info packets at 'pdesttile'. */
4202
4205
4206 if (aplayer == NULL) {
4207 if (pconn->observer) {
4208 /* Global observers see all... */
4211 }
4212 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4213 if (aplayer == pplayer) {
4216 } else {
4219 }
4220 }
4222 }
4223
4224 /* Other moves. */
4226 if (adj && pmove_data == pdata) {
4227 /* If positions are adjacent, we have already shown 'punit' move.
4228 * See above. */
4229 continue;
4230 }
4231
4232 /* Make info packets at 'pdesttile'. */
4236
4239
4240 if (aplayer == NULL) {
4241 if (pconn->observer) {
4242 /* Global observers see all... */
4244 }
4245 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4246 if (aplayer == pmove_data->powner) {
4248 } else {
4250 }
4251 }
4254
4255 /* Clear old vision. */
4257 if (pmove_data->old_vision != NULL) {
4258 vision_clear_sight(pmove_data->old_vision);
4259 vision_free(pmove_data->old_vision);
4260 pmove_data->old_vision = NULL;
4261 }
4263
4264 /* Move consequences. */
4266 struct unit *aunit = pmove_data->punit;
4267
4268 if (aunit != NULL
4269 && unit_owner(aunit) == pmove_data->powner
4270 && unit_tile(aunit) == pdesttile) {
4272 pdata != pmove_data,
4274 }
4276
4277 unit_lives = (pdata->punit == punit);
4278
4279 /* Wakeup units and make contact. */
4280 if (unit_lives) {
4282 }
4284
4285 if (unit_lives) {
4286 /* Special checks for ground units in the ocean. */
4288 if (embark_to != NULL) {
4290 } else if (find_embark_target) {
4291 /* TODO: Consider to stop supporting find_embark_target and make all
4292 * callers that wants auto loading set embark_to. */
4294 } else {
4296 }
4297 if (ptransporter) {
4299
4300 /* Set activity to sentry if boarding a ship. */
4301 if (is_human(pplayer)
4306 }
4307
4309 }
4310 }
4311 }
4312
4313 /* Remove units going out of sight. */
4315 struct unit *aunit = pmove_data->punit;
4316
4317 if (aunit == NULL) {
4318 continue; /* Died! */
4319 }
4320
4322 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4325 }
4328
4329 /* Inform the owner's client about actor unit arrival. Can, depending on
4330 * the client settings, cause the client to start the process that makes
4331 * the action selection dialog pop up. */
4333 if (pdestcity != NULL) {
4334 /* Arrival in a city counts. */
4335
4337 struct unit *ptrans;
4338 bool ok;
4339 struct unit *act_unit;
4340 struct player *act_player;
4341
4342 act_unit = pmove_data->punit;
4344
4345 if (act_unit == NULL
4346 || !unit_is_alive(act_unit->id)) {
4347 /* The unit died before reaching this point. */
4348 continue;
4349 }
4350
4351 if (unit_tile(act_unit) != pdesttile) {
4352 /* The unit didn't arrive at the destination tile. */
4353 continue;
4354 }
4355
4356 if (!is_human(act_player)) {
4357 /* Only humans need reminders. */
4358 continue;
4359 }
4360
4361 if (!unit_transported(act_unit)) {
4362 /* Don't show the action selection dialog again. Non transported
4363 * units are handled before they move to the tile. */
4364 continue;
4365 }
4366
4367 /* Open action dialog only if 'act_unit' and all its transporters
4368 * (recursively) don't have orders. */
4370 /* The unit it self has orders. */
4371 continue;
4372 }
4373
4376 if (NULL == ptrans) {
4377 /* No (recursive) transport has orders. */
4378 ok = TRUE;
4379 break;
4380 } else if (unit_has_orders(ptrans)) {
4381 /* A unit transporting the unit has orders */
4382 ok = FALSE;
4383 break;
4384 }
4385 }
4386
4387 if (!ok) {
4388 /* A unit transporting act_unit has orders. */
4389 continue;
4390 }
4391
4393 /* There is a valid target. */
4394
4395 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4396 act_unit->action_decision_tile = pdesttile;
4397
4398 /* Let the client know that this unit wants the player to decide
4399 * what to do. */
4401 }
4403 }
4404
4406 /* Check cities at source and destination. */
4408 if (psrccity != NULL) {
4410 }
4411 if (pdestcity != NULL) {
4413 }
4414
4415 if (unit_lives) {
4416 /* Let the scripts run ... */
4419 }
4420
4421 if (unit_lives) {
4422 /* Autoattack. */
4424 }
4425
4426 if (unit_lives && (enter_hut || frighten_hut)) {
4427 /* Is there a hut? */
4431 }
4432
4434
4435 if (unit_lives) {
4436 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4437 }
4438
4439 return unit_lives;
4440}
4441
4442/**********************************************************************/
4446 struct tile *ptile)
4447{
4448 struct player *owner = unit_owner(punit);
4449
4450 return (is_non_allied_unit_tile(ptile, owner,
4452 || is_non_allied_city_tile(ptile, owner));
4453}
4454
4455/**********************************************************************/
4462{
4463 bool cancel = FALSE;
4464 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4465 struct player *pplayer = unit_owner(punit);
4466
4467 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4468 struct unit *penemy = tile_non_allied_unit(ptile, pplayer,
4470 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4471
4472 if ((penemy && can_player_see_unit(pplayer, penemy))
4474 && pdcity->occupied)) {
4475 cancel = TRUE;
4476 break;
4477 }
4479
4480 return cancel;
4481}
4482
4483/**********************************************************************/
4491static inline bool player_is_watching(struct unit *punit, const bool fresh)
4492{
4493 /* The player just sent the orders to the unit. The unit has moves left.
4494 * It is therefore safe to assume that the player already is paying
4495 * attention to the unit. */
4496 return fresh && punit->moves_left > 0;
4497}
4498
4499/**********************************************************************/
4518bool execute_orders(struct unit *punit, const bool fresh)
4519{
4520 struct act_prob prob;
4521 bool performed;
4522 const char *name;
4523 bool res, last_order;
4524 int unitid = punit->id;
4525 struct player *pplayer = unit_owner(punit);
4526 int moves_made = 0;
4527 const struct civ_map *nmap = &(wld.map);
4528
4530
4531 if (punit->activity != ACTIVITY_IDLE) {
4532 /* Unit's in the middle of an activity; wait for it to finish. */
4534 return TRUE;
4535 }
4536
4537 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4538
4539 /* Any time the orders are canceled we should give the player a message. */
4540
4541 while (TRUE) {
4542 struct unit_order order;
4543
4544 struct action *oaction;
4545
4546 struct tile *dst_tile;
4547 struct city *tgt_city;
4548 struct unit *tgt_unit;
4549 int tgt_id;
4550 int sub_tgt_id;
4551 struct extra_type *pextra;
4552
4553 if (punit->done_moving) {
4554 log_debug(" stopping because we're done this turn");
4555 return TRUE;
4556 }
4557
4559 /* "Patrol" orders are stopped if an enemy is near. */
4560 cancel_orders(punit, " stopping because of nearby enemy");
4562 _("Orders for %s aborted as there are units nearby."),
4563 unit_link(punit));
4564 return TRUE;
4565 }
4566
4567 if (moves_made == punit->orders.length) {
4568 /* For repeating orders, don't repeat more than once per turn. */
4569 log_debug(" stopping because we ran a round");
4572 return TRUE;
4573 }
4574 moves_made++;
4575
4576 order = punit->orders.list[punit->orders.index];
4577
4578 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4579 * this far. */
4581 || action_id_exists(order.action)),
4582 continue);
4583
4584 switch (order.order) {
4585 case ORDER_MOVE:
4586 case ORDER_ACTION_MOVE:
4587 case ORDER_FULL_MP:
4588 if (0 == punit->moves_left) {
4589 log_debug(" stopping because of no more move points");
4590 return TRUE;
4591 }
4592 break;
4595 log_debug(" stopping. Not enough move points this turn");
4596 return TRUE;
4597 }
4598 break;
4599 case ORDER_ACTIVITY:
4600 case ORDER_LAST:
4601 /* Those actions don't require moves left. */
4602 break;
4603 }
4604
4606 && punit->orders.index + 1 == punit->orders.length);
4607
4608 if (last_order) {
4609 /* Clear the orders before we engage in the move. That way any
4610 * has_orders checks will yield FALSE and this will be treated as
4611 * a normal move. This is important: for instance a caravan goto
4612 * will popup the caravan dialog on the last move only. */
4614 }
4615
4616 /* Advance the orders one step forward. This is needed because any
4617 * updates sent to the client as a result of the action should include
4618 * the new index value. Note that we have to send_unit_info() somewhere
4619 * after this point so that the client is properly updated. */
4620 punit->orders.index++;
4621
4622 switch (order.order) {
4623 case ORDER_FULL_MP:
4625 /* If the unit doesn't have full MP then it just waits until the
4626 * next turn. We assume that the next turn it will have full MP
4627 * (there's no check for that). */
4629 log_debug(" waiting this turn");
4631 }
4632 break;
4633 case ORDER_ACTIVITY:
4634 {
4635 enum unit_activity activity = order.activity;
4636
4637 fc_assert(activity == ACTIVITY_SENTRY);
4638
4639 if (can_unit_do_activity(nmap, punit, activity)) {
4641 set_unit_activity(punit, activity, order.action);
4643
4644 break;
4645 }
4646 }
4647
4648 cancel_orders(punit, " orders canceled because of failed activity");
4650 _("Orders for %s aborted since they "
4651 "give an invalid activity."),
4652 unit_link(punit));
4653 return TRUE;
4654 case ORDER_MOVE:
4655 case ORDER_ACTION_MOVE:
4656 /* Move unit */
4657 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4658 cancel_orders(punit, " move order sent us to invalid location");
4660 _("Orders for %s aborted since they "
4661 "give an invalid location."),
4662 unit_link(punit));
4663 return TRUE;
4664 }
4665
4666 if (order.order != ORDER_ACTION_MOVE
4668 /* Plain move required: no attack, trade route etc. */
4669 cancel_orders(punit, " orders canceled because of enemy");
4671 _("Orders for %s aborted as there "
4672 "are units in the way."),
4673 unit_link(punit));
4674 return TRUE;
4675 }
4676
4677 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4679 order.order != ORDER_ACTION_MOVE);
4680 if (!player_unit_by_number(pplayer, unitid)) {
4681 log_debug(" unit died while moving.");
4682 /* A player notification should already have been sent. */
4683 return FALSE;
4684 }
4685
4686 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4687 /* Movement succeeded but unit didn't move. */
4688 log_debug(" orders resulted in combat.");
4690 return TRUE;
4691 }
4692
4693 if (!res) {
4694 fc_assert(0 <= punit->moves_left);
4695
4696 /* Movement failed (ZOC, etc.) */
4697 cancel_orders(punit, " attempt to move failed.");
4698
4700 /* The final move "failed" because the unit needs to ask the
4701 * player what action it should take.
4702 *
4703 * The action decision request notifies the player. Its
4704 * location at the unit's last order makes it clear to the
4705 * player who the decision is for. ("The Spy I sent to Berlin
4706 * has arrived.")
4707 *
4708 * A notification message is therefore redundant. */
4709 && !(last_order
4712 /* The player may have missed this. No one else will announce it
4713 * in a satisfying manner. Inform the player. */
4714 notify_player(pplayer, unit_tile(punit),
4716 _("Orders for %s aborted because of failed move."),
4717 unit_link(punit));
4718 }
4719
4720 return TRUE;
4721 }
4722 break;
4725
4726 /* Checked in unit_order_list_is_sane() */
4727 fc_assert_action(oaction != NULL, continue);
4728
4729 log_debug(" orders: doing action %s", action_rule_name(oaction));
4730
4731 dst_tile = index_to_tile(&(wld.map), order.target);
4732
4733 if (dst_tile == NULL) {
4734 /* Could be at the edge of the map while trying to target a tile
4735 * outside of it. */
4736
4737 cancel_orders(punit, " target location doesn't exist");
4739 order.action, dst_tile, NULL, NULL);
4740
4741 return TRUE;
4742 }
4743
4744 /* Get the target city from the target tile. */
4746
4747 if (tgt_city == NULL
4749 /* This action targets a city but no city target was found. */
4750
4751 cancel_orders(punit, " perform action vs city with no city");
4753 order.action, dst_tile, tgt_city, NULL);
4754
4755 return TRUE;
4756 }
4757
4758 /* Get a target unit at the target tile. */
4760
4761 if (tgt_unit == NULL
4763 /* This action targets a unit but no target unit was found. */
4764
4765 cancel_orders(punit, " perform action vs unit with no unit");
4767 order.action, dst_tile, tgt_city, tgt_unit);
4768
4769 return TRUE;
4770 }
4771
4772 /* Server side sub target assignment */
4773 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4774 && order.sub_target == NO_TARGET) {
4775 /* Try to find a sub target. */
4777 } else {
4778 /* The client should have specified a sub target if needed */
4779 sub_tgt_id = order.sub_target;
4780 }
4781
4782 /* Get a target extra at the target tile */
4783 pextra = (sub_tgt_id == NO_TARGET ?
4784 NULL :
4785 extra_by_number(sub_tgt_id));
4786
4788 && pextra != NULL
4789 && actres_creates_extra(oaction->result, pextra)
4790 && tile_has_extra(dst_tile, pextra)) {
4791 /* Already there. Move on to the next order. */
4792 break;
4793 }
4794
4796 && pextra != NULL
4797 && actres_removes_extra(oaction->result, pextra)
4798 && !tile_has_extra(dst_tile, pextra)) {
4799 /* Already not there. Move on to the next order. */
4800 break;
4801 }
4802
4803 /* No target selected. */
4804 tgt_id = -1;
4805
4806 /* Assume impossible until told otherwise. */
4807 prob = ACTPROB_IMPOSSIBLE;
4808
4809 switch (action_id_get_target_kind(order.action)) {
4810 case ATK_STACK:
4811 prob = action_prob_vs_stack(nmap, punit, order.action,
4812 dst_tile);
4813 tgt_id = dst_tile->index;
4814 break;
4815 case ATK_TILE:
4816 prob = action_prob_vs_tile(nmap, punit, order.action,
4817 dst_tile, pextra);
4818 tgt_id = dst_tile->index;
4819 break;
4820 case ATK_EXTRAS:
4821 prob = action_prob_vs_extras(nmap, punit, order.action,
4822 dst_tile, pextra);
4823 tgt_id = dst_tile->index;
4824 break;
4825 case ATK_CITY:
4826 prob = action_prob_vs_city(nmap, punit, order.action,
4827 tgt_city);
4828 tgt_id = tgt_city->id;
4829 break;
4830 case ATK_UNIT:
4831 prob = action_prob_vs_unit(nmap, punit, order.action,
4832 tgt_unit);
4833
4834 tgt_id = tgt_unit->id;
4835 break;
4836 case ATK_SELF:
4837 prob = action_prob_self(nmap, punit, order.action);
4838
4839 tgt_id = unitid;
4840 break;
4841 case ATK_COUNT:
4842 log_error("Invalid action target kind");
4843
4844 /* The check below will abort and cancel the orders because prob
4845 * was initialized to impossible above this switch statement. */
4846
4847 break;
4848 }
4849
4850 if (!action_prob_possible(prob)) {
4851 /* The player has enough information to know that this action is
4852 * against the rules. Don't risk any punishment by trying to
4853 * perform it. */
4854
4855 cancel_orders(punit, " illegal action");
4857 _("%s could not do %s to %s."),
4861
4862 /* Try to explain what rule made it illegal. */
4864 order.action, dst_tile, tgt_city, tgt_unit);
4865
4866 return TRUE;
4867 }
4868
4870 /* This action needs a name. */
4872 } else {
4873 /* This action doesn't need a name. */
4874 name = "";
4875 }
4876
4878 unitid,
4879 tgt_id,
4880 sub_tgt_id,
4881 name,
4882 order.action,
4884
4885 if (!player_unit_by_number(pplayer, unitid)) {
4886 /* The unit "died" while performing the action. */
4887 return FALSE;
4888 }
4889
4890 if (!performed) {
4891 /* The action wasn't performed as ordered. */
4892
4893 cancel_orders(punit, " failed action");
4895 _("Orders for %s aborted because "
4896 "doing %s to %s failed."),
4900
4901 return TRUE;
4902 }
4903
4904 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4906 /* Done at turn change. */
4909 break;
4910 }
4911
4912 break;
4913 case ORDER_LAST:
4914 /* Should be caught when loading the unit orders from the savegame or
4915 * when receiving the unit orders from the client. */
4916 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4917 cancel_orders(punit, " invalid order!");
4919 _("Your %s has invalid orders."),
4920 unit_link(punit));
4921 return TRUE;
4922 }
4923
4924 if (last_order) {
4926 log_debug(" stopping because orders are complete");
4927 return TRUE;
4928 }
4929
4930 if (punit->orders.index == punit->orders.length) {
4932 /* Start over. */
4933 log_debug(" repeating orders.");
4934 punit->orders.index = 0;
4935 }
4936 } /* end while */
4937}
4938
4939/**********************************************************************/
4946static int get_unit_vision_base(const struct unit *punit,
4947 enum vision_layer vlayer,
4948 const int base)
4949{
4950 switch (vlayer) {
4951 case V_MAIN:
4952 return MAX(0, base);
4953 case V_INVIS:
4954 case V_SUBSURFACE:
4955 return CLIP(0, base, 2);
4956 case V_COUNT:
4957 break;
4958 }
4959
4960 log_error("Unsupported vision layer variant: %d.", vlayer);
4961
4962 return 0;
4963}
4964
4965/**********************************************************************/
4968static int unit_vision_range_modifiers(const struct unit *punit,
4969 const struct tile *ptile)
4970{
4971 const struct unit_type *utype = unit_type_get(punit);
4972
4973 return (utype->vision_radius_sq
4975 &(const struct req_context) {
4976 .player = unit_owner(punit),
4977 .tile = ptile,
4978 .unittype = utype,
4979 .unit = punit,
4980 },
4982}
4983
4984/**********************************************************************/
4991int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
4992 enum vision_layer vlayer)
4993{
4996}
4997
4998/**********************************************************************/
5005{
5006 struct vision *uvision = punit->server.vision;
5007 const struct tile *utile = unit_tile(punit);
5008 int mod = unit_vision_range_modifiers(punit, utile);
5009 const v_radius_t radius_sq
5013
5014 vision_change_sight(uvision, radius_sq);
5016}
5017
5018/**********************************************************************/
5027
5028/**********************************************************************/
5033{
5034 time_t dt;
5035
5036 if (!punit) {
5037 return FALSE;
5038 }
5039
5040 if (game.server.unitwaittime <= 0) {
5041 return TRUE;
5042 }
5043
5044 if (punit->server.action_turn != game.info.turn - 1) {
5045 return TRUE;
5046 }
5047
5048 dt = time(NULL) - punit->server.action_timestamp;
5049 if (dt < game.server.unitwaittime) {
5050 char buf[64];
5053 ftc_server, _("Your unit may not act for another %s "
5054 "this turn. See /help unitwaittime."), buf);
5055 return FALSE;
5056 }
5057
5058 return TRUE;
5059}
5060
5061/**********************************************************************/
5066{
5067 if (!punit) {
5068 return;
5069 }
5070
5073}
5074
5075/**********************************************************************/
5081{
5082 /* check if there is enemy nearby */
5083 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
5085 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
5086 return FALSE;
5087 }
5088 }
5090
5091 return TRUE;
5092}
5093
5094/**********************************************************************/
5097void random_movements(struct player *pplayer)
5098{
5099 const struct civ_map *nmap = &(wld.map);
5100
5101 game.server.random_move_time = pplayer;
5102
5105 bool moved = TRUE;
5106 struct tile *curtile = unit_tile(punit);
5107 int id = punit->id;
5108
5109 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
5110 /*
5111 * List of all 8 directions
5112 */
5113 enum direction8 dirs[8] = {
5116 };
5117 int n;
5118
5119 moved = FALSE;
5120
5121 for (n = 8; n > 0 && !moved; n--) {
5122 enum direction8 choice = (enum direction8) fc_rand(n);
5123 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
5124
5125 if (dest != NULL) {
5127 dest))) {
5128 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
5130 moved = TRUE;
5131 break;
5132 }
5133 }
5134
5135 if (!moved) {
5137 NULL)) {
5138 if (unit_perform_action(pplayer, id, tile_index(dest),
5140 ACT_REQ_RULES)) {
5141 moved = TRUE;
5142 }
5144 punit, dest, NULL)) {
5145 if (unit_perform_action(pplayer, id, tile_index(dest),
5147 ACT_REQ_RULES)) {
5148 moved = TRUE;
5149 }
5151 punit, dest, NULL)) {
5152 if (unit_perform_action(pplayer, id, tile_index(dest),
5154 ACT_REQ_RULES)) {
5155 moved = TRUE;
5156 }
5157 }
5158 }
5159 }
5160
5161 if (!moved) {
5162 /* Choice was bad, so replace it with the last direction
5163 * in the list. On the next iteration, one fewer choice
5164 * will remain. */
5165 dirs[choice] = dirs[n - 1];
5166 }
5167 }
5168 }
5169 }
5171
5173}
5174
5175/**********************************************************************/
5180void unit_make_contact(const struct unit *punit,
5181 struct tile *ptile, struct player *pplayer) {
5182 fc_assert_ret(punit != nullptr);
5183
5185 return; /* Flagless unit can't make contact */
5186 }
5187
5188 maybe_make_contact(ptile ? ptile : unit_tile(punit),
5189 pplayer ? pplayer : unit_owner(punit));
5190}
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:5569
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1250
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5091
const char * action_name_translation(const struct action *paction)
Definition actions.c:1230
struct act_prob action_prob_vs_tile(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:4612
const char * action_rule_name(const struct action *action)
Definition actions.c:1216
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1119
bool is_action_enabled_unit_on_tile(const struct civ_map *nmap, const action_id wanted_action, const struct unit *actor_unit, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:3332
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:4695
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:4765
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:4254
bool action_id_exists(const action_id act_id)
Definition actions.c:1068
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5151
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:4529
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:3481
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:4337
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5202
static struct action * action_by_number(action_id act_id)
Definition actions.h:396
#define action_has_result(_act_, _res_)
Definition actions.h:180
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:437
#define ACTPROB_IMPOSSIBLE
Definition actions.h:687
#define action_id_get_target_kind(act_id)
Definition actions.h:413
#define action_id_has_result_safe(act_id, result)
Definition actions.h:426
#define ACTION_NONE
Definition actions.h:55
void action_consequence_complete(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
void action_consequence_caught(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct act_prob action_auto_perf_unit_prob(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
const struct action * action_auto_perf_unit_do(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
void action_consequence_success(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
bool actres_removes_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:810
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:789
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
void dbv_to_bv(unsigned char *dest, const struct dbv *src)
Definition bitvector.c:227
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
bool is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile, int distance)
Definition city.c:2092
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
bool city_exists_within_max_city_map(const struct civ_map *nmap, const struct tile *ptile, bool may_be_on_center)
Definition city.c:2112
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:767
#define city_list_iterate(citylist, pcity)
Definition city.h:505
#define city_tile(_pcity_)
Definition city.h:561
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:731
static citizens city_size_get(const struct city *pcity)
Definition city.h:566
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:743
#define output_type_iterate(output)
Definition city.h:842
#define city_owner(_pcity_)
Definition city.h:560
#define city_list_iterate_end
Definition city.h:507
#define output_type_iterate_end
Definition city.h:848
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3342
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:458
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2368
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Definition citytools.c:856
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2220
void sync_cities(void)
Definition citytools.c:3351
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1992
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3165
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:762
bool city_refresh(struct city *pcity)
Definition cityturn.c:158
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:480
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:86
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:994
int get_virtual_defense_power(const struct civ_map *nmap, const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, struct tile *ptile, bool fortified, int veteran)
Definition combat.c:717
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1025
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:772
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:615
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:841
void get_modified_firepower(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, int *att_fp, int *def_fp)
Definition combat.c:411
char * incite_cost
Definition comments.c:76
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:763
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2956
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2683
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2713
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:1066
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct req_context *other_context, enum effect_type effect_type)
Definition effects.c:744
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:824
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:283
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Definition extras.c:804
struct extra_type * extra_by_number(int id)
Definition extras.c:183
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:203
bool is_extra_removed_by(const struct extra_type *pextra, enum extra_rmcause rmcause)
Definition extras.c:353
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
#define extra_type_by_rmcause_iterate_end
Definition extras.h:358
#define extra_index(_e_)
Definition extras.h:183
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:353
#define EXTRA_NONE
Definition extras.h:85
#define extra_type_list_iterate_end
Definition extras.h:167
#define NO_TARGET
Definition fc_types.h:213
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:208
@ RPT_CERTAIN
Definition fc_types.h:533
@ AUT_NONE
Definition fc_types.h:229
@ HB_DISABLED
Definition fc_types.h:999
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:92
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
const char * tile_link(const struct tile *ptile)
const struct ft_color ftc_server
const char * city_link(const struct city *pcity)
const char * unit_link(const struct unit *punit)
const char * unit_tile_link(const struct unit *punit)
#define MAX_LEN_LINK
struct civ_game game
Definition game.c:61
int current_turn_timeout(void)
Definition game.c:853
struct world wld
Definition game.c:62
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:123
struct unit * game_unit_by_number(int id)
Definition game.c:115
struct city * game_city_by_number(int id)
Definition game.c:106
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1039
struct city * owner
Definition citydlg.c:226
GType type
Definition repodlgs.c:1313
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
@ H_LIMITEDHUTS
Definition handicaps.h:20
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:182
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:212
#define log_test
Definition log.h:137
#define log_verbose(message,...)
Definition log.h:110
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define fc_assert_action(condition, action)
Definition log.h:188
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:686
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:712
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:384
bool base_get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile, enum direction8 *dir)
Definition map.c:1469
#define adjc_iterate_end
Definition map.h:430
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:425
#define square_iterate_end
Definition map.h:391
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:290
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:398
#define circle_iterate_end
Definition map.h:401
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2489
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2577
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1926
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2184
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2512
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2680
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:925
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:869
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1444
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:2002
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1387
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2477
#define map_get_player_site(_ptile_, _pplayer_)
Definition maphand.h:93
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_malloc(sz)
Definition mem.h:34
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:289
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:318
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:330
int unit_move_rate(const struct unit *punit)
Definition movement.c:89
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:912
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:341
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:490
@ MR_OK
Definition movement.h:35
@ MR_NOT_ALLOWED
Definition movement.h:53
@ MR_DEATH
Definition movement.h:36
static mpqt_worker * worker
Definition mpgui_qt.cpp:54
static const char * name_translation_get(const struct name_translation *ptrans)
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:463
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:291
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:238
unit_info_use
Definition packets.h:66
@ UNIT_INFO_IDENTITY
Definition packets.h:67
int send_packet_unit_remove(struct connection *pc, const struct packet_unit_remove *packet)
void lsend_packet_unit_remove(struct conn_list *dest, const struct packet_unit_remove *packet)
void dlsend_packet_unit_remove(struct conn_list *dest, int unit_id)
int send_packet_unit_short_info(struct connection *pc, const struct packet_unit_short_info *packet, bool force_to_send)
int send_packet_unit_info(struct connection *pc, const struct packet_unit_info *packet)
void pf_path_destroy(struct pf_path *path)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
void pf_map_destroy(struct pf_map *pfm)
#define pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:843
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1229
struct player * player_by_number(const int player_id)
Definition player.c:849
bool can_player_see_unit_at(const struct player *pplayer, const struct unit *punit, const struct tile *ptile, bool is_transported)
Definition player.c:1034
int player_slot_count(void)
Definition player.c:418
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1104
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1388
int player_index(const struct player *pplayer)
Definition player.c:829
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:324
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1409
struct player_slot * slots
Definition player.c:51
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1463
#define players_iterate_end
Definition player.h:542
#define players_iterate(_pplayer)
Definition player.h:537
#define OWNER_NONE
Definition player.h:50
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define is_ai(plr)
Definition player.h:232
#define is_human(plr)
Definition player.h:231
void player_update_last_war_action(struct player *pplayer)
Definition plrhand.c:865
void player_status_add(struct player *plr, enum player_status pstatus)
Definition plrhand.c:3217
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2364
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1148
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1595
void player_loot_player(struct player *pvictor, struct player *pvictim)
Definition plrhand.c:410
#define phase_players_iterate(pplayer)
Definition plrhand.h:113
#define phase_players_iterate_end
Definition plrhand.h:118
#define fc_rand(_size)
Definition rand.h:56
bool are_reqs_active(const struct req_context *context, const struct req_context *other_context, const struct requirement_vector *reqs, const enum req_problem_type prob_type)
void script_server_signal_emit(const char *signal_name,...)
void script_server_remove_exported_object(void *object)
void flush_packets(void)
Definition sernet.c:376
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1968
#define CLIP(lower, current, upper)
Definition shared.h:57
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MIN(x, y)
Definition shared.h:55
#define MAX(x, y)
Definition shared.h:54
int identity_number(void)
Definition srv_main.c:2061
struct act_prob prob
Definition unittools.c:115
Definition city.h:317
int unitwaittime
Definition game.h:205
struct player * random_move_time
Definition game.h:283
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:139
int killunhomed
Definition game.h:161
int ransom_gold
Definition game.h:182
struct civ_game::@32::@36 server
bool autoattack
Definition game.h:138
int timeoutaddenemymove
Definition game.h:215
enum gameloss_style gameloss_style
enum goods_selection_method goods_selection
enum happyborders_type happyborders
int nuke_defender_survival_chance_pct
bool only_real_fight_makes_veteran
enum airlifting_style airlifting_style
bool only_killing_makes_veteran
bool combat_odds_scaled_veterancy
int upkeep[O_LAST]
enum action_decision action_decision_want
struct unit_order orders[MAX_LEN_ROUTE]
enum unit_activity activity
Unit_type_id type
enum unit_activity changed_from
enum direction8 facing
enum server_side_agent ssa_controller
enum direction8 facing
enum diplstate_type type
Definition player.h:199
int units_used
Definition player.h:108
int units_lost
Definition player.h:106
struct unit_list * units
Definition player.h:282
struct conn_list * connections
Definition player.h:298
int huts
Definition player.h:349
bool is_alive
Definition player.h:268
struct player::@73::@75 server
struct player_economic economic
Definition player.h:284
struct player_score score
Definition player.h:283
const struct player * player
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
bv_player can_see_unit
Definition unittools.c:95
struct player * powner
Definition unittools.c:94
bv_player can_see_move
Definition unittools.c:96
struct unit * punit
Definition unittools.c:93
struct vision * old_vision
Definition unittools.c:97
enum unit_activity activity
Definition unit.h:95
enum unit_orders order
Definition unit.h:94
int action
Definition unit.h:102
enum direction8 dir
Definition unit.h:104
int target
Definition unit.h:98
int sub_target
Definition unit.h:99
int vision_radius_sq
Definition unittype.h:529
enum vision_layer vlayer
Definition unittype.h:576
Definition unit.h:140
time_t action_timestamp
Definition unit.h:248
int length
Definition unit.h:198
int upkeep[O_LAST]
Definition unit.h:150
bool has_orders
Definition unit.h:196
enum action_decision action_decision_want
Definition unit.h:205
int battlegroup
Definition unit.h:194
enum unit_activity activity
Definition unit.h:159
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
enum gen_action action
Definition unit.h:160
struct unit::@83 orders
bool moved
Definition unit.h:176
int index
Definition unit.h:198
struct vision * vision
Definition unit.h:247
bool vigilant
Definition unit.h:200
int hp
Definition unit.h:153
int fuel
Definition unit.h:155
struct extra_type * changed_from_target
Definition unit.h:173
int current_form_turn
Definition unit.h:211
bool stay
Definition unit.h:208
enum direction8 facing
Definition unit.h:144
struct unit::@84::@87 server
struct tile * tile
Definition unit.h:142
struct extra_type * activity_target
Definition unit.h:167
int activity_count
Definition unit.h:165
struct unit_order * list
Definition unit.h:201
enum unit_activity changed_from
Definition unit.h:171
struct player * nationality
Definition unit.h:146
bool repeat
Definition unit.h:199
void(* removal_callback)(struct unit *punit)
Definition unit.h:256
struct unit_move_data * moving
Definition unit.h:250
int action_turn
Definition unit.h:249
int homecity
Definition unit.h:148
bool paradropped
Definition unit.h:177
bool done_moving
Definition unit.h:184
int birth_turn
Definition unit.h:210
struct goods_type * carrying
Definition unit.h:189
struct tile * goto_tile
Definition unit.h:157
struct tile * action_decision_tile
Definition unit.h:206
const struct unit_type * utype
Definition unit.h:141
int veteran
Definition unit.h:154
int changed_from_count
Definition unit.h:172
bool dying
Definition unit.h:253
enum server_side_agent ssa_controller
Definition unit.h:175
struct civ_map map
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:550
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:215
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:681
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:233
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:418
int tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:196
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:89
#define tile_terrain(_tile)
Definition tile.h:111
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:121
#define tile_continent(_tile)
Definition tile.h:93
#define tile_has_extra(ptile, pextra)
Definition tile.h:148
#define tile_owner(_tile)
Definition tile.h:97
struct goods_type * goods_from_city_to_unit(const struct city *src, const struct unit *punit)
Goods_type_id goods_index(const struct goods_type *pgood)
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1820
void free_unit_orders(struct unit *punit)
Definition unit.c:1806
bool unit_is_alive(int id)
Definition unit.c:2290
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:550
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2447
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1274
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2518
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2467
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2220
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:865
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1661
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:892
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1766
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1284
void set_unit_activity(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unit.c:1114
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:2025
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2502
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:776
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2528
bool unit_has_orders(const struct unit *punit)
Definition unit.c:202
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1949
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2072
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:590
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.c:1335
bool can_unit_do_activity_targeted(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, struct extra_type *target)
Definition unit.c:931
#define unit_tile(_pu)
Definition unit.h:404
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:427
#define unit_cargo_iterate_end
Definition unit.h:585
@ ORDER_ACTION_MOVE
Definition unit.h:46
@ ORDER_ACTIVITY
Definition unit.h:42
@ ORDER_FULL_MP
Definition unit.h:44
@ ORDER_MOVE
Definition unit.h:40
@ ORDER_LAST
Definition unit.h:50
@ ORDER_PERFORM_ACTION
Definition unit.h:48
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:415
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:582
#define CHECK_UNIT(punit)
Definition unit.h:273
#define unit_owner(_pu)
Definition unit.h:403
@ UU_OK
Definition unit.h:62
#define unit_home(_pu_)
Definition unit.h:401
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:440
void illegal_action_msg(struct player *pplayer, const enum event_type event, struct unit *actor, const action_id stopped_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit)
Definition unithand.c:2515
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unithand.c:6663
bool unit_perform_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id_incoming, const char *name, const action_id action_type, const enum action_requester requester)
Definition unithand.c:3358
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5715
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void unit_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, const struct action *paction)
Definition unittools.c:359
void unit_did_action(struct unit *punit)
Definition unittools.c:5065
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3461
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2643
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:3066
void unit_make_contact(const struct unit *punit, struct tile *ptile, struct player *pplayer)
Definition unittools.c:5180
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1161
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:2151
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:3999
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4518
static void unit_convert(struct unit *punit)
Definition unittools.c:774
void update_unit_activities(struct player *pplayer)
Definition unittools.c:670
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1305
#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:1553
void random_movements(struct player *pplayer)
Definition unittools.c:5097
bool unit_versus_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, int *att_vet, int *def_vet, const struct action *paction)
Definition unittools.c:292
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1794
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1416
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1488
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1919
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1451
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4445
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:404
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1401
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:3034
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3978
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1771
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3334
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2733
#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:2864
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:661
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3660
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:718
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:818
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3419
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3517
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:702
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:680
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:1113
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2877
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1943
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1370
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3863
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:634
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:428
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3892
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1713
void notify_unit_experience(struct unit *punit)
Definition unittools.c:747
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:800
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:2814
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:1665
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1475
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1053
#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:1632
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1910
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1785
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4991
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:219
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:5004
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:1605
void do_explore(struct unit *punit)
Definition unittools.c:3099
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3389
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:5032
#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:2139
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:692
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3135
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4491
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4946
void player_restore_units(struct player *pplayer)
Definition unittools.c:481
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1530
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4968
static void update_unit_activity(struct unit *punit)
Definition unittools.c:858
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3441
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1521
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Definition unittools.c:175
static bool maybe_become_veteran_real(struct unit *punit, int base_chance, bool worker)
Definition unittools.c:238
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3649
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:5080
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:738
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:830
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2199
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1187
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2949
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3299
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1082
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3475
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:845
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:3730
void unit_get_goods(struct unit *punit)
Definition unittools.c:1616
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2921
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4461
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:4078
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3927
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:5021
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2266
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1225
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1062
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1575
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, bool consider_reg_impr_req)
Definition unittype.c:1974
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2259
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1593
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2574
int num_role_units(int role)
Definition unittype.c:2209
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1933
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1709
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2505
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:196
const struct veteran_level * vsystem_veteran_level(const struct veteran_system *vsystem, int level)
Definition unittype.c:2591
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1566
#define utype_class(_t_)
Definition unittype.h:756
#define utype_fuel(ptype)
Definition unittype.h:846
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624
#define U_LAST
Definition unittype.h:40
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
void vision_free(struct vision *vision)
Definition vision.c:50
#define ASSERT_VISION(v)
Definition vision.h:98
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition vision.h:96
#define vision_site_owner(v)
Definition vision.h:129
short int v_radius_t[V_COUNT]
Definition vision.h:83