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/**********************************************************************/
356void unit_bombs_unit(struct unit *attacker, struct unit *defender,
357 int *att_hp, int *def_hp,
358 const struct action *paction)
359{
360 int i;
361 int rate = unit_bombard_rate(attacker);
362 int attackpower = get_total_attack_power(attacker, defender, paction);
363 int defensepower = get_total_defense_power(attacker, defender);
365 struct player *plr1 = unit_owner(attacker);
366 struct player *plr2 = unit_owner(defender);
367 struct civ_map *nmap = &(wld.map);
368
369 *att_hp = attacker->hp;
370 *def_hp = defender->hp;
371 get_modified_firepower(nmap, attacker, defender,
373
374 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
375 "defense firepower:%d", attackpower, defensepower,
377
380
381 for (i = 0; i < rate; i++) {
383 *def_hp -= attack_firepower;
384 }
385 }
386
387 if (*def_hp <= 0) {
388 if (BV_ISSET(paction->sub_results, ACT_SUB_RES_NON_LETHAL)) {
389 /* Don't kill the target. */
390 *def_hp = 1;
391 } else {
392 *def_hp = 0;
393 }
394 }
395}
396
397/**********************************************************************/
401void combat_veterans(struct unit *attacker, struct unit *defender,
402 bool powerless, int att_vet, int def_vet)
403{
405 if (attacker->hp <= 0 || defender->hp <= 0
408 att_vet = 100;
409 def_vet = 100;
410 }
411 if (attacker->hp > 0) {
412 maybe_make_veteran(attacker, att_vet);
413 }
414 if (defender->hp > 0) {
415 maybe_make_veteran(defender, def_vet);
416 }
417 }
418 }
419}
420
421/**********************************************************************/
425static void do_upgrade_effects(struct player *pplayer)
426{
428 struct unit_list *candidates;
429
430 if (upgrades <= 0) {
431 return;
432 }
434
435 unit_list_iterate(pplayer->units, punit) {
436 /* We have to be careful not to strand units at sea, for example by
437 * upgrading a frigate to an ironclad while it was carrying a unit. */
438 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
439 unit_list_prepend(candidates, punit); /* Potential candidate :) */
440 }
442
443 while (upgrades > 0 && unit_list_size(candidates) > 0) {
444 /* Upgrade one unit. The unit is chosen at random from the list of
445 * available candidates. */
448 const struct unit_type *type_from = unit_type_get(punit);
449 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
450
453 _("%s was upgraded for free to %s."),
457 upgrades--;
458 }
459
461}
462
463/**********************************************************************/
478void player_restore_units(struct player *pplayer)
479{
480 const struct civ_map *nmap = &(wld.map);
481
482 /* 1) get Leonardo out of the way first: */
483 do_upgrade_effects(pplayer);
484
486
487 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
489
490 /* 3) Check that unit has hitpoints */
491 if (punit->hp <= 0) {
492 /* This should usually only happen for heli units, but if any other
493 * units get 0 hp somehow, catch them too. --dwp */
494 /* if 'game.server.killunhomed' is activated unhomed units are slowly
495 * killed; notify player here */
496 if (!punit->homecity && 0 < game.server.killunhomed) {
498 ftc_server, _("Your %s has run out of hit points "
499 "because it was not supported by a city."),
501 } else {
503 _("Your %s has run out of hit points."),
505 }
506
508 continue; /* Continue iterating... */
509 }
510
511 /* 4) Rescue planes if needed */
513 /* Shall we emergency return home on the last vapors? */
514
515 /* I think this is strongly against the spirit of client goto.
516 * The problem is (again) that here we know too much. -- Zamar */
517
518 if (punit->fuel <= 1
520 struct unit *carrier;
521
523 if (carrier) {
525 } else {
526 struct pf_map *pfm;
527 struct pf_parameter parameter;
528 bool alive = TRUE;
529
530 pft_fill_unit_parameter(&parameter, nmap, punit);
531 parameter.omniscience = !has_handicap(pplayer, H_MAP);
532 pfm = pf_map_new(&parameter);
533
534 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
535 if (move_cost > punit->moves_left) {
536 /* Too far */
537 break;
538 }
539
540 if (is_refuel_point(ptile, pplayer, punit)) {
541 struct pf_path *path;
542 int id = punit->id;
543
544 /* Client orders may be running for this unit - if so
545 * we free them before engaging goto. */
547
548 path = pf_map_path(pfm, ptile);
549
550 alive = adv_follow_path(punit, path, ptile);
551
552 if (!alive) {
553 log_error("rescue plane: unit %d died enroute!", id);
554 } else if (!same_pos(unit_tile(punit), ptile)) {
555 /* Enemy units probably blocked our route
556 * FIXME: We should try find alternative route around
557 * the enemy unit instead of just giving up and crashing. */
558 log_debug("rescue plane: unit %d could not move to "
559 "refuel point!", punit->id);
560 }
561
562 if (alive) {
563 /* Clear activity. Unit info will be sent in the end of
564 * the function. */
568
571 if (carrier) {
573 }
574 }
575
576 notify_player(pplayer, unit_tile(punit),
578 _("Your %s has returned to refuel."),
580 }
581 pf_path_destroy(path);
582 break;
583 }
586
587 if (!alive) {
588 /* Unit died trying to move to refuel point. */
589 return;
590 }
591 }
592 }
593
594 /* 5) Update fuel */
595 punit->fuel--;
596
597 /* 6) Automatically refuel air units in cities, airbases, and
598 * transporters (carriers). */
601 }
602 }
604
605 /* 7) Check if there are air units without fuel */
607 const struct unit_type *utype = unit_type_get(punit);
608
609 if (punit->fuel <= 0 && utype_fuel(utype)) {
610 /* Notifications sent from the lua script when unit wiped. */
612 }
614
615 /* Send all updates. */
616 unit_list_iterate(pplayer->units, punit) {
619}
620
621/**********************************************************************/
632{
633 bool was_lower;
634 const struct unit_type *utype = unit_type_get(punit);
635
636 was_lower = (punit->hp < utype->hp);
637
639
640 fc_assert(punit->hp >= 0);
641 fc_assert(punit->hp <= utype->hp);
642
643 if (punit->hp == utype->hp) {
646 }
647 }
648
649 punit->moved = FALSE;
651}
652
653/**********************************************************************/
658static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
659{
662}
663
664/**********************************************************************/
673
674/**********************************************************************/
677void execute_unit_orders(struct player *pplayer)
678{
680 if (unit_has_orders(punit)) {
682 }
684}
685
686/**********************************************************************/
689void unit_tc_effect_refresh(struct player *pplayer)
690{
691 unit_list_iterate(pplayer->units, punit) {
694}
695
696/**********************************************************************/
700{
701 /* Remember activities only after all knock-on effects of unit activities
702 * on other units have been resolved */
703 unit_list_iterate(pplayer->units, punit) {
709}
710
711/**********************************************************************/
715static int total_activity(struct tile *ptile, enum unit_activity act,
716 struct extra_type *tgt)
717{
718 int total = 0;
720
721 unit_list_iterate(ptile->units, punit) {
722 if (punit->activity == act
723 && (!tgt_matters || punit->activity_target == tgt)) {
724 total += punit->activity_count;
725 }
727
728 return total;
729}
730
731/**********************************************************************/
735static bool total_activity_done(struct tile *ptile, enum unit_activity act,
736 struct extra_type *tgt)
737{
738 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
739}
740
741/**********************************************************************/
745{
746 const struct veteran_level *vlevel;
747 const struct veteran_system *vsystem;
748
749 if (!punit) {
750 return;
751 }
752
756
759
762 /* TRANS: Your <unit> became ... rank of <veteran level>. */
763 _("Your %s became more experienced and achieved the rank "
764 "of %s."),
766}
767
768/**********************************************************************/
771static void unit_convert(struct unit *punit)
772{
773 const struct unit_type *to_type;
774 const struct unit_type *from_type;
775
777 to_type = from_type->converted_to;
778
779 if (unit_can_convert(&(wld.map), punit)) {
783 _("%s converted to %s."),
786 } else {
789 _("%s cannot be converted."),
791 }
792}
793
794/**********************************************************************/
798{
799 if (unit_has_orders(punit)) {
802 _("Orders for %s aborted because activity "
803 "is no longer available."),
806 }
807
810}
811
812/**********************************************************************/
823
824/**********************************************************************/
835
836/**********************************************************************/
850
851/**********************************************************************/
855static void update_unit_activity(struct unit *punit)
856{
857 struct player *pplayer = unit_owner(punit);
859 enum unit_activity activity = punit->activity;
860 struct tile *ptile = unit_tile(punit);
861 const struct unit_type *act_utype = unit_type_get(punit);
862
863 switch (activity) {
864 case ACTIVITY_IDLE:
865 case ACTIVITY_EXPLORE:
867 case ACTIVITY_SENTRY:
868 case ACTIVITY_GOTO:
869 case ACTIVITY_LAST:
870 /* We don't need the activity_count for the above */
871 break;
872
874 case ACTIVITY_CONVERT:
876 break;
877
878 case ACTIVITY_CLEAN:
879 case ACTIVITY_MINE:
881 case ACTIVITY_PILLAGE:
883 case ACTIVITY_PLANT:
885 case ACTIVITY_BASE:
888
889 /* Settler may become veteran when doing something useful */
892 }
893 break;
894 };
895
897
898 switch (activity) {
899 case ACTIVITY_EXPLORE:
900 /* Not accumulating activity - will be handled more like movement
901 * after the TC */
903 case ACTIVITY_IDLE:
905 case ACTIVITY_SENTRY:
906 case ACTIVITY_GOTO:
908 case ACTIVITY_CONVERT:
909 case ACTIVITY_LAST:
910 /* No default, ensure all handled */
911 break;
912
913 case ACTIVITY_PILLAGE:
918
920
921 /* Change vision if effects have changed. */
923 }
924 break;
925
926 case ACTIVITY_CLEAN:
927 /* TODO: Remove this fallback target setting when target always correctly
928 * set */
929 {
930 struct extra_type *pextra;
931
932 if (punit->activity_target == NULL) {
933 pextra = prev_extra_in_tile(ptile, ERM_CLEAN,
934 NULL, punit);
935 if (pextra != NULL) {
936 punit->activity_target = pextra;
937 }
938 } else {
940 pextra = punit->activity_target;
941 } else {
942 pextra = NULL;
943 }
944 }
945
946 if (pextra != NULL) {
947 if (total_activity_done(ptile, ACTIVITY_CLEAN, pextra)) {
948 destroy_extra(ptile, pextra);
950 }
951 }
952 }
953 break;
954
955 case ACTIVITY_BASE:
956 {
961 }
962 }
963 break;
964
966 {
971 }
972 }
973 break;
974
976 case ACTIVITY_MINE:
978 case ACTIVITY_PLANT:
980 if (total_activity_done(ptile, activity, punit->activity_target)) {
981 struct terrain *old = tile_terrain(ptile);
982
983 /* The function below could change the terrain. Therefore, we have to
984 * check the terrain (which will also do a sanity check for the tile). */
985 tile_apply_activity(ptile, activity, punit->activity_target);
986 check_terrain_change(ptile, old);
988 }
989 break;
990 }
991
992 if (unit_activity_done) {
994
996
998 if (punit2->activity == activity
999 && punit2->activity_target == act_tgt) {
1000 /* This unit was helping with the work just finished.
1001 * Mark it idle (already finished) so its "current"
1002 * activity is not considered illegal
1003 * in tile_change_side_effects() . */
1005 }
1007
1009 }
1010
1011 if (activity == ACTIVITY_FORTIFYING) {
1014 punit, ptile, punit->activity_target)) {
1017 }
1018 }
1019
1020 if (activity == ACTIVITY_CONVERT) {
1023 punit, ptile, punit->activity_target)) {
1027 }
1028 }
1029
1030 if (unit_activity_done) {
1031 if (activity == ACTIVITY_PILLAGE) {
1032 /* Casus Belli for when the action is completed. */
1033 /* TODO: is it more logical to put Casus_Belli_Success here, change
1034 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1035 * trigger it when an activity successfully has began? */
1038 act_utype,
1042 }
1043 }
1044}
1045
1046/**********************************************************************/
1054
1055/**********************************************************************/
1060{
1061 switch (activity) {
1062 case ACTIVITY_PILLAGE:
1063 /* Can be set server side. */
1064 return FALSE;
1065 default:
1066 return activity_requires_target(activity);
1067 }
1068}
1069
1070/**********************************************************************/
1080 enum unit_activity *activity,
1081 struct extra_type **target)
1082{
1083 const struct civ_map *nmap = &(wld.map);
1084
1085 if (*activity == ACTIVITY_PILLAGE
1086 && *target == NULL) {
1087 struct tile *ptile = unit_tile(punit);
1088 struct extra_type *tgt;
1089 bv_extras extras = *tile_extras(ptile);
1090
1091 while ((tgt = get_preferred_pillage(extras))) {
1092
1093 BV_CLR(extras, extra_index(tgt));
1094
1095 if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
1096 *target = tgt;
1097 return;
1098 }
1099 }
1100
1101 /* Nothing we can pillage here. */
1102 *activity = ACTIVITY_IDLE;
1103 }
1104}
1105
1106/**********************************************************************/
1111 struct player *powner,
1112 struct unit_type *u_type,
1113 int sq_radius,
1114 struct tile **dst_tile)
1115{
1116 int bestvalue = 0;
1117 struct civ_map *nmap = &(wld.map);
1118
1119 /* coords of best tile in arg pointers */
1121 int value;
1122
1123 if (!is_native_tile(u_type, ptile)) {
1124 continue;
1125 }
1126
1127 if (NULL != tile_city(ptile)) {
1128 continue;
1129 }
1130
1131 if (0 < unit_list_size(ptile->units)) {
1132 continue;
1133 }
1134
1135 /* City may not have changed hands yet; see place_partisans(). */
1136 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1137 ptile, FALSE, 0);
1138 value *= 10;
1139
1140 if (tile_continent(ptile) != tile_continent(pcenter)) {
1141 value /= 2;
1142 }
1143
1144 value -= fc_rand(value/3);
1145
1146 if (value > bestvalue) {
1147 *dst_tile = ptile;
1148 bestvalue = value;
1149 }
1151
1152 return bestvalue > 0;
1153}
1154
1155/**********************************************************************/
1158void place_partisans(struct tile *pcenter, struct player *powner,
1159 int count, int sq_radius)
1160{
1161 struct tile *ptile = NULL;
1163 const struct civ_map *nmap = &(wld.map);
1164
1165 while (count-- > 0
1167 sq_radius, &ptile)) {
1168 struct unit *punit;
1169
1170 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1172 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1173 }
1174
1175 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1176 }
1177}
1178
1179/**********************************************************************/
1184bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1185 int move_cost, bool verbose)
1186{
1187 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1188
1189 if (city_owner(pcity) == unit_owner(punit)) {
1190 log_verbose("Teleported %s %s from (%d,%d) to %s",
1192 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1193 if (verbose) {
1196 _("Teleported your %s to %s."),
1198 city_link(pcity));
1199 }
1200
1201 /* Silently free orders since they won't be applicable anymore. */
1203
1204 if (move_cost == -1) {
1205 move_cost = punit->moves_left;
1206 }
1207 unit_move(punit, dst_tile, move_cost,
1209
1210 return TRUE;
1211 }
1212 return FALSE;
1213}
1214
1215/**********************************************************************/
1222void bounce_unit(struct unit *punit, bool verbose)
1223{
1224 struct player *pplayer;
1225 struct tile *punit_tile;
1226 int count = 0;
1227
1228 /* I assume that there are no topologies that have more than
1229 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1230 const int DIST = 2;
1231 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1232
1233 if (!punit) {
1234 return;
1235 }
1236
1237 pplayer = unit_owner(punit);
1239
1240 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1241 if (count >= ARRAY_SIZE(tiles)) {
1242 break;
1243 }
1244
1245 if (ptile == punit_tile) {
1246 continue;
1247 }
1248
1249 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1250 && !is_non_allied_city_tile(ptile, pplayer)
1251 && !is_non_allied_unit_tile(ptile, pplayer)) {
1252 tiles[count++] = ptile;
1253 }
1255
1256 if (count > 0) {
1257 struct tile *ptile = tiles[fc_rand(count)];
1258
1259 if (verbose) {
1260 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1261 /* TRANS: A unit is moved to resolve stack conflicts. */
1262 _("Moved your %s."),
1263 unit_link(punit));
1264 }
1265
1266 /* TODO: should a unit be able to bounce to a transport like is done
1267 * below? What if the unit can't legally enter the transport, say
1268 * because the transport is Unreachable and the unit doesn't have it in
1269 * its embarks field or because "Transport Embark" isn't enabled? Kept
1270 * like it was to preserve the old rules for now. -- Sveinung */
1271 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1272 return;
1273 }
1274
1275 /* Didn't find a place to bounce the unit, going to disband it.
1276 * Try to bounce transported units. */
1278 struct unit_list *pcargo_units;
1279
1282 bounce_unit(pcargo, verbose);
1284 }
1285
1286 if (verbose) {
1288 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1289 _("Disbanded your %s."),
1291 }
1292
1294}
1295
1296/**********************************************************************/
1301static void throw_units_from_illegal_cities(struct player *pplayer,
1302 bool verbose)
1303{
1304 struct tile *ptile;
1305 struct city *pcity;
1306 struct unit *ptrans;
1307 struct unit_list *pcargo_units;
1308
1309 /* Unload undesired units from transports, if possible. */
1310 unit_list_iterate(pplayer->units, punit) {
1311 ptile = unit_tile(punit);
1312 pcity = tile_city(ptile);
1313 if (NULL != pcity
1314 && !pplayers_allied(city_owner(pcity), pplayer)
1318 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1319 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1321 }
1322 }
1324 }
1326
1327 /* Bounce units except transported ones which will be bounced with their
1328 * transport. */
1330 ptile = unit_tile(punit);
1331 pcity = tile_city(ptile);
1332 if (NULL != pcity
1333 && !pplayers_allied(city_owner(pcity), pplayer)) {
1335 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1336 bounce_unit(punit, verbose);
1337 }
1338 }
1340
1341#ifdef FREECIV_DEBUG
1342 /* Sanity check. */
1343 unit_list_iterate(pplayer->units, punit) {
1344 ptile = unit_tile(punit);
1345 pcity = tile_city(ptile);
1346 fc_assert_msg(NULL == pcity
1347 || pplayers_allied(city_owner(pcity), pplayer),
1348 "Failed to throw %s %d from %s %d (%d, %d)",
1350 punit->id,
1351 city_name_get(pcity),
1352 pcity->id,
1353 TILE_XY(ptile));
1355#endif /* FREECIV_DEBUG */
1356}
1357
1358/**********************************************************************/
1366static void resolve_stack_conflicts(struct player *pplayer,
1367 struct player *aplayer, bool verbose)
1368{
1370 struct tile *ptile = unit_tile(punit);
1371
1372 if (is_non_allied_unit_tile(ptile, pplayer)) {
1374 if (unit_owner(aunit) == pplayer
1375 || unit_owner(aunit) == aplayer
1376 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1377 bounce_unit(aunit, verbose);
1378 }
1380 }
1382}
1383
1384/**********************************************************************/
1395void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1396 bool verbose)
1397{
1398 throw_units_from_illegal_cities(pplayer, verbose);
1400
1401 resolve_stack_conflicts(pplayer, aplayer, verbose);
1402 resolve_stack_conflicts(aplayer, pplayer, verbose);
1403}
1404
1405/**********************************************************************/
1410struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1411 const struct player *aplayer)
1412{
1413 struct unit_list *seen_units = unit_list_new();
1414
1415 /* Anybody's units inside ally's cities */
1416 city_list_iterate(aplayer->cities, pcity) {
1417 unit_list_iterate(city_tile(pcity)->units, punit) {
1418 if (can_player_see_unit(pplayer, punit)) {
1420 }
1423
1424 /* Ally's own units inside transports */
1426 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1428 }
1430
1431 /* Make sure the same unit is not added in multiple phases
1432 * (unit within transport in a city) */
1434
1435 return seen_units;
1436}
1437
1438/**********************************************************************/
1445void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1446 const struct unit_list *seen_units)
1447{
1449 /* We need to hide units previously seen by the client. */
1450 if (!can_player_see_unit(pplayer, punit)) {
1451 unit_goes_out_of_sight(pplayer, punit);
1452 }
1454
1455 city_list_iterate(aplayer->cities, pcity) {
1456 /* The player used to know what units were in these cities. Now that
1457 * they don't, they need to get a new short city packet updating the
1458 * occupied status. */
1459 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1460 send_city_info(pplayer, pcity);
1461 }
1463}
1464
1465/**********************************************************************/
1469void give_allied_visibility(struct player *pplayer,
1470 struct player *aplayer)
1471{
1473 if (can_player_see_unit(pplayer, punit)) {
1474 send_unit_info(pplayer->connections, punit);
1475 }
1477}
1478
1479/**********************************************************************/
1482static bool is_refuel_tile(const struct tile *ptile,
1483 const struct player *pplayer,
1484 const struct unit *punit)
1485{
1486 const struct unit_type *utype;
1487 const struct unit_class *pclass;
1488
1489 if (is_allied_city_tile(ptile, pplayer)) {
1490 return TRUE;
1491 }
1492
1493 utype = unit_type_get(punit);
1494 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1495 return TRUE;
1496 }
1497
1498 pclass = utype_class(utype);
1499 if (NULL != pclass->cache.refuel_extras) {
1500 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1501
1502 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1503 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1504 return TRUE;
1505 }
1507 }
1508
1509 return FALSE;
1510}
1511
1512/**********************************************************************/
1516{
1517 return unit_transported(punit) /* Carrier */
1519}
1520
1521/**********************************************************************/
1524bool is_refuel_point(const struct tile *ptile,
1525 const struct player *pplayer,
1526 const struct unit *punit)
1527{
1528 if (is_non_allied_unit_tile(ptile, pplayer)) {
1529 return FALSE;
1530 }
1531
1532 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1533}
1534
1535/**********************************************************************/
1546void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1547 int vet_loss)
1548{
1549 struct player *pplayer = unit_owner(punit);
1550 const struct unit_type *old_type = punit->utype;
1552 int old_hp = unit_type_get(punit)->hp;
1553 int lvls;
1554
1555 punit->utype = to_unit;
1556
1557 /* New type may not have the same veteran system, and we may want to
1558 * knock some levels off. */
1561 /* Keeping the old behavior, so first clip top, then reduce */
1563
1564 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1565 * and don't kill the unit. unit_move_rate() is used to take into account
1566 * global effects like Magellan's Expedition. */
1567 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1568 if (old_mr == 0) {
1570 } else {
1572 }
1573
1575
1579 }
1580
1581 /* Update unit upkeep */
1583
1585
1587
1588 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1590
1593}
1594
1595/**********************************************************************/
1598struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1599 const struct unit_type *type, int veteran_level,
1600 int homecity_id, int moves_left)
1601{
1602 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1603 moves_left, -1, NULL);
1604}
1605
1606/**********************************************************************/
1610{
1611 if (punit->homecity != 0) {
1613
1616 }
1617 }
1618}
1619
1620/**********************************************************************/
1625struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1626 const struct unit_type *type, int veteran_level,
1627 int homecity_id, int moves_left, int hp_left,
1628 struct unit *ptrans)
1629{
1630 struct unit *punit
1631 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1633 struct city *pcity = (!homecity_id || utype_has_flag(type, UTYF_NOHOME))
1635 bool could_place;
1636
1638 could_place = place_unit(punit, pplayer, pcity, ptrans, FALSE);
1640 if (!could_place) {
1642 punit = NULL;
1643 }
1644
1645 return punit;
1646}
1647
1648/**********************************************************************/
1658struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1659 const struct unit_type *type,
1660 int veteran_level, int homecity_id,
1661 int moves_left, int hp_left)
1662{
1663 struct unit *punit;
1664
1665 fc_assert_ret_val(ptile != NULL, NULL);
1667 unit_tile_set(punit, ptile);
1668
1670 punit->homecity = 0; /* none */
1671 } else {
1673 }
1674
1675 if (hp_left >= 0) {
1676 /* Override default full HP */
1677 punit->hp = hp_left;
1678 }
1679
1680 if (moves_left >= 0) {
1681 int mr = unit_move_rate(punit);
1682
1683 /* Override default full MP */
1684 /* FIXME: there are valid situations when a unit have mp
1685 * over its move rate. Here, keeping the old behavior. */
1687 /* Assume that if moves_left < 0 then the unit is "fresh",
1688 * and not moved; else the unit has had something happen
1689 * to it (eg, bribed) which we treat as equivalent to moved.
1690 * (Otherwise could pass moved arg too...) --dwp */
1691 punit->moved = TRUE;
1692 }
1693
1694 return punit;
1695}
1696
1697/**********************************************************************/
1706bool place_unit(struct unit *punit, struct player *pplayer,
1707 struct city *pcity, struct unit *ptrans, bool force)
1708{
1709 struct tile *ptile;
1710
1711 fc_assert_ret_val(pplayer, FALSE);
1713 ptile = punit->tile;
1714 fc_assert_ret_val(ptile, FALSE);
1715
1716 /* Register unit */
1719
1720 if (ptrans) {
1721 /* Set transporter for unit. */
1723 }
1724
1726 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1727 FALSE);
1728
1729 unit_list_prepend(pplayer->units, punit);
1730 unit_list_prepend(ptile->units, punit);
1732 if (pcity && !unit_has_type_flag(punit, UTYF_NOHOME)) {
1733 fc_assert(punit->homecity == pcity->id);
1734 fc_assert(city_owner(pcity) == pplayer);
1736 /* update unit upkeep */
1737 city_units_upkeep(pcity);
1738 /* Refresh the unit's homecity. */
1739 city_refresh(pcity);
1740 send_city_info(pplayer, pcity);
1741 }
1742
1743 punit->server.vision = vision_new(pplayer, ptile);
1745
1747
1750
1751 /* The unit may have changed the available tiles in nearby cities. */
1753 sync_cities();
1754
1755 CALL_FUNC_EACH_AI(unit_created, punit);
1756 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1757
1758 return TRUE;
1759}
1760
1761/**********************************************************************/
1765 void (*callback)(struct unit *punit))
1766{
1767 /* Tried to overwrite another call back. If this assertion is triggered
1768 * in a case where two call back are needed it may be time to support
1769 * more than one unit removal call back at a time. */
1771
1773}
1774
1775/**********************************************************************/
1782
1783/**********************************************************************/
1787static void server_remove_unit_full(struct unit *punit, bool transported,
1789{
1790 struct packet_unit_remove packet;
1791 struct tile *ptile = unit_tile(punit);
1792 struct city *pcity = tile_city(ptile);
1794 struct unit *ptrans;
1795 struct player *pplayer = unit_owner(punit);
1796
1797 /* The unit is doomed. */
1799
1800#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1801 unit_list_iterate(ptile->units, pcargo) {
1804#endif /* FREECIV_DEBUG */
1805
1806 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1807 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1808
1809 /* Save transporter for updating below. */
1811 /* Unload unit. */
1813
1814 /* Since settlers plot in new cities in the minimap before they
1815 are built, so that no two settlers head towards the same city
1816 spot, we need to ensure this reservation is cleared should
1817 the settler disappear on the way. */
1819
1820 /* Clear the vision before sending unit remove. Else, we might duplicate
1821 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1822 if (punit->server.vision != NULL) {
1826 }
1827
1828 packet.unit_id = punit->id;
1829 /* Send to onlookers. */
1832 transported)) {
1833 lsend_packet_unit_remove(aplayer->connections, &packet);
1834 }
1836 /* Send to global observers. */
1840 }
1842
1843 if (punit->server.moving != NULL) {
1844 /* Do not care of this unit for running moves. */
1846 }
1847
1849 /* Run the unit removal call back. */
1851 }
1852
1853 /* check if this unit had UTYF_GAMELOSS flag */
1855 && ULR_EDITOR != reason) {
1857 _("Unable to defend %s, %s has lost the game."),
1859 player_name(pplayer));
1860 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1861 _("Losing %s meant losing the game! "
1862 "Be more careful next time!"),
1863 unit_link(punit));
1865 }
1866
1869
1872 punit = NULL;
1873
1874 if (NULL != ptrans) {
1875 /* Update the occupy info. */
1877 }
1878
1879 /* This unit may have blocked tiles of adjacent cities. Update them. */
1881 sync_cities();
1882
1883 if (phomecity) {
1886 }
1887
1888 if (pcity && pcity != phomecity) {
1889 city_refresh(pcity);
1890 send_city_info(city_owner(pcity), pcity);
1891 }
1892
1893 if (pcity && unit_list_size(ptile->units) == 0) {
1894 /* The last unit in the city was killed: update the occupied flag. */
1895 send_city_info(NULL, pcity);
1896 }
1897}
1898
1899/**********************************************************************/
1908
1909/**********************************************************************/
1912static void unit_lost_with_transport(const struct player *pplayer,
1913 struct unit *pcargo,
1914 const struct unit_type *ptransport,
1915 struct player *killer)
1916{
1918 _("%s lost when %s was lost."),
1921 /* Unit is not transported any more at this point, but it has jumped
1922 * off the transport and drowns outside. So it must be removed from
1923 * all clients.
1924 * However, we don't know if given client has received ANY updates
1925 * about the swimming unit, and we can't remove it if it's not there
1926 * in the first place -> we send it once here just to be sure it's
1927 * there. */
1930}
1931
1932/**********************************************************************/
1936static void wipe_unit_full(struct unit *punit, bool transported,
1938 struct player *killer)
1939{
1940 struct tile *ptile = unit_tile(punit);
1941 struct player *pplayer = unit_owner(punit);
1942 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1943 struct unit_list *helpless = unit_list_new();
1944 struct unit_list *imperiled = unit_list_new();
1945 struct unit_list *unsaved = unit_list_new();
1947 struct city *pexclcity;
1948 struct civ_map *nmap = &(wld.map);
1949
1950 if (killer != NULL
1953 player_loot_player(killer, pplayer);
1954 }
1955
1956 /* The unit is doomed. */
1958
1959 /* If a unit is being lost due to loss of its city, ensure that we don't
1960 * try to teleport any of its cargo to that city (which may not yet
1961 * have changed hands or disappeared). (It is assumed that the unit's
1962 * home city is always the one that is being lost/transferred/etc.) */
1963 if (reason == ULR_CITY_LOST) {
1965 } else {
1966 pexclcity = NULL;
1967 }
1968
1969 /* Remove unit itself from its transport */
1970 if (ptrans != NULL) {
1973 }
1974
1975 /* First pull all units off of the transporter. */
1977 /* Use iterate_safe as unloaded units will be removed from the list
1978 * while iterating. */
1980 bool healthy = FALSE;
1981
1982 if (!can_unit_unload(pcargo, punit)) {
1984 } else {
1985 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
1987 } else {
1988 /* These units do not need to be saved. */
1989 healthy = TRUE;
1990 }
1991 }
1992
1993 /* Could use unit_transport_unload_send() here, but that would
1994 * call send_unit_info() for the transporter unnecessarily.
1995 * Note that this means that unit might to get seen briefly
1996 * by clients other than owner's, for example as a result of
1997 * update of homecity common to this cargo and some other
1998 * destroyed unit. */
2000 if (pcargo->activity == ACTIVITY_SENTRY) {
2001 /* Activate sentried units - like planes on a disbanded carrier.
2002 * Note this will activate ground units even if they just change
2003 * transporter. */
2005 }
2006
2007 /* Unit info for unhealthy units will be sent when they are
2008 * assigned new transport or removed. */
2009 if (healthy) {
2011 }
2013 }
2014
2015 /* Now remove the unit. */
2016 server_remove_unit_full(punit, transported, reason);
2017
2018 switch (reason) {
2019 case ULR_KILLED:
2020 case ULR_EXECUTED:
2021 case ULR_SDI:
2022 case ULR_NUKE:
2023 case ULR_BRIBED:
2024 case ULR_CAPTURED:
2025 case ULR_CAUGHT:
2026 case ULR_ELIMINATED:
2027 case ULR_TRANSPORT_LOST:
2028 if (killer != NULL) {
2029 killer->score.units_killed++;
2030 }
2031 pplayer->score.units_lost++;
2032 break;
2033 case ULR_BARB_UNLEASH:
2034 case ULR_CITY_LOST:
2035 case ULR_STARVED:
2036 case ULR_UPKEEP:
2037 case ULR_NONNATIVE_TERR:
2038 case ULR_ARMISTICE:
2039 case ULR_HP_LOSS:
2040 case ULR_FUEL:
2041 case ULR_STACK_CONFLICT:
2042 case ULR_SOLD:
2043 pplayer->score.units_lost++;
2044 break;
2045 case ULR_RETIRED:
2046 case ULR_DISBANDED:
2047 case ULR_USED:
2048 case ULR_DETONATED:
2049 case ULR_MISSILE:
2050 pplayer->score.units_used++;
2051 break;
2052 case ULR_EDITOR:
2053 case ULR_PLAYER_DIED:
2054 break;
2055 }
2056
2057 /* First, sort out helpless cargo. */
2058 if (unit_list_size(helpless) > 0) {
2059 struct unit_list *remaining = unit_list_new();
2060
2061 /* Grant priority to gameloss units and units with the EvacuateFirst
2062 * unit type flag. */
2069 pexclcity)) {
2071 }
2072 } else {
2073 unit_list_prepend(remaining, pcargo);
2074 }
2076
2077 /* Handle non-priority units. */
2078 unit_list_iterate_safe(remaining, pcargo) {
2081 }
2083
2084 unit_list_destroy(remaining);
2085 }
2087
2088 /* Then, save any imperiled cargo. */
2089 if (unit_list_size(imperiled) > 0) {
2090 struct unit_list *remaining = unit_list_new();
2091
2092 /* Grant priority to gameloss units and units with the EvacuateFirst
2093 * unit type flag. */
2100 pexclcity)) {
2102 }
2103 } else {
2104 unit_list_prepend(remaining, pcargo);
2105 }
2107
2108 /* Handle non-priority units. */
2109 unit_list_iterate_safe(remaining, pcargo) {
2112 }
2114
2115 unit_list_destroy(remaining);
2116 }
2118
2119 /* Finally, kill off the unsaved units. */
2120 if (unit_list_size(unsaved) > 0) {
2124 }
2126}
2127
2128/**********************************************************************/
2137
2138/**********************************************************************/
2144static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2145 bool helpless, bool teleporting,
2146 const struct city *pexclcity)
2147{
2148 struct tile *ptile = unit_tile(punit);
2149 struct player *pplayer = unit_owner(punit);
2151
2152 /* Helpless units cannot board a transport in their current state. */
2153 if (!helpless
2154 && ptransport != NULL) {
2157 return TRUE;
2158 } else {
2159 /* Only units that cannot find transport are considered for teleport. */
2160 if (teleporting) {
2161 struct city *pcity = find_closest_city(ptile, pexclcity,
2165 if (pcity != NULL) {
2166 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2167
2169
2170 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2171 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2172 _("%s escaped the destruction of %s, and fled to %s."),
2173 tplink,
2175 city_link(pcity));
2176 return TRUE;
2177 }
2178 }
2179 }
2180 }
2181
2182 /* The unit could not use transport on the tile, and could not teleport. */
2183 return FALSE;
2184}
2185
2186/**********************************************************************/
2192struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2194{
2195 struct unit *gained_unit;
2196 int id = 0;
2197
2198#ifndef FREECIV_NDEBUG
2199 bool placed;
2200#endif
2201
2204
2205 /* Convert the unit to your cause. It's supposed that the original unit
2206 * is on a valid tile and is not transported. */
2210 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2211
2212 /* Owner changes, nationality not. */
2213 gained_unit->nationality = punit->nationality;
2214
2215 /* Copy some more unit fields */
2216 gained_unit->fuel = punit->fuel;
2217 gained_unit->paradropped = punit->paradropped;
2218 gained_unit->birth_turn = punit->birth_turn;
2219 gained_unit->current_form_turn = punit->current_form_turn;
2220
2221 /* Fog is lifted in the placing algorithm. */
2222#ifndef FREECIV_NDEBUG
2223 placed =
2224#endif
2225 place_unit(gained_unit, pplayer,
2227 NULL, FALSE);
2228
2230
2231 id = gained_unit->id;
2232
2233 /* Update unit upkeep in the new homecity */
2234 if (homecity > 0) {
2236 }
2237
2238 /* Be sure to wipe the converted unit! */
2239 /* Old homecity upkeep is updated in process */
2240#ifndef FREECIV_NDEBUG
2241 uco_wipe:
2242#endif
2243
2245
2246 if (!unit_is_alive(id)) {
2247 /* Destroyed by a script */
2248 return NULL;
2249 }
2250
2251 return gained_unit; /* Returns the replacement. */
2252}
2253
2254/**********************************************************************/
2259void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2260{
2262 struct player *pvictim = unit_owner(punit);
2263 struct player *pvictor = unit_owner(pkiller);
2264 struct tile *deftile = unit_tile(punit);
2265 int unitcount = 0;
2266 bool escaped;
2267 const struct civ_map *nmap = &(wld.map);
2268
2271
2272 /* The unit is doomed. */
2274
2278 unitcount++;
2279 }
2281
2282 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2283 if (vet) {
2285 }
2287 } else { /* Unitcount > 1 */
2288 int i;
2289 int slots = player_slot_count();
2290 int num_killed[slots];
2291 int num_escaped[slots];
2292 struct unit *other_killed[slots];
2293
2294 fc_assert(unitcount > 1);
2295
2296 /* Initialize */
2297 for (i = 0; i < slots; i++) {
2298 num_killed[i] = 0;
2299 other_killed[i] = NULL;
2300 num_escaped[i] = 0;
2301 }
2302
2303 /* Count killed units */
2305 struct player *vplayer = unit_owner(vunit);
2306
2309 escaped = FALSE;
2310
2313 && vunit->hp > 0
2314 && vunit->moves_left > pkiller->moves_left
2315 && fc_rand(2)) {
2316 int curr_def_bonus;
2317 int def_bonus = 0;
2318 struct tile *dsttile = NULL;
2319 int move_cost;
2320
2321 fc_assert(vunit->hp > 0);
2322
2324 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2325 && NULL == tile_city(ptile2)) {
2326 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2327 if (pkiller->moves_left <= vunit->moves_left - move_cost
2329 || unit_list_size(ptile2->units)) == 0) {
2331 vunit->utype);
2332 if (def_bonus <= curr_def_bonus) {
2334 dsttile = ptile2;
2335 }
2336 }
2337 }
2339
2340 if (dsttile != NULL) {
2343 NULL, NULL, dsttile,
2345 NULL, NULL)
2346 != NULL);
2347
2348 if (escaped) {
2350 unitcount--;
2351 }
2352 }
2353 }
2354
2355 if (!escaped) {
2357
2358 if (vunit != punit) {
2361 }
2362 }
2363 }
2365
2366 /* Inform the destroyer again if more than one unit was killed */
2367 if (unitcount > 1) {
2369 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2370 PL_("Your attacking %s succeeded against the %s %s "
2371 "(and %d other unit)!",
2372 "Your attacking %s succeeded against the %s %s "
2373 "(and %d other units)!", unitcount - 1),
2376 punit_link,
2377 unitcount - 1);
2378 }
2379
2380 if (vet) {
2382 }
2383
2384 /* Inform the owners: this only tells about owned units that were killed.
2385 * there may have been 20 units who died but if only 2 belonged to the
2386 * particular player they'll only learn about those.
2387 *
2388 * Also if a large number of units die you don't find out what type
2389 * they all are. */
2390 for (i = 0; i < slots; i++) {
2391 if (num_killed[i] == 1) {
2392 if (i == player_index(pvictim)) {
2396 /* TRANS: "Cannon ... the Polish Destroyer." */
2397 _("%s lost to an attack by the %s %s."),
2398 punit_link,
2400 pkiller_link);
2401 } else {
2405 /* TRANS: "Cannon lost when the Polish Destroyer
2406 * attacked the German Musketeers." */
2407 _("%s lost when the %s %s attacked the %s %s."),
2412 punit_link);
2413 }
2414 } else if (num_killed[i] > 1) {
2415 if (i == player_index(pvictim)) {
2416 int others = num_killed[i] - 1;
2417
2418 if (others == 1) {
2421 /* TRANS: "Musketeers (and Cannon) lost to an
2422 * attack from the Polish Destroyer." */
2423 _("%s (and %s) lost to an attack from the %s %s."),
2424 punit_link,
2427 pkiller_link);
2428 } else {
2431 /* TRANS: "Musketeers and 3 other units lost to
2432 * an attack from the Polish Destroyer."
2433 * (only happens with at least 2 other units) */
2434 PL_("%s and %d other unit lost to an attack "
2435 "from the %s %s.",
2436 "%s and %d other units lost to an attack "
2437 "from the %s %s.", others),
2438 punit_link,
2439 others,
2441 pkiller_link);
2442 }
2443 } else {
2446 /* TRANS: "2 units lost when the Polish Destroyer
2447 * attacked the German Musketeers."
2448 * (only happens with at least 2 other units) */
2449 PL_("%d unit lost when the %s %s attacked the %s %s.",
2450 "%d units lost when the %s %s attacked the %s %s.",
2451 num_killed[i]),
2452 num_killed[i],
2456 punit_link);
2457 }
2458 }
2459 }
2460
2461 /* Inform the owner of the units that escaped.
2462 * 'deftile' is the original tile they defended at, not where
2463 * they escaped to, as there might be multiple different tiles
2464 * different units escaped to. */
2465 for (i = 0; i < slots; i++) {
2466 if (0 < num_escaped[i]) {
2469 PL_("%d unit escaped from attack by %s %s",
2470 "%d units escaped from attack by %s %s",
2471 num_escaped[i]),
2472 num_escaped[i],
2475 );
2476 }
2477 }
2478
2479 /* Remove the units - note the logic of which units actually die
2480 * must be mimiced exactly in at least one place up above. */
2481 punit = NULL; /* Wiped during following iteration so unsafe to use */
2482
2487 }
2489 }
2490}
2491
2492/**********************************************************************/
2495void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
2496{
2497 struct player *pvictim = unit_owner(punit);
2500 struct tile *deftile = unit_tile(punit);
2501 int unitcount, ransom;
2502
2503 /* The unit is doomed. */
2505
2508
2509 if (pvictim->economic.gold < ransom) {
2510 ransom = pvictim->economic.gold;
2511 }
2512
2514 PL_("%d Barbarian leader captured.",
2515 "%d Barbarian leaders captured.",
2516 unitcount),
2517 unitcount);
2519 PL_("%d gold ransom paid.",
2520 "%d gold ransom paid.",
2521 ransom),
2522 ransom);
2523 pvictor->economic.gold += ransom;
2524 pvictim->economic.gold -= ransom;
2525 send_player_info_c(pvictor, NULL); /* Let me see my new gold :-) */
2526
2527 if (vet) {
2529 }
2530
2533
2534 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2536 } else {
2537 int i;
2538 int slots = player_slot_count();
2539 int num_collected[slots];
2540
2541 fc_assert(unitcount > 1);
2542
2543 /* Initialize */
2544 for (i = 0; i < slots; i++) {
2545 num_collected[i] = 0;
2546 }
2547
2548 /* Count captured units */
2550 struct player *vplayer = unit_owner(vunit);
2551
2554
2555 for (i = 0; i < slots; i++) {
2556 if (num_collected[i] == 1) {
2559 _("%s %s collected ransom of %s."),
2562 } else if (num_collected[i] > 1) {
2565 PL_("%s %s collected ransom of %s and %d other unit.",
2566 "%s %s collected ransom of %s and %d other units.",
2567 num_collected[i] - 1),
2570 punit_link,
2571 num_collected[i] - 1);
2572 }
2573 }
2574
2578 }
2579}
2580
2581/**********************************************************************/
2585void package_unit(struct unit *punit, struct packet_unit_info *packet)
2586{
2587 packet->id = punit->id;
2588 packet->owner = player_number(unit_owner(punit));
2590 packet->tile = tile_index(unit_tile(punit));
2591 packet->facing = punit->facing;
2592 packet->homecity = punit->homecity;
2594 packet->upkeep[o] = punit->upkeep[o];
2596 packet->veteran = punit->veteran;
2598 packet->movesleft = punit->moves_left;
2599 packet->hp = punit->hp;
2600 packet->activity = punit->activity;
2602
2603 if (punit->activity_target != NULL) {
2605 } else {
2606 packet->activity_tgt = EXTRA_NONE;
2607 }
2608
2609 packet->changed_from = punit->changed_from;
2611
2612 if (punit->changed_from_target != NULL) {
2614 } else {
2615 packet->changed_from_tgt = EXTRA_NONE;
2616 }
2617
2619 packet->fuel = punit->fuel;
2620 packet->goto_tile = (NULL != punit->goto_tile
2621 ? tile_index(punit->goto_tile) : -1);
2622 packet->paradropped = punit->paradropped;
2623 packet->done_moving = punit->done_moving;
2624 packet->stay = punit->stay;
2625 packet->birth_turn = punit->birth_turn;
2627 if (!unit_transported(punit)) {
2628 packet->transported = FALSE;
2629 packet->transported_by = 0;
2630 } else {
2631 packet->transported = TRUE;
2633 }
2634 if (punit->carrying != NULL) {
2635 packet->carrying = goods_index(punit->carrying);
2636 } else {
2637 packet->carrying = -1;
2638 }
2639 packet->occupied = (get_transporter_occupancy(punit) > 0);
2640 packet->battlegroup = punit->battlegroup;
2641 packet->has_orders = punit->has_orders;
2642 if (punit->has_orders) {
2643 packet->orders_length = punit->orders.length;
2644 packet->orders_index = punit->orders.index;
2645 packet->orders_repeat = punit->orders.repeat;
2647 memcpy(packet->orders, punit->orders.list,
2648 punit->orders.length * sizeof(struct unit_order));
2649 } else {
2650 packet->orders_length = packet->orders_index = 0;
2651 packet->orders_repeat = packet->orders_vigilant = FALSE;
2652 /* No need to initialize array. */
2653 }
2654
2659}
2660
2661/**********************************************************************/
2667 struct packet_unit_short_info *packet,
2668 enum unit_info_use packet_use, int info_city_id)
2669{
2670 packet->packet_use = packet_use;
2671 packet->info_city_id = info_city_id;
2672
2673 packet->id = punit->id;
2674 packet->owner = player_number(unit_owner(punit));
2675 packet->tile = tile_index(unit_tile(punit));
2676 packet->facing = punit->facing;
2677 packet->veteran = punit->veteran;
2679 packet->hp = punit->hp;
2680 packet->occupied = (get_transporter_occupancy(punit) > 0);
2682 || punit->activity == ACTIVITY_GOTO) {
2683 packet->activity = ACTIVITY_IDLE;
2684 } else {
2685 packet->activity = punit->activity;
2686 }
2687
2688 if (punit->activity_target == NULL) {
2689 packet->activity_tgt = EXTRA_NONE;
2690 } else {
2692 }
2693
2694 /* Transported_by information is sent to the client even for units that
2695 * aren't fully known. Note that for non-allied players, any transported
2696 * unit can't be seen at all. For allied players we have to know if
2697 * transporters have room in them so that we can load units properly. */
2698 if (!unit_transported(punit)) {
2699 packet->transported = FALSE;
2700 packet->transported_by = 0;
2701 } else {
2702 packet->transported = TRUE;
2704 }
2705}
2706
2707/**********************************************************************/
2710void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2711{
2713 if (punit->server.moving != NULL) {
2714 /* Update status of 'pplayer' vision for 'punit'. */
2716 }
2717}
2718
2719/**********************************************************************/
2723void send_unit_info(struct conn_list *dest, struct unit *punit)
2724{
2725 const struct player *powner;
2726 struct packet_unit_info info;
2728 struct unit_move_data *pdata;
2729
2730 if (dest == NULL) {
2731 dest = game.est_connections;
2732 }
2733
2735
2737 package_unit(punit, &info);
2740
2741 conn_list_iterate(dest, pconn) {
2742 struct player *pplayer = conn_get_player(pconn);
2743
2744 /* Be careful to consider all cases where pplayer is NULL... */
2745 if (pplayer == NULL) {
2746 if (pconn->observer) {
2748 }
2749 } else if (pplayer == powner) {
2751 if (pdata != NULL) {
2752 BV_SET(pdata->can_see_unit, player_index(pplayer));
2753 }
2754 } else if (can_player_see_unit(pplayer, punit)) {
2756 if (pdata != NULL) {
2757 BV_SET(pdata->can_see_unit, player_index(pplayer));
2758 }
2759 }
2761}
2762
2763/**********************************************************************/
2768{
2769 conn_list_do_buffer(dest);
2770 conn_list_iterate(dest, pconn) {
2771 struct player *pplayer = pconn->playing;
2772
2773 if (NULL == pplayer && !pconn->observer) {
2774 continue;
2775 }
2776
2779 send_unit_info(dest, punit);
2782 }
2785 flush_packets();
2786}
2787
2788/**********************************************************************/
2795static void do_nuke_tile(struct player *pplayer, struct tile *ptile,
2796 const struct action *paction)
2797{
2798 struct city *pcity = NULL;
2799 int pop_loss;
2800
2801 pcity = tile_city(ptile);
2802
2804
2805 /* unit in a city may survive */
2806 if (pcity && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2807 continue;
2808 }
2810 _("Your %s was nuked by %s."),
2812 pplayer == unit_owner(punit)
2813 ? _("yourself")
2814 : nation_plural_for_player(pplayer));
2815 if (unit_owner(punit) != pplayer) {
2816 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2817 _("The %s %s was nuked."),
2820 }
2821 wipe_unit(punit, ULR_NUKE, pplayer);
2823
2824
2825 if (pcity) {
2826 struct player *owner = city_owner(pcity);
2827 char city_name[MAX_LEN_LINK];
2828
2830
2832 _("%s was nuked by %s."),
2833 city_name,
2834 pplayer == owner
2835 ? _("yourself")
2836 : nation_plural_for_player(pplayer));
2837
2838 if (owner != pplayer) {
2839 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2840 _("You nuked %s."),
2841 city_name);
2842 }
2843
2844 pop_loss = round((game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100.0);
2845 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
2846 /* Send city size reduction to everyone seeing it */
2847 send_city_info(NULL, pcity);
2848 } else {
2849 /* City was destroyed */
2851 _("%s was destroyed by the nuke."),
2852 city_name);
2853 if (owner != pplayer) {
2854 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2855 _("Your nuke destroyed %s."),
2856 city_name);
2857 }
2858 }
2859 }
2860
2861 if (fc_rand(2) == 1) {
2862 struct extra_type *pextra;
2863
2864 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
2865 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2866 tile_add_extra(ptile, pextra);
2867 update_tile_knowledge(ptile);
2868 }
2869 }
2870}
2871
2872/**********************************************************************/
2881 const struct unit_type *act_utype,
2882 struct player *pplayer, struct tile *ptile)
2883{
2886 &(const struct req_context) {
2887 .player = pplayer,
2888 /* City: Wait for users before choosing
2889 * home city or target tile city */
2890 .tile = ptile,
2891 .unittype = act_utype,
2892 .action = paction,
2893 },
2894 NULL,
2896
2898 do_nuke_tile(pplayer, ptile1, paction);
2900
2901 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
2902 API_TYPE_PLAYER, pplayer);
2904 _("The %s detonated a nuke!"),
2905 nation_plural_for_player(pplayer));
2906}
2907
2908/**********************************************************************/
2912bool do_airline(struct unit *punit, struct city *pdest_city,
2913 const struct action *paction)
2914{
2916
2919 _("%s transported successfully."),
2920 unit_link(punit));
2921
2924 /* Can only airlift to allied and domestic cities */
2925 FALSE, FALSE,
2926 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
2928
2929 /* Update airlift fields. */
2931 psrc_city->airlift--;
2933 }
2935 pdest_city->airlift--;
2937 }
2938
2939 return TRUE;
2940}
2941
2942/**********************************************************************/
2945void do_explore(struct unit *punit)
2946{
2947 switch (manage_auto_explorer(punit)) {
2948 case MR_DEATH:
2949 /* don't use punit! */
2950 return;
2951 case MR_NOT_ALLOWED:
2952 /* Needed for something else */
2953 return;
2954 case MR_OK:
2955 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
2956 * but don't count on this. See PR#39792.
2957 */
2959 break;
2960 }
2961
2963 default:
2965
2966 /* FIXME: When the manage_auto_explorer() call changes the activity from
2967 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
2968 * alone. We reset it here. See PR#12931. */
2970 break;
2971 }
2972
2973 send_unit_info(NULL, punit); /* probably duplicate */
2974}
2975
2976/**********************************************************************/
2981bool do_paradrop(struct unit *punit, struct tile *ptile,
2982 const struct action *paction)
2983{
2984 struct player *pplayer = unit_owner(punit);
2985 struct player *tgt_player = tile_owner(ptile);
2986 const struct unit_type *act_utype = unit_type_get(punit);
2987 const struct city *pcity;
2988
2989 /* Hard requirements */
2990 /* FIXME: hard requirements belong in common/actions's
2991 * is_action_possible() and the explanation texts belong in
2992 * server/unithand's action not enabled system (expl_act_not_enabl(),
2993 * ane_kind, explain_why_no_action_enabled(), etc)
2994 */
2995 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
2996 /* Only take in account values from player map. */
2997 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
2998
2999 if (NULL == plrtile->site) {
3000 bv_extras fbv;
3001
3002 dbv_to_bv(fbv.vec, &(plrtile->extras));
3003
3005 &fbv)) {
3006 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3007 _("This unit cannot paradrop into %s."),
3009 return FALSE;
3010 }
3011 }
3012
3013 if (NULL != plrtile->site
3014 && plrtile->owner != NULL
3015 && !pplayers_allied(pplayer, plrtile->owner)
3017 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3018 /* TRANS: Paratroopers ... Paradrop Unit */
3019 _("%s cannot conquer a city with \"%s\"."),
3022 return FALSE;
3023 }
3024
3025 if (NULL != plrtile->site
3026 && plrtile->owner != NULL
3027 && (pplayers_non_attack(pplayer, plrtile->owner)
3028 || (player_diplstate_get(pplayer, plrtile->owner)->type
3029 == DS_ALLIANCE)
3030 || (player_diplstate_get(pplayer, plrtile->owner)->type
3031 == DS_TEAM))
3033 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3034 _("Cannot attack unless you declare war first."));
3035 return FALSE;
3036 }
3037 }
3038
3039
3040 /* Kill the unit when the landing goes wrong. */
3041
3042 /* Safe terrain, really? Not transformed since player last saw it. */
3043 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3044 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3045 || !unit_could_load_at(punit, ptile))) {
3046 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3047 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3048 _("Your %s paradropped into the %s and was lost."),
3051 pplayer->score.units_lost++;
3053 return TRUE;
3054 }
3055
3056 pcity = tile_city(ptile);
3057
3058 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3060 || is_non_allied_unit_tile(ptile, pplayer)) {
3061 struct player *main_victim = NULL;
3062 struct player *secondary_victim = NULL;
3064
3065 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3066 maybe_make_contact(ptile, pplayer);
3067 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3068 _("Your %s was killed by enemy units at the "
3069 "paradrop destination."),
3071 /* TODO: Should defender score.units_killed get increased too?
3072 * What if there's units of several allied players? Should the
3073 * city owner or owner of the first/random unit get the kill? */
3074 pplayer->score.units_lost++;
3075
3076 if (pcity != NULL) {
3077 struct player *owner = city_owner(pcity);
3078
3079 if (!pplayers_at_war(pplayer, owner)) {
3081 } else {
3083 }
3084
3086 } else {
3088 }
3089
3090 if (main_victim == NULL) {
3091 unit_list_iterate(ptile->units, tgt) {
3092 struct player *owner = unit_owner(tgt);
3093
3094 if (!pplayers_at_war(pplayer, owner)) {
3096 break;
3097 } else if (secondary_victim == NULL) {
3099 }
3101
3102 if (main_victim == NULL) {
3103 /* There's no victim with whom the attacker isn't in war,
3104 * fallback to one with whom there's already a war. */
3106 }
3107 }
3108
3110 main_victim, ptile,
3111 victim_link);
3112
3114 return TRUE;
3115 }
3116
3117 /* All ok */
3119 if (unit_move(punit, ptile,
3120 /* Done by Action_Success_Actor_Move_Cost */
3121 0,
3122 NULL, BV_ISSET(paction->sub_results,
3126 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3127 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3128 /* Ensure we finished on valid state. */
3131 }
3132
3133 /* May cause an incident */
3135 ptile, tile_link(ptile));
3136
3137 return TRUE;
3138}
3139
3140/**********************************************************************/
3144static bool hut_get_limited(struct unit *punit)
3145{
3146 bool ok = TRUE;
3147 int hut_chance = fc_rand(12);
3148 struct player *pplayer = unit_owner(punit);
3149 const struct civ_map *nmap = &(wld.map);
3150
3151 /* 1 in 12 to get barbarians */
3152 if (hut_chance != 0) {
3153 int cred = 25;
3154
3156 PL_("You found %d gold.",
3157 "You found %d gold.", cred), cred);
3158 pplayer->economic.gold += cred;
3161 notify_player(pplayer, unit_tile(punit),
3163 _("An abandoned village is here."));
3164 } else {
3166 _("Your %s has been killed by barbarians!"),
3169 ok = FALSE;
3170 }
3171
3172 return ok;
3173}
3174
3175/**********************************************************************/
3179static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3180{
3181 struct player *pplayer = unit_owner(punit);
3182 int id = punit->id;
3183 struct tile *ptile = unit_tile(punit);
3184 bool hut = FALSE;
3185 const struct req_context context = {
3186 .player = pplayer,
3187 .tile = ptile,
3188 };
3189
3191 if (tile_has_extra(ptile, pextra)
3192 && are_reqs_active(&context, tile_owner(ptile), &pextra->rmreqs,
3194 ) {
3195 hut = TRUE;
3196 /* FIXME: are all enter-removes extras worth counting? */
3197 pplayer->server.huts++;
3198
3199 destroy_extra(ptile, pextra);
3201
3202 /* FIXME: enable different classes
3203 * to behave differently with different huts */
3204 if (frighten_hut) {
3205 script_server_signal_emit("hut_frighten", punit,
3206 extra_rule_name(pextra));
3207 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3208 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3210 } else {
3211 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3212 }
3213
3214 /* We need punit for the callbacks, can't continue if the unit died */
3215 if (!unit_is_alive(id)) {
3216 break;
3217 }
3218 }
3220
3221 if (hut) {
3222 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3223 }
3224 return;
3225}
3226
3227/**********************************************************************/
3231{
3232 bv_player can_see_unit;
3233
3236
3237 BV_CLR_ALL(can_see_unit);
3238 players_iterate(pplayer) {
3239 if (can_player_see_unit(pplayer, punit)) {
3240 BV_SET(can_see_unit, player_index(pplayer));
3241 }
3243
3245
3246 players_iterate(pplayer) {
3247 if (BV_ISSET(can_see_unit, player_index(pplayer))
3248 && !can_player_see_unit(pplayer, punit)) {
3249 unit_goes_out_of_sight(pplayer, punit);
3250 }
3252
3255}
3256
3257/**********************************************************************/
3261 struct unit *ptrans,
3262 bool force)
3263{
3264 bool had_cargo;
3265
3268
3270
3272
3273 if (!had_cargo) {
3274 /* Transport's loaded status changed */
3276 }
3277}
3278
3279/**********************************************************************/
3283{
3284 struct unit *ptrans;
3285
3287
3289
3291
3293
3296}
3297
3298/**********************************************************************/
3302static void autoattack_prob_free(struct autoattack_prob *prob)
3303{
3304 free(prob);
3305}
3306
3307/**********************************************************************/
3316static int compare_units(const struct autoattack_prob *const *p1,
3317 const struct autoattack_prob *const *q1)
3318{
3319 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3320 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3321
3322 /* Sort by transport depth first. This makes sure that no transport
3323 * attacks before its cargo does -- cargo sorts earlier in the list. */
3324 {
3325 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3326
3327 /* Walk the transport stacks in parallel, so as to bail out as soon as
3328 * one of them is empty (avoid walking deep stacks more often than
3329 * necessary). */
3330 while (p1trans && q1trans) {
3333 }
3334 if (!p1trans && q1trans) {
3335 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3336 * earlier in the list (p1 > q1). */
3337 return 1;
3338 } else if (p1trans && !q1trans) {
3339 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3340 return -1;
3341 }
3342 /* else same depth, so move on to checking win chance: */
3343 }
3344
3345 /* Put the units with the highest probability of success first. The up
3346 * side of this is that units with bonuses against the victim attacks
3347 * before other units. The downside is that strong units can be led
3348 * away by sacrificial units. */
3349 return (-1
3350 /* Assume the worst. */
3351 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3352}
3353
3354/**********************************************************************/
3359{
3360 struct autoattack_prob_list *autoattack;
3361 int moves = punit->moves_left;
3362 int sanity1 = punit->id;
3363 struct civ_map *nmap = &(wld.map);
3364
3365 if (!game.server.autoattack) {
3366 return TRUE;
3367 }
3368
3370
3371 /* Kludge to prevent attack power from dropping to zero during calc */
3373
3374 adjc_iterate(nmap, unit_tile(punit), ptile) {
3375 /* First add all eligible units to a autoattack list */
3376 unit_list_iterate(ptile->units, penemy) {
3378 struct tile *tgt_tile = unit_tile(punit);
3379
3380 fc_assert_action(tgt_tile, continue);
3381
3382 probability->prob =
3386 punit, NULL);
3387
3388 if (action_prob_possible(probability->prob)) {
3389 probability->unit_id = penemy->id;
3391 } else {
3393 }
3396
3397 /* Sort the potential attackers from highest to lowest success
3398 * probability. */
3399 if (autoattack_prob_list_size(autoattack) >= 2) {
3401 }
3402
3404 int sanity2 = penemy->id;
3405 struct tile *ptile = unit_tile(penemy);
3406 struct unit *enemy_defender = get_defender(nmap, punit, ptile, NULL);
3407 double punitwin, penemywin;
3408 double threshold = 0.25;
3409 struct tile *tgt_tile = unit_tile(punit);
3410
3412
3413 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3414 /* Don't leave city defenseless */
3415 threshold = 0.90;
3416 }
3417
3418 if (NULL != enemy_defender) {
3420 } else {
3421 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3422 punitwin = 1.0;
3423 }
3424
3425 /* Previous attacks may have changed the odds. Recalculate. */
3426 peprob->prob =
3430 punit, NULL);
3431
3432 if (!action_prob_possible(peprob->prob)) {
3433 /* No longer legal. */
3434 continue;
3435 }
3436
3437 /* Assume the worst. */
3439
3440 if ((penemywin > 1.0 - punitwin
3442 && penemywin > threshold) {
3443
3444#ifdef REALLY_DEBUG_THIS
3445 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3448 1.0 - punitwin, threshold);
3449#endif
3450
3455 } else {
3456#ifdef REALLY_DEBUG_THIS
3457 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3460 1.0 - punitwin, threshold);
3461#endif
3462 continue;
3463 }
3464
3467 }
3470 } else {
3471 autoattack_prob_list_destroy(autoattack);
3472 return FALSE; /* moving unit dead */
3473 }
3475
3476 autoattack_prob_list_destroy(autoattack);
3478 /* We could have lost movement in combat */
3481 return TRUE;
3482 } else {
3483 return FALSE;
3484 }
3485}
3486
3487/**********************************************************************/
3490static void cancel_orders(struct unit *punit, char *dbg_msg)
3491{
3494 log_debug("%s", dbg_msg);
3495}
3496
3497/**********************************************************************/
3502{
3503 bool alone_in_city;
3504
3505 if (NULL != tile_city(unit_tile(punit))) {
3506 int count = 0;
3507
3509 /* Consider only units not transported. */
3510 if (!unit_transported(aunit)) {
3511 count++;
3512 }
3514
3515 alone_in_city = (1 == count);
3516 } else {
3518 }
3519
3520 /* There may be sentried units with a sightrange > 3, but we don't
3521 wake them up if the punit is farther away than 3. */
3522 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3523 unit_list_iterate(ptile->units, penemy) {
3525 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3526
3528 && penemy->activity == ACTIVITY_SENTRY
3529 && radius_sq >= distance_sq
3530 /* If the unit moved on a city, and the unit is alone, consider
3531 * it is visible. */
3532 && (alone_in_city
3534 /* on board transport; don't awaken */
3538 }
3541
3542 /* Wakeup patrolling units we bump into.
3543 We do not wakeup units further away than 3 squares... */
3544 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3545 unit_list_iterate(ptile->units, ppatrol) {
3546 if (punit != ppatrol
3548 && ppatrol->orders.vigilant) {
3550 cancel_orders(ppatrol, " stopping because of nearby enemy");
3553 _("Orders for %s aborted after enemy movement was "
3554 "spotted."),
3556 }
3557 }
3560}
3561
3562/**********************************************************************/
3572 struct tile *src_tile,
3573 struct tile *dst_tile,
3574 bool passenger,
3576{
3577 struct city *fromcity = tile_city(src_tile);
3578 struct city *tocity = tile_city(dst_tile);
3579 struct city *homecity_start_pos = NULL;
3580 struct city *homecity_end_pos = NULL;
3586 const struct unit_type *type_end_pos = type_start_pos;
3589 int saved_id = punit->id;
3590 bool alive = TRUE;
3591 const struct civ_map *nmap = &(wld.map);
3592
3594 if (!passenger) {
3595 /* The unit that does the move may conquer. */
3597 }
3598
3599 /* Run for passengers too. A passenger may have been killed when its
3600 * transport conquered a city. (unit_conquer_city() can cause Lua code
3601 * to run) */
3602
3604 if (alive) {
3605 /* In case script has changed something about unit */
3609 }
3610 }
3611
3612 if (homecity_id_start_pos != 0) {
3614 }
3617 } else {
3619 }
3620
3621 /* We only do refreshes for non-AI players to now make sure the AI turns
3622 doesn't take too long. Perhaps we should make a special refresh_city
3623 functions that only refreshed happines. */
3624
3625 /* might have changed owners or may be destroyed */
3627
3628 if (tocity) { /* entering a city */
3629 if (tocity->owner == pplayer_end_pos) {
3633 }
3634 }
3635 if (homecity_start_pos) {
3637 }
3638 }
3639
3640 if (fromcity) { /* leaving a city */
3641 if (homecity_start_pos) {
3643 }
3645 && fromcity->owner == pplayer_start_pos
3649 }
3650 }
3651
3652 /* Entering/leaving a fortress or friendly territory */
3654 bool friendly_end = FALSE;
3655
3658 } else {
3660 type_end_pos);
3661
3662 if (max_friendliness_range >= 0
3665 } else {
3668
3669 if (max_friendliness_range >= 0
3672 }
3673 }
3674 }
3675
3676 if (friendly_end) {
3679 }
3680 }
3681
3685 }
3692 }
3693
3695 sync_cities();
3696
3697 return alive;
3698}
3699
3700/**********************************************************************/
3704static void check_unit_activity(struct unit *punit)
3705{
3706 switch (punit->activity) {
3707 case ACTIVITY_IDLE:
3708 case ACTIVITY_SENTRY:
3709 case ACTIVITY_EXPLORE:
3710 case ACTIVITY_GOTO:
3711 break;
3712 case ACTIVITY_CLEAN:
3713 case ACTIVITY_MINE:
3714 case ACTIVITY_IRRIGATE:
3715 case ACTIVITY_CULTIVATE:
3716 case ACTIVITY_PLANT:
3717 case ACTIVITY_FORTIFIED:
3718 case ACTIVITY_PILLAGE:
3719 case ACTIVITY_TRANSFORM:
3721 case ACTIVITY_BASE:
3722 case ACTIVITY_GEN_ROAD:
3723 case ACTIVITY_CONVERT:
3724 case ACTIVITY_LAST:
3726 break;
3727 };
3728}
3729
3730/**********************************************************************/
3734 const struct tile *psrctile,
3735 const struct tile *pdesttile)
3736{
3737 struct unit_move_data *pdata;
3738 struct player *powner = unit_owner(punit);
3739
3740 if (punit->server.moving) {
3741 /* Recursive moving (probably due to a script). */
3743 pdata->ref_count++;
3744 fc_assert_msg(pdata->punit == punit,
3745 "Unit number %d (%p) was going to die, but "
3746 "server attempts to move it.",
3747 punit->id, punit);
3748 fc_assert_msg(pdata->old_vision == NULL,
3749 "Unit number %d (%p) has done an incomplete move.",
3750 punit->id, punit);
3751 } else {
3752 pdata = fc_malloc(sizeof(*pdata));
3753 pdata->ref_count = 1;
3754 pdata->punit = punit;
3756 BV_CLR_ALL(pdata->can_see_unit);
3757 }
3758 pdata->powner = powner;
3759 BV_CLR_ALL(pdata->can_see_move);
3760 pdata->old_vision = punit->server.vision;
3761
3762 return pdata;
3763}
3764
3765/**********************************************************************/
3769 const struct tile *psrctile,
3770 struct tile *pdesttile)
3771{
3772 struct vision *new_vision;
3773 struct unit *punit = pdata->punit;
3775 const v_radius_t radius_sq
3779
3780 /* Remove unit from the source tile. */
3782
3783#ifndef FREECIV_NDEBUG
3784 bool success =
3785#endif
3788
3789 /* Set new tile. */
3792
3793 if (unit_transported(punit)) {
3794 /* Silently free orders since they won't be applicable anymore. */
3796 }
3797
3798 /* Check unit activity. */
3802
3803 /* We first unfog the destination, then send the move,
3804 * and then fog the old territory. This means that the player
3805 * gets a chance to see the newly explored territory while the
3806 * client moves the unit, and both areas are visible during the
3807 * move */
3808
3809 /* Enhance vision if unit steps into a fortress */
3812 vision_change_sight(new_vision, radius_sq);
3814}
3815
3816/**********************************************************************/
3820{
3822 fc_assert_ret(pdata->ref_count > 0);
3823 fc_assert_msg(pdata->old_vision == NULL,
3824 "Unit number %d (%p) has done an incomplete move.",
3825 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3826
3827 pdata->ref_count--;
3828 if (pdata->ref_count == 0) {
3829 if (pdata->punit != NULL) {
3830 fc_assert(pdata->punit->server.moving == pdata);
3831 pdata->punit->server.moving = NULL;
3832 }
3833 free(pdata);
3834 }
3835}
3836
3837/**********************************************************************/
3841 const struct tile *psrctile,
3842 struct tile *pdesttile,
3843 bool adj)
3844{
3847 struct unit_move_data *pdata;
3848
3849 /* Make new data for 'punit'. */
3852
3853 /* Add all contained units. */
3855 struct unit_move_data *cargo_data;
3856
3860
3861 /* Determine the players able to see the move(s), now that the player
3862 * vision has been increased. */
3863 if (adj) {
3864 /* Main unit for adjacent move: the move is visible for every player
3865 * able to see on the matching unit layer. */
3866 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
3867
3871 BV_SET(pdata->can_see_unit, player_index(oplayer));
3872 BV_SET(pdata->can_see_move, player_index(oplayer));
3873 }
3875 }
3876
3878
3880
3881 if (adj && pmove_data->punit == punit) {
3882 /* If positions are adjacent, we have already handled 'punit'. See
3883 * above. */
3884 continue;
3885 }
3886
3888 if ((adj
3890 pmove_data != pdata))
3892 pmove_data != pdata)) {
3893 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3894 BV_SET(pmove_data->can_see_move, player_index(oplayer));
3895 }
3897 pmove_data != pdata)) {
3898 /* The unit was seen with its source tile even if it was
3899 * teleported. */
3900 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
3901 }
3904
3905 return plist;
3906}
3907
3908/**********************************************************************/
3919bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3920 struct unit *embark_to, bool find_embark_target,
3922 bool enter_hut, bool frighten_hut)
3923{
3924 struct player *pplayer;
3925 struct tile *psrctile;
3926 struct city *psrccity;
3927 struct city *pdestcity;
3928 struct unit *ptransporter;
3931 struct unit_move_data_list *plist;
3932 struct unit_move_data *pdata;
3933 int saved_id;
3934 bool unit_lives;
3935 bool adj;
3936 enum direction8 facing;
3937
3938 /* Some checks. */
3941
3942 pplayer = unit_owner(punit);
3943 saved_id = punit->id;
3946
3948
3949 /* Unload the unit if on a transport. */
3951 if (ptransporter != NULL) {
3952 /* Unload unit _before_ setting the new tile! */
3954 /* Send updated information to anyone watching that transporter
3955 * was unloading cargo. */
3957 }
3958
3959 /* Wakup units next to us before we move. */
3961
3962 /* Make info packets at 'psrctile'. */
3963 if (adj) {
3964 /* If tiles are adjacent, we will show the move to users able
3965 * to see it. */
3968 }
3969
3970 /* Set unit orientation */
3971 if (adj) {
3972 /* Only change orientation when moving to adjacent tile */
3973 punit->facing = facing;
3974 }
3975
3977
3978 /* Move magic. */
3979 punit->moved = TRUE;
3980 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3981 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3982 /* The next order may not require any remaining move fragments. */
3984 }
3985
3986 /* No longer relevant. */
3989
3990 /* Claim ownership of fortress? */
3993 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3994 * Even if original unit cannot claim other kind of bases, the
3995 * first claimed base will have influence over other bases,
3996 * or something like that. */
3997 tile_claim_bases(pdesttile, pplayer);
3998 }
3999
4001 fc_assert(pdata->punit == punit);
4002
4003 /* Check timeout settings. */
4006
4007 /* FIXME: Seen enemy cargo in a non-enemy transport should count too,
4008 * if they are ever seen. */
4010 /* Increase the timeout if an enemy unit moves and the
4011 * timeoutaddenemymove setting is in use. */
4012 if (penemy->is_connected
4013 && pplayer != penemy
4014 && pplayers_at_war(pplayer, penemy)
4015 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4017 break;
4018 }
4020
4023 }
4024 }
4025
4027 /* The unit can perform an action to the city at the destination tile.
4028 * A long distance move (like an airlift) doesn't ask what action to
4029 * perform before moving. Ask now. */
4030
4033 }
4034
4035 /* Notifications of the move to the clients. */
4036 if (adj) {
4037 /* Special case: 'punit' is moving to adjacent position. Then we show
4038 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4039
4040 /* Make info packets at 'pdesttile'. */
4043
4046
4047 if (aplayer == NULL) {
4048 if (pconn->observer) {
4049 /* Global observers see all... */
4052 }
4053 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4054 if (aplayer == pplayer) {
4057 } else {
4060 }
4061 }
4063 }
4064
4065 /* Other moves. */
4067 if (adj && pmove_data == pdata) {
4068 /* If positions are adjacent, we have already shown 'punit' move.
4069 * See above. */
4070 continue;
4071 }
4072
4073 /* Make info packets at 'pdesttile'. */
4077
4080
4081 if (aplayer == NULL) {
4082 if (pconn->observer) {
4083 /* Global observers see all... */
4085 }
4086 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4087 if (aplayer == pmove_data->powner) {
4089 } else {
4091 }
4092 }
4095
4096 /* Clear old vision. */
4098 if (pmove_data->old_vision != NULL) {
4099 vision_clear_sight(pmove_data->old_vision);
4100 vision_free(pmove_data->old_vision);
4101 pmove_data->old_vision = NULL;
4102 }
4104
4105 /* Move consequences. */
4107 struct unit *aunit = pmove_data->punit;
4108
4109 if (aunit != NULL
4110 && unit_owner(aunit) == pmove_data->powner
4111 && unit_tile(aunit) == pdesttile) {
4113 pdata != pmove_data,
4115 }
4117
4118 unit_lives = (pdata->punit == punit);
4119
4120 /* Wakeup units and make contact. */
4121 if (unit_lives) {
4123 }
4124 maybe_make_contact(pdesttile, pplayer);
4125
4126 if (unit_lives) {
4127 /* Special checks for ground units in the ocean. */
4129 if (embark_to != NULL) {
4131 } else if (find_embark_target) {
4132 /* TODO: Consider to stop supporting find_embark_target and make all
4133 * callers that wants auto loading set embark_to. */
4135 } else {
4137 }
4138 if (ptransporter) {
4140
4141 /* Set activity to sentry if boarding a ship. */
4142 if (is_human(pplayer)
4147 }
4148
4150 }
4151 }
4152 }
4153
4154 /* Remove units going out of sight. */
4156 struct unit *aunit = pmove_data->punit;
4157
4158 if (aunit == NULL) {
4159 continue; /* Died! */
4160 }
4161
4163 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4166 }
4169
4170 /* Inform the owner's client about actor unit arrival. Can, depending on
4171 * the client settings, cause the client to start the process that makes
4172 * the action selection dialog pop up. */
4174 if (pdestcity != NULL) {
4175 /* Arrival in a city counts. */
4176
4178 struct unit *ptrans;
4179 bool ok;
4180 struct unit *act_unit;
4181 struct player *act_player;
4182
4183 act_unit = pmove_data->punit;
4185
4186 if (act_unit == NULL
4187 || !unit_is_alive(act_unit->id)) {
4188 /* The unit died before reaching this point. */
4189 continue;
4190 }
4191
4192 if (unit_tile(act_unit) != pdesttile) {
4193 /* The unit didn't arrive at the destination tile. */
4194 continue;
4195 }
4196
4197 if (!is_human(act_player)) {
4198 /* Only humans need reminders. */
4199 continue;
4200 }
4201
4202 if (!unit_transported(act_unit)) {
4203 /* Don't show the action selection dialog again. Non transported
4204 * units are handled before they move to the tile. */
4205 continue;
4206 }
4207
4208 /* Open action dialog only if 'act_unit' and all its transporters
4209 * (recursively) don't have orders. */
4211 /* The unit it self has orders. */
4212 continue;
4213 }
4214
4217 if (NULL == ptrans) {
4218 /* No (recursive) transport has orders. */
4219 ok = TRUE;
4220 break;
4221 } else if (unit_has_orders(ptrans)) {
4222 /* A unit transporting the unit has orders */
4223 ok = FALSE;
4224 break;
4225 }
4226 }
4227
4228 if (!ok) {
4229 /* A unit transporting act_unit has orders. */
4230 continue;
4231 }
4232
4234 /* There is a valid target. */
4235
4236 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4237 act_unit->action_decision_tile = pdesttile;
4238
4239 /* Let the client know that this unit wants the player to decide
4240 * what to do. */
4242 }
4244 }
4245
4247 /* Check cities at source and destination. */
4249 if (psrccity != NULL) {
4251 }
4252 if (pdestcity != NULL) {
4254 }
4255
4256 if (unit_lives) {
4257 /* Let the scripts run ... */
4260 }
4261
4262 if (unit_lives) {
4263 /* Autoattack. */
4265 }
4266
4267 if (unit_lives && (enter_hut || frighten_hut)) {
4268 /* Is there a hut? */
4272 }
4273
4275
4276 if (unit_lives) {
4277 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4278 }
4279
4280 return unit_lives;
4281}
4282
4283/**********************************************************************/
4287 struct tile *ptile)
4288{
4289 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
4291}
4292
4293/**********************************************************************/
4300{
4301 bool cancel = FALSE;
4302 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4303 struct player *pplayer = unit_owner(punit);
4304
4305 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4306 struct unit *penemy = tile_non_allied_unit(ptile, pplayer);
4307 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4308
4309 if ((penemy && can_player_see_unit(pplayer, penemy))
4311 && pdcity->occupied)) {
4312 cancel = TRUE;
4313 break;
4314 }
4316
4317 return cancel;
4318}
4319
4320/**********************************************************************/
4328static inline bool player_is_watching(struct unit *punit, const bool fresh)
4329{
4330 /* The player just sent the orders to the unit. The unit has moves left.
4331 * It is therefore safe to assume that the player already is paying
4332 * attention to the unit. */
4333 return fresh && punit->moves_left > 0;
4334}
4335
4336/**********************************************************************/
4355bool execute_orders(struct unit *punit, const bool fresh)
4356{
4357 struct act_prob prob;
4358 bool performed;
4359 const char *name;
4360 bool res, last_order;
4361 int unitid = punit->id;
4362 struct player *pplayer = unit_owner(punit);
4363 int moves_made = 0;
4364 const struct civ_map *nmap = &(wld.map);
4365
4367
4368 if (punit->activity != ACTIVITY_IDLE) {
4369 /* Unit's in the middle of an activity; wait for it to finish. */
4371 return TRUE;
4372 }
4373
4374 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4375
4376 /* Any time the orders are canceled we should give the player a message. */
4377
4378 while (TRUE) {
4379 struct unit_order order;
4380
4381 struct action *oaction;
4382
4383 struct tile *dst_tile;
4384 struct city *tgt_city;
4385 struct unit *tgt_unit;
4386 int tgt_id;
4387 int sub_tgt_id;
4388 struct extra_type *pextra;
4389
4390 if (punit->done_moving) {
4391 log_debug(" stopping because we're done this turn");
4392 return TRUE;
4393 }
4394
4396 /* "Patrol" orders are stopped if an enemy is near. */
4397 cancel_orders(punit, " stopping because of nearby enemy");
4399 _("Orders for %s aborted as there are units nearby."),
4400 unit_link(punit));
4401 return TRUE;
4402 }
4403
4404 if (moves_made == punit->orders.length) {
4405 /* For repeating orders, don't repeat more than once per turn. */
4406 log_debug(" stopping because we ran a round");
4409 return TRUE;
4410 }
4411 moves_made++;
4412
4413 order = punit->orders.list[punit->orders.index];
4414
4415 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4416 * this far. */
4418 || action_id_exists(order.action)),
4419 continue);
4420
4421 switch (order.order) {
4422 case ORDER_MOVE:
4423 case ORDER_ACTION_MOVE:
4424 case ORDER_FULL_MP:
4425 if (0 == punit->moves_left) {
4426 log_debug(" stopping because of no more move points");
4427 return TRUE;
4428 }
4429 break;
4432 log_debug(" stopping. Not enough move points this turn");
4433 return TRUE;
4434 }
4435 break;
4436 case ORDER_ACTIVITY:
4437 case ORDER_LAST:
4438 /* Those actions don't require moves left. */
4439 break;
4440 }
4441
4443 && punit->orders.index + 1 == punit->orders.length);
4444
4445 if (last_order) {
4446 /* Clear the orders before we engage in the move. That way any
4447 * has_orders checks will yield FALSE and this will be treated as
4448 * a normal move. This is important: for instance a caravan goto
4449 * will popup the caravan dialog on the last move only. */
4451 }
4452
4453 /* Advance the orders one step forward. This is needed because any
4454 * updates sent to the client as a result of the action should include
4455 * the new index value. Note that we have to send_unit_info somewhere
4456 * after this point so that the client is properly updated. */
4457 punit->orders.index++;
4458
4459 switch (order.order) {
4460 case ORDER_FULL_MP:
4462 /* If the unit doesn't have full MP then it just waits until the
4463 * next turn. We assume that the next turn it will have full MP
4464 * (there's no check for that). */
4466 log_debug(" waiting this turn");
4468 }
4469 break;
4470 case ORDER_ACTIVITY:
4471 {
4472 enum unit_activity activity = order.activity;
4473
4474 fc_assert(activity == ACTIVITY_SENTRY);
4475
4476 if (can_unit_do_activity(nmap, punit, activity)) {
4478 set_unit_activity(punit, activity);
4480
4481 break;
4482 }
4483 }
4484
4485 cancel_orders(punit, " orders canceled because of failed activity");
4487 _("Orders for %s aborted since they "
4488 "give an invalid activity."),
4489 unit_link(punit));
4490 return TRUE;
4491 case ORDER_MOVE:
4492 case ORDER_ACTION_MOVE:
4493 /* Move unit */
4494 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4495 cancel_orders(punit, " move order sent us to invalid location");
4497 _("Orders for %s aborted since they "
4498 "give an invalid location."),
4499 unit_link(punit));
4500 return TRUE;
4501 }
4502
4503 if (order.order != ORDER_ACTION_MOVE
4505 /* Plain move required: no attack, trade route etc. */
4506 cancel_orders(punit, " orders canceled because of enemy");
4508 _("Orders for %s aborted as there "
4509 "are units in the way."),
4510 unit_link(punit));
4511 return TRUE;
4512 }
4513
4514 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4516 order.order != ORDER_ACTION_MOVE);
4517 if (!player_unit_by_number(pplayer, unitid)) {
4518 log_debug(" unit died while moving.");
4519 /* A player notification should already have been sent. */
4520 return FALSE;
4521 }
4522
4523 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4524 /* Movement succeeded but unit didn't move. */
4525 log_debug(" orders resulted in combat.");
4527 return TRUE;
4528 }
4529
4530 if (!res) {
4531 fc_assert(0 <= punit->moves_left);
4532
4533 /* Movement failed (ZOC, etc.) */
4534 cancel_orders(punit, " attempt to move failed.");
4535
4537 /* The final move "failed" because the unit needs to ask the
4538 * player what action it should take.
4539 *
4540 * The action decision request notifies the player. Its
4541 * location at the unit's last order makes it clear to the
4542 * player who the decision is for. ("The Spy I sent to Berlin
4543 * has arrived.")
4544 *
4545 * A notification message is therefore redundant. */
4546 && !(last_order
4549 /* The player may have missed this. No one else will announce it
4550 * in a satisfying manner. Inform the player. */
4551 notify_player(pplayer, unit_tile(punit),
4553 _("Orders for %s aborted because of failed move."),
4554 unit_link(punit));
4555 }
4556
4557 return TRUE;
4558 }
4559 break;
4562
4563 /* Checked in unit_order_list_is_sane() */
4564 fc_assert_action(oaction != NULL, continue);
4565
4566 log_debug(" orders: doing action %s", action_rule_name(oaction));
4567
4568 dst_tile = index_to_tile(&(wld.map), order.target);
4569
4570 if (dst_tile == NULL) {
4571 /* Could be at the edge of the map while trying to target a tile
4572 * outside of it. */
4573
4574 cancel_orders(punit, " target location doesn't exist");
4576 order.action, dst_tile, NULL, NULL);
4577
4578 return TRUE;
4579 }
4580
4581 /* Get the target city from the target tile. */
4583
4584 if (tgt_city == NULL
4586 /* This action targets a city but no city target was found. */
4587
4588 cancel_orders(punit, " perform action vs city with no city");
4590 order.action, dst_tile, tgt_city, NULL);
4591
4592 return TRUE;
4593 }
4594
4595 /* Get a target unit at the target tile. */
4597
4598 if (tgt_unit == NULL
4600 /* This action targets a unit but no target unit was found. */
4601
4602 cancel_orders(punit, " perform action vs unit with no unit");
4604 order.action, dst_tile, tgt_city, tgt_unit);
4605
4606 return TRUE;
4607 }
4608
4609 /* Server side sub target assignment */
4610 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4611 && order.sub_target == NO_TARGET) {
4612 /* Try to find a sub target. */
4614 } else {
4615 /* The client should have specified a sub target if needed */
4616 sub_tgt_id = order.sub_target;
4617 }
4618
4619 /* Get a target extra at the target tile */
4620 pextra = (sub_tgt_id == NO_TARGET ?
4621 NULL :
4622 extra_by_number(sub_tgt_id));
4623
4625 && pextra != NULL
4626 && actres_creates_extra(oaction->result, pextra)
4627 && tile_has_extra(dst_tile, pextra)) {
4628 /* Already there. Move on to the next order. */
4629 break;
4630 }
4631
4633 && pextra != NULL
4634 && actres_removes_extra(oaction->result, pextra)
4635 && !tile_has_extra(dst_tile, pextra)) {
4636 /* Already not there. Move on to the next order. */
4637 break;
4638 }
4639
4640 /* No target selected. */
4641 tgt_id = -1;
4642
4643 /* Assume impossible until told otherwise. */
4644 prob = ACTPROB_IMPOSSIBLE;
4645
4646 switch (action_id_get_target_kind(order.action)) {
4647 case ATK_UNITS:
4648 prob = action_prob_vs_stack(nmap, punit, order.action,
4649 dst_tile);
4650 tgt_id = dst_tile->index;
4651 break;
4652 case ATK_TILE:
4653 prob = action_prob_vs_tile(nmap, punit, order.action,
4654 dst_tile, pextra);
4655 tgt_id = dst_tile->index;
4656 break;
4657 case ATK_EXTRAS:
4658 prob = action_prob_vs_extras(nmap, punit, order.action,
4659 dst_tile, pextra);
4660 tgt_id = dst_tile->index;
4661 break;
4662 case ATK_CITY:
4663 prob = action_prob_vs_city(nmap, punit, order.action,
4664 tgt_city);
4665 tgt_id = tgt_city->id;
4666 break;
4667 case ATK_UNIT:
4668 prob = action_prob_vs_unit(nmap, punit, order.action,
4669 tgt_unit);
4670
4671 tgt_id = tgt_unit->id;
4672 break;
4673 case ATK_SELF:
4674 prob = action_prob_self(nmap, punit, order.action);
4675
4676 tgt_id = unitid;
4677 break;
4678 case ATK_COUNT:
4679 log_error("Invalid action target kind");
4680
4681 /* The check below will abort and cancel the orders because prob
4682 * was initialized to impossible above this switch statement. */
4683
4684 break;
4685 }
4686
4687 if (!action_prob_possible(prob)) {
4688 /* The player has enough information to know that this action is
4689 * against the rules. Don't risk any punishment by trying to
4690 * perform it. */
4691
4692 cancel_orders(punit, " illegal action");
4694 _("%s could not do %s to %s."),
4698
4699 /* Try to explain what rule made it illegal. */
4701 order.action, dst_tile, tgt_city, tgt_unit);
4702
4703 return TRUE;
4704 }
4705
4707 /* This action needs a name. */
4709 } else {
4710 /* This action doesn't need a name. */
4711 name = "";
4712 }
4713
4715 unitid,
4716 tgt_id,
4717 sub_tgt_id,
4718 name,
4719 order.action,
4721
4722 if (!player_unit_by_number(pplayer, unitid)) {
4723 /* The unit "died" while performing the action. */
4724 return FALSE;
4725 }
4726
4727 if (!performed) {
4728 /* The action wasn't performed as ordered. */
4729
4730 cancel_orders(punit, " failed action");
4732 _("Orders for %s aborted because "
4733 "doing %s to %s failed."),
4737
4738 return TRUE;
4739 }
4740
4741 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4743 /* Done at turn change. */
4746 break;
4747 }
4748
4749 break;
4750 case ORDER_LAST:
4751 /* Should be caught when loading the unit orders from the savegame or
4752 * when receiving the unit orders from the client. */
4753 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4754 cancel_orders(punit, " invalid order!");
4756 _("Your %s has invalid orders."),
4757 unit_link(punit));
4758 return TRUE;
4759 }
4760
4761 if (last_order) {
4763 log_debug(" stopping because orders are complete");
4764 return TRUE;
4765 }
4766
4767 if (punit->orders.index == punit->orders.length) {
4769 /* Start over. */
4770 log_debug(" repeating orders.");
4771 punit->orders.index = 0;
4772 }
4773 } /* end while */
4774}
4775
4776/**********************************************************************/
4783static int get_unit_vision_base(const struct unit *punit,
4784 enum vision_layer vlayer,
4785 const int base)
4786{
4787 switch (vlayer) {
4788 case V_MAIN:
4789 return MAX(0, base);
4790 case V_INVIS:
4791 case V_SUBSURFACE:
4792 return CLIP(0, base, 2);
4793 case V_COUNT:
4794 break;
4795 }
4796
4797 log_error("Unsupported vision layer variant: %d.", vlayer);
4798
4799 return 0;
4800}
4801
4802/**********************************************************************/
4805static int unit_vision_range_modifiers(const struct unit *punit,
4806 const struct tile *ptile)
4807{
4808 const struct unit_type *utype = unit_type_get(punit);
4809
4810 return (utype->vision_radius_sq
4812 &(const struct req_context) {
4813 .player = unit_owner(punit),
4814 .tile = ptile,
4815 .unittype = utype,
4816 .unit = punit,
4817 },
4819}
4820
4821/**********************************************************************/
4828int get_unit_vision_at(const struct unit *punit, const struct tile *ptile,
4829 enum vision_layer vlayer)
4830{
4833}
4834
4835/**********************************************************************/
4842{
4843 struct vision *uvision = punit->server.vision;
4844 const struct tile *utile = unit_tile(punit);
4845 int mod = unit_vision_range_modifiers(punit, utile);
4846 const v_radius_t radius_sq
4850
4851 vision_change_sight(uvision, radius_sq);
4853}
4854
4855/**********************************************************************/
4864
4865/**********************************************************************/
4870{
4871 time_t dt;
4872
4873 if (!punit) {
4874 return FALSE;
4875 }
4876
4877 if (game.server.unitwaittime <= 0) {
4878 return TRUE;
4879 }
4880
4881 if (punit->server.action_turn != game.info.turn - 1) {
4882 return TRUE;
4883 }
4884
4886 if (dt < game.server.unitwaittime) {
4887 char buf[64];
4890 ftc_server, _("Your unit may not act for another %s "
4891 "this turn. See /help unitwaittime."), buf);
4892 return FALSE;
4893 }
4894
4895 return TRUE;
4896}
4897
4898/**********************************************************************/
4903{
4904 if (!punit) {
4905 return;
4906 }
4907
4910}
4911
4912/**********************************************************************/
4918{
4919 /* check if there is enemy nearby */
4920 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
4922 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4923 return FALSE;
4924 }
4925 }
4927
4928 return TRUE;
4929}
4930
4931/**********************************************************************/
4934void random_movements(struct player *pplayer)
4935{
4936 const struct civ_map *nmap = &(wld.map);
4937
4938 game.server.random_move_time = pplayer;
4939
4942 bool moved = TRUE;
4943 struct tile *curtile = unit_tile(punit);
4944 int id = punit->id;
4945
4946 while (moved && unit_is_alive(id) && punit->moves_left > 0) {
4947 /*
4948 * List of all 8 directions
4949 */
4950 enum direction8 dirs[8] = {
4953 };
4954 int n;
4955
4956 moved = FALSE;
4957
4958 for (n = 8; n > 0 && !moved; n--) {
4959 enum direction8 choice = (enum direction8) fc_rand(n);
4960 struct tile *dest = mapstep(&(wld.map), curtile, dirs[choice]);
4961
4962 if (dest != NULL) {
4964 dest))) {
4965 if (unit_perform_action(pplayer, id, tile_index(dest), NO_TARGET,
4967 moved = TRUE;
4968 break;
4969 }
4970 }
4971
4972 if (!moved) {
4974 NULL)) {
4975 if (unit_perform_action(pplayer, id, tile_index(dest),
4977 ACT_REQ_RULES)) {
4978 moved = TRUE;
4979 }
4981 punit, dest, NULL)) {
4982 if (unit_perform_action(pplayer, id, tile_index(dest),
4984 ACT_REQ_RULES)) {
4985 moved = TRUE;
4986 }
4988 punit, dest, NULL)) {
4989 if (unit_perform_action(pplayer, id, tile_index(dest),
4991 ACT_REQ_RULES)) {
4992 moved = TRUE;
4993 }
4994 }
4995 }
4996 }
4997
4998 if (!moved) {
4999 /* Choice was bad, so replace it with the last direction
5000 * in the list. On the next iteration, one fewer choice
5001 * will remain. */
5002 dirs[choice] = dirs[n - 1];
5003 }
5004 }
5005 }
5006 }
5008
5010}
const char * action_name_translation(const struct action *action)
Definition actions.c:1991
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:6292
const char * action_id_name_translation(action_id act_id)
Definition actions.c:2011
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5821
struct act_prob action_prob_vs_tile(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5342
const char * action_rule_name(const struct action *action)
Definition actions.c:1977
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1880
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:4082
struct act_prob action_prob_vs_extras(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:5425
struct act_prob action_prob_self(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id)
Definition actions.c:5495
struct act_prob action_prob_vs_city(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Definition actions.c:4984
bool action_id_exists(const action_id act_id)
Definition actions.c:1829
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:5881
struct act_prob action_prob_vs_stack(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:5259
struct act_prob action_prob_vs_unit(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5067
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:5932
static struct action * action_by_number(action_id act_id)
Definition actions.h:635
#define action_has_result(_act_, _res_)
Definition actions.h:431
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:676
#define ACTPROB_IMPOSSIBLE
Definition actions.h:922
#define action_id_get_target_kind(act_id)
Definition actions.h:652
#define action_id_has_result_safe(act_id, result)
Definition actions.h:665
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:803
bool actres_creates_extra(enum action_result result, const struct extra_type *pextra)
Definition actres.c:782
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:387
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:377
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
void dbv_to_bv(unsigned char *dest, const struct dbv *src)
Definition bitvector.c:235
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
bool is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile, int distance)
Definition city.c:2092
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
bool city_exists_within_max_city_map(const struct civ_map *nmap, const struct tile *ptile, bool may_be_on_center)
Definition city.c:2112
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:770
#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:734
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:746
#define output_type_iterate(output)
Definition city.h:845
#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:851
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3333
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:458
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2363
struct city * find_closest_city(const struct tile *ptile, const struct city *pexclcity, const struct player *pplayer, bool only_ocean, bool only_continent, bool only_known, bool only_player, bool only_enemy, const struct unit_class *pclass)
Definition citytools.c:856
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2216
void sync_cities(void)
Definition citytools.c:3342
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1987
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3156
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:763
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:989
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:712
int unit_bombard_rate(struct unit *punit)
Definition combat.c:1020
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:767
int get_total_attack_power(const struct unit *attacker, const struct unit *defender, const struct action *paction)
Definition combat.c:610
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile, const struct action *paction)
Definition combat.c:836
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:75
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:2940
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2655
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2685
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:354
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:349
@ RPT_CERTAIN
Definition fc_types.h:701
@ AUT_NONE
Definition fc_types.h:370
@ HB_DISABLED
Definition fc_types.h:1290
#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:848
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:226
GType type
Definition repodlgs.c:1313
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
@ H_LIMITEDHUTS
Definition handicaps.h:20
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:82
const char * name
Definition inputfile.c:127
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:211
#define log_test
Definition log.h:136
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c: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:2533
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2621
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1919
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2220
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2556
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2724
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:1439
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:1995
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1382
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2521
#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:279
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:351
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:363
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:943
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:374
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:523
@ 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:291
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:238
unit_info_use
Definition packets.h:66
@ UNIT_INFO_IDENTITY
Definition packets.h:67
int send_packet_unit_remove(struct connection *pc, const struct packet_unit_remove *packet)
void lsend_packet_unit_remove(struct conn_list *dest, const struct packet_unit_remove *packet)
void dlsend_packet_unit_remove(struct conn_list *dest, int unit_id)
int send_packet_unit_short_info(struct connection *pc, const struct packet_unit_short_info *packet, bool force_to_send)
int send_packet_unit_info(struct connection *pc, const struct packet_unit_info *packet)
void pf_path_destroy(struct pf_path *path)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
void pf_map_destroy(struct pf_map *pfm)
#define pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c: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:865
void player_status_add(struct player *plr, enum player_status pstatus)
Definition plrhand.c:3213
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2362
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1146
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1594
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:1967
#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:202
struct player * random_move_time
Definition game.h:279
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:136
int killunhomed
Definition game.h:158
struct civ_game::@31::@35 server
int ransom_gold
Definition game.h:179
bool autoattack
Definition game.h:135
int timeoutaddenemymove
Definition game.h:212
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:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:550
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:955
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:215
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:681
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:233
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:418
int tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:196
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:88
#define tile_terrain(_tile)
Definition tile.h:114
#define TILE_XY(ptile)
Definition tile.h:43
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:124
#define tile_continent(_tile)
Definition tile.h:92
#define tile_has_extra(ptile, pextra)
Definition tile.h:151
#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:1314
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1791
void free_unit_orders(struct unit *punit)
Definition unit.c:1777
bool unit_is_alive(int id)
Definition unit.c:2261
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:534
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2378
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1096
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1253
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2449
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2398
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2191
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:849
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1632
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:876
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1737
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1263
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1996
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2433
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:760
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2459
bool unit_has_orders(const struct unit *punit)
Definition unit.c:210
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1920
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2043
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:574
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:915
#define unit_tile(_pu)
Definition unit.h:397
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:420
#define unit_cargo_iterate_end
Definition unit.h:573
@ 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:408
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:570
#define CHECK_UNIT(punit)
Definition unit.h:270
#define unit_owner(_pu)
Definition unit.h:396
@ UU_OK
Definition unit.h:61
#define unit_home(_pu_)
Definition unit.h:394
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:432
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:6471
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:3313
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5533
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void unit_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, const struct action *paction)
Definition unittools.c:356
void unit_did_action(struct unit *punit)
Definition unittools.c:4902
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3302
void collect_ransom(struct unit *pcollector, struct unit *punit, bool vet)
Definition unittools.c:2495
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:2912
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1158
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:2144
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:3840
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4355
static void unit_convert(struct unit *punit)
Definition unittools.c:771
void update_unit_activities(struct player *pplayer)
Definition unittools.c:667
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1301
#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:1546
void random_movements(struct player *pplayer)
Definition unittools.c:4934
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:1787
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1410
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1482
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1912
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1445
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4286
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:401
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1395
void do_nuclear_explosion(const struct action *paction, const struct unit_type *act_utype, struct player *pplayer, struct tile *ptile)
Definition unittools.c:2880
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3819
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1764
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3179
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2585
#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:2710
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:658
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3501
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:715
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:815
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3260
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3358
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:699
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:677
static bool find_a_good_partisan_spot(struct tile *pcenter, struct player *powner, struct unit_type *u_type, int sq_radius, struct tile **dst_tile)
Definition unittools.c:1110
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2723
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1936
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1366
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3704
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:631
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:425
static struct unit_move_data * unit_move_data_get(struct unit *punit, const struct tile *psrctile, const struct tile *pdesttile)
Definition unittools.c:3733
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1706
void notify_unit_experience(struct unit *punit)
Definition unittools.c:744
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:797
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:2666
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:1658
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1469
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1050
#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:1625
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1903
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1778
int get_unit_vision_at(const struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4828
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:219
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4841
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:1598
void do_explore(struct unit *punit)
Definition unittools.c:2945
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3230
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:4869
#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:2132
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:689
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:2981
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4328
static int get_unit_vision_base(const struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4783
void player_restore_units(struct player *pplayer)
Definition unittools.c:478
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1524
static int unit_vision_range_modifiers(const struct unit *punit, const struct tile *ptile)
Definition unittools.c:4805
static void update_unit_activity(struct unit *punit)
Definition unittools.c:855
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3282
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1515
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:3490
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:4917
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:735
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:827
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2192
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1184
static void do_nuke_tile(struct player *pplayer, struct tile *ptile, const struct action *paction)
Definition unittools.c:2795
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3144
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1079
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3316
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:842
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:3571
void unit_get_goods(struct unit *punit)
Definition unittools.c:1609
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2767
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:4299
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:3919
static void unit_move_by_data(struct unit_move_data *pdata, const struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3768
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4858
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2259
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1222
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1059
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:2568
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:2499
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
const struct veteran_level * vsystem_veteran_level(const struct veteran_system *vsystem, int level)
Definition unittype.c:2585
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:839
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:129
short int v_radius_t[V_COUNT]
Definition vision.h:83