Freeciv-3.2
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 "autosettlers.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 settler);
146
147static void unit_transport_load_tp_status(struct unit *punit,
148 struct unit *ptrans,
149 bool force);
150
151static void wipe_unit_full(struct unit *punit, bool transported,
153 struct player *killer);
154
155static int get_unit_vision_base(const struct unit *punit,
156 enum vision_layer vlayer,
157 const int base);
158static int unit_vision_range_modifiers(const struct unit *punit,
159 const struct tile *ptile);
160
161/**********************************************************************/
177{
178 struct unit_type *which[U_LAST];
179 int i, num = 0;
180
181 if (role_tech != -1) {
182 for (i = 0; i < num_role_units(role_tech); i++) {
184 const int minplayers = 2;
185 int players = 0;
186
187 /* Note, if there's only one player in the game this check will always
188 * fail. */
189 players_iterate(pplayer) {
190 if (!is_barbarian(pplayer)
192 players++;
193 }
195
196 if (players > minplayers) {
197 which[num++] = iunit;
198 }
199 }
200 }
201 if (num == 0) {
202 for (i = 0; i < num_role_units(role); i++) {
203 which[num++] = get_role_unit(role, i);
204 }
205 }
206
207 /* Ruleset code should ensure there is at least one unit for each
208 * possibly-required role, or check before calling this function. */
209 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
210 role, role_tech);
211
212 return which[fc_rand(num)];
213}
214
215/**********************************************************************/
223
224/**********************************************************************/
238 bool settler)
239{
240 const struct veteran_system *vsystem;
241 const struct veteran_level *vlevel;
242 int chance;
243
245
249
252
253 if (punit->veteran + 1 >= vsystem->levels
255 return FALSE;
256 } else if (!settler) {
258
259 /* The modification is tacked on as a multiplier to the base chance.
260 * For example with a base chance of 50% for green units and a modifier
261 * of +50% the end chance is 75%. */
262 chance = vlevel->base_raise_chance * mod / 100;
263 } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
264 chance = base_chance * vlevel->work_raise_chance / 100;
265 } else {
266 /* No battle and no work done. */
267 return FALSE;
268 }
269
270 if (fc_rand(100) < chance) {
271 punit->veteran++;
272 return TRUE;
273 }
274
275 return FALSE;
276}
277
278/**********************************************************************/
288bool unit_versus_unit(struct unit *attacker, struct unit *defender,
289 int *att_hp, int *def_hp, int *att_vet, int *def_vet,
290 const struct action *paction)
291{
292 int attackpower = get_total_attack_power(attacker, defender, paction);
293 int defensepower = get_total_defense_power(attacker, defender);
295 struct player *plr1 = unit_owner(attacker);
296 struct player *plr2 = unit_owner(defender);
297 struct civ_map *nmap = &(wld.map);
298 int max_rounds;
299 int rounds;
300 int att_strength;
301 int def_strength;
302
303 *att_hp = attacker->hp;
304 *def_hp = defender->hp;
305 get_modified_firepower(nmap, attacker, defender,
307
308 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
309 "defense firepower:%d", attackpower, defensepower,
311
314
317
318 /* In a combat between equal strength units the values are 50% / 50%.
319 * -> scaling that to 100% by doubling, to match scale of chances
320 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
323
324 if (attackpower == 0) {
325 *att_hp = 0;
326 } else if (defensepower == 0) {
327 *def_hp = 0;
328 }
330 for (rounds = 0;
331 *att_hp > 0 && *def_hp > 0
333 rounds++) {
335 *def_hp -= attack_firepower;
336 } else {
337 *att_hp -= defense_firepower;
338 }
339 }
340 if (*att_hp < 0) {
341 *att_hp = 0;
342 }
343 if (*def_hp < 0) {
344 *def_hp = 0;
345 }
346
347 return attackpower <= 0 || defensepower <= 0;
348}
349
350/**********************************************************************/
355void unit_bombs_unit(struct unit *attacker, struct unit *defender,
356 int *att_hp, int *def_hp,
357 const struct action *paction)
358{
359 int i;
360 int rate = unit_bombard_rate(attacker);
361 int attackpower = get_total_attack_power(attacker, defender, paction);
362 int defensepower = get_total_defense_power(attacker, defender);
364 struct player *plr1 = unit_owner(attacker);
365 struct player *plr2 = unit_owner(defender);
366 struct civ_map *nmap = &(wld.map);
367
368 *att_hp = attacker->hp;
369 *def_hp = defender->hp;
370 get_modified_firepower(nmap, attacker, defender,
372
373 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
374 "defense firepower:%d", attackpower, defensepower,
376
379
380 for (i = 0; i < rate; i++) {
382 *def_hp -= attack_firepower;
383 }
384 }
385
386 if (*def_hp <= 0) {
387 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
388 /* Don't kill the target. */
389 *def_hp = 1;
390 } else {
391 *def_hp = 0;
392 }
393 }
394}
395
396/**********************************************************************/
400void combat_veterans(struct unit *attacker, struct unit *defender,
401 bool powerless, int att_vet, int def_vet)
402{
404 if (attacker->hp <= 0 || defender->hp <= 0
407 att_vet = 100;
408 def_vet = 100;
409 }
410 if (attacker->hp > 0) {
411 maybe_make_veteran(attacker, att_vet);
412 }
413 if (defender->hp > 0) {
414 maybe_make_veteran(defender, def_vet);
415 }
416 }
417 }
418}
419
420/**********************************************************************/
424static void do_upgrade_effects(struct player *pplayer)
425{
427 struct unit_list *candidates;
428
429 if (upgrades <= 0) {
430 return;
431 }
433
434 unit_list_iterate(pplayer->units, punit) {
435 /* We have to be careful not to strand units at sea, for example by
436 * upgrading a frigate to an ironclad while it was carrying a unit. */
437 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
438 unit_list_prepend(candidates, punit); /* Potential candidate :) */
439 }
441
442 while (upgrades > 0 && unit_list_size(candidates) > 0) {
443 /* Upgrade one unit. The unit is chosen at random from the list of
444 * available candidates. */
447 const struct unit_type *type_from = unit_type_get(punit);
448 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
449
452 _("%s was upgraded for free to %s."),
456 upgrades--;
457 }
458
460}
461
462/**********************************************************************/
477void player_restore_units(struct player *pplayer)
478{
479 const struct civ_map *nmap = &(wld.map);
480
481 /* 1) get Leonardo out of the way first: */
482 do_upgrade_effects(pplayer);
483
485
486 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
488
489 /* 3) Check that unit has hitpoints */
490 if (punit->hp <= 0) {
491 /* This should usually only happen for heli units, but if any other
492 * units get 0 hp somehow, catch them too. --dwp */
493 /* if 'game.server.killunhomed' is activated unhomed units are slowly
494 * killed; notify player here */
495 if (!punit->homecity && 0 < game.server.killunhomed) {
497 ftc_server, _("Your %s has run out of hit points "
498 "because it was not supported by a city."),
500 } else {
502 _("Your %s has run out of hit points."),
504 }
505
507 continue; /* Continue iterating... */
508 }
509
510 /* 4) Rescue planes if needed */
512 /* Shall we emergency return home on the last vapors? */
513
514 /* I think this is strongly against the spirit of client goto.
515 * The problem is (again) that here we know too much. -- Zamar */
516
517 if (punit->fuel <= 1
519 struct unit *carrier;
520
522 if (carrier) {
524 } else {
525 struct pf_map *pfm;
526 struct pf_parameter parameter;
527 bool alive = TRUE;
528
529 pft_fill_unit_parameter(&parameter, nmap, punit);
530 parameter.omniscience = !has_handicap(pplayer, H_MAP);
531 pfm = pf_map_new(&parameter);
532
533 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
534 if (move_cost > punit->moves_left) {
535 /* Too far */
536 break;
537 }
538
539 if (is_refuel_point(ptile, pplayer, punit)) {
540 struct pf_path *path;
541 int id = punit->id;
542
543 /* Client orders may be running for this unit - if so
544 * we free them before engaging goto. */
546
547 path = pf_map_path(pfm, ptile);
548
549 alive = adv_follow_path(punit, path, ptile);
550
551 if (!alive) {
552 log_error("rescue plane: unit %d died enroute!", id);
553 } else if (!same_pos(unit_tile(punit), ptile)) {
554 /* Enemy units probably blocked our route
555 * FIXME: We should try find alternative route around
556 * the enemy unit instead of just giving up and crashing. */
557 log_debug("rescue plane: unit %d could not move to "
558 "refuel point!", punit->id);
559 }
560
561 if (alive) {
562 /* Clear activity. Unit info will be sent in the end of
563 * the function. */
567
570 if (carrier) {
572 }
573 }
574
575 notify_player(pplayer, unit_tile(punit),
577 _("Your %s has returned to refuel."),
579 }
580 pf_path_destroy(path);
581 break;
582 }
585
586 if (!alive) {
587 /* Unit died trying to move to refuel point. */
588 return;
589 }
590 }
591 }
592
593 /* 5) Update fuel */
594 punit->fuel--;
595
596 /* 6) Automatically refuel air units in cities, airbases, and
597 * transporters (carriers). */
600 }
601 }
603
604 /* 7) Check if there are air units without fuel */
606 const struct unit_type *utype = unit_type_get(punit);
607
608 if (punit->fuel <= 0 && utype_fuel(utype)) {
609 /* Notifications sent from the lua script when unit wiped. */
611 }
613
614 /* Send all updates. */
615 unit_list_iterate(pplayer->units, punit) {
618}
619
620/**********************************************************************/
631{
632 bool was_lower;
633 const struct unit_type *utype = unit_type_get(punit);
634
635 was_lower = (punit->hp < utype->hp);
636
638
639 fc_assert(punit->hp >= 0);
640 fc_assert(punit->hp <= utype->hp);
641
642 if (punit->hp == utype->hp) {
645 }
646 }
647
648 punit->moved = FALSE;
650}
651
652/**********************************************************************/
657static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
658{
661}
662
663/**********************************************************************/
672
673/**********************************************************************/
676void execute_unit_orders(struct player *pplayer)
677{
679 if (unit_has_orders(punit)) {
681 }
683}
684
685/**********************************************************************/
688void unit_tc_effect_refresh(struct player *pplayer)
689{
690 unit_list_iterate(pplayer->units, punit) {
693}
694
695/**********************************************************************/
699{
700 /* Remember activities only after all knock-on effects of unit activities
701 * on other units have been resolved */
702 unit_list_iterate(pplayer->units, punit) {
708}
709
710/**********************************************************************/
714static int total_activity(struct tile *ptile, enum unit_activity act,
715 struct extra_type *tgt)
716{
717 int total = 0;
719
720 unit_list_iterate(ptile->units, punit) {
721 if (punit->activity == act
722 && (!tgt_matters || punit->activity_target == tgt)) {
723 total += punit->activity_count;
724 }
726
727 return total;
728}
729
730/**********************************************************************/
734static bool total_activity_done(struct tile *ptile, enum unit_activity act,
735 struct extra_type *tgt)
736{
737 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
738}
739
740/**********************************************************************/
744{
745 const struct veteran_level *vlevel;
746#ifndef FREECIV_NDEBUG
747 const struct veteran_system *vsystem;
748#endif
749
750 if (!punit) {
751 return;
752 }
753
754#ifndef FREECIV_NDEBUG
758#endif /* FREECIV_NDEBUG */
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 /* Settler 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);
989 check_terrain_change(ptile, old);
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/**********************************************************************/
1187bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
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",
1195 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
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)) {
1255 tiles[count++] = ptile;
1256 }
1258
1259 if (count > 0) {
1260 struct tile *ptile = tiles[fc_rand(count)];
1261
1262 if (verbose) {
1263 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1264 /* TRANS: A unit is moved to resolve stack conflicts. */
1265 _("Moved your %s."),
1266 unit_link(punit));
1267 }
1268
1269 /* TODO: should a unit be able to bounce to a transport like is done
1270 * below? What if the unit can't legally enter the transport, say
1271 * because the transport is Unreachable and the unit doesn't have it in
1272 * its embarks field or because "Transport Embark" isn't enabled? Kept
1273 * like it was to preserve the old rules for now. -- Sveinung */
1274 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1275 return;
1276 }
1277
1278 /* Didn't find a place to bounce the unit, going to disband it.
1279 * Try to bounce transported units. */
1281 struct unit_list *pcargo_units;
1282
1285 bounce_unit(pcargo, verbose);
1287 }
1288
1289 if (verbose) {
1291 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1292 _("Disbanded your %s."),
1294 }
1295
1297}
1298
1299/**********************************************************************/
1304static void throw_units_from_illegal_cities(struct player *pplayer,
1305 bool verbose)
1306{
1307 struct tile *ptile;
1308 struct city *pcity;
1309 struct unit *ptrans;
1310 struct unit_list *pcargo_units;
1311
1312 /* Unload undesired units from transports, if possible. */
1313 unit_list_iterate(pplayer->units, punit) {
1314 ptile = unit_tile(punit);
1315 pcity = tile_city(ptile);
1316 if (NULL != pcity
1317 && !pplayers_allied(city_owner(pcity), pplayer)
1321 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1322 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1324 }
1325 }
1327 }
1329
1330 /* Bounce units except transported ones which will be bounced with their
1331 * transport. */
1333 ptile = unit_tile(punit);
1334 pcity = tile_city(ptile);
1335 if (NULL != pcity
1336 && !pplayers_allied(city_owner(pcity), pplayer)) {
1338 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1339 bounce_unit(punit, verbose);
1340 }
1341 }
1343
1344#ifdef FREECIV_DEBUG
1345 /* Sanity check. */
1346 unit_list_iterate(pplayer->units, punit) {
1347 ptile = unit_tile(punit);
1348 pcity = tile_city(ptile);
1349 fc_assert_msg(NULL == pcity
1350 || pplayers_allied(city_owner(pcity), pplayer),
1351 "Failed to throw %s %d from %s %d (%d, %d)",
1353 punit->id,
1354 city_name_get(pcity),
1355 pcity->id,
1356 TILE_XY(ptile));
1358#endif /* FREECIV_DEBUG */
1359}
1360
1361/**********************************************************************/
1369static void resolve_stack_conflicts(struct player *pplayer,
1370 struct player *aplayer, bool verbose)
1371{
1373 struct tile *ptile = unit_tile(punit);
1374
1375 if (is_non_allied_unit_tile(ptile, pplayer)) {
1377 if (unit_owner(aunit) == pplayer
1378 || unit_owner(aunit) == aplayer
1379 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1380 bounce_unit(aunit, verbose);
1381 }
1383 }
1385}
1386
1387/**********************************************************************/
1398void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1399 bool verbose)
1400{
1401 throw_units_from_illegal_cities(pplayer, verbose);
1403
1404 resolve_stack_conflicts(pplayer, aplayer, verbose);
1405 resolve_stack_conflicts(aplayer, pplayer, verbose);
1406}
1407
1408/**********************************************************************/
1413struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1414 const struct player *aplayer)
1415{
1416 struct unit_list *seen_units = unit_list_new();
1417
1418 /* Anybody's units inside ally's cities */
1419 city_list_iterate(aplayer->cities, pcity) {
1420 unit_list_iterate(city_tile(pcity)->units, punit) {
1421 if (can_player_see_unit(pplayer, punit)) {
1423 }
1426
1427 /* Ally's own units inside transports */
1429 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1431 }
1433
1434 /* Make sure the same unit is not added in multiple phases
1435 * (unit within transport in a city) */
1437
1438 return seen_units;
1439}
1440
1441/**********************************************************************/
1448void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1449 const struct unit_list *seen_units)
1450{
1452 /* We need to hide units previously seen by the client. */
1453 if (!can_player_see_unit(pplayer, punit)) {
1454 unit_goes_out_of_sight(pplayer, punit);
1455 }
1457
1458 city_list_iterate(aplayer->cities, pcity) {
1459 /* The player used to know what units were in these cities. Now that
1460 * they don't, they need to get a new short city packet updating the
1461 * occupied status. */
1462 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1463 send_city_info(pplayer, pcity);
1464 }
1466}
1467
1468/**********************************************************************/
1472void give_allied_visibility(struct player *pplayer,
1473 struct player *aplayer)
1474{
1476 if (can_player_see_unit(pplayer, punit)) {
1477 send_unit_info(pplayer->connections, punit);
1478 }
1480}
1481
1482/**********************************************************************/
1485static bool is_refuel_tile(const struct tile *ptile,
1486 const struct player *pplayer,
1487 const struct unit *punit)
1488{
1489 const struct unit_type *utype;
1490 const struct unit_class *pclass;
1491
1492 if (is_allied_city_tile(ptile, pplayer)) {
1493 return TRUE;
1494 }
1495
1496 utype = unit_type_get(punit);
1497 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1498 return TRUE;
1499 }
1500
1501 pclass = utype_class(utype);
1502 if (NULL != pclass->cache.refuel_extras) {
1503 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1504
1505 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1506 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1507 return TRUE;
1508 }
1510 }
1511
1512 return FALSE;
1513}
1514
1515/**********************************************************************/
1519{
1520 return unit_transported(punit) /* Carrier */
1522}
1523
1524/**********************************************************************/
1527bool is_refuel_point(const struct tile *ptile,
1528 const struct player *pplayer,
1529 const struct unit *punit)
1530{
1531 if (is_non_allied_unit_tile(ptile, pplayer)) {
1532 return FALSE;
1533 }
1534
1535 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1536}
1537
1538/**********************************************************************/
1549void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1550 int vet_loss)
1551{
1552 struct player *pplayer = unit_owner(punit);
1553 const struct unit_type *old_type = punit->utype;
1555 int old_hp = unit_type_get(punit)->hp;
1556 int lvls;
1557
1558 punit->utype = to_unit;
1559
1560 /* New type may not have the same veteran system, and we may want to
1561 * knock some levels off. */
1564 /* Keeping the old behaviour, so first clip top, then reduce */
1566
1567 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1568 * and don't kill the unit. unit_move_rate() is used to take into account
1569 * global effects like Magellan's Expedition. */
1570 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1571 if (old_mr == 0) {
1573 } else {
1575 }
1576
1578
1582 }
1583
1584 /* Update unit upkeep */
1586
1588
1590
1591 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1593
1596}
1597
1598/**********************************************************************/
1601struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1602 const struct unit_type *type, int veteran_level,
1603 int homecity_id, int moves_left)
1604{
1605 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1606 moves_left, -1, NULL);
1607}
1608
1609/**********************************************************************/
1613{
1614 if (punit->homecity != 0) {
1616
1619 }
1620 }
1621}
1622
1623/**********************************************************************/
1628struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1629 const struct unit_type *type, int veteran_level,
1630 int homecity_id, int moves_left, int hp_left,
1631 struct unit *ptrans)
1632{
1633 struct unit *punit
1634 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1636 struct city *pcity = (!homecity_id || utype_has_flag(type, UTYF_NOHOME))
1638 bool could_place;
1639
1641 could_place = place_unit(punit, pplayer, pcity, ptrans, FALSE);
1643 if (!could_place) {
1645 punit = NULL;
1646 }
1647
1648 return punit;
1649}
1650
1651/**********************************************************************/
1661struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1662 const struct unit_type *type,
1663 int veteran_level, int homecity_id,
1664 int moves_left, int hp_left)
1665{
1666 struct unit *punit;
1667
1668 fc_assert_ret_val(ptile != NULL, NULL);
1670 unit_tile_set(punit, ptile);
1671
1673 punit->homecity = 0; /* none */
1674 } else {
1676 }
1677
1678 if (hp_left >= 0) {
1679 /* Override default full HP */
1680 punit->hp = hp_left;
1681 }
1682
1683 if (moves_left >= 0) {
1684 int mr = unit_move_rate(punit);
1685
1686 /* Override default full MP */
1687 /* FIXME: there are valid situations when a unit have mp
1688 * over its move rate. Here, keeping the old behavior. */
1690 /* Assume that if moves_left < 0 then the unit is "fresh",
1691 * and not moved; else the unit has had something happen
1692 * to it (eg, bribed) which we treat as equivalent to moved.
1693 * (Otherwise could pass moved arg too...) --dwp */
1694 punit->moved = TRUE;
1695 }
1696
1697 return punit;
1698}
1699
1700/**********************************************************************/
1709bool place_unit(struct unit *punit, struct player *pplayer,
1710 struct city *pcity, struct unit *ptrans, bool force)
1711{
1712 struct tile *ptile;
1713
1714 fc_assert_ret_val(pplayer, FALSE);
1716 ptile = punit->tile;
1717 fc_assert_ret_val(ptile, FALSE);
1718
1719 /* Register unit */
1722
1723 if (ptrans) {
1724 /* Set transporter for unit. */
1726 }
1727
1729 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1730 FALSE);
1731
1732 unit_list_prepend(pplayer->units, punit);
1733 unit_list_prepend(ptile->units, punit);
1735 if (pcity && !unit_has_type_flag(punit, UTYF_NOHOME)) {
1736 fc_assert(punit->homecity == pcity->id);
1737 fc_assert(city_owner(pcity) == pplayer);
1739 /* update unit upkeep */
1740 city_units_upkeep(pcity);
1741 /* Refresh the unit's homecity. */
1742 city_refresh(pcity);
1743 send_city_info(pplayer, pcity);
1744 }
1745
1746 punit->server.vision = vision_new(pplayer, ptile);
1748
1751
1752 /* The unit may have changed the available tiles in nearby cities. */
1754 sync_cities();
1755
1757
1758 CALL_FUNC_EACH_AI(unit_created, punit);
1759 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1760
1761 return TRUE;
1762}
1763
1764/**********************************************************************/
1768 void (*callback)(struct unit *punit))
1769{
1770 /* Tried to overwrite another call back. If this assertion is triggered
1771 * in a case where two call back are needed it may be time to support
1772 * more than one unit removal call back at a time. */
1774
1776}
1777
1778/**********************************************************************/
1785
1786/**********************************************************************/
1790static void server_remove_unit_full(struct unit *punit, bool transported,
1792{
1793 struct packet_unit_remove packet;
1794 struct tile *ptile = unit_tile(punit);
1795 struct city *pcity = tile_city(ptile);
1797 struct unit *ptrans;
1798 struct player *pplayer = unit_owner(punit);
1799
1800 /* The unit is doomed. */
1802
1803#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1804 unit_list_iterate(ptile->units, pcargo) {
1807#endif /* FREECIV_DEBUG */
1808
1809 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1810 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1811
1812 /* Save transporter for updating below. */
1814 /* Unload unit. */
1816
1817 /* Since settlers plot in new cities in the minimap before they
1818 are built, so that no two settlers head towards the same city
1819 spot, we need to ensure this reservation is cleared should
1820 the settler disappear on the way. */
1822
1823 /* Clear the vision before sending unit remove. Else, we might duplicate
1824 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1825 if (punit->server.vision != NULL) {
1829 }
1830
1831 packet.unit_id = punit->id;
1832 /* Send to onlookers. */
1835 transported)) {
1836 lsend_packet_unit_remove(aplayer->connections, &packet);
1837 }
1839 /* Send to global observers. */
1843 }
1845
1846 if (punit->server.moving != NULL) {
1847 /* Do not care of this unit for running moves. */
1849 }
1850
1852 /* Run the unit removal call back. */
1854 }
1855
1856 /* check if this unit had UTYF_GAMELOSS flag */
1858 && ULR_EDITOR != reason) {
1860 _("Unable to defend %s, %s has lost the game."),
1862 player_name(pplayer));
1863 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1864 _("Losing %s meant losing the game! "
1865 "Be more careful next time!"),
1866 unit_link(punit));
1868 }
1869
1872
1875 punit = NULL;
1876
1877 if (NULL != ptrans) {
1878 /* Update the occupy info. */
1880 }
1881
1882 /* This unit may have blocked tiles of adjacent cities. Update them. */
1884 sync_cities();
1885
1886 if (phomecity) {
1889 }
1890
1891 if (pcity && pcity != phomecity) {
1892 city_refresh(pcity);
1893 send_city_info(city_owner(pcity), pcity);
1894 }
1895
1896 if (pcity && unit_list_size(ptile->units) == 0) {
1897 /* The last unit in the city was killed: update the occupied flag. */
1898 send_city_info(NULL, pcity);
1899 }
1900}
1901
1902/**********************************************************************/
1911
1912/**********************************************************************/
1915static void unit_lost_with_transport(const struct player *pplayer,
1916 struct unit *pcargo,
1917 const struct unit_type *ptransport,
1918 struct player *killer)
1919{
1921 _("%s lost when %s was lost."),
1924 /* Unit is not transported any more at this point, but it has jumped
1925 * off the transport and drowns outside. So it must be removed from
1926 * all clients.
1927 * However, we don't know if given client has received ANY updates
1928 * about the swimming unit, and we can't remove it if it's not there
1929 * in the first place -> we send it once here just to be sure it's
1930 * there. */
1933}
1934
1935/**********************************************************************/
1939static void wipe_unit_full(struct unit *punit, bool transported,
1941 struct player *killer)
1942{
1943 struct tile *ptile = unit_tile(punit);
1944 struct player *pplayer = unit_owner(punit);
1945 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1946 struct unit_list *helpless = unit_list_new();
1947 struct unit_list *imperiled = unit_list_new();
1948 struct unit_list *unsaved = unit_list_new();
1950 struct city *pexclcity;
1951 struct civ_map *nmap = &(wld.map);
1952
1953 if (killer != NULL
1956 player_loot_player(killer, pplayer);
1957 }
1958
1959 /* The unit is doomed. */
1961
1962 /* If a unit is being lost due to loss of its city, ensure that we don't
1963 * try to teleport any of its cargo to that city (which may not yet
1964 * have changed hands or disappeared). (It is assumed that the unit's
1965 * home city is always the one that is being lost/transferred/etc.) */
1966 if (reason == ULR_CITY_LOST) {
1968 } else {
1969 pexclcity = NULL;
1970 }
1971
1972 /* Remove unit itself from its transport */
1973 if (ptrans != NULL) {
1976 }
1977
1978 /* First pull all units off of the transporter. */
1980 /* Use iterate_safe as unloaded units will be removed from the list
1981 * while iterating. */
1983 bool healthy = FALSE;
1984
1985 if (!can_unit_unload(pcargo, punit)) {
1987 } else {
1988 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
1990 } else {
1991 /* These units do not need to be saved. */
1992 healthy = TRUE;
1993 }
1994 }
1995
1996 /* Could use unit_transport_unload_send() here, but that would
1997 * call send_unit_info() for the transporter unnecessarily.
1998 * Note that this means that unit might to get seen briefly
1999 * by clients other than owner's, for example as a result of
2000 * update of homecity common to this cargo and some other
2001 * destroyed unit. */
2003 if (pcargo->activity == ACTIVITY_SENTRY) {
2004 /* Activate sentried units - like planes on a disbanded carrier.
2005 * Note this will activate ground units even if they just change
2006 * transporter. */
2008 }
2009
2010 /* Unit info for unhealthy units will be sent when they are
2011 * assigned new transport or removed. */
2012 if (healthy) {
2014 }
2016 }
2017
2018 /* Now remove the unit. */
2019 server_remove_unit_full(punit, transported, reason);
2020
2021 switch (reason) {
2022 case ULR_KILLED:
2023 case ULR_EXECUTED:
2024 case ULR_SDI:
2025 case ULR_NUKE:
2026 case ULR_BRIBED:
2027 case ULR_CAPTURED:
2028 case ULR_CAUGHT:
2029 case ULR_ELIMINATED:
2030 case ULR_TRANSPORT_LOST:
2031 if (killer != NULL) {
2032 killer->score.units_killed++;
2033 }
2034 pplayer->score.units_lost++;
2035 break;
2036 case ULR_BARB_UNLEASH:
2037 case ULR_CITY_LOST:
2038 case ULR_STARVED:
2039 case ULR_UPKEEP:
2040 case ULR_NONNATIVE_TERR:
2041 case ULR_ARMISTICE:
2042 case ULR_HP_LOSS:
2043 case ULR_FUEL:
2044 case ULR_STACK_CONFLICT:
2045 case ULR_SOLD:
2046 pplayer->score.units_lost++;
2047 break;
2048 case ULR_RETIRED:
2049 case ULR_DISBANDED:
2050 case ULR_USED:
2051 case ULR_DETONATED:
2052 case ULR_MISSILE:
2053 pplayer->score.units_used++;
2054 break;
2055 case ULR_EDITOR:
2056 case ULR_PLAYER_DIED:
2057 break;
2058 }
2059
2060 /* First, sort out helpless cargo. */
2061 if (unit_list_size(helpless) > 0) {
2062 struct unit_list *remaining = unit_list_new();
2063
2064 /* Grant priority to gameloss units and units with the EvacuateFirst
2065 * unit type flag. */
2072 pexclcity)) {
2074 }
2075 } else {
2076 unit_list_prepend(remaining, pcargo);
2077 }
2079
2080 /* Handle non-priority units. */
2081 unit_list_iterate_safe(remaining, pcargo) {
2084 }
2086
2087 unit_list_destroy(remaining);
2088 }
2090
2091 /* Then, save any imperiled cargo. */
2092 if (unit_list_size(imperiled) > 0) {
2093 struct unit_list *remaining = unit_list_new();
2094
2095 /* Grant priority to gameloss units and units with the EvacuateFirst
2096 * unit type flag. */
2103 pexclcity)) {
2105 }
2106 } else {
2107 unit_list_prepend(remaining, pcargo);
2108 }
2110
2111 /* Handle non-priority units. */
2112 unit_list_iterate_safe(remaining, pcargo) {
2115 }
2117
2118 unit_list_destroy(remaining);
2119 }
2121
2122 /* Finally, kill off the unsaved units. */
2123 if (unit_list_size(unsaved) > 0) {
2127 }
2129}
2130
2131/**********************************************************************/
2140
2141/**********************************************************************/
2147static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2148 bool helpless, bool teleporting,
2149 const struct city *pexclcity)
2150{
2151 struct tile *ptile = unit_tile(punit);
2152 struct player *pplayer = unit_owner(punit);
2154
2155 /* Helpless units cannot board a transport in their current state. */
2156 if (!helpless
2157 && ptransport != NULL) {
2160 return TRUE;
2161 } else {
2162 /* Only units that cannot find transport are considered for teleport. */
2163 if (teleporting) {
2164 struct city *pcity = find_closest_city(ptile, pexclcity,
2168 if (pcity != NULL) {
2169 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2170
2172
2173 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2174 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2175 _("%s escaped the destruction of %s, and fled to %s."),
2176 tplink,
2178 city_link(pcity));
2179 return TRUE;
2180 }
2181 }
2182 }
2183 }
2184
2185 /* The unit could not use transport on the tile, and could not teleport. */
2186 return FALSE;
2187}
2188
2189/**********************************************************************/
2195struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2197{
2198 struct unit *gained_unit;
2199 int id = 0;
2200
2201#ifndef FREECIV_NDEBUG
2202 bool placed;
2203#endif
2204
2207
2208 /* Convert the unit to your cause. It's supposed that the original unit
2209 * is on a valid tile and is not transported. */
2213 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2214
2215 /* Owner changes, nationality not. */
2216 gained_unit->nationality = punit->nationality;
2217
2218 /* Copy some more unit fields */
2219 gained_unit->fuel = punit->fuel;
2220 gained_unit->paradropped = punit->paradropped;
2221 gained_unit->birth_turn = punit->birth_turn;
2222 gained_unit->current_form_turn = punit->current_form_turn;
2223
2224 /* Fog is lifted in the placing algorithm. */
2225#ifndef FREECIV_NDEBUG
2226 placed =
2227#endif
2228 place_unit(gained_unit, pplayer,
2230 NULL, FALSE);
2231
2233
2234 id = gained_unit->id;
2235
2236 /* Update unit upkeep in the new homecity */
2237 if (homecity > 0) {
2239 }
2240
2241 /* Be sure to wipe the converted unit! */
2242 /* Old homecity upkeep is updated in process */
2243#ifndef FREECIV_NDEBUG
2244 uco_wipe:
2245#endif
2246
2248
2249 if (!unit_is_alive(id)) {
2250 /* Destroyed by a script */
2251 return NULL;
2252 }
2253
2254 return gained_unit; /* Returns the replacement. */
2255}
2256
2257/**********************************************************************/
2262void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2263{
2265 struct player *pvictim = unit_owner(punit);
2266 struct player *pvictor = unit_owner(pkiller);
2267 struct tile *deftile = unit_tile(punit);
2268 int unitcount = 0;
2269 bool escaped;
2270
2273
2274 /* The unit is doomed. */
2276
2280 unitcount++;
2281 }
2283
2284 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2285 if (vet) {
2287 }
2289 } else { /* Unitcount > 1 */
2290 int i;
2291 int slots = player_slot_count();
2292 int num_killed[slots];
2293 int num_escaped[slots];
2294 struct unit *other_killed[slots];
2295
2296 fc_assert(unitcount > 1);
2297
2298 /* Initialize */
2299 for (i = 0; i < slots; i++) {
2300 num_killed[i] = 0;
2301 other_killed[i] = NULL;
2302 num_escaped[i] = 0;
2303 }
2304
2305 /* Count killed units */
2307 struct player *vplayer = unit_owner(vunit);
2308
2311 escaped = FALSE;
2312
2315 && vunit->hp > 0
2316 && vunit->moves_left > pkiller->moves_left
2317 && fc_rand(2)) {
2318 int curr_def_bonus;
2319 int def_bonus = 0;
2320 struct tile *dsttile = NULL;
2321 int move_cost;
2322
2323 fc_assert(vunit->hp > 0);
2324
2326 if (can_exist_at_tile(&(wld.map), vunit->utype, ptile2)
2327 && NULL == tile_city(ptile2)) {
2328 move_cost = map_move_cost_unit(&(wld.map), vunit, ptile2);
2329 if (pkiller->moves_left <= vunit->moves_left - move_cost
2331 || unit_list_size(ptile2->units)) == 0) {
2333 vunit->utype);
2334 if (def_bonus <= curr_def_bonus) {
2336 dsttile = ptile2;
2337 }
2338 }
2339 }
2341
2342 if (dsttile != NULL) {
2345 NULL, NULL, dsttile,
2347 NULL, NULL)
2348 != NULL);
2349
2350 if (escaped) {
2352 unitcount--;
2353 }
2354 }
2355 }
2356
2357 if (!escaped) {
2359
2360 if (vunit != punit) {
2363 }
2364 }
2365 }
2367
2368 /* Inform the destroyer again if more than one unit was killed */
2369 if (unitcount > 1) {
2371 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2372 PL_("Your attacking %s succeeded against the %s %s "
2373 "(and %d other unit)!",
2374 "Your attacking %s succeeded against the %s %s "
2375 "(and %d other units)!", unitcount - 1),
2378 punit_link,
2379 unitcount - 1);
2380 }
2381
2382 if (vet) {
2384 }
2385
2386 /* Inform the owners: this only tells about owned units that were killed.
2387 * there may have been 20 units who died but if only 2 belonged to the
2388 * particular player they'll only learn about those.
2389 *
2390 * Also if a large number of units die you don't find out what type
2391 * they all are. */
2392 for (i = 0; i < slots; i++) {
2393 if (num_killed[i] == 1) {
2394 if (i == player_index(pvictim)) {
2398 /* TRANS: "Cannon ... the Polish Destroyer." */
2399 _("%s lost to an attack by the %s %s."),
2400 punit_link,
2402 pkiller_link);
2403 } else {
2407 /* TRANS: "Cannon lost when the Polish Destroyer
2408 * attacked the German Musketeers." */
2409 _("%s lost when the %s %s attacked the %s %s."),
2414 punit_link);
2415 }
2416 } else if (num_killed[i] > 1) {
2417 if (i == player_index(pvictim)) {
2418 int others = num_killed[i] - 1;
2419
2420 if (others == 1) {
2423 /* TRANS: "Musketeers (and Cannon) lost to an
2424 * attack from the Polish Destroyer." */
2425 _("%s (and %s) lost to an attack from the %s %s."),
2426 punit_link,
2429 pkiller_link);
2430 } else {
2433 /* TRANS: "Musketeers and 3 other units lost to
2434 * an attack from the Polish Destroyer."
2435 * (only happens with at least 2 other units) */
2436 PL_("%s and %d other unit lost to an attack "
2437 "from the %s %s.",
2438 "%s and %d other units lost to an attack "
2439 "from the %s %s.", others),
2440 punit_link,
2441 others,
2443 pkiller_link);
2444 }
2445 } else {
2448 /* TRANS: "2 units lost when the Polish Destroyer
2449 * attacked the German Musketeers."
2450 * (only happens with at least 2 other units) */
2451 PL_("%d unit lost when the %s %s attacked the %s %s.",
2452 "%d units lost when the %s %s attacked the %s %s.",
2453 num_killed[i]),
2454 num_killed[i],
2458 punit_link);
2459 }
2460 }
2461 }
2462
2463 /* Inform the owner of the units that escaped.
2464 * 'deftile' is the original tile they defended at, not where
2465 * they escaped to, as there might be multiple different tiles
2466 * different units escaped to. */
2467 for (i = 0; i < slots; i++) {
2468 if (0 < num_escaped[i]) {
2471 PL_("%d unit escaped from attack by %s %s",
2472 "%d units escaped from attack by %s %s",
2473 num_escaped[i]),
2474 num_escaped[i],
2477 );
2478 }
2479 }
2480
2481 /* Remove the units - note the logic of which units actually die
2482 * must be mimiced exactly in at least one place up above. */
2483 punit = NULL; /* Wiped during following iteration so unsafe to use */
2484
2489 }
2491 }
2492}
2493
2494/**********************************************************************/
2497void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2498{
2499 struct player *pvictim = unit_owner(punit);
2502 struct tile *deftile = unit_tile(punit);
2503 int unitcount, ransom;
2504
2505 /* The unit is doomed. */
2507
2510
2511 if (pvictim->economic.gold < ransom) {
2512 ransom = pvictim->economic.gold;
2513 }
2514
2516 PL_("%d Barbarian leader captured.",
2517 "%d Barbarian leaders captured.",
2518 unitcount),
2519 unitcount);
2521 PL_("%d gold ransom paid.",
2522 "%d gold ransom paid.",
2523 ransom),
2524 ransom);
2525 pvictor->economic.gold += ransom;
2526 pvictim->economic.gold -= ransom;
2527 send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */
2528
2529 if (vet) {
2531 }
2532
2535
2536 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2538 } else {
2539 int i;
2540 int slots = player_slot_count();
2541 int num_collected[slots];
2542
2543 fc_assert(unitcount > 1);
2544
2545 /* Initialize */
2546 for (i = 0; i < slots; i++) {
2547 num_collected[i] = 0;
2548 }
2549
2550 /* Count captured units */
2552 struct player *vplayer = unit_owner(vunit);
2553
2556
2557 for (i = 0; i < slots; i++) {
2558 if (num_collected[i] == 1) {
2561 _("%s %s collected ransom of %s."),
2564 } else if (num_collected[i] > 1) {
2567 PL_("%s %s collected ransom of %s and %d other unit.",
2568 "%s %s collected ransom of %s and %d other units.",
2569 num_collected[i] - 1),
2572 punit_link,
2573 num_collected[i] - 1);
2574 }
2575 }
2576
2580 }
2581}
2582
2583/**********************************************************************/
2587void package_unit(struct unit *punit, struct packet_unit_info *packet)
2588{
2589 packet->id = punit->id;
2590 packet->owner = player_number(unit_owner(punit));
2592 packet->tile = tile_index(unit_tile(punit));
2593 packet->facing = punit->facing;
2594 packet->homecity = punit->homecity;
2596 packet->upkeep[o] = punit->upkeep[o];
2598 packet->veteran = punit->veteran;
2600 packet->movesleft = punit->moves_left;
2601 packet->hp = punit->hp;
2602 packet->activity = punit->activity;
2604
2605 if (punit->activity_target != NULL) {
2607 } else {
2608 packet->activity_tgt = EXTRA_NONE;
2609 }
2610
2611 packet->changed_from = punit->changed_from;
2613
2614 if (punit->changed_from_target != NULL) {
2616 } else {
2617 packet->changed_from_tgt = EXTRA_NONE;
2618 }
2619
2621 packet->fuel = punit->fuel;
2622 packet->goto_tile = (NULL != punit->goto_tile
2623 ? tile_index(punit->goto_tile) : -1);
2624 packet->paradropped = punit->paradropped;
2625 packet->done_moving = punit->done_moving;
2626 packet->stay = punit->stay;
2627 packet->birth_turn = punit->birth_turn;
2629 if (!unit_transported(punit)) {
2630 packet->transported = FALSE;
2631 packet->transported_by = 0;
2632 } else {
2633 packet->transported = TRUE;
2635 }
2636 if (punit->carrying != NULL) {
2637 packet->carrying = goods_index(punit->carrying);
2638 } else {
2639 packet->carrying = -1;
2640 }
2641 packet->occupied = (get_transporter_occupancy(punit) > 0);
2642 packet->battlegroup = punit->battlegroup;
2643 packet->has_orders = punit->has_orders;
2644 if (punit->has_orders) {
2645 packet->orders_length = punit->orders.length;
2646 packet->orders_index = punit->orders.index;
2647 packet->orders_repeat = punit->orders.repeat;
2649 memcpy(packet->orders, punit->orders.list,
2650 punit->orders.length * sizeof(struct unit_order));
2651 } else {
2652 packet->orders_length = packet->orders_index = 0;
2653 packet->orders_repeat = packet->orders_vigilant = FALSE;
2654 /* No need to initialize array. */
2655 }
2656
2661}
2662
2663/**********************************************************************/
2669 struct packet_unit_short_info *packet,
2670 enum unit_info_use packet_use, int info_city_id)
2671{
2672 packet->packet_use = packet_use;
2673 packet->info_city_id = info_city_id;
2674
2675 packet->id = punit->id;
2676 packet->owner = player_number(unit_owner(punit));
2677 packet->tile = tile_index(unit_tile(punit));
2678 packet->facing = punit->facing;
2679 packet->veteran = punit->veteran;
2681 packet->hp = punit->hp;
2682 packet->occupied = (get_transporter_occupancy(punit) > 0);
2684 || punit->activity == ACTIVITY_GOTO) {
2685 packet->activity = ACTIVITY_IDLE;
2686 } else {
2687 packet->activity = punit->activity;
2688 }
2689
2690 if (punit->activity_target == NULL) {
2691 packet->activity_tgt = EXTRA_NONE;
2692 } else {
2694 }
2695
2696 /* Transported_by information is sent to the client even for units that
2697 * aren't fully known. Note that for non-allied players, any transported
2698 * unit can't be seen at all. For allied players we have to know if
2699 * transporters have room in them so that we can load units properly. */
2700 if (!unit_transported(punit)) {
2701 packet->transported = FALSE;
2702 packet->transported_by = 0;
2703 } else {
2704 packet->transported = TRUE;
2706 }
2707}
2708
2709/**********************************************************************/
2712void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2713{
2715 if (punit->server.moving != NULL) {
2716 /* Update status of 'pplayer' vision for 'punit'. */
2718 }
2719}
2720
2721/**********************************************************************/
2725void send_unit_info(struct conn_list *dest, struct unit *punit)
2726{
2727 const struct player *powner;
2728 struct packet_unit_info info;
2730 struct unit_move_data *pdata;
2731
2732 if (dest == NULL) {
2733 dest = game.est_connections;
2734 }
2735
2737
2739 package_unit(punit, &info);
2742
2743 conn_list_iterate(dest, pconn) {
2744 struct player *pplayer = conn_get_player(pconn);
2745
2746 /* Be careful to consider all cases where pplayer is NULL... */
2747 if (pplayer == NULL) {
2748 if (pconn->observer) {
2750 }
2751 } else if (pplayer == powner) {
2753 if (pdata != NULL) {
2754 BV_SET(pdata->can_see_unit, player_index(pplayer));
2755 }
2756 } else if (can_player_see_unit(pplayer, punit)) {
2758 if (pdata != NULL) {
2759 BV_SET(pdata->can_see_unit, player_index(pplayer));
2760 }
2761 }
2763}
2764
2765/**********************************************************************/
2770{
2771 conn_list_do_buffer(dest);
2772 conn_list_iterate(dest, pconn) {
2773 struct player *pplayer = pconn->playing;
2774
2775 if (NULL == pplayer && !pconn->observer) {
2776 continue;
2777 }
2778
2781 send_unit_info(dest, punit);
2784 }
2787 flush_packets();
2788}
2789
2790/**********************************************************************/
2797static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2798 const struct action *paction)
2799{
2800 struct city *pcity = NULL;
2801 int pop_loss;
2802
2803 pcity = tile_city(ptile);
2804
2806
2807 /* unit in a city may survive */
2808 if (pcity && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2809 continue;
2810 }
2812 _("Your %s was nuked by %s."),
2814 pplayer == unit_owner(punit)
2815 ? _("yourself")
2816 : nation_plural_for_player(pplayer));
2817 if (unit_owner(punit) != pplayer) {
2818 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2819 _("The %s %s was nuked."),
2822 }
2823 wipe_unit(punit, ULR_NUKE, pplayer);
2825
2826
2827 if (pcity) {
2828 struct player *owner = city_owner(pcity);
2829 char city_name[MAX_LEN_LINK];
2830
2832
2834 _("%s was nuked by %s."),
2835 city_name,
2836 pplayer == owner
2837 ? _("yourself")
2838 : nation_plural_for_player(pplayer));
2839
2840 if (owner != pplayer) {
2841 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2842 _("You nuked %s."),
2843 city_name);
2844 }
2845
2846 pop_loss = round((game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100.0);
2847 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
2848 /* Send city size reduction to everyone seeing it */
2849 send_city_info(NULL, pcity);
2850 } else {
2851 /* City was destroyed */
2853 _("%s was destroyed by the nuke."),
2854 city_name);
2855 if (owner != pplayer) {
2856 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2857 _("Your nuke destroyed %s."),
2858 city_name);
2859 }
2860 }
2861 }
2862
2863 if (fc_rand(2) == 1) {
2864 struct extra_type *pextra;
2865
2866 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
2867 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2868 tile_add_extra(ptile, pextra);
2869 update_tile_knowledge(ptile);
2870 }
2871 }
2872}
2873
2874/**********************************************************************/
2883 const struct unit_type *act_utype,
2884 struct player *pplayer, struct tile *ptile)
2885{
2888 &(const struct req_context) {
2889 .player = pplayer,
2890 /* City: Wait for users before choosing
2891 * home city or target tile city */
2892 .tile = ptile,
2893 .unittype = act_utype,
2894 .action = paction,
2895 },
2896 NULL,
2898
2900 do_nuke_tile(pplayer, ptile1, paction);
2902
2903 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
2904 API_TYPE_PLAYER, pplayer);
2906 _("The %s detonated a nuke!"),
2907 nation_plural_for_player(pplayer));
2908}
2909
2910/**********************************************************************/
2914bool do_airline(struct unit *punit, struct city *pdest_city,
2915 const struct action *paction)
2916{
2918
2921 _("%s transported successfully."),
2922 unit_link(punit));
2923
2926 /* Can only airlift to allied and domestic cities */
2927 FALSE, FALSE,
2928 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
2930
2931 /* Update airlift fields. */
2933 psrc_city->airlift--;
2935 }
2937 pdest_city->airlift--;
2939 }
2940
2941 return TRUE;
2942}
2943
2944/**********************************************************************/
2947void do_explore(struct unit *punit)
2948{
2949 switch (manage_auto_explorer(punit)) {
2950 case MR_DEATH:
2951 /* don't use punit! */
2952 return;
2953 case MR_NOT_ALLOWED:
2954 /* Needed for something else */
2955 return;
2956 case MR_OK:
2957 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2958 * but don't count on this. See PR#39792.
2959 */
2961 break;
2962 }
2963
2965 default:
2967
2968 /* FIXME: When the manage_auto_explorer() call changes the activity from
2969 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2970 * alone. We reset it here. See PR#12931. */
2972 break;
2973 }
2974
2975 send_unit_info(NULL, punit); /* probably duplicate */
2976}
2977
2978/**********************************************************************/
2983bool do_paradrop(struct unit *punit, struct tile *ptile,
2984 const struct action *paction)
2985{
2986 struct player *pplayer = unit_owner(punit);
2987 struct player *tgt_player = tile_owner(ptile);
2988 const struct unit_type *act_utype = unit_type_get(punit);
2989 const struct city *pcity;
2990
2991 /* Hard requirements */
2992 /* FIXME: hard requirements belong in common/actions's
2993 * is_action_possible() and the explanation texts belong in
2994 * server/unithand's action not enabled system (expl_act_not_enabl(),
2995 * ane_kind, explain_why_no_action_enabled(), etc)
2996 */
2997 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
2998 /* Only take in account values from player map. */
2999 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3000
3001 if (NULL == plrtile->site) {
3002 bv_extras fbv;
3003
3004 dbv_to_bv(fbv.vec, &(plrtile->extras));
3005
3007 &fbv)) {
3008 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3009 _("This unit cannot paradrop into %s."),
3011 return FALSE;
3012 }
3013 }
3014
3015 if (NULL != plrtile->site
3016 && plrtile->owner != NULL
3017 && !pplayers_allied(pplayer, plrtile->owner)
3019 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3020 /* TRANS: Paratroopers ... Paradrop Unit */
3021 _("%s cannot conquer a city with \"%s\"."),
3024 return FALSE;
3025 }
3026
3027 if (NULL != plrtile->site
3028 && plrtile->owner != NULL
3029 && (pplayers_non_attack(pplayer, plrtile->owner)
3030 || (player_diplstate_get(pplayer, plrtile->owner)->type
3031 == DS_ALLIANCE)
3032 || (player_diplstate_get(pplayer, plrtile->owner)->type
3033 == DS_TEAM))
3035 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3036 _("Cannot attack unless you declare war first."));
3037 return FALSE;
3038 }
3039 }
3040
3041
3042 /* Kill the unit when the landing goes wrong. */
3043
3044 /* Safe terrain, really? Not transformed since player last saw it. */
3045 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3046 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3047 || !unit_could_load_at(punit, ptile))) {
3048 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3049 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3050 _("Your %s paradropped into the %s and was lost."),
3053 pplayer->score.units_lost++;
3055 return TRUE;
3056 }
3057
3058 pcity = tile_city(ptile);
3059
3060 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3062 || is_non_allied_unit_tile(ptile, pplayer)) {
3063 struct player *main_victim = NULL;
3064 struct player *secondary_victim = NULL;
3066
3067 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3068 maybe_make_contact(ptile, pplayer);
3069 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3070 _("Your %s was killed by enemy units at the "
3071 "paradrop destination."),
3073 /* TODO: Should defender score.units_killed get increased too?
3074 * What if there's units of several allied players? Should the
3075 * city owner or owner of the first/random unit get the kill? */
3076 pplayer->score.units_lost++;
3077
3078 if (pcity != NULL) {
3079 struct player *owner = city_owner(pcity);
3080
3081 if (!pplayers_at_war(pplayer, owner)) {
3083 } else {
3085 }
3086
3088 } else {
3090 }
3091
3092 if (main_victim == NULL) {
3093 unit_list_iterate(ptile->units, tgt) {
3094 struct player *owner = unit_owner(tgt);
3095
3096 if (!pplayers_at_war(pplayer, owner)) {
3098 break;
3099 } else if (secondary_victim == NULL) {
3101 }
3103
3104 if (main_victim == NULL) {
3105 /* There's no victim with whom the attacker isn't in war,
3106 * fallback to one with whom there's already a war. */
3108 }
3109 }
3110
3112 main_victim, ptile,
3113 victim_link);
3114
3116 return TRUE;
3117 }
3118
3119 /* All ok */
3121 if (unit_move(punit, ptile,
3122 /* Done by Action_Success_Actor_Move_Cost */
3123 0,
3124 NULL, BV_ISSET(paction->sub_results,
3128 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3129 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3130 /* Ensure we finished on valid state. */
3133 }
3134
3135 /* May cause an incident */
3137 ptile, tile_link(ptile));
3138
3139 return TRUE;
3140}
3141
3142/**********************************************************************/
3146static bool hut_get_limited(struct unit *punit)
3147{
3148 bool ok = TRUE;
3149 int hut_chance = fc_rand(12);
3150 struct player *pplayer = unit_owner(punit);
3151 /* 1 in 12 to get barbarians */
3152 if (hut_chance != 0) {
3153 int cred = 25;
3155 PL_("You found %d gold.",
3156 "You found %d gold.", cred), cred);
3157 pplayer->economic.gold += cred;
3160 notify_player(pplayer, unit_tile(punit),
3162 _("An abandoned village is here."));
3163 } else {
3165 _("Your %s has been killed by barbarians!"),
3168 ok = FALSE;
3169 }
3170 return ok;
3171}
3172
3173/**********************************************************************/
3177static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3178{
3179 struct player *pplayer = unit_owner(punit);
3180 int id = punit->id;
3181 struct tile *ptile = unit_tile(punit);
3182 bool hut = FALSE;
3183 const struct req_context context = {
3184 .player = pplayer,
3185 .tile = ptile,
3186 };
3187
3189 if (tile_has_extra(ptile, pextra)
3190 && are_reqs_active(&context, tile_owner(ptile), &pextra->rmreqs,
3192 ) {
3193 hut = TRUE;
3194 /* FIXME: are all enter-removes extras worth counting? */
3195 pplayer->server.huts++;
3196
3197 destroy_extra(ptile, pextra);
3199
3200 /* FIXME: enable different classes
3201 * to behave differently with different huts */
3202 if (frighten_hut) {
3203 script_server_signal_emit("hut_frighten", punit,
3204 extra_rule_name(pextra));
3205 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3206 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3208 } else {
3209 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3210 }
3211
3212 /* We need punit for the callbacks, can't continue if the unit died */
3213 if (!unit_is_alive(id)) {
3214 break;
3215 }
3216 }
3218
3219 if (hut) {
3220 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3221 }
3222 return;
3223}
3224
3225/**********************************************************************/
3229{
3230 bv_player can_see_unit;
3231
3234
3235 BV_CLR_ALL(can_see_unit);
3236 players_iterate(pplayer) {
3237 if (can_player_see_unit(pplayer, punit)) {
3238 BV_SET(can_see_unit, player_index(pplayer));
3239 }
3241
3243
3244 players_iterate(pplayer) {
3245 if (BV_ISSET(can_see_unit, player_index(pplayer))
3246 && !can_player_see_unit(pplayer, punit)) {
3247 unit_goes_out_of_sight(pplayer, punit);
3248 }
3250
3253}
3254
3255/**********************************************************************/
3259 struct unit *ptrans,
3260 bool force)
3261{
3262 bool had_cargo;
3263
3266
3268
3270
3271 if (!had_cargo) {
3272 /* Transport's loaded status changed */
3274 }
3275}
3276
3277/**********************************************************************/
3281{
3282 struct unit *ptrans;
3283
3285
3287
3289
3291
3294}
3295
3296/**********************************************************************/
3300static void autoattack_prob_free(struct autoattack_prob *prob)
3301{
3302 free(prob);
3303}
3304
3305/**********************************************************************/
3314static int compare_units(const struct autoattack_prob *const *p1,
3315 const struct autoattack_prob *const *q1)
3316{
3317 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3318 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3319
3320 /* Sort by transport depth first. This makes sure that no transport
3321 * attacks before its cargo does -- cargo sorts earlier in the list. */
3322 {
3323 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3324
3325 /* Walk the transport stacks in parallel, so as to bail out as soon as
3326 * one of them is empty (avoid walking deep stacks more often than
3327 * necessary). */
3328 while (p1trans && q1trans) {
3331 }
3332 if (!p1trans && q1trans) {
3333 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3334 * earlier in the list (p1 > q1). */
3335 return 1;
3336 } else if (p1trans && !q1trans) {
3337 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3338 return -1;
3339 }
3340 /* else same depth, so move on to checking win chance: */
3341 }
3342
3343 /* Put the units with the highest probability of success first. The up
3344 * side of this is that units with bonuses against the victim attacks
3345 * before other units. The downside is that strong units can be led
3346 * away by sacrificial units. */
3347 return (-1
3348 /* Assume the worst. */
3349 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3350}
3351
3352/**********************************************************************/
3357{
3358 struct autoattack_prob_list *autoattack;
3359 int moves = punit->moves_left;
3360 int sanity1 = punit->id;
3361 struct civ_map *nmap = &(wld.map);
3362
3363 if (!game.server.autoattack) {
3364 return TRUE;
3365 }
3366
3368
3369 /* Kludge to prevent attack power from dropping to zero during calc */
3371
3372 adjc_iterate(nmap, unit_tile(punit), ptile) {
3373 /* First add all eligible units to a autoattack list */
3374 unit_list_iterate(ptile->units, penemy) {
3376 struct tile *tgt_tile = unit_tile(punit);
3377
3378 fc_assert_action(tgt_tile, continue);
3379
3380 probability->prob =
3384 punit, NULL);
3385
3386 if (action_prob_possible(probability->prob)) {
3387 probability->unit_id = penemy->id;
3389 } else {
3391 }
3394
3395 /* Sort the potential attackers from highest to lowest success
3396 * probability. */
3397 if (autoattack_prob_list_size(autoattack) >= 2) {
3399 }
3400
3402 int sanity2 = penemy->id;
3403 struct tile *ptile = unit_tile(penemy);
3404 struct unit *enemy_defender = get_defender(nmap, punit, ptile, NULL);
3405 double punitwin, penemywin;
3406 double threshold = 0.25;
3407 struct tile *tgt_tile = unit_tile(punit);
3408
3410
3411 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3412 /* Don't leave city defenseless */
3413 threshold = 0.90;
3414 }
3415
3416 if (NULL != enemy_defender) {
3418 } else {
3419 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3420 punitwin = 1.0;
3421 }
3422
3423 /* Previous attacks may have changed the odds. Recalculate. */
3424 peprob->prob =
3428 punit, NULL);
3429
3430 if (!action_prob_possible(peprob->prob)) {
3431 /* No longer legal. */
3432 continue;
3433 }
3434
3435 /* Assume the worst. */
3437
3438 if ((penemywin > 1.0 - punitwin
3440 && penemywin > threshold) {
3441
3442#ifdef REALLY_DEBUG_THIS
3443 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3446 1.0 - punitwin, threshold);
3447#endif
3448
3453 } else {
3454#ifdef REALLY_DEBUG_THIS
3455 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3458 1.0 - punitwin, threshold);
3459#endif
3460 continue;
3461 }
3462
3465 }
3468 } else {
3469 autoattack_prob_list_destroy(autoattack);
3470 return FALSE; /* moving unit dead */
3471 }
3473
3474 autoattack_prob_list_destroy(autoattack);
3476 /* We could have lost movement in combat */
3479 return TRUE;
3480 } else {
3481 return FALSE;
3482 }
3483}
3484
3485/**********************************************************************/
3488static void cancel_orders(struct unit *punit, char *dbg_msg)
3489{
3492 log_debug("%s", dbg_msg);
3493}
3494
3495/**********************************************************************/
3500{
3501 bool alone_in_city;
3502
3503 if (NULL != tile_city(unit_tile(punit))) {
3504 int count = 0;
3505
3507 /* Consider only units not transported. */
3508 if (!unit_transported(aunit)) {
3509 count++;
3510 }
3512
3513 alone_in_city = (1 == count);
3514 } else {
3516 }
3517
3518 /* There may be sentried units with a sightrange > 3, but we don't
3519 wake them up if the punit is farther away than 3. */
3520 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3521 unit_list_iterate(ptile->units, penemy) {
3523 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3524
3526 && penemy->activity == ACTIVITY_SENTRY
3527 && radius_sq >= distance_sq
3528 /* If the unit moved on a city, and the unit is alone, consider
3529 * it is visible. */
3530 && (alone_in_city
3532 /* on board transport; don't awaken */
3536 }
3539
3540 /* Wakeup patrolling units we bump into.
3541 We do not wakeup units further away than 3 squares... */
3542 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3543 unit_list_iterate(ptile->units, ppatrol) {
3544 if (punit != ppatrol
3546 && ppatrol->orders.vigilant) {
3548 cancel_orders(ppatrol, " stopping because of nearby enemy");
3551 _("Orders for %s aborted after enemy movement was "
3552 "spotted."),
3554 }
3555 }
3558}
3559
3560/**********************************************************************/
3570 struct tile *src_tile,
3571 struct tile *dst_tile,
3572 bool passenger,
3574{
3575 struct city *fromcity = tile_city(src_tile);
3576 struct city *tocity = tile_city(dst_tile);
3577 struct city *homecity_start_pos = NULL;
3578 struct city *homecity_end_pos = NULL;
3584 const struct unit_type *type_end_pos = type_start_pos;
3587 int saved_id = punit->id;
3588 bool alive = TRUE;
3589
3591 if (!passenger) {
3592 /* The unit that does the move may conquer. */
3594 }
3595
3596 /* Run for passengers too. A passenger may have been killed when its
3597 * transport conquered a city. (unit_conquer_city() can cause Lua code
3598 * to run) */
3599
3601 if (alive) {
3602 /* In case script has changed something about unit */
3606 }
3607 }
3608
3609 if (homecity_id_start_pos != 0) {
3611 }
3614 } else {
3616 }
3617
3618 /* We only do refreshes for non-AI players to now make sure the AI turns
3619 doesn't take too long. Perhaps we should make a special refresh_city
3620 functions that only refreshed happines. */
3621
3622 /* might have changed owners or may be destroyed */
3624
3625 if (tocity) { /* entering a city */
3626 if (tocity->owner == pplayer_end_pos) {
3630 }
3631 }
3632 if (homecity_start_pos) {
3634 }
3635 }
3636
3637 if (fromcity) { /* leaving a city */
3638 if (homecity_start_pos) {
3640 }
3642 && fromcity->owner == pplayer_start_pos
3646 }
3647 }
3648
3649 /* Entering/leaving a fortress or friendly territory */
3651 bool friendly_end = FALSE;
3652
3655 } else {
3657 type_end_pos);
3658
3659 if (max_friendliness_range >= 0
3662 } else {
3665
3666 if (max_friendliness_range >= 0
3669 }
3670 }
3671 }
3672
3673 if (friendly_end) {
3676 }
3677 }
3678
3682 }
3689 }
3690
3692 sync_cities();
3693
3694 return alive;
3695}
3696
3697/**********************************************************************/
3701static void check_unit_activity(struct unit *punit)
3702{
3703 switch (punit->activity) {
3704 case ACTIVITY_IDLE:
3705 case ACTIVITY_SENTRY:
3706 case ACTIVITY_EXPLORE:
3707 case ACTIVITY_GOTO:
3708 break;
3709 case ACTIVITY_CLEAN:
3710 case ACTIVITY_MINE:
3711 case ACTIVITY_IRRIGATE:
3712 case ACTIVITY_CULTIVATE:
3713 case ACTIVITY_PLANT:
3714 case ACTIVITY_FORTIFIED:
3715 case ACTIVITY_PILLAGE:
3716 case ACTIVITY_TRANSFORM:
3718 case ACTIVITY_BASE:
3719 case ACTIVITY_GEN_ROAD:
3720 case ACTIVITY_CONVERT:
3721 case ACTIVITY_LAST:
3723 break;
3724 };
3725}
3726
3727/**********************************************************************/
3731 const struct tile *psrctile,
3732 const struct tile *pdesttile)
3733{
3734 struct unit_move_data *pdata;
3735 struct player *powner = unit_owner(punit);
3736
3737 if (punit->server.moving) {
3738 /* Recursive moving (probably due to a script). */
3740 pdata->ref_count++;
3741 fc_assert_msg(pdata->punit == punit,
3742 "Unit number %d (%p) was going to die, but "
3743 "server attempts to move it.",
3744 punit->id, punit);
3745 fc_assert_msg(pdata->old_vision == NULL,
3746 "Unit number %d (%p) has done an incomplete move.",
3747 punit->id, punit);
3748 } else {
3749 pdata = fc_malloc(sizeof(*pdata));
3750 pdata->ref_count = 1;
3751 pdata->punit = punit;
3753 BV_CLR_ALL(pdata->can_see_unit);
3754 }
3755 pdata->powner = powner;
3756 BV_CLR_ALL(pdata->can_see_move);
3757 pdata->old_vision = punit->server.vision;
3758
3759 return pdata;
3760}
3761
3762/**********************************************************************/
3766 const struct tile *psrctile,
3767 struct tile *pdesttile)
3768{
3769 struct vision *new_vision;
3770 struct unit *punit = pdata->punit;
3772 const v_radius_t radius_sq
3776
3777 /* Remove unit from the source tile. */
3779
3780#ifndef FREECIV_NDEBUG
3781 bool success =
3782#endif
3785
3786 /* Set new tile. */
3789
3790 if (unit_transported(punit)) {
3791 /* Silently free orders since they won't be applicable anymore. */
3793 }
3794
3795 /* Check unit activity. */
3799
3800 /* We first unfog the destination, then send the move,
3801 * and then fog the old territory. This means that the player
3802 * gets a chance to see the newly explored territory while the
3803 * client moves the unit, and both areas are visible during the
3804 * move */
3805
3806 /* Enhance vision if unit steps into a fortress */
3809 vision_change_sight(new_vision, radius_sq);
3811}
3812
3813/**********************************************************************/
3817{
3819 fc_assert_ret(pdata->ref_count > 0);
3820 fc_assert_msg(pdata->old_vision == NULL,
3821 "Unit number %d (%p) has done an incomplete move.",
3822 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3823
3824 pdata->ref_count--;
3825 if (pdata->ref_count == 0) {
3826 if (pdata->punit != NULL) {
3827 fc_assert(pdata->punit->server.moving == pdata);
3828 pdata->punit->server.moving = NULL;
3829 }
3830 free(pdata);
3831 }
3832}
3833
3834/**********************************************************************/
3838 const struct tile *psrctile,
3839 struct tile *pdesttile,
3840 bool adj)
3841{
3844 struct unit_move_data *pdata;
3845
3846 /* Make new data for 'punit'. */
3849
3850 /* Add all contained units. */
3852 struct unit_move_data *cargo_data;
3853
3857
3858 /* Determine the players able to see the move(s), now that the player
3859 * vision has been increased. */
3860 if (adj) {
3861 /* Main unit for adjacent move: the move is visible for every player
3862 * able to see on the matching unit layer. */
3863 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
3864
3868 BV_SET(pdata->can_see_unit, player_index(oplayer));
3869 BV_SET(pdata->can_see_move, player_index(oplayer));
3870 }
3872 }
3873
3875
3877
3878 if (adj && pmove_data->punit == punit) {
3879 /* If positions are adjacent, we have already handled 'punit'. See
3880 * above. */
3881 continue;
3882 }
3883
3885 if ((adj
3887 pmove_data != pdata))
3889 pmove_data != pdata)) {
3890 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3891 BV_SET(pmove_data->can_see_move, player_index(oplayer));
3892 }
3894 pmove_data != pdata)) {
3895 /* The unit was seen with its source tile even if it was
3896 * teleported. */
3897 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3898 }
3901
3902 return plist;
3903}
3904
3905/**********************************************************************/
3916bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3917 struct unit *embark_to, bool find_embark_target,
3919 bool enter_hut, bool frighten_hut)
3920{
3921 struct player *pplayer;
3922 struct tile *psrctile;
3923 struct city *psrccity;
3924 struct city *pdestcity;
3925 struct unit *ptransporter;
3928 struct unit_move_data_list *plist;
3929 struct unit_move_data *pdata;
3930 int saved_id;
3931 bool unit_lives;
3932 bool adj;
3933 enum direction8 facing;
3934
3935 /* Some checks. */
3938
3939 pplayer = unit_owner(punit);
3940 saved_id = punit->id;
3943
3945
3946 /* Unload the unit if on a transport. */
3948 if (ptransporter != NULL) {
3949 /* Unload unit _before_ setting the new tile! */
3951 /* Send updated information to anyone watching that transporter
3952 * was unloading cargo. */
3954 }
3955
3956 /* Wakup units next to us before we move. */
3958
3959 /* Make info packets at 'psrctile'. */
3960 if (adj) {
3961 /* If tiles are adjacent, we will show the move to users able
3962 * to see it. */
3965 }
3966
3967 /* Set unit orientation */
3968 if (adj) {
3969 /* Only change orientation when moving to adjacent tile */
3970 punit->facing = facing;
3971 }
3972
3974
3975 /* Move magic. */
3976 punit->moved = TRUE;
3977 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3978 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3979 /* The next order may not require any remaining move fragments. */
3981 }
3982
3983 /* No longer relevant. */
3986
3988 /* The unit can perform an action to the city at the destination tile.
3989 * A long distance move (like an airlift) doesn't ask what action to
3990 * perform before moving. Ask now. */
3991
3994 }
3995
3996 /* Claim ownership of fortress? */
3999 /* Yes. We claim *all* bases if there's *any* claimable base(s).
4000 * Even if original unit cannot claim other kind of bases, the
4001 * first claimed base will have influence over other bases,
4002 * or something like that. */
4003 tile_claim_bases(pdesttile, pplayer);
4004 }
4005
4007 fc_assert(pdata->punit == punit);
4008
4009 /* Check timeout settings. */
4012
4013 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4014 * if they are ever seen. */
4016 /* Increase the timeout if an enemy unit moves and the
4017 * timeoutaddenemymove setting is in use. */
4018 if (penemy->is_connected
4019 && pplayer != penemy
4020 && pplayers_at_war(pplayer, penemy)
4021 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4023 break;
4024 }
4026
4029 }
4030 }
4031
4032 /* Notifications of the move to the clients. */
4033 if (adj) {
4034 /* Special case: 'punit' is moving to adjacent position. Then we show
4035 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4036
4037 /* Make info packets at 'pdesttile'. */
4040
4043
4044 if (aplayer == NULL) {
4045 if (pconn->observer) {
4046 /* Global observers see all... */
4049 }
4050 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4051 if (aplayer == pplayer) {
4054 } else {
4057 }
4058 }
4060 }
4061
4062 /* Other moves. */
4064 if (adj && pmove_data == pdata) {
4065 /* If positions are adjacent, we have already shown 'punit' move.
4066 * See above. */
4067 continue;
4068 }
4069
4070 /* Make info packets at 'pdesttile'. */
4074
4077
4078 if (aplayer == NULL) {
4079 if (pconn->observer) {
4080 /* Global observers see all... */
4082 }
4083 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4084 if (aplayer == pmove_data->powner) {
4086 } else {
4088 }
4089 }
4092
4093 /* Clear old vision. */
4095 if (pmove_data->old_vision != NULL) {
4096 vision_clear_sight(pmove_data->old_vision);
4097 vision_free(pmove_data->old_vision);
4098 pmove_data->old_vision = NULL;
4099 }
4101
4102 /* Move consequences. */
4104 struct unit *aunit = pmove_data->punit;
4105
4106 if (aunit != NULL
4107 && unit_owner(aunit) == pmove_data->powner
4108 && unit_tile(aunit) == pdesttile) {
4110 pdata != pmove_data,
4112 }
4114
4115 unit_lives = (pdata->punit == punit);
4116
4117 /* Wakeup units and make contact. */
4118 if (unit_lives) {
4120 }
4121 maybe_make_contact(pdesttile, pplayer);
4122
4123 if (unit_lives) {
4124 /* Special checks for ground units in the ocean. */
4126 if (embark_to != NULL) {
4128 } else if (find_embark_target) {
4129 /* TODO: Consider to stop supporting find_embark_target and make all
4130 * callers that wants auto loading set embark_to. */
4132 } else {
4134 }
4135 if (ptransporter) {
4137
4138 /* Set activity to sentry if boarding a ship. */
4139 if (is_human(pplayer)
4144 }
4145
4147 }
4148 }
4149 }
4150
4151 /* Remove units going out of sight. */
4153 struct unit *aunit = pmove_data->punit;
4154
4155 if (aunit == NULL) {
4156 continue; /* Died! */
4157 }
4158
4160 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4163 }
4166
4167 /* Inform the owner's client about actor unit arrival. Can, depending on
4168 * the client settings, cause the client to start the process that makes
4169 * the action selection dialog pop up. */
4171 if (pdestcity != NULL) {
4172 /* Arrival in a city counts. */
4173
4175 struct unit *ptrans;
4176 bool ok;
4177 struct unit *act_unit;
4178 struct player *act_player;
4179
4180 act_unit = pmove_data->punit;
4182
4183 if (act_unit == NULL
4184 || !unit_is_alive(act_unit->id)) {
4185 /* The unit died before reaching this point. */
4186 continue;
4187 }
4188
4189 if (unit_tile(act_unit) != pdesttile) {
4190 /* The unit didn't arrive at the destination tile. */
4191 continue;
4192 }
4193
4194 if (!is_human(act_player)) {
4195 /* Only humans need reminders. */
4196 continue;
4197 }
4198
4199 if (!unit_transported(act_unit)) {
4200 /* Don't show the action selection dialog again. Non transported
4201 * units are handled before they move to the tile. */
4202 continue;
4203 }
4204
4205 /* Open action dialog only if 'act_unit' and all its transporters
4206 * (recursively) don't have orders. */
4208 /* The unit it self has orders. */
4209 continue;
4210 }
4211
4214 if (NULL == ptrans) {
4215 /* No (recursive) transport has orders. */
4216 ok = TRUE;
4217 break;
4218 } else if (unit_has_orders(ptrans)) {
4219 /* A unit transporting the unit has orders */
4220 ok = FALSE;
4221 break;
4222 }
4223 }
4224
4225 if (!ok) {
4226 /* A unit transporting act_unit has orders. */
4227 continue;
4228 }
4229
4231 /* There is a valid target. */
4232
4233 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4234 act_unit->action_decision_tile = pdesttile;
4235
4236 /* Let the client know that this unit wants the player to decide
4237 * what to do. */
4239 }
4241 }
4242
4244 /* Check cities at source and destination. */
4246 if (psrccity != NULL) {
4248 }
4249 if (pdestcity != NULL) {
4251 }
4252
4253 if (unit_lives) {
4254 /* Let the scripts run ... */
4257 }
4258
4259 if (unit_lives) {
4260 /* Autoattack. */
4262 }
4263
4264 if (unit_lives && (enter_hut || frighten_hut)) {
4265 /* Is there a hut? */
4269 }
4270
4272
4273 if (unit_lives) {
4274 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4275 }
4276
4277 return unit_lives;
4278}
4279
4280/**********************************************************************/
4284 struct tile *ptile)
4285{
4286 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
4288}
4289
4290/**********************************************************************/
4297{
4298 bool cancel = FALSE;
4299 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4300 struct player *pplayer = unit_owner(punit);
4301
4302 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4303 struct unit *penemy = tile_non_allied_unit(ptile, pplayer);
4304 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4305
4306 if ((penemy && can_player_see_unit(pplayer, penemy))
4308 && pdcity->occupied)) {
4309 cancel = TRUE;
4310 break;
4311 }
4313
4314 return cancel;
4315}
4316
4317/**********************************************************************/
4325static inline bool player_is_watching(struct unit *punit, const bool fresh)
4326{
4327 /* The player just sent the orders to the unit. The unit has moves left.
4328 * It is therefore safe to assume that the player already is paying
4329 * attention to the unit. */
4330 return fresh && punit->moves_left > 0;
4331}
4332
4333/**********************************************************************/
4352bool execute_orders(struct unit *punit, const bool fresh)
4353{
4354 struct act_prob prob;
4355 bool performed;
4356 const char *name;
4357 bool res, last_order;
4358 int unitid = punit->id;
4359 struct player *pplayer = unit_owner(punit);
4360 int moves_made = 0;
4361 const struct civ_map *nmap = &(wld.map);
4362
4364
4365 if (punit->activity != ACTIVITY_IDLE) {
4366 /* Unit's in the middle of an activity; wait for it to finish. */
4368 return TRUE;
4369 }
4370
4371 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4372
4373 /* Any time the orders are canceled we should give the player a message. */
4374
4375 while (TRUE) {
4376 struct unit_order order;
4377
4378 struct action *oaction;
4379
4380 struct tile *dst_tile;
4381 struct city *tgt_city;
4382 struct unit *tgt_unit;
4383 int tgt_id;
4384 int sub_tgt_id;
4385 struct extra_type *pextra;
4386
4387 if (punit->done_moving) {
4388 log_debug(" stopping because we're done this turn");
4389 return TRUE;
4390 }
4391
4393 /* "Patrol" orders are stopped if an enemy is near. */
4394 cancel_orders(punit, " stopping because of nearby enemy");
4396 _("Orders for %s aborted as there are units nearby."),
4397 unit_link(punit));
4398 return TRUE;
4399 }
4400
4401 if (moves_made == punit->orders.length) {
4402 /* For repeating orders, don't repeat more than once per turn. */
4403 log_debug(" stopping because we ran a round");
4406 return TRUE;
4407 }
4408 moves_made++;
4409
4410 order = punit->orders.list[punit->orders.index];
4411
4412 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4413 * this far. */
4415 || action_id_exists(order.action)),
4416 continue);
4417
4418 switch (order.order) {
4419 case ORDER_MOVE:
4420 case ORDER_ACTION_MOVE:
4421 case ORDER_FULL_MP:
4422 if (0 == punit->moves_left) {
4423 log_debug(" stopping because of no more move points");
4424 return TRUE;
4425 }
4426 break;
4429 log_debug(" stopping. Not enough move points this turn");
4430 return TRUE;
4431 }
4432 break;
4433 case ORDER_ACTIVITY:
4434 case ORDER_LAST:
4435 /* Those actions don't require moves left. */
4436 break;
4437 }
4438
4440 && punit->orders.index + 1 == punit->orders.length);
4441
4442 if (last_order) {
4443 /* Clear the orders before we engage in the move. That way any
4444 * has_orders checks will yield FALSE and this will be treated as
4445 * a normal move. This is important: for instance a caravan goto
4446 * will popup the caravan dialog on the last move only. */
4448 }
4449
4450 /* Advance the orders one step forward. This is needed because any
4451 * updates sent to the client as a result of the action should include
4452 * the new index value. Note that we have to send_unit_info somewhere
4453 * after this point so that the client is properly updated. */
4454 punit->orders.index++;
4455
4456 switch (order.order) {
4457 case ORDER_FULL_MP:
4459 /* If the unit doesn't have full MP then it just waits until the
4460 * next turn. We assume that the next turn it will have full MP
4461 * (there's no check for that). */
4463 log_debug(" waiting this turn");
4465 }
4466 break;
4467 case ORDER_ACTIVITY:
4468 {
4469 enum unit_activity activity = order.activity;
4470
4471 fc_assert(activity == ACTIVITY_SENTRY);
4472
4473 if (can_unit_do_activity(nmap, punit, activity)) {
4475 set_unit_activity(punit, activity);
4477
4478 break;
4479 }
4480 }
4481
4482 cancel_orders(punit, " orders canceled because of failed activity");
4484 _("Orders for %s aborted since they "
4485 "give an invalid activity."),
4486 unit_link(punit));
4487 return TRUE;
4488 case ORDER_MOVE:
4489 case ORDER_ACTION_MOVE:
4490 /* Move unit */
4491 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4492 cancel_orders(punit, " move order sent us to invalid location");
4494 _("Orders for %s aborted since they "
4495 "give an invalid location."),
4496 unit_link(punit));
4497 return TRUE;
4498 }
4499
4500 if (order.order != ORDER_ACTION_MOVE
4502 /* Plain move required: no attack, trade route etc. */
4503 cancel_orders(punit, " orders canceled because of enemy");
4505 _("Orders for %s aborted as there "
4506 "are units in the way."),
4507 unit_link(punit));
4508 return TRUE;
4509 }
4510
4511 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4513 order.order != ORDER_ACTION_MOVE);
4514 if (!player_unit_by_number(pplayer, unitid)) {
4515 log_debug(" unit died while moving.");
4516 /* A player notification should already have been sent. */
4517 return FALSE;
4518 }
4519
4520 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4521 /* Movement succeeded but unit didn't move. */
4522 log_debug(" orders resulted in combat.");
4524 return TRUE;
4525 }
4526
4527 if (!res) {
4528 fc_assert(0 <= punit->moves_left);
4529
4530 /* Movement failed (ZOC, etc.) */
4531 cancel_orders(punit, " attempt to move failed.");
4532
4534 /* The final move "failed" because the unit needs to ask the
4535 * player what action it should take.
4536 *
4537 * The action decision request notifies the player. Its
4538 * location at the unit's last order makes it clear to the
4539 * player who the decision is for. ("The Spy I sent to Berlin
4540 * has arrived.")
4541 *
4542 * A notification message is therefore redundant. */
4543 && !(last_order
4546 /* The player may have missed this. No one else will announce it
4547 * in a satisfying manner. Inform the player. */
4548 notify_player(pplayer, unit_tile(punit),
4550 _("Orders for %s aborted because of failed move."),
4551 unit_link(punit));
4552 }
4553
4554 return TRUE;
4555 }
4556 break;
4559
4560 /* Checked in unit_order_list_is_sane() */
4561 fc_assert_action(oaction != NULL, continue);
4562
4563 log_debug(" orders: doing action %s", action_rule_name(oaction));
4564
4565 dst_tile = index_to_tile(&(wld.map), order.target);
4566
4567 if (dst_tile == NULL) {
4568 /* Could be at the edge of the map while trying to target a tile
4569 * outside of it. */
4570
4571 cancel_orders(punit, " target location doesn't exist");
4573 order.action, dst_tile, NULL, NULL);
4574
4575 return TRUE;
4576 }
4577
4578 /* Get the target city from the target tile. */
4580
4581 if (tgt_city == NULL
4583 /* This action targets a city but no city target was found. */
4584
4585 cancel_orders(punit, " perform action vs city with no city");
4587 order.action, dst_tile, tgt_city, NULL);
4588
4589 return TRUE;
4590 }
4591
4592 /* Get a target unit at the target tile. */
4594
4595 if (tgt_unit == NULL
4597 /* This action targets a unit but no target unit was found. */
4598
4599 cancel_orders(punit, " perform action vs unit with no unit");
4601 order.action, dst_tile, tgt_city, tgt_unit);
4602
4603 return TRUE;
4604 }
4605
4606 /* Server side sub target assignment */
4607 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4608 && order.sub_target == NO_TARGET) {
4609 /* Try to find a sub target. */
4611 } else {
4612 /* The client should have specified a sub target if needed */
4613 sub_tgt_id = order.sub_target;
4614 }
4615
4616 /* Get a target extra at the target tile */
4617 pextra = (sub_tgt_id == NO_TARGET ?
4618 NULL :
4619 extra_by_number(sub_tgt_id));
4620
4622 && pextra != NULL
4623 && actres_creates_extra(oaction->result, pextra)
4624 && tile_has_extra(dst_tile, pextra)) {
4625 /* Already there. Move on to the next order. */
4626 break;
4627 }
4628
4630 && pextra != NULL
4631 && actres_removes_extra(oaction->result, pextra)
4632 && !tile_has_extra(dst_tile, pextra)) {
4633 /* Already not there. Move on to the next order. */
4634 break;
4635 }
4636
4637 /* No target selected. */
4638 tgt_id = -1;
4639
4640 /* Assume impossible until told otherwise. */
4641 prob = ACTPROB_IMPOSSIBLE;
4642
4643 switch (action_id_get_target_kind(order.action)) {
4644 case ATK_UNITS:
4645 prob = action_prob_vs_stack(punit, order.action,
4646 dst_tile);
4647 tgt_id = dst_tile->index;
4648 break;
4649 case ATK_TILE:
4650 prob = action_prob_vs_tile(punit, order.action,
4651 dst_tile, pextra);
4652 tgt_id = dst_tile->index;
4653 break;
4654 case ATK_EXTRAS:
4655 prob = action_prob_vs_extras(punit, order.action,
4656 dst_tile, pextra);
4657 tgt_id = dst_tile->index;
4658 break;
4659 case ATK_CITY:
4660 prob = action_prob_vs_city(punit, order.action,
4661 tgt_city);
4662 tgt_id = tgt_city->id;
4663 break;
4664 case ATK_UNIT:
4665 prob = action_prob_vs_unit(punit, order.action,
4666 tgt_unit);
4667
4668 tgt_id = tgt_unit->id;
4669 break;
4670 case ATK_SELF:
4671 prob = action_prob_self(punit, order.action);
4672
4673 tgt_id = unitid;
4674 break;
4675 case ATK_COUNT:
4676 log_error("Invalid action target kind");
4677
4678 /* The check below will abort and cancel the orders because prob
4679 * was initialized to impossible above this switch statement. */
4680
4681 break;
4682 }
4683
4684 if (!action_prob_possible(prob)) {
4685 /* The player has enough information to know that this action is
4686 * against the rules. Don't risk any punishment by trying to
4687 * perform it. */
4688
4689 cancel_orders(punit, " illegal action");
4691 _("%s could not do %s to %s."),
4695
4696 /* Try to explain what rule made it illegal. */
4698 order.action, dst_tile, tgt_city, tgt_unit);
4699
4700 return TRUE;
4701 }
4702
4704 /* This action needs a name. */
4706 } else {
4707 /* This action doesn't need a name. */
4708 name = "";
4709 }
4710
4712 unitid,
4713 tgt_id,
4714 sub_tgt_id,
4715 name,
4716 order.action,
4718
4719 if (!player_unit_by_number(pplayer, unitid)) {
4720 /* The unit "died" while performing the action. */
4721 return FALSE;
4722 }
4723
4724 if (!performed) {
4725 /* The action wasn't performed as ordered. */
4726
4727 cancel_orders(punit, " failed action");
4729 _("Orders for %s aborted because "
4730 "doing %s to %s failed."),
4734
4735 return TRUE;
4736 }
4737
4738 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4740 /* Done at turn change. */
4743 break;
4744 }
4745
4746 break;
4747 case ORDER_LAST:
4748 /* Should be caught when loading the unit orders from the savegame or
4749 * when receiving the unit orders from the client. */
4750 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4751 cancel_orders(punit, " invalid order!");
4753 _("Your %s has invalid orders."),
4754 unit_link(punit));
4755 return TRUE;
4756 }
4757
4758 if (last_order) {
4760 log_debug(" stopping because orders are complete");
4761 return TRUE;
4762 }
4763
4764 if (punit->orders.index == punit->orders.length) {
4766 /* Start over. */
4767 log_debug(" repeating orders.");
4768 punit->orders.index = 0;
4769 }
4770 } /* end while */
4771}
4772
4773/**********************************************************************/
4780static int get_unit_vision_base(const struct unit *punit,
4781 enum vision_layer vlayer,
4782 const int base)
4783{
4784 switch (vlayer) {
4785 case V_MAIN:
4786 return MAX(0, base);
4787 case V_INVIS:
4788 case V_SUBSURFACE:
4789 return CLIP(0, base, 2);
4790 case V_COUNT:
4791 break;
4792 }
4793
4794 log_error("Unsupported vision layer variant: %d.", vlayer);
4795
4796 return 0;
4797}
4798
4799/**********************************************************************/
4802static int unit_vision_range_modifiers(const struct unit *punit,
4803 const struct tile *ptile)
4804{
4805 const struct unit_type *utype = unit_type_get(punit);
4806
4807 return (utype->vision_radius_sq
4809 &(const struct req_context) {
4810 .player = unit_owner(punit),
4811 .tile = ptile,
4812 .unittype = utype,
4813 .unit = punit,
4814 },
4816}
4817
4818/**********************************************************************/
4825int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
4826 enum vision_layer vlayer)
4827{
4830}
4831
4832/**********************************************************************/
4839{
4840 struct vision *uvision = punit->server.vision;
4841 const struct tile *utile = unit_tile(punit);
4842 int mod = unit_vision_range_modifiers(punit, utile);
4843 const v_radius_t radius_sq
4847
4848 vision_change_sight(uvision, radius_sq);
4850}
4851
4852/**********************************************************************/
4861
4862/**********************************************************************/
4867{
4868 time_t dt;
4869
4870 if (!punit) {
4871 return FALSE;
4872 }
4873
4874 if (game.server.unitwaittime <= 0) {
4875 return TRUE;
4876 }
4877
4878 if (punit->server.action_turn != game.info.turn - 1) {
4879 return TRUE;
4880 }
4881
4883 if (dt < game.server.unitwaittime) {
4884 char buf[64];
4887 ftc_server, _("Your unit may not act for another %s "
4888 "this turn. See /help unitwaittime."), buf);
4889 return FALSE;
4890 }
4891
4892 return TRUE;
4893}
4894
4895/**********************************************************************/
4900{
4901 if (!punit) {
4902 return;
4903 }
4904
4907}
4908
4909/**********************************************************************/
4915{
4916 /* check if there is enemy nearby */
4917 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
4919 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4920 return FALSE;
4921 }
4922 }
4924
4925 return TRUE;
4926}
4927
4928/**********************************************************************/
4931void random_movements(struct player *pplayer)
4932{
4933 const struct civ_map *nmap = &(wld.map);
4934
4935 game.server.random_move_time = pplayer;
4936
4939 bool moved = TRUE;
4940 struct tile *curtile = unit_tile(punit);
4941 int id = punit->id;
4942
4943 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
4944 /*
4945 * List of all 8 directions
4946 */
4947 enum direction8 dirs[8] = {
4950 };
4951 int n;
4952
4953 moved = FALSE;
4954
4955 for (n = 8; n > 0 && !moved; n--) {
4956 enum direction8 choice = (enum direction8) fc_rand(n);
4957 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
4958
4959 if (dest != NULL) {
4961 dest))) {
4962 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
4964 moved = TRUE;
4965 break;
4966 }
4967 }
4968
4969 if (!moved) {
4971 NULL)) {
4972 if (unit_perform_action(pplayer, id, tile_index(dest),
4974 ACT_REQ_RULES)) {
4975 moved = TRUE;
4976 }
4978 punit, dest, NULL)) {
4979 if (unit_perform_action(pplayer, id, tile_index(dest),
4981 ACT_REQ_RULES)) {
4982 moved = TRUE;
4983 }
4985 punit, dest, NULL)) {
4986 if (unit_perform_action(pplayer, id, tile_index(dest),
4988 ACT_REQ_RULES)) {
4989 moved = TRUE;
4990 }
4991 }
4992 }
4993 }
4994
4995 if (!moved) {
4996 /* Choice was bad, so replace it with the last direction
4997 * in the list. On the next iteration, one fewer choice
4998 * will remain. */
4999 dirs[choice] = dirs[n - 1];
5000 }
5001 }
5002 }
5003 }
5005
5007}
const char * action_name_translation(const struct action *action)
Definition actions.c:1982
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:6294
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2002
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Definition actions.c:5497
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5823
struct act_prob action_prob_vs_city(const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Definition actions.c:4981
struct act_prob action_prob_vs_unit(const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5065
const char * action_rule_name(const struct action *action)
Definition actions.c:1968
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1871
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5342
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:4073
struct act_prob action_prob_vs_stack(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:5258
struct act_prob action_prob_vs_extras(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5426
bool action_id_exists(const action_id act_id)
Definition actions.c:1820
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5883
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5934
static struct action * action_by_number(action_id act_id)
Definition actions.h:633
#define action_has_result(_act_, _res_)
Definition actions.h:429
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:674
#define ACTPROB_IMPOSSIBLE
Definition actions.h:904
#define action_id_get_target_kind(act_id)
Definition actions.h:650
#define action_id_has_result_safe(act_id, result)
Definition actions.h:663
void action_consequence_complete(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
void action_consequence_caught(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct act_prob action_auto_perf_unit_prob(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
const struct action * action_auto_perf_unit_do(const enum action_auto_perf_cause cause, struct unit *actor, const struct player *other_player, const struct output_type *eval_output, const struct action *eval_action, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
void action_consequence_success(const struct action *paction, struct player *offender, const struct unit_type *offender_utype, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
bool actres_removes_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:806
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:785
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:384
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
void dbv_to_bv(unsigned char *dest, const struct dbv *src)
Definition bitvector.c:235
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool city_exists_within_max_city_map(const struct tile *ptile, bool may_be_on_center)
Definition city.c:2102
bool is_friendly_city_near(const struct player *owner, const struct tile *ptile, int distance)
Definition city.c:2083
const char * city_name_get(const struct city *pcity)
Definition city.c:1128
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:762
#define city_list_iterate(citylist, pcity)
Definition city.h:508
#define city_tile(_pcity_)
Definition city.h:564
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:726
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:738
#define output_type_iterate(output)
Definition city.h:833
#define city_owner(_pcity_)
Definition city.h:563
#define city_list_iterate_end
Definition city.h:510
#define output_type_iterate_end
Definition city.h:839
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3304
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:453
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2343
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Definition citytools.c:851
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2196
void sync_cities(void)
Definition citytools.c:3313
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1973
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3127
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:159
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:478
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:85
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:987
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:710
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1018
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:765
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:608
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:834
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:409
char * incite_cost
Definition comments.c:74
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:763
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:366
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:356
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:753
#define conn_list_iterate(connlist, pconn)
Definition connection.h:108
#define conn_list_iterate_end
Definition connection.h:110
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2931
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2658
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2688
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
int get_target_bonus_effects(struct effect_list *plist, const struct req_context *context, const struct player *other_player, enum effect_type effect_type)
Definition effects.c:748
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:1070
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:828
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:790
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:357
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:352
@ RPT_CERTAIN
Definition fc_types.h:704
@ AUT_NONE
Definition fc_types.h:373
@ HB_DISABLED
Definition fc_types.h:1291
#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:62
int current_turn_timeout(void)
Definition game.c:846
struct world wld
Definition game.c:63
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:124
struct unit * game_unit_by_number(int id)
Definition game.c:116
struct city * game_city_by_number(int id)
Definition game.c:107
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1036
struct city * owner
Definition citydlg.c:220
GType type
Definition repodlgs.c:1313
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
@ H_LIMITEDHUTS
Definition handicaps.h:20
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:211
#define log_test
Definition log.h:136
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:641
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:667
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:940
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:371
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:1328
#define adjc_iterate_end
Definition map.h:433
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
#define square_iterate_end
Definition map.h:394
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:293
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:401
#define circle_iterate_end
Definition map.h:404
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2511
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2586
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1906
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2198
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2521
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2689
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:920
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:864
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1436
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:1979
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1379
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2499
#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:290
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:331
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:911
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:342
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:491
@ MR_OK
Definition movement.h:35
@ MR_NOT_ALLOWED
Definition movement.h:53
@ MR_DEATH
Definition movement.h:36
static const char * name_translation_get(const struct name_translation *ptrans)
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:138
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:463
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:292
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:239
unit_info_use
Definition packets.h:66
@ UNIT_INFO_IDENTITY
Definition packets.h:67
int send_packet_unit_remove(struct connection *pc, const struct packet_unit_remove *packet)
void lsend_packet_unit_remove(struct conn_list *dest, const struct packet_unit_remove *packet)
void dlsend_packet_unit_remove(struct conn_list *dest, int unit_id)
int send_packet_unit_short_info(struct connection *pc, const struct packet_unit_short_info *packet, bool force_to_send)
int send_packet_unit_info(struct connection *pc, const struct packet_unit_info *packet)
void pf_path_destroy(struct pf_path *path)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
void pf_map_destroy(struct pf_map *pfm)
#define pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
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:1405
struct player_slot * slots
Definition player.c:51
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1459
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define is_ai(plr)
Definition player.h:230
#define is_human(plr)
Definition player.h:229
void player_update_last_war_action(struct player *pplayer)
Definition plrhand.c:863
void player_status_add(struct player *plr, enum player_status pstatus)
Definition plrhand.c:3208
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2357
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1142
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1589
void player_loot_player(struct player *pvictor, struct player *pvictim)
Definition plrhand.c:411
#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 player *other_player, 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:381
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1964
#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:2020
struct act_prob prob
Definition unittools.c:115
Definition city.h:320
int id
Definition city.h:326
struct tile * tile
Definition city.h:322
struct unit_list * units_supported
Definition city.h:406
int unitwaittime
Definition game.h:198
struct player * random_move_time
Definition game.h:275
struct conn_list * est_connections
Definition game.h:97
struct packet_game_info info
Definition game.h:89
int autoupgrade_veteran_loss
Definition game.h:132
int killunhomed
Definition game.h:154
struct civ_game::@31::@35 server
int ransom_gold
Definition game.h:175
bool autoattack
Definition game.h:131
int timeoutaddenemymove
Definition game.h:208
enum gameloss_style gameloss_style
enum goods_selection_method goods_selection
enum happyborders_type happyborders
int nuke_defender_survival_chance_pct
bool only_real_fight_makes_veteran
enum airlifting_style airlifting_style
bool only_killing_makes_veteran
bool combat_odds_scaled_veterancy
int upkeep[O_LAST]
enum action_decision action_decision_want
struct unit_order orders[MAX_LEN_ROUTE]
enum unit_activity activity
Unit_type_id type
enum unit_activity changed_from
enum direction8 facing
enum server_side_agent ssa_controller
enum direction8 facing
enum diplstate_type type
Definition player.h:197
int units_used
Definition player.h:106
int units_lost
Definition player.h:104
struct unit_list * units
Definition player.h:280
struct conn_list * connections
Definition player.h:296
int huts
Definition player.h:347
bool is_alive
Definition player.h:266
struct player_economic economic
Definition player.h:282
struct player_score score
Definition player.h:281
struct player::@70::@72 server
const struct player * player
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
bv_player can_see_unit
Definition unittools.c:95
struct player * powner
Definition unittools.c:94
bv_player can_see_move
Definition unittools.c:96
struct unit * punit
Definition unittools.c:93
struct vision * old_vision
Definition unittools.c:97
enum unit_activity activity
Definition unit.h:94
enum unit_orders order
Definition unit.h:93
int action
Definition unit.h:100
enum direction8 dir
Definition unit.h:102
int target
Definition unit.h:97
int sub_target
Definition unit.h:98
int vision_radius_sq
Definition unittype.h:522
enum vision_layer vlayer
Definition unittype.h:569
Definition unit.h:138
time_t action_timestamp
Definition unit.h:245
int length
Definition unit.h:195
int upkeep[O_LAST]
Definition unit.h:148
bool has_orders
Definition unit.h:193
struct unit::@80 orders
enum action_decision action_decision_want
Definition unit.h:202
int battlegroup
Definition unit.h:191
enum unit_activity activity
Definition unit.h:157
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
bool moved
Definition unit.h:173
int index
Definition unit.h:195
struct vision * vision
Definition unit.h:244
bool vigilant
Definition unit.h:197
int hp
Definition unit.h:151
int fuel
Definition unit.h:153
struct extra_type * changed_from_target
Definition unit.h:170
int current_form_turn
Definition unit.h:208
bool stay
Definition unit.h:205
enum direction8 facing
Definition unit.h:142
struct unit::@81::@84 server
struct tile * tile
Definition unit.h:140
struct extra_type * activity_target
Definition unit.h:164
int activity_count
Definition unit.h:162
struct unit_order * list
Definition unit.h:198
enum unit_activity changed_from
Definition unit.h:168
struct player * nationality
Definition unit.h:144
bool repeat
Definition unit.h:196
void(* removal_callback)(struct unit *punit)
Definition unit.h:253
struct unit_move_data * moving
Definition unit.h:247
int action_turn
Definition unit.h:246
int homecity
Definition unit.h:146
bool paradropped
Definition unit.h:174
bool done_moving
Definition unit.h:181
int birth_turn
Definition unit.h:207
struct goods_type * carrying
Definition unit.h:186
struct tile * goto_tile
Definition unit.h:155
struct tile * action_decision_tile
Definition unit.h:203
const struct unit_type * utype
Definition unit.h:139
int veteran
Definition unit.h:152
int changed_from_count
Definition unit.h:169
bool dying
Definition unit.h:250
enum server_side_agent ssa_controller
Definition unit.h:172
struct civ_map map
#define sz_strlcpy(dest, src)
Definition support.h:189
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:550
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:215
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:681
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:233
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:418
int tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:196
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:88
#define tile_terrain(_tile)
Definition tile.h:110
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:120
#define tile_continent(_tile)
Definition tile.h:92
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
#define tile_owner(_tile)
Definition tile.h:96
struct goods_type * goods_from_city_to_unit(struct city *src, struct unit *punit)
Goods_type_id goods_index(const struct goods_type *pgood)
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer)
Definition unit.c:1303
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1779
void free_unit_orders(struct unit *punit)
Definition unit.c:1765
bool unit_is_alive(int id)
Definition unit.c:2249
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:522
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2366
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1085
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1242
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2437
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2386
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2179
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:838
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1620
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:865
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1725
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1252
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1984
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2421
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:748
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2447
bool unit_has_orders(const struct unit *punit)
Definition unit.c:205
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1908
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2031
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:562
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:904
#define unit_tile(_pu)
Definition unit.h:390
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:413
#define unit_cargo_iterate_end
Definition unit.h:565
@ ORDER_ACTION_MOVE
Definition unit.h:45
@ ORDER_ACTIVITY
Definition unit.h:41
@ ORDER_FULL_MP
Definition unit.h:43
@ ORDER_MOVE
Definition unit.h:39
@ ORDER_LAST
Definition unit.h:49
@ ORDER_PERFORM_ACTION
Definition unit.h:47
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:401
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:562
#define CHECK_UNIT(punit)
Definition unit.h:270
#define unit_owner(_pu)
Definition unit.h:389
@ UU_OK
Definition unit.h:61
#define unit_home(_pu_)
Definition unit.h:387
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:425
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:2492
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6468
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:3311
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5531
#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:355
void unit_did_action(struct unit *punit)
Definition unittools.c:4899
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3300
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2497
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:2914
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:2147
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:3837
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4352
static void unit_convert(struct unit *punit)
Definition unittools.c:774
void update_unit_activities(struct player *pplayer)
Definition unittools.c:666
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1304
#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:1549
void random_movements(struct player *pplayer)
Definition unittools.c:4931
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:288
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1790
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1413
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1485
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1915
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1448
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4283
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:400
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1398
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:2882
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3816
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1767
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3177
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2587
#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:2712
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:657
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3499
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:714
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:3258
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3356
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:698
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:676
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:2725
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1939
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1369
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3701
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:630
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:424
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3730
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1709
void notify_unit_experience(struct unit *punit)
Definition unittools.c:743
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:2668
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:1661
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1472
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:1628
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1906
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1781
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4825
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:219
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4838
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:1601
void do_explore(struct unit *punit)
Definition unittools.c:2947
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3228
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:4866
#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:2135
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:688
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:2983
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4325
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4780
void player_restore_units(struct player *pplayer)
Definition unittools.c:477
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1527
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4802
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:3280
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1518
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Definition unittools.c:175
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3488
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:4914
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:734
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:2195
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:2797
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3146
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:3314
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:3569
void unit_get_goods(struct unit *punit)
Definition unittools.c:1612
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2769
static bool maybe_become_veteran_real(struct unit *punit, int base_chance, bool settler)
Definition unittools.c:237
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4296
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:3916
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3765
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4855
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2262
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:1569
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype, bool consider_reg_impr_req)
Definition unittype.c:1968
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2253
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2567
int num_role_units(int role)
Definition unittype.c:2203
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1927
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1703
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2498
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2583
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
#define utype_class(_t_)
Definition unittype.h:749
#define utype_fuel(ptype)
Definition unittype.h:836
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
#define U_LAST
Definition unittype.h:40
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
void vision_free(struct vision *vision)
Definition vision.c:50
#define ASSERT_VISION(v)
Definition vision.h:98
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition vision.h:96
#define vision_site_owner(v)
Definition vision.h:128
short int v_radius_t[V_COUNT]
Definition vision.h:83