Freeciv-3.1: /fast/freeciv/nightly/S3_1/server/unittools.c Source File

Freeciv-3.1

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). */
91 struct unit_move_data {
92 int ref_count;
93 struct unit *punit; /* NULL for invalidating. */
94 struct player *powner;
95 bv_player can_see_unit;
96 bv_player can_see_move;
97 struct vision *old_vision;
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. */
113 struct autoattack_prob {
114 int unit_id;
115 struct act_prob prob;
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,
152 enum unit_loss_reason reason,
153 struct player *killer);
154
155static int get_unit_vision_base(struct unit *punit, enum vision_layer vlayer,
156 const int base);
157static int unit_vision_range_modifiers(struct unit *punit,
158 const struct tile *ptile);
159
160/**********************************************************************/
174 struct unit_type *find_a_unit_type(enum unit_role_id role,
175 enum unit_role_id role_tech)
176{
177 struct unit_type *which[U_LAST];
178 int i, num = 0;
179
180 if (role_tech != -1) {
181 for (i = 0; i < num_role_units(role_tech); i++) {
182 struct unit_type *iunit = get_role_unit(role_tech, i);
183 const int minplayers = 2;
184 int players = 0;
185
186 /* Note, if there's only one player in the game this check will always
187 * fail. */
188 players_iterate(pplayer) {
189 if (!is_barbarian(pplayer)
190 && can_player_build_unit_direct(pplayer, iunit)) {
191 players++;
192 }
193 } players_iterate_end;
194 if (players > minplayers) {
195 which[num++] = iunit;
196 }
197 }
198 }
199 if (num == 0) {
200 for (i = 0; i < num_role_units(role); i++) {
201 which[num++] = get_role_unit(role, i);
202 }
203 }
204
205 /* Ruleset code should ensure there is at least one unit for each
206 * possibly-required role, or check before calling this function. */
207 fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
208 role, role_tech);
209
210 return which[fc_rand(num)];
211}
212
213/**********************************************************************/
217 bool maybe_make_veteran(struct unit *punit, int base_chance)
218{
219 return maybe_become_veteran_real(punit, base_chance, FALSE);
220}
221
222/**********************************************************************/
235 static bool maybe_become_veteran_real(struct unit *punit, int base_chance,
236 bool settler)
237{
238 const struct veteran_system *vsystem;
239 const struct veteran_level *vlevel;
240 int chance;
241
242 fc_assert_ret_val(punit != NULL, FALSE);
243
244 vsystem = utype_veteran_system(unit_type_get(punit));
245 fc_assert_ret_val(vsystem != NULL, FALSE);
246 fc_assert_ret_val(vsystem->levels > punit->veteran, FALSE);
247
248 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
249 fc_assert_ret_val(vlevel != NULL, FALSE);
250
251 if (punit->veteran + 1 >= vsystem->levels
252 || unit_has_type_flag(punit, UTYF_NO_VETERAN)) {
253 return FALSE;
254 } else if (!settler) {
255 int mod = base_chance + get_unit_bonus(punit, EFT_VETERAN_COMBAT);
256
257 /* The modification is tacked on as a multiplier to the base chance.
258 * For example with a base chance of 50% for green units and a modifier
259 * of +50% the end chance is 75%. */
260 chance = vlevel->base_raise_chance * mod / 100;
261 } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
262 chance = base_chance * vlevel->work_raise_chance / 100;
263 } else {
264 /* No battle and no work done. */
265 return FALSE;
266 }
267
268 if (fc_rand(100) < chance) {
269 punit->veteran++;
270 return TRUE;
271 }
272
273 return FALSE;
274}
275
276/**********************************************************************/
286 bool unit_versus_unit(struct unit *attacker, struct unit *defender,
287 int *att_hp, int *def_hp, int *att_vet, int *def_vet)
288{
289 int attackpower = get_total_attack_power(attacker, defender);
290 int defensepower = get_total_defense_power(attacker, defender);
291 int attack_firepower, defense_firepower;
292 struct player *plr1 = unit_owner(attacker);
293 struct player *plr2 = unit_owner(defender);
294 struct civ_map *nmap = &(wld.map);
295 int max_rounds;
296 int rounds;
297 int att_strength;
298 int def_strength;
299
300 *att_hp = attacker->hp;
301 *def_hp = defender->hp;
302 get_modified_firepower(nmap, attacker, defender,
303 &attack_firepower, &defense_firepower);
304
305 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
306 "defense firepower:%d", attackpower, defensepower,
307 attack_firepower, defense_firepower);
308
309 player_update_last_war_action(plr1);
310 player_update_last_war_action(plr2);
311
312 att_strength = attackpower * attacker->hp * attack_firepower;
313 def_strength = defensepower * defender->hp * defense_firepower;
314
315 /* In a combat between equal strength units the values are 50% / 50%.
316 * -> scaling that to 100% by doubling, to match scale of chances
317 * in existing rulesets, and in !combat_odds_scaled_veterancy case. */
318 *att_vet = def_strength * 2 / (att_strength + def_strength);
319 *def_vet = att_strength * 2 / (att_strength + def_strength);
320
321 if (attackpower == 0) {
322 *att_hp = 0;
323 } else if (defensepower == 0) {
324 *def_hp = 0;
325 }
326 max_rounds = get_unit_bonus(attacker, EFT_COMBAT_ROUNDS);
327 for (rounds = 0;
328 *att_hp > 0 && *def_hp > 0
329 && (max_rounds <= 0 || max_rounds > rounds);
330 rounds++) {
331 if (fc_rand(attackpower + defensepower) >= defensepower) {
332 *def_hp -= attack_firepower;
333 } else {
334 *att_hp -= defense_firepower;
335 }
336 }
337 if (*att_hp < 0) {
338 *att_hp = 0;
339 }
340 if (*def_hp < 0) {
341 *def_hp = 0;
342 }
343
344 return attackpower <= 0 || defensepower <= 0;
345}
346
347/**********************************************************************/
352 void unit_bombs_unit(struct unit *attacker, struct unit *defender,
353 int *att_hp, int *def_hp)
354{
355 int i;
356 int rate = unit_bombard_rate(attacker);
357 int attackpower = get_total_attack_power(attacker, defender);
358 int defensepower = get_total_defense_power(attacker, defender);
359 int attack_firepower, defense_firepower;
360 struct player *plr1 = unit_owner(attacker);
361 struct player *plr2 = unit_owner(defender);
362 struct civ_map *nmap = &(wld.map);
363
364 *att_hp = attacker->hp;
365 *def_hp = defender->hp;
366 get_modified_firepower(nmap, attacker, defender,
367 &attack_firepower, &defense_firepower);
368
369 log_verbose("attack:%d, defense:%d, attack firepower:%d, "
370 "defense firepower:%d", attackpower, defensepower,
371 attack_firepower, defense_firepower);
372
373 player_update_last_war_action(plr1);
374 player_update_last_war_action(plr2);
375
376 for (i = 0; i < rate; i++) {
377 if (fc_rand(attackpower + defensepower) >= defensepower) {
378 *def_hp -= attack_firepower;
379 }
380 }
381
382 /* Don't kill the target. */
383 if (*def_hp <= 0) {
384 *def_hp = 1;
385 }
386}
387
388/**********************************************************************/
392 void combat_veterans(struct unit *attacker, struct unit *defender,
393 bool powerless, int att_vet, int def_vet)
394{
395 if (!powerless || !game.info.only_real_fight_makes_veteran) {
396 if (attacker->hp <= 0 || defender->hp <= 0
397 || !game.info.only_killing_makes_veteran) {
398 if (!game.info.combat_odds_scaled_veterancy) {
399 att_vet = 100;
400 def_vet = 100;
401 }
402 if (attacker->hp > 0) {
403 maybe_make_veteran(attacker, att_vet);
404 }
405 if (defender->hp > 0) {
406 maybe_make_veteran(defender, def_vet);
407 }
408 }
409 }
410}
411
412/**********************************************************************/
416 static void do_upgrade_effects(struct player *pplayer)
417{
418 int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT);
419 struct unit_list *candidates;
420
421 if (upgrades <= 0) {
422 return;
423 }
424 candidates = unit_list_new();
425
426 unit_list_iterate(pplayer->units, punit) {
427 /* We have to be careful not to strand units at sea, for example by
428 * upgrading a frigate to an ironclad while it was carrying a unit. */
429 if (UU_OK == unit_upgrade_test(&(wld.map), punit, TRUE)) {
430 unit_list_prepend(candidates, punit); /* Potential candidate :) */
431 }
432 } unit_list_iterate_end;
433
434 while (upgrades > 0 && unit_list_size(candidates) > 0) {
435 /* Upgrade one unit. The unit is chosen at random from the list of
436 * available candidates. */
437 int candidate_to_upgrade = fc_rand(unit_list_size(candidates));
438 struct unit *punit = unit_list_get(candidates, candidate_to_upgrade);
439 const struct unit_type *type_from = unit_type_get(punit);
440 const struct unit_type *type_to = can_upgrade_unittype(pplayer, type_from);
441
442 transform_unit(punit, type_to, game.server.autoupgrade_veteran_loss);
443 notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
444 _("%s was upgraded for free to %s."),
445 utype_name_translation(type_from),
446 unit_link(punit));
447 unit_list_remove(candidates, punit);
448 upgrades--;
449 }
450
451 unit_list_destroy(candidates);
452}
453
454/**********************************************************************/
469 void player_restore_units(struct player *pplayer)
470{
471 const struct civ_map *nmap = &(wld.map);
472
473 /* 1) get Leonardo out of the way first: */
474 do_upgrade_effects(pplayer);
475
476 unit_list_iterate_safe(pplayer->units, punit) {
477
478 /* 2) Modify unit hitpoints. Helicopters can even lose them. */
479 unit_restore_hitpoints(punit);
480
481 /* 3) Check that unit has hitpoints */
482 if (punit->hp <= 0) {
483 /* This should usually only happen for heli units, but if any other
484 * units get 0 hp somehow, catch them too. --dwp */
485 /* if 'game.server.killunhomed' is activated unhomed units are slowly
486 * killed; notify player here */
487 if (!punit->homecity && 0 < game.server.killunhomed) {
488 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
489 ftc_server, _("Your %s has run out of hit points "
490 "because it was not supported by a city."),
491 unit_tile_link(punit));
492 } else {
493 notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
494 _("Your %s has run out of hit points."),
495 unit_tile_link(punit));
496 }
497
498 wipe_unit(punit, ULR_HP_LOSS, NULL);
499 continue; /* Continue iterating... */
500 }
501
502 /* 4) Rescue planes if needed */
503 if (utype_fuel(unit_type_get(punit))) {
504 /* Shall we emergency return home on the last vapors? */
505
506 /* I think this is strongly against the spirit of client goto.
507 * The problem is (again) that here we know too much. -- Zamar */
508
509 if (punit->fuel <= 1
510 && !is_unit_being_refueled(punit)) {
511 struct unit *carrier;
512
513 carrier = transporter_for_unit(punit);
514 if (carrier) {
515 unit_transport_load_tp_status(punit, carrier, FALSE);
516 } else {
517 struct pf_map *pfm;
518 struct pf_parameter parameter;
519 bool alive = TRUE;
520
521 pft_fill_unit_parameter(&parameter, nmap, punit);
522 parameter.omniscience = !has_handicap(pplayer, H_MAP);
523 pfm = pf_map_new(&parameter);
524
525 pf_map_move_costs_iterate(pfm, ptile, move_cost, TRUE) {
526 if (move_cost > punit->moves_left) {
527 /* Too far */
528 break;
529 }
530
531 if (is_refuel_point(ptile, pplayer, punit)) {
532 struct pf_path *path;
533 int id = punit->id;
534
535 /* Client orders may be running for this unit - if so
536 * we free them before engaging goto. */
537 free_unit_orders(punit);
538
539 path = pf_map_path(pfm, ptile);
540
541 alive = adv_follow_path(punit, path, ptile);
542
543 if (!alive) {
544 log_error("rescue plane: unit %d died enroute!", id);
545 } else if (!same_pos(unit_tile(punit), ptile)) {
546 /* Enemy units probably blocked our route
547 * FIXME: We should try find alternative route around
548 * the enemy unit instead of just giving up and crashing. */
549 log_debug("rescue plane: unit %d could not move to "
550 "refuel point!", punit->id);
551 }
552
553 if (alive) {
554 /* Clear activity. Unit info will be sent in the end of
555 * the function. */
556 unit_activity_handling(punit, ACTIVITY_IDLE);
557 adv_unit_new_task(punit, AUT_NONE, NULL);
558 punit->goto_tile = NULL;
559
560 if (!is_unit_being_refueled(punit)) {
561 carrier = transporter_for_unit(punit);
562 if (carrier) {
563 unit_transport_load_tp_status(punit, carrier, FALSE);
564 }
565 }
566
567 notify_player(pplayer, unit_tile(punit),
568 E_UNIT_ORDERS, ftc_server,
569 _("Your %s has returned to refuel."),
570 unit_link(punit));
571 }
572 pf_path_destroy(path);
573 break;
574 }
575 } pf_map_move_costs_iterate_end;
576 pf_map_destroy(pfm);
577
578 if (!alive) {
579 /* Unit died trying to move to refuel point. */
580 return;
581 }
582 }
583 }
584
585 /* 5) Update fuel */
586 punit->fuel--;
587
588 /* 6) Automatically refuel air units in cities, airbases, and
589 * transporters (carriers). */
590 if (is_unit_being_refueled(punit)) {
591 punit->fuel = utype_fuel(unit_type_get(punit));
592 }
593 }
594 } unit_list_iterate_safe_end;
595
596 /* 7) Check if there are air units without fuel */
597 unit_list_iterate_safe(pplayer->units, punit) {
598 const struct unit_type *utype = unit_type_get(punit);
599
600 if (punit->fuel <= 0 && utype_fuel(utype)) {
601 /* Notifications sent from the lua script when unit wiped. */
602 wipe_unit(punit, ULR_FUEL, NULL);
603 }
604 } unit_list_iterate_safe_end;
605
606 /* Send all updates. */
607 unit_list_iterate(pplayer->units, punit) {
608 send_unit_info(NULL, punit);
609 } unit_list_iterate_end;
610}
611
612/**********************************************************************/
622 static void unit_restore_hitpoints(struct unit *punit)
623{
624 bool was_lower;
625 const struct unit_type *utype = unit_type_get(punit);
626
627 was_lower = (punit->hp < utype->hp);
628
629 punit->hp += unit_gain_hitpoints(punit);
630
631 fc_assert(punit->hp >= 0);
632 fc_assert(punit->hp <= utype->hp);
633
634 if (punit->hp == utype->hp) {
635 if (was_lower && punit->activity == ACTIVITY_SENTRY) {
636 set_unit_activity(punit, ACTIVITY_IDLE);
637 }
638 }
639
640 punit->moved = FALSE;
641 punit->paradropped = FALSE;
642}
643
644/**********************************************************************/
649 static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
650{
651 punit->moves_left = unit_move_rate(punit);
652 punit->done_moving = FALSE;
653}
654
655/**********************************************************************/
658 void update_unit_activities(struct player *pplayer)
659{
660 unit_list_iterate_safe(pplayer->units, punit) {
661 update_unit_activity(punit);
662 } unit_list_iterate_safe_end;
663}
664
665/**********************************************************************/
668 void execute_unit_orders(struct player *pplayer)
669{
670 unit_list_iterate_safe(pplayer->units, punit) {
671 if (unit_has_orders(punit)) {
672 execute_orders(punit, FALSE);
673 }
674 } unit_list_iterate_safe_end;
675}
676
677/**********************************************************************/
680 void unit_tc_effect_refresh(struct player *pplayer)
681{
682 unit_list_iterate(pplayer->units, punit) {
683 unit_refresh_vision(punit);
684 } unit_list_iterate_end;
685}
686
687/**********************************************************************/
690 void finalize_unit_phase_beginning(struct player *pplayer)
691{
692 /* Remember activities only after all knock-on effects of unit activities
693 * on other units have been resolved */
694 unit_list_iterate(pplayer->units, punit) {
695 punit->changed_from = punit->activity;
696 punit->changed_from_target = punit->activity_target;
697 punit->changed_from_count = punit->activity_count;
698 send_unit_info(NULL, punit);
699 } unit_list_iterate_end;
700}
701
702/**********************************************************************/
706 static int total_activity(struct tile *ptile, enum unit_activity act,
707 struct extra_type *tgt)
708{
709 int total = 0;
710 bool tgt_matters = activity_requires_target(act);
711
712 unit_list_iterate(ptile->units, punit) {
713 if (punit->activity == act
714 && (!tgt_matters || punit->activity_target == tgt)) {
715 total += punit->activity_count;
716 }
717 } unit_list_iterate_end;
718
719 return total;
720}
721
722/**********************************************************************/
726 static bool total_activity_done(struct tile *ptile, enum unit_activity act,
727 struct extra_type *tgt)
728{
729 return total_activity(ptile, act, tgt) >= tile_activity_time(act, ptile, tgt);
730}
731
732/**********************************************************************/
735 void notify_unit_experience(struct unit *punit)
736{
737 const struct veteran_level *vlevel;
738#ifndef FREECIV_NDEBUG
739 const struct veteran_system *vsystem;
740#endif
741
742 if (!punit) {
743 return;
744 }
745
746#ifndef FREECIV_NDEBUG
747 vsystem = utype_veteran_system(unit_type_get(punit));
748 fc_assert_ret(vsystem != NULL);
749 fc_assert_ret(vsystem->levels > punit->veteran);
750#endif /* FREECIV_NDEBUG */
751
752 vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
753 fc_assert_ret(vlevel != NULL);
754
755 notify_player(unit_owner(punit), unit_tile(punit),
756 E_UNIT_BECAME_VET, ftc_server,
757 /* TRANS: Your <unit> became ... rank of <veteran level>. */
758 _("Your %s became more experienced and achieved the rank "
759 "of %s."),
760 unit_link(punit), name_translation_get(&vlevel->name));
761}
762
763/**********************************************************************/
766 static void unit_convert(struct unit *punit)
767{
768 const struct unit_type *to_type;
769 const struct unit_type *from_type;
770
771 from_type = unit_type_get(punit);
772 to_type = from_type->converted_to;
773
774 if (unit_can_convert(&(wld.map), punit)) {
775 transform_unit(punit, to_type, 0);
776 notify_player(unit_owner(punit), unit_tile(punit),
777 E_UNIT_UPGRADED, ftc_server,
778 _("%s converted to %s."),
779 utype_name_translation(from_type),
780 utype_name_translation(to_type));
781 } else {
782 notify_player(unit_owner(punit), unit_tile(punit),
783 E_UNIT_UPGRADED, ftc_server,
784 _("%s cannot be converted."),
785 utype_name_translation(from_type));
786 }
787}
788
789/**********************************************************************/
792 void unit_activities_cancel(struct unit *punit)
793{
794 if (unit_has_orders(punit)) {
795 notify_player(unit_owner(punit), unit_tile(punit),
796 E_UNIT_ORDERS, ftc_server,
797 _("Orders for %s aborted because activity "
798 "is no longer available."),
799 unit_link(punit));
800 free_unit_orders(punit);
801 }
802
803 set_unit_activity(punit, ACTIVITY_IDLE);
804 send_unit_info(NULL, punit);
805}
806
807/**********************************************************************/
810 void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
811{
812 unit_list_iterate(pplayer->units, punit) {
813 if (!can_unit_continue_current_activity(&(wld.map), punit)) {
814 unit_activities_cancel(punit);
815 }
816 } unit_list_iterate_end;
817}
818
819/**********************************************************************/
822 void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
823{
824 unit_list_iterate(ptile->units, punit) {
825 if (!can_unit_continue_current_activity(&(wld.map), punit)) {
826 unit_activities_cancel(punit);
827 }
828 } unit_list_iterate_end;
829}
830
831/**********************************************************************/
837 void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
838{
839 unit_activities_cancel_all_illegal_tile(ptile);
840
841 adjc_iterate(&(wld.map), ptile, ptile2) {
842 unit_activities_cancel_all_illegal_tile(ptile2);
843 } adjc_iterate_end;
844}
845
846/**********************************************************************/
852 static void update_unit_activity(struct unit *punit)
853{
854 struct player *pplayer = unit_owner(punit);
855 bool unit_activity_done = FALSE;
856 enum unit_activity activity = punit->activity;
857 struct tile *ptile = unit_tile(punit);
858 const struct unit_type *act_utype = unit_type_get(punit);
859
860 switch (activity) {
861 case ACTIVITY_IDLE:
862 case ACTIVITY_EXPLORE:
863 case ACTIVITY_FORTIFIED:
864 case ACTIVITY_SENTRY:
865 case ACTIVITY_GOTO:
866 case ACTIVITY_PATROL_UNUSED:
867 case ACTIVITY_UNKNOWN:
868 case ACTIVITY_LAST:
869 /* We don't need the activity_count for the above */
870 break;
871
872 case ACTIVITY_FORTIFYING:
873 case ACTIVITY_CONVERT:
874 punit->activity_count += get_activity_rate_this_turn(punit);
875 break;
876
877 case ACTIVITY_POLLUTION:
878 case ACTIVITY_MINE:
879 case ACTIVITY_IRRIGATE:
880 case ACTIVITY_PILLAGE:
881 case ACTIVITY_CULTIVATE:
882 case ACTIVITY_PLANT:
883 case ACTIVITY_TRANSFORM:
884 case ACTIVITY_FALLOUT:
885 case ACTIVITY_BASE:
886 case ACTIVITY_GEN_ROAD:
887 punit->activity_count += get_activity_rate_this_turn(punit);
888
889 /* settler may become veteran when doing something useful */
890 if (maybe_become_veteran_real(punit, 100, TRUE)) {
891 notify_unit_experience(punit);
892 }
893 break;
894 case ACTIVITY_OLD_ROAD:
895 case ACTIVITY_OLD_RAILROAD:
896 case ACTIVITY_FORTRESS:
897 case ACTIVITY_AIRBASE:
898 fc_assert(FALSE);
899 break;
900 };
901
902 unit_restore_movepoints(pplayer, punit);
903
904 switch (activity) {
905 case ACTIVITY_IDLE:
906 case ACTIVITY_FORTIFIED:
907 case ACTIVITY_SENTRY:
908 case ACTIVITY_GOTO:
909 case ACTIVITY_UNKNOWN:
910 case ACTIVITY_FORTIFYING:
911 case ACTIVITY_CONVERT:
912 case ACTIVITY_PATROL_UNUSED:
913 case ACTIVITY_LAST:
914 /* no default, ensure all handled */
915 break;
916
917 case ACTIVITY_EXPLORE:
918 do_explore(punit);
919 return;
920
921 case ACTIVITY_PILLAGE:
922 if (total_activity_done(ptile, ACTIVITY_PILLAGE,
923 punit->activity_target)) {
924 destroy_extra(ptile, punit->activity_target);
925 unit_activity_done = TRUE;
926
927 bounce_units_on_terrain_change(ptile);
928
929 /* Change vision if effects have changed. */
930 unit_list_refresh_vision(ptile->units);
931 }
932 break;
933
934 case ACTIVITY_POLLUTION:
935 /* TODO: Remove this fallback target setting when target always correctly
936 * set */
937 if (punit->activity_target == NULL) {
938 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANPOLLUTION,
939 NULL, punit);
940 }
941 if (total_activity_done(ptile, ACTIVITY_POLLUTION, punit->activity_target)) {
942 destroy_extra(ptile, punit->activity_target);
943 unit_activity_done = TRUE;
944 }
945 break;
946
947 case ACTIVITY_FALLOUT:
948 /* TODO: Remove this fallback target setting when target always correctly
949 * set */
950 if (punit->activity_target == NULL) {
951 punit->activity_target = prev_extra_in_tile(ptile, ERM_CLEANFALLOUT,
952 NULL, punit);
953 }
954 if (total_activity_done(ptile, ACTIVITY_FALLOUT, punit->activity_target)) {
955 destroy_extra(ptile, punit->activity_target);
956 unit_activity_done = TRUE;
957 }
958 break;
959
960 case ACTIVITY_BASE:
961 {
962 if (total_activity(ptile, ACTIVITY_BASE, punit->activity_target)
963 >= tile_activity_time(ACTIVITY_BASE, ptile, punit->activity_target)) {
964 create_extra(ptile, punit->activity_target, unit_owner(punit));
965 unit_activity_done = TRUE;
966 }
967 }
968 break;
969
970 case ACTIVITY_GEN_ROAD:
971 {
972 if (total_activity(ptile, ACTIVITY_GEN_ROAD, punit->activity_target)
973 >= tile_activity_time(ACTIVITY_GEN_ROAD, ptile, punit->activity_target)) {
974 create_extra(ptile, punit->activity_target, unit_owner(punit));
975 unit_activity_done = TRUE;
976 }
977 }
978 break;
979
980 case ACTIVITY_IRRIGATE:
981 case ACTIVITY_MINE:
982 case ACTIVITY_CULTIVATE:
983 case ACTIVITY_PLANT:
984 case ACTIVITY_TRANSFORM:
985 if (total_activity_done(ptile, activity, punit->activity_target)) {
986 struct terrain *old = tile_terrain(ptile);
987
988 /* The function below could change the terrain. Therefore, we have to
989 * check the terrain (which will also do a sanity check for the tile). */
990 tile_apply_activity(ptile, activity, punit->activity_target);
991 check_terrain_change(ptile, old);
992 unit_activity_done = TRUE;
993 }
994 break;
995
996 case ACTIVITY_OLD_ROAD:
997 case ACTIVITY_OLD_RAILROAD:
998 case ACTIVITY_FORTRESS:
999 case ACTIVITY_AIRBASE:
1000 fc_assert(FALSE);
1001 break;
1002 }
1003
1004 if (unit_activity_done) {
1005 update_tile_knowledge(ptile);
1006 if (ACTIVITY_CULTIVATE == activity
1007 || ACTIVITY_PLANT == activity
1008 || ACTIVITY_TRANSFORM == activity) {
1009 unit_list_iterate(ptile->units, punit2) {
1010 if (punit2->activity == activity) {
1011 fc_assert(punit->activity_target == NULL);
1012
1013 set_unit_activity(punit2, ACTIVITY_IDLE);
1014 }
1015 } unit_list_iterate_end;
1016 } else {
1017 struct extra_type *act_tgt = punit->activity_target;
1018
1019 unit_list_iterate(ptile->units, punit2) {
1020 if (punit2->activity == activity
1021 && punit2->activity_target == act_tgt) {
1022 /* This unit was helping with the work just finished.
1023 * Mark it idle (already finished) so its "current"
1024 * activity is not considered illegal
1025 * in tile_change_side_effects() . */
1026 set_unit_activity(punit2, ACTIVITY_IDLE);
1027 }
1028 } unit_list_iterate_end;
1029 }
1030
1031 tile_change_side_effects(ptile, FALSE);
1032 }
1033
1034 if (activity == ACTIVITY_FORTIFYING) {
1035 if (punit->activity_count
1036 >= action_id_get_act_time(ACTION_FORTIFY,
1037 punit, ptile, punit->activity_target)) {
1038 set_unit_activity(punit, ACTIVITY_FORTIFIED);
1039 unit_activity_done = TRUE;
1040 }
1041 }
1042
1043 if (activity == ACTIVITY_CONVERT) {
1044 if (punit->activity_count
1045 >= action_id_get_act_time(ACTION_CONVERT,
1046 punit, ptile, punit->activity_target)) {
1047 unit_convert(punit);
1048 set_unit_activity(punit, ACTIVITY_IDLE);
1049 unit_activity_done = TRUE;
1050 }
1051 }
1052
1053 if (unit_activity_done) {
1054 if (activity == ACTIVITY_PILLAGE) {
1055 /* Casus Belli for when the action is completed. */
1056 /* TODO: is it more logical to put Casus_Belli_Success here, change
1057 * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
1058 * trigger it when an activity successfully has began? */
1059 action_consequence_complete(action_by_number(ACTION_PILLAGE),
1060 unit_owner(punit),
1061 act_utype,
1062 tile_owner(unit_tile(punit)),
1063 unit_tile(punit),
1064 tile_link(unit_tile(punit)));
1065 }
1066 }
1067}
1068
1069/**********************************************************************/
1073 void unit_forget_last_activity(struct unit *punit)
1074{
1075 punit->changed_from = ACTIVITY_IDLE;
1076}
1077
1078/**********************************************************************/
1082 bool unit_activity_needs_target_from_client(enum unit_activity activity)
1083{
1084 switch (activity) {
1085 case ACTIVITY_PILLAGE:
1086 /* Can be set server side. */
1087 return FALSE;
1088 default:
1089 return activity_requires_target(activity);
1090 }
1091}
1092
1093/**********************************************************************/
1102 void unit_assign_specific_activity_target(struct unit *punit,
1103 enum unit_activity *activity,
1104 struct extra_type **target)
1105{
1106 const struct civ_map *nmap = &(wld.map);
1107
1108 if (*activity == ACTIVITY_PILLAGE
1109 && *target == NULL) {
1110 struct tile *ptile = unit_tile(punit);
1111 struct extra_type *tgt;
1112 bv_extras extras = *tile_extras(ptile);
1113
1114 while ((tgt = get_preferred_pillage(extras))) {
1115
1116 BV_CLR(extras, extra_index(tgt));
1117
1118 if (can_unit_do_activity_targeted(nmap, punit, *activity, tgt)) {
1119 *target = tgt;
1120 return;
1121 }
1122 }
1123
1124 /* Nothing we can pillage here. */
1125 *activity = ACTIVITY_IDLE;
1126 }
1127}
1128
1129/**********************************************************************/
1133 static bool find_a_good_partisan_spot(struct tile *pcenter,
1134 struct player *powner,
1135 struct unit_type *u_type,
1136 int sq_radius,
1137 struct tile **dst_tile)
1138{
1139 int bestvalue = 0;
1140 struct civ_map *nmap = &(wld.map);
1141
1142 /* coords of best tile in arg pointers */
1143 circle_iterate(nmap, pcenter, sq_radius, ptile) {
1144 int value;
1145
1146 if (!is_native_tile(u_type, ptile)) {
1147 continue;
1148 }
1149
1150 if (NULL != tile_city(ptile)) {
1151 continue;
1152 }
1153
1154 if (0 < unit_list_size(ptile->units)) {
1155 continue;
1156 }
1157
1158 /* City may not have changed hands yet; see place_partisans(). */
1159 value = get_virtual_defense_power(nmap, NULL, u_type, powner,
1160 ptile, FALSE, 0);
1161 value *= 10;
1162
1163 if (tile_continent(ptile) != tile_continent(pcenter)) {
1164 value /= 2;
1165 }
1166
1167 value -= fc_rand(value/3);
1168
1169 if (value > bestvalue) {
1170 *dst_tile = ptile;
1171 bestvalue = value;
1172 }
1173 } circle_iterate_end;
1174
1175 return bestvalue > 0;
1176}
1177
1178/**********************************************************************/
1181 void place_partisans(struct tile *pcenter, struct player *powner,
1182 int count, int sq_radius)
1183{
1184 struct tile *ptile = NULL;
1185 struct unit_type *u_type = get_role_unit(L_PARTISAN, 0);
1186 const struct civ_map *nmap = &(wld.map);
1187
1188 while (count-- > 0
1189 && find_a_good_partisan_spot(pcenter, powner, u_type,
1190 sq_radius, &ptile)) {
1191 struct unit *punit;
1192
1193 punit = unit_virtual_prepare(powner, ptile, u_type, 0, 0, -1, -1);
1194 if (can_unit_do_activity(nmap, punit, ACTIVITY_FORTIFYING)) {
1195 punit->activity = ACTIVITY_FORTIFIED; /* Yes; directly fortified */
1196 }
1197
1198 (void) place_unit(punit, powner, NULL, NULL, FALSE);
1199 }
1200}
1201
1202/**********************************************************************/
1207 bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1208 int move_cost, bool verbose)
1209{
1210 struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1211
1212 if (city_owner(pcity) == unit_owner(punit)) {
1213 log_verbose("Teleported %s %s from (%d,%d) to %s",
1214 nation_rule_name(nation_of_unit(punit)),
1215 unit_rule_name(punit), TILE_XY(src_tile), city_name_get(pcity));
1216 if (verbose) {
1217 notify_player(unit_owner(punit), city_tile(pcity),
1218 E_UNIT_RELOCATED, ftc_server,
1219 _("Teleported your %s to %s."),
1220 unit_link(punit),
1221 city_link(pcity));
1222 }
1223
1224 /* Silently free orders since they won't be applicable anymore. */
1225 free_unit_orders(punit);
1226
1227 if (move_cost == -1) {
1228 move_cost = punit->moves_left;
1229 }
1230 unit_move(punit, dst_tile, move_cost,
1231 NULL, FALSE, FALSE, FALSE, FALSE, FALSE);
1232
1233 return TRUE;
1234 }
1235 return FALSE;
1236}
1237
1238/**********************************************************************/
1245 void bounce_unit(struct unit *punit, bool verbose)
1246{
1247 struct player *pplayer;
1248 struct tile *punit_tile;
1249 int count = 0;
1250
1251 /* I assume that there are no topologies that have more than
1252 * (2d + 1)^2 tiles in the "square" of "radius" d. */
1253 const int DIST = 2;
1254 struct tile *tiles[(2 * DIST + 1) * (2 * DIST + 1)];
1255
1256 if (!punit) {
1257 return;
1258 }
1259
1260 pplayer = unit_owner(punit);
1261 punit_tile = unit_tile(punit);
1262
1263 square_iterate(&(wld.map), punit_tile, DIST, ptile) {
1264 if (count >= ARRAY_SIZE(tiles)) {
1265 break;
1266 }
1267
1268 if (ptile == punit_tile) {
1269 continue;
1270 }
1271
1272 if (can_unit_survive_at_tile(&(wld.map), punit, ptile)
1273 && !is_non_allied_city_tile(ptile, pplayer)
1274 && !is_non_allied_unit_tile(ptile, pplayer)) {
1275 tiles[count++] = ptile;
1276 }
1277 } square_iterate_end;
1278
1279 if (count > 0) {
1280 struct tile *ptile = tiles[fc_rand(count)];
1281
1282 if (verbose) {
1283 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
1284 /* TRANS: A unit is moved to resolve stack conflicts. */
1285 _("Moved your %s."),
1286 unit_link(punit));
1287 }
1288
1289 /* TODO: should a unit be able to bounce to a transport like is done
1290 * below? What if the unit can't legally enter the transport, say
1291 * because the transport is Unreachable and the unit doesn't have it in
1292 * its embarks field or because "Transport Embark" isn't enabled? Kept
1293 * like it was to preserve the old rules for now. -- Sveinung */
1294 unit_move(punit, ptile, 0, NULL, TRUE, FALSE, FALSE, FALSE, FALSE);
1295 return;
1296 }
1297
1298 /* Didn't find a place to bounce the unit, going to disband it.
1299 * Try to bounce transported units. */
1300 if (0 < get_transporter_occupancy(punit)) {
1301 struct unit_list *pcargo_units;
1302
1303 pcargo_units = unit_transport_cargo(punit);
1304 unit_list_iterate_safe(pcargo_units, pcargo) {
1305 bounce_unit(pcargo, verbose);
1306 } unit_list_iterate_safe_end;
1307 }
1308
1309 if (verbose) {
1310 notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1311 /* TRANS: A unit is disbanded to resolve stack conflicts. */
1312 _("Disbanded your %s."),
1313 unit_tile_link(punit));
1314 }
1315
1316 wipe_unit(punit, ULR_STACK_CONFLICT, NULL);
1317}
1318
1319/**********************************************************************/
1324 static void throw_units_from_illegal_cities(struct player *pplayer,
1325 bool verbose)
1326{
1327 struct tile *ptile;
1328 struct city *pcity;
1329 struct unit *ptrans;
1330 struct unit_list *pcargo_units;
1331
1332 /* Unload undesired units from transports, if possible. */
1333 unit_list_iterate(pplayer->units, punit) {
1334 ptile = unit_tile(punit);
1335 pcity = tile_city(ptile);
1336 if (NULL != pcity
1337 && !pplayers_allied(city_owner(pcity), pplayer)
1338 && 0 < get_transporter_occupancy(punit)) {
1339 pcargo_units = unit_transport_cargo(punit);
1340 unit_list_iterate(pcargo_units, pcargo) {
1341 if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1342 if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1343 unit_transport_unload_send(pcargo);
1344 }
1345 }
1346 } unit_list_iterate_end;
1347 }
1348 } unit_list_iterate_end;
1349
1350 /* Bounce units except transported ones which will be bounced with their
1351 * transport. */
1352 unit_list_iterate_safe(pplayer->units, punit) {
1353 ptile = unit_tile(punit);
1354 pcity = tile_city(ptile);
1355 if (NULL != pcity
1356 && !pplayers_allied(city_owner(pcity), pplayer)) {
1357 ptrans = unit_transport_get(punit);
1358 if (NULL == ptrans || pplayer != unit_owner(ptrans)) {
1359 bounce_unit(punit, verbose);
1360 }
1361 }
1362 } unit_list_iterate_safe_end;
1363
1364#ifdef FREECIV_DEBUG
1365 /* Sanity check. */
1366 unit_list_iterate(pplayer->units, punit) {
1367 ptile = unit_tile(punit);
1368 pcity = tile_city(ptile);
1369 fc_assert_msg(NULL == pcity
1370 || pplayers_allied(city_owner(pcity), pplayer),
1371 "Failed to throw %s %d from %s %d (%d, %d)",
1372 unit_rule_name(punit),
1373 punit->id,
1374 city_name_get(pcity),
1375 pcity->id,
1376 TILE_XY(ptile));
1377 } unit_list_iterate_end;
1378#endif /* FREECIV_DEBUG */
1379}
1380
1381/**********************************************************************/
1389 static void resolve_stack_conflicts(struct player *pplayer,
1390 struct player *aplayer, bool verbose)
1391{
1392 unit_list_iterate_safe(pplayer->units, punit) {
1393 struct tile *ptile = unit_tile(punit);
1394
1395 if (is_non_allied_unit_tile(ptile, pplayer)) {
1396 unit_list_iterate_safe(ptile->units, aunit) {
1397 if (unit_owner(aunit) == pplayer
1398 || unit_owner(aunit) == aplayer
1399 || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1400 bounce_unit(aunit, verbose);
1401 }
1402 } unit_list_iterate_safe_end;
1403 }
1404 } unit_list_iterate_safe_end;
1405}
1406
1407/**********************************************************************/
1418 void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1419 bool verbose)
1420{
1421 throw_units_from_illegal_cities(pplayer, verbose);
1422 throw_units_from_illegal_cities(aplayer, verbose);
1423
1424 resolve_stack_conflicts(pplayer, aplayer, verbose);
1425 resolve_stack_conflicts(aplayer, pplayer, verbose);
1426}
1427
1428/**********************************************************************/
1433 struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1434 const struct player *aplayer)
1435{
1436 struct unit_list *seen_units = unit_list_new();
1437
1438 /* Anybody's units inside ally's cities */
1439 city_list_iterate(aplayer->cities, pcity) {
1440 unit_list_iterate(city_tile(pcity)->units, punit) {
1441 if (can_player_see_unit(pplayer, punit)) {
1442 unit_list_append(seen_units, punit);
1443 }
1444 } unit_list_iterate_end;
1445 } city_list_iterate_end;
1446
1447 /* Ally's own units inside transports */
1448 unit_list_iterate(aplayer->units, punit) {
1449 if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1450 unit_list_append(seen_units, punit);
1451 }
1452 } unit_list_iterate_end;
1453
1454 /* Make sure the same unit is not added in multiple phases
1455 * (unit within transport in a city) */
1456 unit_list_unique(seen_units);
1457
1458 return seen_units;
1459}
1460
1461/**********************************************************************/
1468 void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1469 const struct unit_list *seen_units)
1470{
1471 unit_list_iterate(seen_units, punit) {
1472 /* We need to hide units previously seen by the client. */
1473 if (!can_player_see_unit(pplayer, punit)) {
1474 unit_goes_out_of_sight(pplayer, punit);
1475 }
1476 } unit_list_iterate_end;
1477
1478 city_list_iterate(aplayer->cities, pcity) {
1479 /* The player used to know what units were in these cities. Now that
1480 * they don't, they need to get a new short city packet updating the
1481 * occupied status. */
1482 if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1483 send_city_info(pplayer, pcity);
1484 }
1485 } city_list_iterate_end;
1486}
1487
1488/**********************************************************************/
1492 void give_allied_visibility(struct player *pplayer,
1493 struct player *aplayer)
1494{
1495 unit_list_iterate(aplayer->units, punit) {
1496 if (can_player_see_unit(pplayer, punit)) {
1497 send_unit_info(pplayer->connections, punit);
1498 }
1499 } unit_list_iterate_end;
1500}
1501
1502/**********************************************************************/
1505 static bool is_refuel_tile(const struct tile *ptile,
1506 const struct player *pplayer,
1507 const struct unit *punit)
1508{
1509 const struct unit_type *utype;
1510 const struct unit_class *pclass;
1511
1512 if (is_allied_city_tile(ptile, pplayer)) {
1513 return TRUE;
1514 }
1515
1516 utype = unit_type_get(punit);
1517 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(&(wld.map), ptile)) {
1518 return TRUE;
1519 }
1520
1521 pclass = utype_class(utype);
1522 if (NULL != pclass->cache.refuel_extras) {
1523 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1524
1525 extra_type_list_iterate(pclass->cache.refuel_extras, pextra) {
1526 if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1527 return TRUE;
1528 }
1529 } extra_type_list_iterate_end;
1530 }
1531
1532 return FALSE;
1533}
1534
1535/**********************************************************************/
1538 bool is_unit_being_refueled(const struct unit *punit)
1539{
1540 return unit_transported(punit) /* Carrier */
1541 || is_refuel_tile(unit_tile(punit), unit_owner(punit), punit);
1542}
1543
1544/**********************************************************************/
1547 bool is_refuel_point(const struct tile *ptile,
1548 const struct player *pplayer,
1549 const struct unit *punit)
1550{
1551 if (is_non_allied_unit_tile(ptile, pplayer)) {
1552 return FALSE;
1553 }
1554
1555 return is_refuel_tile(ptile, pplayer, punit) || unit_could_load_at(punit, ptile);
1556}
1557
1558/**********************************************************************/
1569 void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1570 int vet_loss)
1571{
1572 struct player *pplayer = unit_owner(punit);
1573 const struct unit_type *old_type = punit->utype;
1574 int old_mr = unit_move_rate(punit);
1575 int old_hp = unit_type_get(punit)->hp;
1576 int lvls;
1577
1578 punit->utype = to_unit;
1579
1580 /* New type may not have the same veteran system, and we may want to
1581 * knock some levels off. */
1582 lvls = utype_veteran_system(to_unit)->levels - 1;
1583 punit->veteran = MIN(punit->veteran, lvls);
1584 /* Keeping the old behaviour, so first clip top, then reduce */
1585 punit->veteran = MAX(punit->veteran - vet_loss, 0);
1586
1587 /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1588 * and don't kill the unit. unit_move_rate() is used to take into account
1589 * global effects like Magellan's Expedition. */
1590 punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1591 if (old_mr == 0) {
1592 punit->moves_left = unit_move_rate(punit);
1593 } else {
1594 punit->moves_left = punit->moves_left * unit_move_rate(punit) / old_mr;
1595 }
1596
1597 unit_forget_last_activity(punit);
1598 if (!can_unit_continue_current_activity(&(wld.map), punit)) {
1599 unit_activities_cancel(punit);
1600 }
1601
1602 /* update unit upkeep */
1603 city_units_upkeep(game_city_by_number(punit->homecity));
1604
1605 conn_list_do_buffer(pplayer->connections);
1606
1607 unit_refresh_vision(punit);
1608
1609 CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1610 CALL_FUNC_EACH_AI(unit_info, punit);
1611
1612 send_unit_info(NULL, punit);
1613 conn_list_do_unbuffer(pplayer->connections);
1614}
1615
1616/**********************************************************************/
1619 struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1620 const struct unit_type *type, int veteran_level,
1621 int homecity_id, int moves_left)
1622{
1623 return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1624 moves_left, -1, NULL);
1625}
1626
1627/**********************************************************************/
1630 void unit_get_goods(struct unit *punit)
1631{
1632 if (punit->homecity != 0) {
1633 struct city *home = game_city_by_number(punit->homecity);
1634
1635 if (home != NULL && game.info.goods_selection == GSM_LEAVING) {
1636 punit->carrying = goods_from_city_to_unit(home, punit);
1637 }
1638 }
1639}
1640
1641/**********************************************************************/
1646 struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1647 const struct unit_type *type, int veteran_level,
1648 int homecity_id, int moves_left, int hp_left,
1649 struct unit *ptrans)
1650{
1651 struct unit *punit
1652 = unit_virtual_prepare(pplayer, ptile, type, veteran_level,
1653 homecity_id, moves_left, hp_left);
1654 struct city *pcity = (!homecity_id || utype_has_flag(type, UTYF_NOHOME))
1655 ? NULL : game_city_by_number(homecity_id);
1656 bool could_place;
1657
1658 fc_assert_ret_val(punit, NULL);
1659 could_place = place_unit(punit, pplayer, pcity, ptrans, FALSE);
1660 fc_assert(could_place);
1661 if (!could_place) {
1662 unit_virtual_destroy(punit);
1663 punit = NULL;
1664 }
1665
1666 return punit;
1667}
1668
1669/**********************************************************************/
1679 struct unit *unit_virtual_prepare(struct player *pplayer, struct tile *ptile,
1680 const struct unit_type *type,
1681 int veteran_level, int homecity_id,
1682 int moves_left, int hp_left)
1683{
1684 struct unit *punit;
1685
1686 fc_assert_ret_val(ptile != NULL, NULL);
1687 punit = unit_virtual_create(pplayer, NULL, type, veteran_level);
1688 unit_tile_set(punit, ptile);
1689
1690 if (utype_has_flag(type, UTYF_NOHOME)) {
1691 punit->homecity = 0; /* none */
1692 } else {
1693 punit->homecity = homecity_id;
1694 }
1695
1696 if (hp_left >= 0) {
1697 /* Override default full HP */
1698 punit->hp = hp_left;
1699 }
1700
1701 if (moves_left >= 0) {
1702 int mr = unit_move_rate(punit);
1703
1704 /* Override default full MP */
1705 /* FIXME: there are valid situations when a unit have mp
1706 * over its move rate. Here, keeping the old behavior. */
1707 punit->moves_left = MIN(moves_left, mr);
1708 /* Assume that if moves_left < 0 then the unit is "fresh",
1709 * and not moved; else the unit has had something happen
1710 * to it (eg, bribed) which we treat as equivalent to moved.
1711 * (Otherwise could pass moved arg too...) --dwp */
1712 punit->moved = TRUE;
1713 }
1714
1715 return punit;
1716}
1717
1718/**********************************************************************/
1727 bool place_unit(struct unit *punit, struct player *pplayer,
1728 struct city *pcity, struct unit *ptrans, bool force)
1729{
1730 struct tile *ptile;
1731
1732 fc_assert_ret_val(pplayer, FALSE);
1733 fc_assert_ret_val(punit, FALSE);
1734 ptile = punit->tile;
1735 fc_assert_ret_val(ptile, FALSE);
1736
1737 /* Register unit */
1738 punit->id = identity_number();
1739 idex_register_unit(&wld, punit);
1740
1741 if (ptrans) {
1742 /* Set transporter for unit. */
1743 unit_transport_load_tp_status(punit, ptrans, force);
1744 }
1745
1746 fc_assert_ret_val(unit_transport_get(punit)
1747 || can_unit_exist_at_tile(&(wld.map), punit, ptile),
1748 FALSE);
1749
1750 unit_list_prepend(pplayer->units, punit);
1751 unit_list_prepend(ptile->units, punit);
1752 maybe_make_contact(ptile, unit_owner(punit));
1753 if (pcity && !unit_has_type_flag(punit, UTYF_NOHOME)) {
1754 fc_assert(punit->homecity == pcity->id);
1755 fc_assert(city_owner(pcity) == pplayer);
1756 unit_list_prepend(pcity->units_supported, punit);
1757 /* update unit upkeep */
1758 city_units_upkeep(pcity);
1759 /* Refresh the unit's homecity. */
1760 city_refresh(pcity);
1761 send_city_info(pplayer, pcity);
1762 }
1763
1764 punit->server.vision = vision_new(pplayer, ptile);
1765 unit_refresh_vision(punit);
1766
1767 send_unit_info(NULL, punit);
1768 wakeup_neighbor_sentries(punit);
1769
1770 /* The unit may have changed the available tiles in nearby cities. */
1771 city_map_update_tile_now(ptile);
1772 sync_cities();
1773
1774 unit_get_goods(punit);
1775
1776 CALL_FUNC_EACH_AI(unit_created, punit);
1777 CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1778
1779 return TRUE;
1780}
1781
1782/**********************************************************************/
1785 void unit_set_removal_callback(struct unit *punit,
1786 void (*callback)(struct unit *punit))
1787{
1788 /* Tried to overwrite another call back. If this assertion is triggered
1789 * in a case where two call back are needed it may be time to support
1790 * more than one unit removal call back at a time. */
1791 fc_assert_ret(punit->server.removal_callback == NULL);
1792
1793 punit->server.removal_callback = callback;
1794}
1795
1796/**********************************************************************/
1799 void unit_unset_removal_callback(struct unit *punit)
1800{
1801 punit->server.removal_callback = NULL;
1802}
1803
1804/**********************************************************************/
1808 static void server_remove_unit_full(struct unit *punit, bool transported,
1809 enum unit_loss_reason reason)
1810{
1811 struct packet_unit_remove packet;
1812 struct tile *ptile = unit_tile(punit);
1813 struct city *pcity = tile_city(ptile);
1814 struct city *phomecity = game_city_by_number(punit->homecity);
1815 struct unit *ptrans;
1816 struct player *pplayer = unit_owner(punit);
1817
1818 /* The unit is doomed. */
1819 punit->server.dying = TRUE;
1820
1821#if defined(FREECIV_DEBUG) && !defined(FREECIV_NDEBUG)
1822 unit_list_iterate(ptile->units, pcargo) {
1823 fc_assert(unit_transport_get(pcargo) != punit);
1824 } unit_list_iterate_end;
1825#endif /* FREECIV_DEBUG */
1826
1827 CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1828 CALL_FUNC_EACH_AI(unit_destroyed, punit);
1829
1830 /* Save transporter for updating below. */
1831 ptrans = unit_transport_get(punit);
1832 /* Unload unit. */
1833 unit_transport_unload(punit);
1834
1835 /* Since settlers plot in new cities in the minimap before they
1836 are built, so that no two settlers head towards the same city
1837 spot, we need to ensure this reservation is cleared should
1838 the settler disappear on the way. */
1839 adv_unit_new_task(punit, AUT_NONE, NULL);
1840
1841 /* Clear the vision before sending unit remove. Else, we might duplicate
1842 * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1843 if (punit->server.vision != NULL) {
1844 vision_clear_sight(punit->server.vision);
1845 vision_free(punit->server.vision);
1846 punit->server.vision = NULL;
1847 }
1848
1849 packet.unit_id32 = punit->id;
1850 packet.unit_id16 = packet.unit_id32;
1851 /* Send to onlookers. */
1852 players_iterate(aplayer) {
1853 if (can_player_see_unit_at(aplayer, punit, unit_tile(punit),
1854 transported)) {
1855 lsend_packet_unit_remove(aplayer->connections, &packet);
1856 }
1857 } players_iterate_end;
1858 /* Send to global observers. */
1859 conn_list_iterate(game.est_connections, pconn) {
1860 if (conn_is_global_observer(pconn)) {
1861 send_packet_unit_remove(pconn, &packet);
1862 }
1863 } conn_list_iterate_end;
1864
1865 if (punit->server.moving != NULL) {
1866 /* Do not care of this unit for running moves. */
1867 punit->server.moving->punit = NULL;
1868 }
1869
1870 if (punit->server.removal_callback != NULL) {
1871 /* Run the unit removal call back. */
1872 punit->server.removal_callback(punit);
1873 }
1874
1875 /* check if this unit had UTYF_GAMELOSS flag */
1876 if (unit_has_type_flag(punit, UTYF_GAMELOSS) && unit_owner(punit)->is_alive
1877 && ULR_EDITOR != reason) {
1878 notify_conn(game.est_connections, ptile, E_UNIT_LOST_MISC, ftc_server,
1879 _("Unable to defend %s, %s has lost the game."),
1880 unit_link(punit),
1881 player_name(pplayer));
1882 notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1883 _("Losing %s meant losing the game! "
1884 "Be more careful next time!"),
1885 unit_link(punit));
1886 player_status_add(unit_owner(punit), PSTATUS_DYING);
1887 }
1888
1889 /* Have to pass new ULR_UPKEEP as ULR_DISBAND for compatibility reasons.
1890 * Changes in freeciv-3.2 */
1891 script_server_signal_emit("unit_lost", punit, unit_owner(punit),
1892 unit_loss_reason_name((reason == ULR_UPKEEP)
1893 ? ULR_DISBANDED
1894 : reason));
1895
1896 script_server_remove_exported_object(punit);
1897 game_remove_unit(&wld, punit);
1898 punit = NULL;
1899
1900 if (NULL != ptrans) {
1901 /* Update the occupy info. */
1902 send_unit_info(NULL, ptrans);
1903 }
1904
1905 /* This unit may have blocked tiles of adjacent cities. Update them. */
1906 city_map_update_tile_now(ptile);
1907 sync_cities();
1908
1909 if (phomecity) {
1910 city_refresh(phomecity);
1911 send_city_info(city_owner(phomecity), phomecity);
1912 }
1913
1914 if (pcity && pcity != phomecity) {
1915 city_refresh(pcity);
1916 send_city_info(city_owner(pcity), pcity);
1917 }
1918
1919 if (pcity && unit_list_size(ptile->units) == 0) {
1920 /* The last unit in the city was killed: update the occupied flag. */
1921 send_city_info(NULL, pcity);
1922 }
1923}
1924
1925/**********************************************************************/
1929 static void server_remove_unit(struct unit *punit,
1930 enum unit_loss_reason reason)
1931{
1932 server_remove_unit_full(punit, unit_transported(punit), reason);
1933}
1934
1935/**********************************************************************/
1938 static void unit_lost_with_transport(const struct player *pplayer,
1939 struct unit *pcargo,
1940 const struct unit_type *ptransport,
1941 struct player *killer)
1942{
1943 notify_player(pplayer, unit_tile(pcargo), E_UNIT_LOST_MISC, ftc_server,
1944 _("%s lost when %s was lost."),
1945 unit_tile_link(pcargo),
1946 utype_name_translation(ptransport));
1947 /* Unit is not transported any more at this point, but it has jumped
1948 * off the transport and drowns outside. So it must be removed from
1949 * all clients.
1950 * However, we don't know if given client has received ANY updates
1951 * about the swimming unit, and we can't remove it if it's not there
1952 * in the first place -> we send it once here just to be sure it's
1953 * there. */
1954 send_unit_info(NULL, pcargo);
1955 wipe_unit_full(pcargo, FALSE, ULR_TRANSPORT_LOST, killer);
1956}
1957
1958/**********************************************************************/
1962 static void wipe_unit_full(struct unit *punit, bool transported,
1963 enum unit_loss_reason reason,
1964 struct player *killer)
1965{
1966 struct tile *ptile = unit_tile(punit);
1967 struct player *pplayer = unit_owner(punit);
1968 const struct unit_type *putype_save = unit_type_get(punit); /* for notify messages */
1969 struct unit_list *helpless = unit_list_new();
1970 struct unit_list *imperiled = unit_list_new();
1971 struct unit_list *unsaved = unit_list_new();
1972 struct unit *ptrans = unit_transport_get(punit);
1973 struct city *pexclcity;
1974 struct civ_map *nmap = &(wld.map);
1975
1976 if (killer != NULL
1977 && (game.info.gameloss_style & GAMELOSS_STYLE_LOOT)
1978 && unit_has_type_flag(punit, UTYF_GAMELOSS)) {
1979 int ransom = fc_rand(1 + pplayer->economic.gold);
1980 int n;
1981
1982 /* Give map */
1983 if (give_distorted_map(pplayer, killer, 50, TRUE)) {
1984 notify_player(killer, NULL, E_HUT_MAP,
1985 ftc_server,
1986 _("You looted parts of %s map!"),
1987 nation_adjective_for_player(pplayer));
1988 }
1989
1990 log_debug("victim has money: %d", pplayer->economic.gold);
1991
1992 if (ransom > 0) {
1993 notify_player(killer, NULL, E_HUT_GOLD,
1994 ftc_server,
1995 PL_("You loot %d gold!", "You loot %d gold!", ransom),
1996 ransom);
1997 }
1998 killer->economic.gold += ransom;
1999 pplayer->economic.gold -= ransom;
2000
2001 n = 1 + fc_rand(3);
2002
2003 while (n > 0) {
2004 Tech_type_id ttid;
2005
2006 /* steal_a_tech() handles also notifying of the player */
2007 ttid = steal_a_tech(killer, pplayer, A_UNSET);
2008
2009 if (ttid == A_NONE) {
2010 log_debug("Worthless enemy doesn't have more techs to steal.");
2011 break;
2012 } else {
2013 log_debug("Pressed tech %s from captured enemy",
2014 research_advance_rule_name(research_get(killer), ttid));
2015 if (!fc_rand(3)) {
2016 break; /* Out of luck */
2017 }
2018 n--;
2019 }
2020 }
2021
2022 {
2023 /* Try to submit some cities */
2024 int vcsize = city_list_size(pplayer->cities);
2025 int evcsize = vcsize;
2026 int conqsize;
2027
2028 if (evcsize < 3) {
2029 evcsize = 0;
2030 } else {
2031 evcsize -=3;
2032 }
2033
2034 /* About a quarter on average with high numbers less probable */
2035 conqsize = fc_rand(fc_rand(evcsize));
2036
2037 log_debug("conqsize=%d", conqsize);
2038
2039 if (conqsize > 0) {
2040 bool palace = game.server.savepalace;
2041 bool submit = FALSE;
2042
2043 game.server.savepalace = FALSE; /* Moving it around is dumb */
2044
2045 city_list_iterate_safe(pplayer->cities, pcity) {
2046 /* Kindly ask the citizens to submit */
2047 if (fc_rand(vcsize) < conqsize) {
2048 submit = TRUE;
2049 }
2050 vcsize--;
2051 if (submit) {
2052 conqsize--;
2053 /* Transfer city to the victorious player
2054 * kill all its units outside of a radius of 7,
2055 * give verbose messages of every unit transferred,
2056 * and raze buildings according to raze chance
2057 * (also removes palace) */
2058 notify_player(killer, city_tile(pcity), E_UNIT_WIN_ATT,
2059 ftc_server,
2060 /* TRANS: Getting a city as loot */
2061 _("You conquer %s as loot!"),
2062 city_link(pcity));
2063
2064 (void) transfer_city(killer, pcity, 7, TRUE, TRUE, TRUE,
2065 !is_barbarian(killer));
2066 submit = FALSE;
2067 }
2068 if (conqsize <= 0) {
2069 break;
2070 }
2071 } city_list_iterate_safe_end;
2072 game.server.savepalace = palace;
2073 }
2074 }
2075 }
2076
2077 /* The unit is doomed. */
2078 punit->server.dying = TRUE;
2079
2080 /* If a unit is being lost due to loss of its city, ensure that we don't
2081 * try to teleport any of its cargo to that city (which may not yet
2082 * have changed hands or disappeared). (It is assumed that the unit's
2083 * home city is always the one that is being lost/transferred/etc.) */
2084 if (reason == ULR_CITY_LOST) {
2085 pexclcity = unit_home(punit);
2086 } else {
2087 pexclcity = NULL;
2088 }
2089
2090 /* Remove unit itself from its transport */
2091 if (ptrans != NULL) {
2092 unit_transport_unload(punit);
2093 send_unit_info(NULL, ptrans);
2094 }
2095
2096 /* First pull all units off of the transporter. */
2097 if (get_transporter_occupancy(punit) > 0) {
2098 /* Use iterate_safe as unloaded units will be removed from the list
2099 * while iterating. */
2100 unit_list_iterate_safe(unit_transport_cargo(punit), pcargo) {
2101 bool healthy = FALSE;
2102
2103 if (!can_unit_unload(pcargo, punit)) {
2104 unit_list_prepend(helpless, pcargo);
2105 } else {
2106 if (!can_unit_exist_at_tile(nmap, pcargo, ptile)) {
2107 unit_list_prepend(imperiled, pcargo);
2108 } else {
2109 /* These units do not need to be saved. */
2110 healthy = TRUE;
2111 }
2112 }
2113
2114 /* Could use unit_transport_unload_send() here, but that would
2115 * call send_unit_info() for the transporter unnecessarily.
2116 * Note that this means that unit might to get seen briefly
2117 * by clients other than owner's, for example as a result of
2118 * update of homecity common to this cargo and some other
2119 * destroyed unit. */
2120 unit_transport_unload(pcargo);
2121 if (pcargo->activity == ACTIVITY_SENTRY) {
2122 /* Activate sentried units - like planes on a disbanded carrier.
2123 * Note this will activate ground units even if they just change
2124 * transporter. */
2125 set_unit_activity(pcargo, ACTIVITY_IDLE);
2126 }
2127
2128 /* Unit info for unhealthy units will be sent when they are
2129 * assigned new transport or removed. */
2130 if (healthy) {
2131 send_unit_info(NULL, pcargo);
2132 }
2133 } unit_list_iterate_safe_end;
2134 }
2135
2136 /* Now remove the unit. */
2137 server_remove_unit_full(punit, transported, reason);
2138
2139 switch (reason) {
2140 case ULR_KILLED:
2141 case ULR_EXECUTED:
2142 case ULR_SDI:
2143 case ULR_NUKE:
2144 case ULR_BRIBED:
2145 case ULR_CAPTURED:
2146 case ULR_CAUGHT:
2147 case ULR_ELIMINATED:
2148 case ULR_TRANSPORT_LOST:
2149 if (killer != NULL) {
2150 killer->score.units_killed++;
2151 }
2152 pplayer->score.units_lost++;
2153 break;
2154 case ULR_BARB_UNLEASH:
2155 case ULR_CITY_LOST:
2156 case ULR_STARVED:
2157 case ULR_UPKEEP:
2158 case ULR_NONNATIVE_TERR:
2159 case ULR_ARMISTICE:
2160 case ULR_HP_LOSS:
2161 case ULR_FUEL:
2162 case ULR_STACK_CONFLICT:
2163 case ULR_SOLD:
2164 pplayer->score.units_lost++;
2165 break;
2166 case ULR_RETIRED:
2167 case ULR_DISBANDED:
2168 case ULR_USED:
2169 case ULR_EDITOR:
2170 case ULR_PLAYER_DIED:
2171 case ULR_DETONATED:
2172 case ULR_MISSILE:
2173 break;
2174 }
2175
2176 /* First, sort out helpless cargo. */
2177 if (unit_list_size(helpless) > 0) {
2178 struct unit_list *remaining = unit_list_new();
2179
2180 /* Grant priority to gameloss units and units with the EvacuateFirst
2181 * unit type flag. */
2182 unit_list_iterate_safe(helpless, pcargo) {
2183 if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
2184 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
2185 if (!try_to_save_unit(pcargo, putype_save, TRUE,
2186 unit_has_type_flag(pcargo,
2187 UTYF_EVAC_FIRST),
2188 pexclcity)) {
2189 unit_list_prepend(unsaved, pcargo);
2190 }
2191 } else {
2192 unit_list_prepend(remaining, pcargo);
2193 }
2194 } unit_list_iterate_safe_end;
2195
2196 /* Handle non-priority units. */
2197 unit_list_iterate_safe(remaining, pcargo) {
2198 if (!try_to_save_unit(pcargo, putype_save, TRUE, FALSE, pexclcity)) {
2199 unit_list_prepend(unsaved, pcargo);
2200 }
2201 } unit_list_iterate_safe_end;
2202
2203 unit_list_destroy(remaining);
2204 }
2205 unit_list_destroy(helpless);
2206
2207 /* Then, save any imperiled cargo. */
2208 if (unit_list_size(imperiled) > 0) {
2209 struct unit_list *remaining = unit_list_new();
2210
2211 /* Grant priority to gameloss units and units with the EvacuateFirst
2212 * unit type flag. */
2213 unit_list_iterate_safe(imperiled, pcargo) {
2214 if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
2215 || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
2216 if (!try_to_save_unit(pcargo, putype_save, FALSE,
2217 unit_has_type_flag(pcargo,
2218 UTYF_EVAC_FIRST),
2219 pexclcity)) {
2220 unit_list_prepend(unsaved, pcargo);
2221 }
2222 } else {
2223 unit_list_prepend(remaining, pcargo);
2224 }
2225 } unit_list_iterate_safe_end;
2226
2227 /* Handle non-priority units. */
2228 unit_list_iterate_safe(remaining, pcargo) {
2229 if (!try_to_save_unit(pcargo, putype_save, FALSE, FALSE, pexclcity)) {
2230 unit_list_prepend(unsaved, pcargo);
2231 }
2232 } unit_list_iterate_safe_end;
2233
2234 unit_list_destroy(remaining);
2235 }
2236 unit_list_destroy(imperiled);
2237
2238 /* Finally, kill off the unsaved units. */
2239 if (unit_list_size(unsaved) > 0) {
2240 unit_list_iterate_safe(unsaved, dying_unit) {
2241 unit_lost_with_transport(pplayer, dying_unit, putype_save, killer);
2242 } unit_list_iterate_safe_end;
2243 }
2244 unit_list_destroy(unsaved);
2245}
2246
2247/**********************************************************************/
2251 void wipe_unit(struct unit *punit, enum unit_loss_reason reason,
2252 struct player *killer)
2253{
2254 wipe_unit_full(punit, unit_transported(punit), reason, killer);
2255}
2256
2257/**********************************************************************/
2263 static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype,
2264 bool helpless, bool teleporting,
2265 const struct city *pexclcity)
2266{
2267 struct tile *ptile = unit_tile(punit);
2268 struct player *pplayer = unit_owner(punit);
2269 struct unit *ptransport = transporter_for_unit(punit);
2270
2271 /* Helpless units cannot board a transport in their current state. */
2272 if (!helpless
2273 && ptransport != NULL) {
2274 unit_transport_load_tp_status(punit, ptransport, FALSE);
2275 send_unit_info(NULL, punit);
2276 return TRUE;
2277 } else {
2278 /* Only units that cannot find transport are considered for teleport. */
2279 if (teleporting) {
2280 struct city *pcity = find_closest_city(ptile, pexclcity,
2281 unit_owner(punit),
2282 FALSE, FALSE, FALSE, TRUE, FALSE,
2283 utype_class(pttype));
2284 if (pcity != NULL) {
2285 char tplink[MAX_LEN_LINK]; /* In case unit dies when teleported */
2286
2287 sz_strlcpy(tplink, unit_link(punit));
2288
2289 if (teleport_unit_to_city(punit, pcity, 0, FALSE)) {
2290 notify_player(pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2291 _("%s escaped the destruction of %s, and fled to %s."),
2292 tplink,
2293 utype_name_translation(pttype),
2294 city_link(pcity));
2295 return TRUE;
2296 }
2297 }
2298 }
2299 }
2300
2301 /* The unit could not use transport on the tile, and could not teleport. */
2302 return FALSE;
2303}
2304
2305/**********************************************************************/
2311 struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2312 int homecity, enum unit_loss_reason reason)
2313{
2314 struct unit *gained_unit;
2315 int id = 0;
2316
2317#ifndef FREECIV_NDEBUG
2318 bool placed;
2319#endif
2320
2321 fc_assert(!utype_player_already_has_this_unique(pplayer,
2322 unit_type_get(punit)));
2323
2324 /* Convert the unit to your cause. It's supposed that the original unit
2325 * is on a valid tile and is not transported. */
2326 gained_unit = unit_virtual_prepare(pplayer, unit_tile(punit),
2327 unit_type_get(punit), punit->veteran,
2328 homecity, punit->moves_left, punit->hp);
2329 fc_assert_action(gained_unit, goto uco_wipe); /* Tile must be valid */
2330
2331 /* Owner changes, nationality not. */
2332 gained_unit->nationality = punit->nationality;
2333
2334 /* Copy some more unit fields */
2335 gained_unit->fuel = punit->fuel;
2336 gained_unit->paradropped = punit->paradropped;
2337 gained_unit->server.birth_turn = punit->server.birth_turn;
2338
2339 /* Fog is lifted in the placing algorithm. */
2340#ifndef FREECIV_NDEBUG
2341 placed =
2342#endif
2343 place_unit(gained_unit, pplayer,
2344 homecity ? game_city_by_number(homecity) : NULL,
2345 NULL, FALSE);
2346
2347 fc_assert_action(placed, unit_virtual_destroy(gained_unit); goto uco_wipe);
2348
2349 id = gained_unit->id;
2350
2351 /* Update unit upkeep in the new homecity */
2352 if (homecity > 0) {
2353 city_units_upkeep(game_city_by_number(homecity));
2354 }
2355
2356 /* Be sure to wipe the converted unit! */
2357 /* Old homecity upkeep is updated in process */
2358#ifndef FREECIV_NDEBUG
2359 uco_wipe:
2360#endif
2361
2362 wipe_unit(punit, reason, NULL);
2363
2364 if (!unit_is_alive(id)) {
2365 /* Destroyed by a script */
2366 return NULL;
2367 }
2368
2369 return gained_unit; /* Returns the replacement. */
2370}
2371
2372/**********************************************************************/
2377 void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2378{
2379 char pkiller_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK];
2380 struct player *pvictim = unit_owner(punit);
2381 struct player *pvictor = unit_owner(pkiller);
2382 struct tile *deftile = unit_tile(punit);
2383 int ransom, unitcount = 0;
2384 bool escaped;
2385 bool collect_ransom = FALSE;
2386 const struct civ_map *nmap = &(wld.map);
2387
2388 sz_strlcpy(pkiller_link, unit_link(pkiller));
2389 sz_strlcpy(punit_link, unit_tile_link(punit));
2390
2391 /* The unit is doomed. */
2392 punit->server.dying = TRUE;
2393
2394 /* barbarian leader ransom hack */
2395 if (is_barbarian(pvictim)
2396 && uclass_has_flag(unit_class_get(pkiller), UCF_COLLECT_RANSOM)) {
2397 collect_ransom = TRUE;
2398
2399 unit_list_iterate(deftile->units, capture) {
2400 if (!unit_has_type_role(capture, L_BARBARIAN_LEADER)) {
2401 /* Cannot get ransom when there are other kind of units in the tile */
2402 collect_ransom = FALSE;
2403 break;
2404 }
2405 } unit_list_iterate_end;
2406
2407 if (collect_ransom) {
2408 unitcount = unit_list_size(deftile->units);
2409 ransom = unitcount * game.server.ransom_gold;
2410
2411 if (pvictim->economic.gold < ransom) {
2412 ransom = pvictim->economic.gold;
2413 }
2414
2415 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2416 PL_("%d Barbarian leader captured.",
2417 "%d Barbarian leaders captured.",
2418 unitcount),
2419 unitcount);
2420 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2421 PL_("%d gold ransom paid.",
2422 "%d gold ransom paid.",
2423 ransom),
2424 ransom);
2425 pvictor->economic.gold += ransom;
2426 pvictim->economic.gold -= ransom;
2427 send_player_info_c(pvictor, NULL); /* let me see my new gold :-) */
2428 }
2429 }
2430
2431 if (unitcount == 0) {
2432 unit_list_iterate(deftile->units, vunit) {
2433 if (pplayers_at_war(pvictor, unit_owner(vunit))
2434 && is_unit_reachable_at(vunit, pkiller, deftile)) {
2435 unitcount++;
2436 }
2437 } unit_list_iterate_end;
2438 }
2439
2440 if (!is_stack_vulnerable(deftile) || unitcount == 1) {
2441 if (vet) {
2442 notify_unit_experience(pkiller);
2443 }
2444 wipe_unit(punit, ULR_KILLED, pvictor);
2445 } else { /* unitcount > 1 */
2446 int i;
2447 int slots = player_slot_count();
2448 int num_killed[slots];
2449 int num_escaped[slots];
2450 struct unit *other_killed[slots];
2451
2452 fc_assert(unitcount > 1);
2453
2454 /* initialize */
2455 for (i = 0; i < slots; i++) {
2456 num_killed[i] = 0;
2457 other_killed[i] = NULL;
2458 num_escaped[i] = 0;
2459 }
2460
2461 /* count killed units */
2462 unit_list_iterate_safe(deftile->units, vunit) {
2463 struct player *vplayer = unit_owner(vunit);
2464
2465 if (pplayers_at_war(pvictor, vplayer)
2466 && is_unit_reachable_at(vunit, pkiller, deftile)) {
2467 escaped = FALSE;
2468
2469 if (unit_has_type_flag(vunit, UTYF_CANESCAPE)
2470 && !unit_has_type_flag(pkiller, UTYF_CANKILLESCAPING)
2471 && vunit->hp > 0
2472 && vunit->moves_left > pkiller->moves_left
2473 && fc_rand(2)) {
2474 int curr_def_bonus;
2475 int def_bonus = 0;
2476 struct tile *dsttile = NULL;
2477 int move_cost;
2478
2479 fc_assert(vunit->hp > 0);
2480
2481 adjc_iterate(nmap, deftile, ptile2) {
2482 if (can_exist_at_tile(nmap, vunit->utype, ptile2)
2483 && NULL == tile_city(ptile2)) {
2484 move_cost = map_move_cost_unit(nmap, vunit, ptile2);
2485 if (pkiller->moves_left <= vunit->moves_left - move_cost
2486 && (is_allied_unit_tile(ptile2, pvictim)
2487 || unit_list_size(ptile2->units)) == 0) {
2488 curr_def_bonus = tile_extras_defense_bonus(ptile2,
2489 vunit->utype);
2490 if (def_bonus <= curr_def_bonus) {
2491 def_bonus = curr_def_bonus;
2492 dsttile = ptile2;
2493 }
2494 }
2495 }
2496 } adjc_iterate_end;
2497
2498 if (dsttile != NULL) {
2499 escaped = (action_auto_perf_unit_do(AAPC_UNIT_STACK_DEATH,
2500 vunit, tile_owner(dsttile),
2501 NULL, NULL, dsttile,
2502 tile_city(dsttile),
2503 NULL, NULL)
2504 != NULL);
2505
2506 if (escaped) {
2507 num_escaped[player_index(vplayer)]++;
2508 unitcount--;
2509 }
2510 }
2511 }
2512
2513 if (!escaped) {
2514 num_killed[player_index(vplayer)]++;
2515
2516 if (vunit != punit) {
2517 other_killed[player_index(vplayer)] = vunit;
2518 other_killed[player_index(pvictor)] = vunit;
2519 }
2520 }
2521 }
2522 } unit_list_iterate_safe_end;
2523
2524 /* Inform the destroyer again if more than one unit was killed */
2525 if (unitcount > 1 && !collect_ransom) {
2526 notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2527 /* TRANS: "... Cannon ... the Polish Destroyer ...." */
2528 PL_("Your attacking %s succeeded against the %s %s "
2529 "(and %d other unit)!",
2530 "Your attacking %s succeeded against the %s %s "
2531 "(and %d other units)!", unitcount - 1),
2532 pkiller_link,
2533 nation_adjective_for_player(pvictim),
2534 punit_link,
2535 unitcount - 1);
2536 }
2537
2538 if (vet) {
2539 notify_unit_experience(pkiller);
2540 }
2541
2542 /* inform the owners: this only tells about owned units that were killed.
2543 * there may have been 20 units who died but if only 2 belonged to the
2544 * particular player they'll only learn about those.
2545 *
2546 * Also if a large number of units die you don't find out what type
2547 * they all are. */
2548 for (i = 0; i < slots; i++) {
2549 if (num_killed[i] == 1) {
2550 if (i == player_index(pvictim)) {
2551 fc_assert(other_killed[i] == NULL);
2552 notify_player(player_by_number(i), deftile,
2553 E_UNIT_LOST_DEF, ftc_server,
2554 /* TRANS: "Cannon ... the Polish Destroyer." */
2555 _("%s lost to an attack by the %s %s."),
2556 punit_link,
2557 nation_adjective_for_player(pvictor),
2558 pkiller_link);
2559 } else {
2560 fc_assert(other_killed[i] != punit);
2561 notify_player(player_by_number(i), deftile,
2562 E_UNIT_LOST_DEF, ftc_server,
2563 /* TRANS: "Cannon lost when the Polish Destroyer
2564 * attacked the German Musketeers." */
2565 _("%s lost when the %s %s attacked the %s %s."),
2566 unit_link(other_killed[i]),
2567 nation_adjective_for_player(pvictor),
2568 pkiller_link,
2569 nation_adjective_for_player(pvictim),
2570 punit_link);
2571 }
2572 } else if (num_killed[i] > 1) {
2573 if (i == player_index(pvictim)) {
2574 int others = num_killed[i] - 1;
2575
2576 if (others == 1) {
2577 notify_player(player_by_number(i), deftile,
2578 E_UNIT_LOST_DEF, ftc_server,
2579 /* TRANS: "Musketeers (and Cannon) lost to an
2580 * attack from the Polish Destroyer." */
2581 _("%s (and %s) lost to an attack from the %s %s."),
2582 punit_link,
2583 unit_link(other_killed[i]),
2584 nation_adjective_for_player(pvictor),
2585 pkiller_link);
2586 } else {
2587 notify_player(player_by_number(i), deftile,
2588 E_UNIT_LOST_DEF, ftc_server,
2589 /* TRANS: "Musketeers and 3 other units lost to
2590 * an attack from the Polish Destroyer."
2591 * (only happens with at least 2 other units) */
2592 PL_("%s and %d other unit lost to an attack "
2593 "from the %s %s.",
2594 "%s and %d other units lost to an attack "
2595 "from the %s %s.", others),
2596 punit_link,
2597 others,
2598 nation_adjective_for_player(pvictor),
2599 pkiller_link);
2600 }
2601 } else {
2602 notify_player(player_by_number(i), deftile,
2603 E_UNIT_LOST_DEF, ftc_server,
2604 /* TRANS: "2 units lost when the Polish Destroyer
2605 * attacked the German Musketeers."
2606 * (only happens with at least 2 other units) */
2607 PL_("%d unit lost when the %s %s attacked the %s %s.",
2608 "%d units lost when the %s %s attacked the %s %s.",
2609 num_killed[i]),
2610 num_killed[i],
2611 nation_adjective_for_player(pvictor),
2612 pkiller_link,
2613 nation_adjective_for_player(pvictim),
2614 punit_link);
2615 }
2616 }
2617 }
2618
2619 /* Inform the owner of the units that escaped.
2620 * 'deftile' is the original tile they defended at, not where
2621 * they escaped to, as there might be multiple different tiles
2622 * different units escaped to. */
2623 for (i = 0; i < slots; i++) {
2624 if (0 < num_escaped[i]) {
2625 notify_player(player_by_number(i), deftile,
2626 E_UNIT_ESCAPED, ftc_server,
2627 PL_("%d unit escaped from attack by %s %s",
2628 "%d units escaped from attack by %s %s",
2629 num_escaped[i]),
2630 num_escaped[i],
2631 pkiller_link,
2632 nation_adjective_for_player(pkiller->nationality)
2633 );
2634 }
2635 }
2636
2637 /* remove the units - note the logic of which units actually die
2638 * must be mimiced exactly in at least one place up above. */
2639 punit = NULL; /* wiped during following iteration so unsafe to use */
2640
2641 unit_list_iterate_safe(deftile->units, punit2) {
2642 if (pplayers_at_war(pvictor, unit_owner(punit2))
2643 && is_unit_reachable_at(punit2, pkiller, deftile)) {
2644 wipe_unit(punit2, ULR_KILLED, pvictor);
2645 }
2646 } unit_list_iterate_safe_end;
2647 }
2648}
2649
2650/**********************************************************************/
2654 void package_unit(struct unit *punit, struct packet_unit_info *packet)
2655{
2656 packet->id32 = punit->id;
2657 packet->id16 = packet->id32;
2658 packet->owner = player_number(unit_owner(punit));
2659 packet->nationality = player_number(unit_nationality(punit));
2660 packet->tile = tile_index(unit_tile(punit));
2661 packet->facing = punit->facing;
2662 packet->homecity32 = punit->homecity;
2663 packet->homecity16 = packet->homecity32;
2664 output_type_iterate(o) {
2665 packet->upkeep[o] = punit->upkeep[o];
2666 } output_type_iterate_end;
2667 packet->veteran = punit->veteran;
2668 packet->type = utype_number(unit_type_get(punit));
2669 packet->movesleft = punit->moves_left;
2670 packet->hp = punit->hp;
2671 packet->activity = punit->activity;
2672 packet->activity_count = punit->activity_count;
2673
2674 if (punit->activity_target != NULL) {
2675 packet->activity_tgt = extra_index(punit->activity_target);
2676 } else {
2677 packet->activity_tgt = EXTRA_NONE;
2678 }
2679
2680 packet->changed_from = punit->changed_from;
2681 packet->changed_from_count = punit->changed_from_count;
2682
2683 if (punit->changed_from_target != NULL) {
2684 packet->changed_from_tgt = extra_index(punit->changed_from_target);
2685 } else {
2686 packet->changed_from_tgt = EXTRA_NONE;
2687 }
2688
2689 packet->ssa_controller = punit->ssa_controller;
2690 packet->fuel = punit->fuel;
2691 packet->goto_tile = (NULL != punit->goto_tile
2692 ? tile_index(punit->goto_tile) : -1);
2693 packet->paradropped = punit->paradropped;
2694 packet->done_moving = punit->done_moving;
2695 packet->stay = punit->stay;
2696 if (!unit_transported(punit)) {
2697 packet->transported = FALSE;
2698 packet->transported_by32 = 0;
2699 packet->transported_by16 = 0;
2700 } else {
2701 packet->transported = TRUE;
2702 packet->transported_by32 = unit_transport_get(punit)->id;
2703 packet->transported_by16 = packet->transported_by32;
2704 }
2705 if (punit->carrying != NULL) {
2706 packet->carrying = goods_index(punit->carrying);
2707 } else {
2708 packet->carrying = -1;
2709 }
2710 packet->occupied = (get_transporter_occupancy(punit) > 0);
2711 packet->battlegroup = punit->battlegroup;
2712 packet->has_orders = punit->has_orders;
2713 if (punit->has_orders) {
2714 packet->orders_length = punit->orders.length;
2715 packet->orders_index = punit->orders.index;
2716 packet->orders_repeat = punit->orders.repeat;
2717 packet->orders_vigilant = punit->orders.vigilant;
2718 memcpy(packet->orders, punit->orders.list,
2719 punit->orders.length * sizeof(struct unit_order));
2720 } else {
2721 packet->orders_length = packet->orders_index = 0;
2722 packet->orders_repeat = packet->orders_vigilant = FALSE;
2723 /* No need to initialize array. */
2724 }
2725
2726 packet->action_decision_want = punit->action_decision_want;
2727 packet->action_decision_tile = (punit->action_decision_tile
2728 ? tile_index(punit->action_decision_tile)
2729 : IDENTITY_NUMBER_ZERO);
2730}
2731
2732/**********************************************************************/
2737 void package_short_unit(struct unit *punit,
2738 struct packet_unit_short_info *packet,
2739 enum unit_info_use packet_use, int info_city_id)
2740{
2741 packet->packet_use = packet_use;
2742 packet->info_city_id32 = info_city_id;
2743 packet->info_city_id16 = packet->info_city_id32;
2744
2745 packet->id32 = punit->id;
2746 packet->id16 = packet->id32;
2747 packet->owner = player_number(unit_owner(punit));
2748 packet->tile = tile_index(unit_tile(punit));
2749 packet->facing = punit->facing;
2750 packet->veteran = punit->veteran;
2751 packet->type = utype_number(unit_type_get(punit));
2752 packet->hp = punit->hp;
2753 packet->occupied = (get_transporter_occupancy(punit) > 0);
2754 if (punit->activity == ACTIVITY_EXPLORE
2755 || punit->activity == ACTIVITY_GOTO) {
2756 packet->activity = ACTIVITY_IDLE;
2757 } else {
2758 packet->activity = punit->activity;
2759 }
2760
2761 if (punit->activity_target == NULL) {
2762 packet->activity_tgt = EXTRA_NONE;
2763 } else {
2764 packet->activity_tgt = extra_index(punit->activity_target);
2765 }
2766
2767 /* Transported_by information is sent to the client even for units that
2768 * aren't fully known. Note that for non-allied players, any transported
2769 * unit can't be seen at all. For allied players we have to know if
2770 * transporters have room in them so that we can load units properly. */
2771 if (!unit_transported(punit)) {
2772 packet->transported = FALSE;
2773 packet->transported_by32 = 0;
2774 packet->transported_by16 = 0;
2775 } else {
2776 packet->transported = TRUE;
2777 packet->transported_by32 = unit_transport_get(punit)->id;
2778 packet->transported_by16 = packet->transported_by32;
2779 }
2780}
2781
2782/**********************************************************************/
2785 void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
2786{
2787 dlsend_packet_unit_remove(pplayer->connections, punit->id, punit->id);
2788 if (punit->server.moving != NULL) {
2789 /* Update status of 'pplayer' vision for 'punit'. */
2790 BV_CLR(punit->server.moving->can_see_unit, player_index(pplayer));
2791 }
2792}
2793
2794/**********************************************************************/
2798 void send_unit_info(struct conn_list *dest, struct unit *punit)
2799{
2800 const struct player *powner;
2801 struct packet_unit_info info;
2802 struct packet_unit_short_info sinfo;
2803 struct unit_move_data *pdata;
2804
2805 if (dest == NULL) {
2806 dest = game.est_connections;
2807 }
2808
2809 CHECK_UNIT(punit);
2810
2811 powner = unit_owner(punit);
2812 package_unit(punit, &info);
2813 package_short_unit(punit, &sinfo, UNIT_INFO_IDENTITY, 0);
2814 pdata = punit->server.moving;
2815
2816 conn_list_iterate(dest, pconn) {
2817 struct player *pplayer = conn_get_player(pconn);
2818
2819 /* Be careful to consider all cases where pplayer is NULL... */
2820 if (pplayer == NULL) {
2821 if (pconn->observer) {
2822 send_packet_unit_info(pconn, &info);
2823 }
2824 } else if (pplayer == powner) {
2825 send_packet_unit_info(pconn, &info);
2826 if (pdata != NULL) {
2827 BV_SET(pdata->can_see_unit, player_index(pplayer));
2828 }
2829 } else if (can_player_see_unit(pplayer, punit)) {
2830 send_packet_unit_short_info(pconn, &sinfo, FALSE);
2831 if (pdata != NULL) {
2832 BV_SET(pdata->can_see_unit, player_index(pplayer));
2833 }
2834 }
2835 } conn_list_iterate_end;
2836}
2837
2838/**********************************************************************/
2842 void send_all_known_units(struct conn_list *dest)
2843{
2844 conn_list_do_buffer(dest);
2845 conn_list_iterate(dest, pconn) {
2846 struct player *pplayer = pconn->playing;
2847
2848 if (NULL == pplayer && !pconn->observer) {
2849 continue;
2850 }
2851
2852 players_iterate(unitowner) {
2853 unit_list_iterate(unitowner->units, punit) {
2854 send_unit_info(dest, punit);
2855 } unit_list_iterate_end;
2856 } players_iterate_end;
2857 }
2858 conn_list_iterate_end;
2859 conn_list_do_unbuffer(dest);
2860 flush_packets();
2861}
2862
2863/**********************************************************************/
2870 static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
2871{
2872 struct city *pcity = NULL;
2873 int pop_loss;
2874
2875 pcity = tile_city(ptile);
2876
2877 unit_list_iterate_safe(ptile->units, punit) {
2878
2879 /* unit in a city may survive */
2880 if (pcity && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2881 continue;
2882 }
2883 notify_player(unit_owner(punit), ptile, E_UNIT_LOST_MISC, ftc_server,
2884 _("Your %s was nuked by %s."),
2885 unit_tile_link(punit),
2886 pplayer == unit_owner(punit)
2887 ? _("yourself")
2888 : nation_plural_for_player(pplayer));
2889 if (unit_owner(punit) != pplayer) {
2890 notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2891 _("The %s %s was nuked."),
2892 nation_adjective_for_player(unit_owner(punit)),
2893 unit_tile_link(punit));
2894 }
2895 wipe_unit(punit, ULR_NUKE, pplayer);
2896 } unit_list_iterate_safe_end;
2897
2898
2899 if (pcity) {
2900 struct player *owner = city_owner(pcity);
2901 char city_name[MAX_LEN_LINK];
2902
2903 sz_strlcpy(city_name, city_link(pcity));
2904
2905 notify_player(owner, ptile, E_CITY_NUKED, ftc_server,
2906 _("%s was nuked by %s."),
2907 city_name,
2908 pplayer == owner
2909 ? _("yourself")
2910 : nation_plural_for_player(pplayer));
2911
2912 if (owner != pplayer) {
2913 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2914 _("You nuked %s."),
2915 city_name);
2916 }
2917
2918 pop_loss = round((game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100.0);
2919 if (city_reduce_size(pcity, pop_loss, pplayer, "nuke")) {
2920 /* Send city size reduction to everyone seeing it */
2921 send_city_info(NULL, pcity);
2922 } else {
2923 /* City was destroyed */
2924 notify_player(owner, ptile, E_CITY_NUKED, ftc_server,
2925 _("%s was destroyed by the nuke."),
2926 city_name);
2927 if (owner != pplayer) {
2928 notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2929 _("Your nuke destroyed %s."),
2930 city_name);
2931 }
2932 }
2933 }
2934
2935 if (fc_rand(2) == 1) {
2936 struct extra_type *pextra;
2937
2938 pextra = rand_extra_for_tile(ptile, EC_FALLOUT, FALSE);
2939 if (pextra != NULL && !tile_has_extra(ptile, pextra)) {
2940 tile_add_extra(ptile, pextra);
2941 update_tile_knowledge(ptile);
2942 }
2943 }
2944}
2945
2946/**********************************************************************/
2950 void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
2951{
2952 square_iterate(&(wld.map), ptile, 1, ptile1) {
2953 do_nuke_tile(pplayer, ptile1);
2954 } square_iterate_end;
2955
2956 script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
2957 API_TYPE_PLAYER, pplayer);
2958 notify_conn(NULL, ptile, E_NUKE, ftc_server,
2959 _("The %s detonated a nuke!"),
2960 nation_plural_for_player(pplayer));
2961}
2962
2963/**********************************************************************/
2967 bool do_airline(struct unit *punit, struct city *pdest_city,
2968 const struct action *paction)
2969{
2970 struct city *psrc_city = tile_city(unit_tile(punit));
2971
2972 notify_player(unit_owner(punit), city_tile(pdest_city),
2973 E_UNIT_RELOCATED, ftc_server,
2974 _("%s transported successfully."),
2975 unit_link(punit));
2976
2977 unit_move(punit, pdest_city->tile, punit->moves_left,
2978 NULL, BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK),
2979 /* Can only airlift to allied and domestic cities */
2980 FALSE, FALSE,
2981 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
2982 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN));
2983
2984 /* Update airlift fields. */
2985 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
2986 psrc_city->airlift--;
2987 send_city_info(city_owner(psrc_city), psrc_city);
2988 }
2989 if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
2990 pdest_city->airlift--;
2991 send_city_info(city_owner(pdest_city), pdest_city);
2992 }
2993
2994 return TRUE;
2995}
2996
2997/**********************************************************************/
3000 void do_explore(struct unit *punit)
3001{
3002 switch (manage_auto_explorer(punit)) {
3003 case MR_DEATH:
3004 /* don't use punit! */
3005 return;
3006 case MR_NOT_ALLOWED:
3007 /* Needed for something else */
3008 return;
3009 case MR_OK:
3010 /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3011 * but don't count on this. See PR#39792.
3012 */
3013 if (punit->activity == ACTIVITY_EXPLORE) {
3014 break;
3015 }
3016
3017 fc__fallthrough;
3018 default:
3019 unit_activity_handling(punit, ACTIVITY_IDLE);
3020
3021 /* FIXME: When the manage_auto_explorer() call changes the activity from
3022 * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3023 * alone. We reset it here. See PR#12931. */
3024 punit->ssa_controller = SSA_NONE;
3025 break;
3026 }
3027
3028 send_unit_info(NULL, punit); /* probably duplicate */
3029}
3030
3031/**********************************************************************/
3036 bool do_paradrop(struct unit *punit, struct tile *ptile,
3037 const struct action *paction)
3038{
3039 struct player *pplayer = unit_owner(punit);
3040 struct player *tgt_player = tile_owner(ptile);
3041 const struct unit_type *act_utype = unit_type_get(punit);
3042 const struct city *pcity;
3043
3044 /* Hard requirements */
3045 /* FIXME: hard requirements belong in common/actions's
3046 * is_action_possible() and the explanation texts belong in
3047 * server/unithand's action not enabled system (expl_act_not_enabl(),
3048 * ane_kind, explain_why_no_action_enabled(), etc)
3049 */
3050 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3051 /* Only take in account values from player map. */
3052 const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3053
3054 if (NULL == plrtile->site
3055 && !is_native_to_class(unit_class_get(punit), plrtile->terrain,
3056 &(plrtile->extras))) {
3057 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3058 _("This unit cannot paradrop into %s."),
3059 terrain_name_translation(plrtile->terrain));
3060 return FALSE;
3061 }
3062
3063 if (NULL != plrtile->site
3064 && plrtile->owner != NULL
3065 && !pplayers_allied(pplayer, plrtile->owner)
3066 && !action_has_result(paction, ACTRES_PARADROP_CONQUER)) {
3067 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3068 /* TRANS: Paratroopers ... Paradrop Unit */
3069 _("%s cannot conquer a city with \"%s\"."),
3070 unit_name_translation(punit),
3071 action_name_translation(paction));
3072 return FALSE;
3073 }
3074
3075 if (NULL != plrtile->site
3076 && plrtile->owner != NULL
3077 && (pplayers_non_attack(pplayer, plrtile->owner)
3078 || (player_diplstate_get(pplayer, plrtile->owner)->type
3079 == DS_ALLIANCE)
3080 || (player_diplstate_get(pplayer, plrtile->owner)->type
3081 == DS_TEAM))
3082 && action_has_result(paction, ACTRES_PARADROP_CONQUER)) {
3083 notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3084 _("Cannot attack unless you declare war first."));
3085 return FALSE;
3086 }
3087 }
3088
3089
3090 /* Kill the unit when the landing goes wrong. */
3091
3092 /* Safe terrain, really? Not transformed since player last saw it. */
3093 if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3094 && (!BV_ISSET(paction->sub_results, ACT_SUB_RES_MAY_EMBARK)
3095 || !unit_could_load_at(punit, ptile))) {
3096 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3097 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3098 _("Your %s paradropped into the %s and was lost."),
3099 unit_tile_link(punit),
3100 terrain_name_translation(tile_terrain(ptile)));
3101 pplayer->score.units_lost++;
3102 server_remove_unit(punit, ULR_NONNATIVE_TERR);
3103 return TRUE;
3104 }
3105
3106 pcity = tile_city(ptile);
3107
3108 if ((pcity != NULL && !pplayers_allied(pplayer, city_owner(pcity))
3109 && !action_has_result(paction, ACTRES_PARADROP_CONQUER))
3110 || is_non_allied_unit_tile(ptile, pplayer)) {
3111 struct player *main_victim = NULL;
3112 struct player *secondary_victim = NULL;
3113 char victim_link[MAX_LEN_LINK];
3114
3115 map_show_circle(pplayer, ptile, act_utype->vision_radius_sq);
3116 maybe_make_contact(ptile, pplayer);
3117 notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3118 _("Your %s was killed by enemy units at the "
3119 "paradrop destination."),
3120 unit_tile_link(punit));
3121 /* TODO: Should defender score.units_killed get increased too?
3122 * What if there's units of several allied players? Should the
3123 * city owner or owner of the first/random unit get the kill? */
3124 pplayer->score.units_lost++;
3125
3126 if (pcity != NULL) {
3127 struct player *owner = city_owner(pcity);
3128
3129 if (!pplayers_at_war(pplayer, owner)) {
3130 main_victim = owner;
3131 } else {
3132 secondary_victim = owner;
3133 }
3134
3135 sz_strlcpy(victim_link, city_link(pcity));
3136 } else {
3137 sz_strlcpy(victim_link, tile_link(ptile));
3138 }
3139
3140 if (main_victim == NULL) {
3141 unit_list_iterate(ptile->units, tgt) {
3142 struct player *owner = unit_owner(tgt);
3143
3144 if (!pplayers_at_war(pplayer, owner)) {
3145 main_victim = owner;
3146 break;
3147 } else if (secondary_victim == NULL) {
3148 secondary_victim = owner;
3149 }
3150 } unit_list_iterate_end;
3151
3152 if (main_victim == NULL) {
3153 /* There's no victim with whom the attacker isn't in war,
3154 * fallback to one with whom there's already a war. */
3155 main_victim = secondary_victim;
3156 }
3157 }
3158
3159 action_consequence_caught(paction, pplayer, act_utype,
3160 main_victim, ptile,
3161 victim_link);
3162
3163 server_remove_unit(punit, ULR_KILLED);
3164 return TRUE;
3165 }
3166
3167 /* All ok */
3168 punit->paradropped = TRUE;
3169 if (unit_move(punit, ptile,
3170 /* Done by Action_Success_Actor_Move_Cost */
3171 0,
3172 NULL, BV_ISSET(paction->sub_results,
3173 ACT_SUB_RES_MAY_EMBARK),
3174 paction->result == ACTRES_PARADROP_CONQUER,
3175 paction->result == ACTRES_PARADROP_CONQUER,
3176 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_ENTER),
3177 BV_ISSET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN))) {
3178 /* Ensure we finished on valid state. */
3179 fc_assert(can_unit_exist_at_tile(&(wld.map), punit, unit_tile(punit))
3180 || unit_transported(punit));
3181 }
3182
3183 /* May cause an incident */
3184 action_consequence_success(paction, pplayer, act_utype, tgt_player,
3185 ptile, tile_link(ptile));
3186
3187 return TRUE;
3188}
3189
3190/**********************************************************************/
3194 static bool hut_get_limited(struct unit *punit)
3195{
3196 bool ok = TRUE;
3197 int hut_chance = fc_rand(12);
3198 struct player *pplayer = unit_owner(punit);
3199 /* 1 in 12 to get barbarians */
3200 if (hut_chance != 0) {
3201 int cred = 25;
3202 notify_player(pplayer, unit_tile(punit), E_HUT_GOLD, ftc_server,
3203 PL_("You found %d gold.",
3204 "You found %d gold.", cred), cred);
3205 pplayer->economic.gold += cred;
3206 } else if (city_exists_within_max_city_map(unit_tile(punit), TRUE)
3207 || unit_has_type_flag(punit, UTYF_GAMELOSS)) {
3208 notify_player(pplayer, unit_tile(punit),
3209 E_HUT_BARB_CITY_NEAR, ftc_server,
3210 _("An abandoned village is here."));
3211 } else {
3212 notify_player(pplayer, unit_tile(punit), E_HUT_BARB_KILLED, ftc_server,
3213 _("Your %s has been killed by barbarians!"),
3214 unit_tile_link(punit));
3215 wipe_unit(punit, ULR_BARB_UNLEASH, NULL);
3216 ok = FALSE;
3217 }
3218 return ok;
3219}
3220
3221/**********************************************************************/
3225 static void unit_enter_hut(struct unit *punit, bool frighten_hut)
3226{
3227 struct player *pplayer = unit_owner(punit);
3228 int id = punit->id;
3229 struct tile *ptile = unit_tile(punit);
3230 bool hut = FALSE;
3231 const struct req_context context = {
3232 .player = pplayer,
3233 .tile = ptile,
3234 };
3235
3236 extra_type_by_rmcause_iterate(ERM_ENTER, pextra) {
3237 if (tile_has_extra(ptile, pextra)
3238 && are_reqs_active(&context, tile_owner(ptile), &pextra->rmreqs,
3239 RPT_CERTAIN)
3240 ) {
3241 hut = TRUE;
3242 /* FIXME: are all enter-removes extras worth counting? */
3243 pplayer->server.huts++;
3244
3245 destroy_extra(ptile, pextra);
3246 update_tile_knowledge(unit_tile(punit));
3247
3248 /* FIXME: enable different classes
3249 * to behave differently with different huts */
3250 if (frighten_hut) {
3251 script_server_signal_emit("hut_frighten", punit,
3252 extra_rule_name(pextra));
3253 } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3254 /* AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky) */
3255 (void) hut_get_limited(punit);
3256 } else {
3257 script_server_signal_emit("hut_enter", punit, extra_rule_name(pextra));
3258 }
3259
3260 /* We need punit for the callbacks, can't continue if the unit died */
3261 if (!unit_is_alive(id)) {
3262 break;
3263 }
3264 }
3265 } extra_type_by_rmcause_iterate_end;
3266
3267 if (hut) {
3268 send_player_info_c(pplayer, pplayer->connections); /* eg, gold */
3269 }
3270 return;
3271}
3272
3273/**********************************************************************/
3276 void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
3277{
3278 bv_player can_see_unit;
3279
3280 fc_assert_ret(punit != NULL);
3281 fc_assert_ret(ptrans != NULL);
3282
3283 BV_CLR_ALL(can_see_unit);
3284 players_iterate(pplayer) {
3285 if (can_player_see_unit(pplayer, punit)) {
3286 BV_SET(can_see_unit, player_index(pplayer));
3287 }
3288 } players_iterate_end;
3289
3290 unit_transport_load(punit, ptrans, FALSE);
3291
3292 players_iterate(pplayer) {
3293 if (BV_ISSET(can_see_unit, player_index(pplayer))
3294 && !can_player_see_unit(pplayer, punit)) {
3295 unit_goes_out_of_sight(pplayer, punit);
3296 }
3297 } players_iterate_end;
3298
3299 send_unit_info(NULL, punit);
3300 send_unit_info(NULL, ptrans);
3301}
3302
3303/**********************************************************************/
3306 static void unit_transport_load_tp_status(struct unit *punit,
3307 struct unit *ptrans,
3308 bool force)
3309{
3310 bool had_cargo;
3311
3312 fc_assert_ret(punit != NULL);
3313 fc_assert_ret(ptrans != NULL);
3314
3315 had_cargo = get_transporter_occupancy(ptrans) > 0;
3316
3317 unit_transport_load(punit, ptrans, force);
3318
3319 if (!had_cargo) {
3320 /* Transport's loaded status changed */
3321 send_unit_info(NULL, ptrans);
3322 }
3323}
3324
3325/**********************************************************************/
3328 void unit_transport_unload_send(struct unit *punit)
3329{
3330 struct unit *ptrans;
3331
3332 fc_assert_ret(punit);
3333
3334 ptrans = unit_transport_get(punit);
3335
3336 fc_assert_ret(ptrans);
3337
3338 unit_transport_unload(punit);
3339
3340 send_unit_info(NULL, punit);
3341 send_unit_info(NULL, ptrans);
3342}
3343
3344/**********************************************************************/
3348 static void autoattack_prob_free(struct autoattack_prob *prob)
3349{
3350 free(prob);
3351}
3352
3353/**********************************************************************/
3362 static int compare_units(const struct autoattack_prob *const *p1,
3363 const struct autoattack_prob *const *q1)
3364{
3365 const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3366 const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3367
3368 /* Sort by transport depth first. This makes sure that no transport
3369 * attacks before its cargo does -- cargo sorts earlier in the list. */
3370 {
3371 const struct unit *p1trans = p1unit, *q1trans = q1unit;
3372
3373 /* Walk the transport stacks in parallel, so as to bail out as soon as
3374 * one of them is empty (avoid walking deep stacks more often than
3375 * necessary). */
3376 while (p1trans && q1trans) {
3377 p1trans = unit_transport_get(p1trans);
3378 q1trans = unit_transport_get(q1trans);
3379 }
3380 if (!p1trans && q1trans) {
3381 /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3382 * earlier in the list (p1 > q1). */
3383 return 1;
3384 } else if (p1trans && !q1trans) {
3385 /* p1 is at greater depth, so should sort earlier (p1 < q1). */
3386 return -1;
3387 }
3388 /* else same depth, so move on to checking win chance: */
3389 }
3390
3391 /* Put the units with the highest probability of success first. The up
3392 * side of this is that units with bonuses against the victim attacks
3393 * before other units. The downside is that strong units can be led
3394 * away by sacrificial units. */
3395 return (-1
3396 /* Assume the worst. */
3397 * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3398}
3399
3400/**********************************************************************/
3404 static bool unit_survive_autoattack(struct unit *punit)
3405{
3406 struct autoattack_prob_list *autoattack;
3407 int moves = punit->moves_left;
3408 int sanity1 = punit->id;
3409 struct civ_map *nmap = &(wld.map);
3410
3411 if (!game.server.autoattack) {
3412 return TRUE;
3413 }
3414
3415 autoattack = autoattack_prob_list_new_full(autoattack_prob_free);
3416
3417 /* Kludge to prevent attack power from dropping to zero during calc */
3418 punit->moves_left = MAX(punit->moves_left, 1);
3419
3420 adjc_iterate(nmap, unit_tile(punit), ptile) {
3421 /* First add all eligible units to a autoattack list */
3422 unit_list_iterate(ptile->units, penemy) {
3423 struct autoattack_prob *probability = fc_malloc(sizeof(*probability));
3424 struct tile *tgt_tile = unit_tile(punit);
3425
3426 fc_assert_action(tgt_tile, continue);
3427
3428 probability->prob =
3429 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ,
3430 penemy, unit_owner(punit), NULL, NULL,
3431 tgt_tile, tile_city(tgt_tile),
3432 punit, NULL);
3433
3434 if (action_prob_possible(probability->prob)) {
3435 probability->unit_id = penemy->id;
3436 autoattack_prob_list_prepend(autoattack, probability);
3437 } else {
3438 FC_FREE(probability);
3439 }
3440 } unit_list_iterate_end;
3441 } adjc_iterate_end;
3442
3443 /* Sort the potential attackers from highest to lowest success
3444 * probability. */
3445 if (autoattack_prob_list_size(autoattack) >= 2) {
3446 autoattack_prob_list_sort(autoattack, &compare_units);
3447 }
3448
3449 autoattack_prob_list_iterate_safe(autoattack, peprob, penemy) {
3450 int sanity2 = penemy->id;
3451 struct tile *ptile = unit_tile(penemy);
3452 struct unit *enemy_defender = get_defender(nmap, punit, ptile);
3453 double punitwin, penemywin;
3454 double threshold = 0.25;
3455 struct tile *tgt_tile = unit_tile(punit);
3456
3457 fc_assert(tgt_tile);
3458
3459 if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3460 /* Don't leave city defenseless */
3461 threshold = 0.90;
3462 }
3463
3464 if (NULL != enemy_defender) {
3465 punitwin = unit_win_chance(nmap, punit, enemy_defender);
3466 } else {
3467 /* 'penemy' can attack 'punit' but it may be not reciproque. */
3468 punitwin = 1.0;
3469 }
3470
3471 /* Previous attacks may have changed the odds. Recalculate. */
3472 peprob->prob =
3473 action_auto_perf_unit_prob(AAPC_UNIT_MOVED_ADJ,
3474 penemy, unit_owner(punit), NULL, NULL,
3475 tgt_tile, tile_city(tgt_tile),
3476 punit, NULL);
3477
3478 if (!action_prob_possible(peprob->prob)) {
3479 /* No longer legal. */
3480 continue;
3481 }
3482
3483 /* Assume the worst. */
3484 penemywin = action_prob_to_0_to_1_pessimist(peprob->prob);
3485
3486 if ((penemywin > 1.0 - punitwin
3487 || unit_has_type_flag(punit, UTYF_PROVOKING))
3488 && penemywin > threshold) {
3489
3490#ifdef REALLY_DEBUG_THIS
3491 log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3492 unit_rule_name(penemy), unit_rule_name(punit),
3493 TILE_XY(unit_tile(punit)), penemywin,
3494 1.0 - punitwin, threshold);
3495#endif
3496
3497 unit_activity_handling(penemy, ACTIVITY_IDLE);
3498 action_auto_perf_unit_do(AAPC_UNIT_MOVED_ADJ,
3499 penemy, unit_owner(punit), NULL, NULL,
3500 tgt_tile, tile_city(tgt_tile), punit, NULL);
3501 } else {
3502#ifdef REALLY_DEBUG_THIS
3503 log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3504 unit_rule_name(penemy), unit_rule_name(punit),
3505 TILE_XY(unit_tile(punit)), penemywin,
3506 1.0 - punitwin, threshold);
3507#endif
3508 continue;
3509 }
3510
3511 if (game_unit_by_number(sanity2)) {
3512 send_unit_info(NULL, penemy);
3513 }
3514 if (game_unit_by_number(sanity1)) {
3515 send_unit_info(NULL, punit);
3516 } else {
3517 autoattack_prob_list_destroy(autoattack);
3518 return FALSE; /* moving unit dead */
3519 }
3520 } autoattack_prob_list_iterate_safe_end;
3521
3522 autoattack_prob_list_destroy(autoattack);
3523 if (game_unit_by_number(sanity1)) {
3524 /* We could have lost movement in combat */
3525 punit->moves_left = MIN(punit->moves_left, moves);
3526 send_unit_info(NULL, punit);
3527 return TRUE;
3528 } else {
3529 return FALSE;
3530 }
3531}
3532
3533/**********************************************************************/
3536 static void cancel_orders(struct unit *punit, char *dbg_msg)
3537{
3538 free_unit_orders(punit);
3539 send_unit_info(NULL, punit);
3540 log_debug("%s", dbg_msg);
3541}
3542
3543/**********************************************************************/
3547 static void wakeup_neighbor_sentries(struct unit *punit)
3548{
3549 bool alone_in_city;
3550
3551 if (NULL != tile_city(unit_tile(punit))) {
3552 int count = 0;
3553
3554 unit_list_iterate(unit_tile(punit)->units, aunit) {
3555 /* Consider only units not transported. */
3556 if (!unit_transported(aunit)) {
3557 count++;
3558 }
3559 } unit_list_iterate_end;
3560
3561 alone_in_city = (1 == count);
3562 } else {
3563 alone_in_city = FALSE;
3564 }
3565
3566 /* There may be sentried units with a sightrange > 3, but we don't
3567 wake them up if the punit is farther away than 3. */
3568 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3569 unit_list_iterate(ptile->units, penemy) {
3570 int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3571 int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3572
3573 if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
3574 && penemy->activity == ACTIVITY_SENTRY
3575 && radius_sq >= distance_sq
3576 /* If the unit moved on a city, and the unit is alone, consider
3577 * it is visible. */
3578 && (alone_in_city
3579 || can_player_see_unit(unit_owner(penemy), punit))
3580 /* on board transport; don't awaken */
3581 && can_unit_exist_at_tile(&(wld.map), penemy, unit_tile(penemy))) {
3582 set_unit_activity(penemy, ACTIVITY_IDLE);
3583 send_unit_info(NULL, penemy);
3584 }
3585 } unit_list_iterate_end;
3586 } square_iterate_end;
3587
3588 /* Wakeup patrolling units we bump into.
3589 We do not wakeup units further away than 3 squares... */
3590 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
3591 unit_list_iterate(ptile->units, ppatrol) {
3592 if (punit != ppatrol
3593 && unit_has_orders(ppatrol)
3594 && ppatrol->orders.vigilant) {
3595 if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
3596 cancel_orders(ppatrol, " stopping because of nearby enemy");
3597 notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
3598 E_UNIT_ORDERS, ftc_server,
3599 _("Orders for %s aborted after enemy movement was "
3600 "spotted."),
3601 unit_link(ppatrol));
3602 }
3603 }
3604 } unit_list_iterate_end;
3605 } square_iterate_end;
3606}
3607
3608/**********************************************************************/
3617 static bool unit_move_consequences(struct unit *punit,
3618 struct tile *src_tile,
3619 struct tile *dst_tile,
3620 bool passenger,
3621 bool conquer_city_allowed)
3622{
3623 struct city *fromcity = tile_city(src_tile);
3624 struct city *tocity = tile_city(dst_tile);
3625 struct city *homecity_start_pos = NULL;
3626 struct city *homecity_end_pos = NULL;
3627 int homecity_id_start_pos = punit->homecity;
3628 int homecity_id_end_pos = punit->homecity;
3629 struct player *pplayer_start_pos = unit_owner(punit);
3630 struct player *pplayer_end_pos = pplayer_start_pos;
3631 const struct unit_type *type_start_pos = unit_type_get(punit);
3632 const struct unit_type *type_end_pos = type_start_pos;
3633 bool refresh_homecity_start_pos = FALSE;
3634 bool refresh_homecity_end_pos = FALSE;
3635 int saved_id = punit->id;
3636 bool alive = TRUE;
3637 const struct civ_map *nmap = &(wld.map);
3638
3639 if (tocity && conquer_city_allowed) {
3640 if (!passenger) {
3641 /* The unit that does the move may conquer. */
3642 unit_conquer_city(punit, tocity);
3643 }
3644
3645 /* Run for passengers too. A passenger may have been killed when its
3646 * transport conquered a city. (unit_conquer_city() can cause Lua code
3647 * to run) */
3648
3649 alive = unit_is_alive(saved_id);
3650 if (alive) {
3651 /* In case script has changed something about unit */
3652 pplayer_end_pos = unit_owner(punit);
3653 type_end_pos = unit_type_get(punit);
3654 homecity_id_end_pos = punit->homecity;
3655 }
3656 }
3657
3658 if (homecity_id_start_pos != 0) {
3659 homecity_start_pos = game_city_by_number(homecity_id_start_pos);
3660 }
3661 if (homecity_id_start_pos != homecity_id_end_pos) {
3662 homecity_end_pos = game_city_by_number(homecity_id_end_pos);
3663 } else {
3664 homecity_end_pos = homecity_start_pos;
3665 }
3666
3667 /* We only do refreshes for non-AI players to now make sure the AI turns
3668 doesn't take too long. Perhaps we should make a special refresh_city
3669 functions that only refreshed happines. */
3670
3671 /* might have changed owners or may be destroyed */
3672 tocity = tile_city(dst_tile);
3673
3674 if (tocity) { /* entering a city */
3675 if (tocity->owner == pplayer_end_pos) {
3676 if (tocity != homecity_end_pos && is_human(pplayer_end_pos)) {
3677 city_refresh(tocity);
3678 send_city_info(pplayer_end_pos, tocity);
3679 }
3680 }
3681 if (homecity_start_pos) {
3682 refresh_homecity_start_pos = TRUE;
3683 }
3684 }
3685
3686 if (fromcity) { /* leaving a city */
3687 if (homecity_start_pos) {
3688 refresh_homecity_start_pos = TRUE;
3689 }
3690 if (fromcity != homecity_start_pos
3691 && fromcity->owner == pplayer_start_pos
3692 && is_human(pplayer_start_pos)) {
3693 city_refresh(fromcity);
3694 send_city_info(pplayer_start_pos, fromcity);
3695 }
3696 }
3697
3698 /* Entering/leaving a fortress or friendly territory */
3699 if (homecity_start_pos || homecity_end_pos) {
3700 if ((game.info.happyborders != HB_DISABLED && tile_owner(src_tile) != tile_owner(dst_tile))
3701 || (tile_has_not_aggressive_extra_for_unit(dst_tile,
3702 type_end_pos)
3703 && is_friendly_city_near(nmap, pplayer_end_pos, dst_tile))
3704 || (tile_has_not_aggressive_extra_for_unit(src_tile,
3705 type_start_pos)
3706 && is_friendly_city_near(nmap, pplayer_start_pos, src_tile))) {
3707 refresh_homecity_start_pos = TRUE;
3708 refresh_homecity_end_pos = TRUE;
3709 }
3710 }
3711
3712 if (refresh_homecity_start_pos && is_human(pplayer_start_pos)) {
3713 city_refresh(homecity_start_pos);
3714 send_city_info(pplayer_start_pos, homecity_start_pos);
3715 }
3716 if (refresh_homecity_end_pos
3717 && (!refresh_homecity_start_pos
3718 || homecity_start_pos != homecity_end_pos)
3719 && is_human(pplayer_end_pos)) {
3720 city_refresh(homecity_end_pos);
3721 send_city_info(pplayer_end_pos, homecity_end_pos);
3722 }
3723
3724 city_map_update_tile_now(dst_tile);
3725 sync_cities();
3726
3727 return alive;
3728}
3729
3730/**********************************************************************/
3734 static void check_unit_activity(struct unit *punit)
3735{
3736 switch (punit->activity) {
3737 case ACTIVITY_IDLE:
3738 case ACTIVITY_SENTRY:
3739 case ACTIVITY_EXPLORE:
3740 case ACTIVITY_GOTO:
3741 break;
3742 case ACTIVITY_POLLUTION:
3743 case ACTIVITY_MINE:
3744 case ACTIVITY_IRRIGATE:
3745 case ACTIVITY_CULTIVATE:
3746 case ACTIVITY_PLANT:
3747 case ACTIVITY_FORTIFIED:
3748 case ACTIVITY_FORTRESS:
3749 case ACTIVITY_PILLAGE:
3750 case ACTIVITY_TRANSFORM:
3751 case ACTIVITY_UNKNOWN:
3752 case ACTIVITY_AIRBASE:
3753 case ACTIVITY_FORTIFYING:
3754 case ACTIVITY_FALLOUT:
3755 case ACTIVITY_PATROL_UNUSED:
3756 case ACTIVITY_BASE:
3757 case ACTIVITY_GEN_ROAD:
3758 case ACTIVITY_CONVERT:
3759 case ACTIVITY_OLD_ROAD:
3760 case ACTIVITY_OLD_RAILROAD:
3761 case ACTIVITY_LAST:
3762 set_unit_activity(punit, ACTIVITY_IDLE);
3763 break;
3764 };
3765}
3766
3767/**********************************************************************/
3770 static struct unit_move_data *unit_move_data(struct unit *punit,
3771 struct tile *psrctile,
3772 struct tile *pdesttile)
3773{
3774 struct unit_move_data *pdata;
3775 struct player *powner = unit_owner(punit);
3776
3777 if (punit->server.moving) {
3778 /* Recursive moving (probably due to a script). */
3779 pdata = punit->server.moving;
3780 pdata->ref_count++;
3781 fc_assert_msg(pdata->punit == punit,
3782 "Unit number %d (%p) was going to die, but "
3783 "server attempts to move it.",
3784 punit->id, punit);
3785 fc_assert_msg(pdata->old_vision == NULL,
3786 "Unit number %d (%p) has done an incomplete move.",
3787 punit->id, punit);
3788 } else {
3789 pdata = fc_malloc(sizeof(*pdata));
3790 pdata->ref_count = 1;
3791 pdata->punit = punit;
3792 punit->server.moving = pdata;
3793 BV_CLR_ALL(pdata->can_see_unit);
3794 }
3795 pdata->powner = powner;
3796 BV_CLR_ALL(pdata->can_see_move);
3797 pdata->old_vision = punit->server.vision;
3798
3799 return pdata;
3800}
3801
3802/**********************************************************************/
3805 static void unit_move_by_data(struct unit_move_data *pdata,
3806 struct tile *psrctile, struct tile *pdesttile)
3807{
3808 struct vision *new_vision;
3809 struct unit *punit = pdata->punit;
3810 int mod = unit_vision_range_modifiers(punit, pdesttile);
3811 const v_radius_t radius_sq =
3812 V_RADIUS(get_unit_vision_base(punit, V_MAIN, mod),
3813 get_unit_vision_base(punit, V_INVIS, mod),
3814 get_unit_vision_base(punit, V_SUBSURFACE, mod));
3815
3816 /* Remove unit from the source tile. */
3817 fc_assert(unit_tile(punit) == psrctile);
3818
3819#ifndef FREECIV_NDEBUG
3820 bool success =
3821#endif
3822 unit_list_remove(psrctile->units, punit);
3823 fc_assert(success);
3824
3825 /* Set new tile. */
3826 unit_tile_set(punit, pdesttile);
3827 unit_list_prepend(pdesttile->units, punit);
3828
3829 if (unit_transported(punit)) {
3830 /* Silently free orders since they won't be applicable anymore. */
3831 free_unit_orders(punit);
3832 }
3833
3834 /* Check unit activity. */
3835 check_unit_activity(punit);
3836 unit_did_action(punit);
3837 unit_forget_last_activity(punit);
3838
3839 /* We first unfog the destination, then send the move,
3840 * and then fog the old territory. This means that the player
3841 * gets a chance to see the newly explored territory while the
3842 * client moves the unit, and both areas are visible during the
3843 * move */
3844
3845 /* Enhance vision if unit steps into a fortress */
3846 new_vision = vision_new(pdata->powner, pdesttile);
3847 punit->server.vision = new_vision;
3848 vision_change_sight(new_vision, radius_sq);
3849 ASSERT_VISION(new_vision);
3850}
3851
3852/**********************************************************************/
3855 static void unit_move_data_unref(struct unit_move_data *pdata)
3856{
3857 fc_assert_ret(pdata != NULL);
3858 fc_assert_ret(pdata->ref_count > 0);
3859 fc_assert_msg(pdata->old_vision == NULL,
3860 "Unit number %d (%p) has done an incomplete move.",
3861 pdata->punit != NULL ? pdata->punit->id : -1, pdata->punit);
3862
3863 pdata->ref_count--;
3864 if (pdata->ref_count == 0) {
3865 if (pdata->punit != NULL) {
3866 fc_assert(pdata->punit->server.moving == pdata);
3867 pdata->punit->server.moving = NULL;
3868 }
3869 free(pdata);
3870 }
3871}
3872
3873/**********************************************************************/
3884 bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3885 struct unit *embark_to, bool find_embark_target,
3886 bool conquer_city_allowed, bool conquer_extras_allowed,
3887 bool enter_hut, bool frighten_hut)
3888{
3889 struct player *pplayer;
3890 struct tile *psrctile;
3891 struct city *psrccity;
3892 struct city *pdestcity;
3893 struct unit *ptransporter;
3894 struct packet_unit_info src_info, dest_info;
3895 struct packet_unit_short_info src_sinfo, dest_sinfo;
3896 struct unit_move_data_list *plist =
3897 unit_move_data_list_new_full(unit_move_data_unref);
3898 struct unit_move_data *pdata;
3899 int saved_id;
3900 bool unit_lives;
3901 bool adj;
3902 enum direction8 facing;
3903
3904 /* Some checks. */
3905 fc_assert_ret_val(punit != NULL, FALSE);
3906 fc_assert_ret_val(pdesttile != NULL, FALSE);
3907
3908 pplayer = unit_owner(punit);
3909 saved_id = punit->id;
3910 psrctile = unit_tile(punit);
3911 adj = base_get_direction_for_step(&(wld.map), psrctile, pdesttile, &facing);
3912
3913 conn_list_do_buffer(game.est_connections);
3914
3915 /* Unload the unit if on a transport. */
3916 ptransporter = unit_transport_get(punit);
3917 if (ptransporter != NULL) {
3918 /* Unload unit _before_ setting the new tile! */
3919 unit_transport_unload(punit);
3920 /* Send updated information to anyone watching that transporter
3921 * was unloading cargo. */
3922 send_unit_info(NULL, ptransporter);
3923 }
3924
3925 /* Wakup units next to us before we move. */
3926 wakeup_neighbor_sentries(punit);
3927
3928 /* Make info packets at 'psrctile'. */
3929 if (adj) {
3930 /* If tiles are adjacent, we will show the move to users able
3931 * to see it. */
3932 package_unit(punit, &src_info);
3933 package_short_unit(punit, &src_sinfo, UNIT_INFO_IDENTITY, 0);
3934 }
3935
3936 /* Make new data for 'punit'. */
3937 pdata = unit_move_data(punit, psrctile, pdesttile);
3938 unit_move_data_list_prepend(plist, pdata);
3939
3940 /* Set unit orientation */
3941 if (adj) {
3942 /* Only change orientation when moving to adjacent tile */
3943 punit->facing = facing;
3944 }
3945
3946 /* Move magic. */
3947 punit->moved = TRUE;
3948 punit->moves_left = MAX(0, punit->moves_left - move_cost);
3949 if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3950 /* The next order may not require any remaining move fragments. */
3951 punit->done_moving = TRUE;
3952 }
3953
3954 /* No longer relevant. */
3955 punit->action_decision_tile = NULL;
3956 punit->action_decision_want = ACT_DEC_NOTHING;
3957
3958 if (!adj
3959 && action_tgt_city(punit, pdesttile, FALSE)) {
3960 /* The unit can perform an action to the city at the destination tile.
3961 * A long distance move (like an airlift) doesn't ask what action to
3962 * perform before moving. Ask now. */
3963
3964 punit->action_decision_want = ACT_DEC_PASSIVE;
3965 punit->action_decision_tile = pdesttile;
3966 }
3967
3968 /* Claim ownership of fortress? */
3969 if (conquer_extras_allowed
3970 && tile_has_claimable_base(pdesttile, unit_type_get(punit))) {
3971 /* Yes. We claim *all* bases if there's *any* claimable base(s).
3972 * Even if original unit cannot claim other kind of bases, the
3973 * first claimed base will have influence over other bases,
3974 * or something like that. */
3975 tile_claim_bases(pdesttile, pplayer);
3976 }
3977
3978 /* Move all contained units. */
3979 unit_cargo_iterate(punit, pcargo) {
3980 pdata = unit_move_data(pcargo, psrctile, pdesttile);
3981 unit_move_data_list_append(plist, pdata);
3982 } unit_cargo_iterate_end;
3983
3984 /* Get data for 'punit'. */
3985 pdata = unit_move_data_list_front(plist);
3986
3987 /* Determine the players able to see the move(s), now that the player
3988 * vision has been increased. */
3989 if (adj) {
3990 /* Main unit for adjacent move: the move is visible for every player
3991 * able to see on the matching unit layer. */
3992 enum vision_layer vlayer = unit_type_get(punit)->vlayer;
3993
3994 players_iterate(oplayer) {
3995 if (map_is_known_and_seen(psrctile, oplayer, vlayer)
3996 || map_is_known_and_seen(pdesttile, oplayer, vlayer)) {
3997 BV_SET(pdata->can_see_unit, player_index(oplayer));
3998 BV_SET(pdata->can_see_move, player_index(oplayer));
3999 }
4000 } players_iterate_end;
4001 }
4002
4003 unit_move_data_list_iterate(plist, pmove_data) {
4004
4005 unit_move_by_data(pmove_data, psrctile, pdesttile);
4006
4007 if (adj && pmove_data == pdata) {
4008 /* If positions are adjacent, we have already handled 'punit'. See
4009 * above. */
4010 continue;
4011 }
4012
4013 players_iterate(oplayer) {
4014 if ((adj
4015 && can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
4016 pmove_data != pdata))
4017 || can_player_see_unit_at(oplayer, pmove_data->punit, pdesttile,
4018 pmove_data != pdata)) {
4019 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4020 BV_SET(pmove_data->can_see_move, player_index(oplayer));
4021 }
4022 if (can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
4023 pmove_data != pdata)) {
4024 /* The unit was seen with its source tile even if it was
4025 * teleported. */
4026 BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4027 }
4028 } players_iterate_end;
4029 } unit_move_data_list_iterate_end;
4030
4031 /* Check timeout settings. */
4032 if (current_turn_timeout() != 0 && game.server.timeoutaddenemymove > 0) {
4033 bool new_information_for_enemy = FALSE;
4034
4035 phase_players_iterate(penemy) {
4036 /* Increase the timeout if an enemy unit moves and the
4037 * timeoutaddenemymove setting is in use. */
4038 if (penemy->is_connected
4039 && pplayer != penemy
4040 && pplayers_at_war(pplayer, penemy)
4041 && BV_ISSET(pdata->can_see_move, player_index(penemy))) {
4042 new_information_for_enemy = TRUE;
4043 break;
4044 }
4045 } phase_players_iterate_end;
4046
4047 if (new_information_for_enemy) {
4048 increase_timeout_because_unit_moved();
4049 }
4050 }
4051
4052 /* Notifications of the move to the clients. */
4053 if (adj) {
4054 /* Special case: 'punit' is moving to adjacent position. Then we show
4055 * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4056
4057 /* Make info packets at 'pdesttile'. */
4058 package_unit(punit, &dest_info);
4059 package_short_unit(punit, &dest_sinfo, UNIT_INFO_IDENTITY, 0);
4060
4061 conn_list_iterate(game.est_connections, pconn) {
4062 struct player *aplayer = conn_get_player(pconn);
4063
4064 if (aplayer == NULL) {
4065 if (pconn->observer) {
4066 /* Global observers see all... */
4067 send_packet_unit_info(pconn, &src_info);
4068 send_packet_unit_info(pconn, &dest_info);
4069 }
4070 } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4071 if (aplayer == pplayer) {
4072 send_packet_unit_info(pconn, &src_info);
4073 send_packet_unit_info(pconn, &dest_info);
4074 } else {
4075 send_packet_unit_short_info(pconn, &src_sinfo, FALSE);
4076 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
4077 }
4078 }
4079 } conn_list_iterate_end;
4080 }
4081
4082 /* Other moves. */
4083 unit_move_data_list_iterate(plist, pmove_data) {
4084 if (adj && pmove_data == pdata) {
4085 /* If positions are adjacent, we have already shown 'punit' move.
4086 * See above. */
4087 continue;
4088 }
4089
4090 /* Make info packets at 'pdesttile'. */
4091 package_unit(pmove_data->punit, &dest_info);
4092 package_short_unit(pmove_data->punit, &dest_sinfo,
4093 UNIT_INFO_IDENTITY, 0);
4094
4095 conn_list_iterate(game.est_connections, pconn) {
4096 struct player *aplayer = conn_get_player(pconn);
4097
4098 if (aplayer == NULL) {
4099 if (pconn->observer) {
4100 /* Global observers see all... */
4101 send_packet_unit_info(pconn, &dest_info);
4102 }
4103 } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4104 if (aplayer == pmove_data->powner) {
4105 send_packet_unit_info(pconn, &dest_info);
4106 } else {
4107 send_packet_unit_short_info(pconn, &dest_sinfo, FALSE);
4108 }
4109 }
4110 } conn_list_iterate_end;
4111 } unit_move_data_list_iterate_end;
4112
4113 /* Clear old vision. */
4114 unit_move_data_list_iterate(plist, pmove_data) {
4115 if (pmove_data->old_vision != NULL) {
4116 vision_clear_sight(pmove_data->old_vision);
4117 vision_free(pmove_data->old_vision);
4118 pmove_data->old_vision = NULL;
4119 }
4120 } unit_move_data_list_iterate_end;
4121
4122 /* Move consequences. */
4123 unit_move_data_list_iterate(plist, pmove_data) {
4124 struct unit *aunit = pmove_data->punit;
4125
4126 if (aunit != NULL
4127 && unit_owner(aunit) == pmove_data->powner
4128 && unit_tile(aunit) == pdesttile) {
4129 (void) unit_move_consequences(aunit, psrctile, pdesttile,
4130 pdata != pmove_data,
4131 conquer_city_allowed);
4132 }
4133 } unit_move_data_list_iterate_end;
4134
4135 unit_lives = (pdata->punit == punit);
4136
4137 /* Wakeup units and make contact. */
4138 if (unit_lives) {
4139 wakeup_neighbor_sentries(punit);
4140 }
4141 maybe_make_contact(pdesttile, pplayer);
4142
4143 if (unit_lives) {
4144 /* Special checks for ground units in the ocean. */
4145 if (embark_to || !can_unit_survive_at_tile(&(wld.map), punit, pdesttile)) {
4146 if (embark_to != NULL) {
4147 ptransporter = embark_to;
4148 } else if (find_embark_target) {
4149 /* TODO: Consider to stop supporting find_embark_target and make all
4150 * callers that wants auto loading set embark_to. */
4151 ptransporter = transporter_for_unit(punit);
4152 } else {
4153 ptransporter = NULL;
4154 }
4155 if (ptransporter) {
4156 unit_transport_load_tp_status(punit, ptransporter, FALSE);
4157
4158 /* Set activity to sentry if boarding a ship. */
4159 if (is_human(pplayer)
4160 && !unit_has_orders(punit)
4161 && punit->ssa_controller == SSA_NONE
4162 && !can_unit_exist_at_tile(&(wld.map), punit, pdesttile)) {
4163 set_unit_activity(punit, ACTIVITY_SENTRY);
4164 }
4165
4166 send_unit_info(NULL, punit);
4167 }
4168 }
4169 }
4170
4171 /* Remove units going out of sight. */
4172 unit_move_data_list_iterate_rev(plist, pmove_data) {
4173 struct unit *aunit = pmove_data->punit;
4174
4175 if (aunit == NULL) {
4176 continue; /* Died! */
4177 }
4178
4179 players_iterate(aplayer) {
4180 if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4181 && !can_player_see_unit(aplayer, aunit)) {
4182 unit_goes_out_of_sight(aplayer, aunit);
4183 }
4184 } players_iterate_end;
4185 } unit_move_data_list_iterate_rev_end;
4186
4187 /* Inform the owner's client about actor unit arrival. Can, depending on
4188 * the client settings, cause the client to start the process that makes
4189 * the action selection dialog pop up. */
4190 pdestcity = tile_city(pdesttile);
4191 if (pdestcity != NULL) {
4192 /* Arrival in a city counts. */
4193
4194 unit_move_data_list_iterate(plist, pmove_data) {
4195 struct unit *ptrans;
4196 bool ok;
4197 struct unit *act_unit;
4198 struct player *act_player;
4199
4200 act_unit = pmove_data->punit;
4201 act_player = unit_owner(act_unit);
4202
4203 if (act_unit == NULL
4204 || !unit_is_alive(act_unit->id)) {
4205 /* The unit died before reaching this point. */
4206 continue;
4207 }
4208
4209 if (unit_tile(act_unit) != pdesttile) {
4210 /* The unit didn't arrive at the destination tile. */
4211 continue;
4212 }
4213
4214 if (!is_human(act_player)) {
4215 /* Only humans need reminders. */
4216 continue;
4217 }
4218
4219 if (!unit_transported(act_unit)) {
4220 /* Don't show the action selection dialog again. Non transported
4221 * units are handled before they move to the tile. */
4222 continue;
4223 }
4224
4225 /* Open action dialog only if 'act_unit' and all its transporters
4226 * (recursively) don't have orders. */
4227 if (unit_has_orders(act_unit)) {
4228 /* The unit it self has orders. */
4229 continue;
4230 }
4231
4232 for (ptrans = unit_transport_get(act_unit);;
4233 ptrans = unit_transport_get(ptrans)) {
4234 if (NULL == ptrans) {
4235 /* No (recursive) transport has orders. */
4236 ok = TRUE;
4237 break;
4238 } else if (unit_has_orders(ptrans)) {
4239 /* A unit transporting the unit has orders */
4240 ok = FALSE;
4241 break;
4242 }
4243 }
4244
4245 if (!ok) {
4246 /* A unit transporting act_unit has orders. */
4247 continue;
4248 }
4249
4250 if (action_tgt_city(act_unit, pdesttile, FALSE)) {
4251 /* There is a valid target. */
4252
4253 act_unit->action_decision_want = ACT_DEC_PASSIVE;
4254 act_unit->action_decision_tile = pdesttile;
4255
4256 /* Let the client know that this unit wants the player to decide
4257 * what to do. */
4258 send_unit_info(player_reply_dest(act_player), act_unit);
4259 }
4260 } unit_move_data_list_iterate_end;
4261 }
4262
4263 unit_move_data_list_destroy(plist);
4264 /* Check cities at source and destination. */
4265 psrccity = tile_city(psrctile);
4266 if (psrccity != NULL) {
4267 refresh_dumb_city(psrccity);
4268 }
4269 if (pdestcity != NULL) {
4270 refresh_dumb_city(pdestcity);
4271 }
4272
4273 if (unit_lives) {
4274 /* Let the scripts run ... */
4275 script_server_signal_emit("unit_moved", punit, psrctile, pdesttile);
4276 unit_lives = unit_is_alive(saved_id);
4277 }
4278
4279 if (unit_lives) {
4280 /* Autoattack. */
4281 unit_lives = unit_survive_autoattack(punit);
4282 }
4283
4284 if (unit_lives && (enter_hut || frighten_hut)) {
4285 /* Is there a hut? */
4286 unit_enter_hut(punit, frighten_hut);
4287 fc_assert(!(enter_hut && frighten_hut));
4288 unit_lives = unit_is_alive(saved_id);
4289 }
4290
4291 conn_list_do_unbuffer(game.est_connections);
4292
4293 if (unit_lives) {
4294 CALL_FUNC_EACH_AI(unit_move_seen, punit);
4295 }
4296
4297 return unit_lives;
4298}
4299
4300/**********************************************************************/
4303 static bool maybe_cancel_goto_due_to_enemy(struct unit *punit,
4304 struct tile *ptile)
4305{
4306 return (is_non_allied_unit_tile(ptile, unit_owner(punit))
4307 || is_non_allied_city_tile(ptile, unit_owner(punit)));
4308}
4309
4310/**********************************************************************/
4316 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
4317{
4318 bool cancel = FALSE;
4319 int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4320 struct player *pplayer = unit_owner(punit);
4321
4322 circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile) {
4323 struct unit *penemy = tile_non_allied_unit(ptile, pplayer);
4324 struct vision_site *pdcity = map_get_player_site(ptile, pplayer);
4325
4326 if ((penemy && can_player_see_unit(pplayer, penemy))
4327 || (pdcity && !pplayers_allied(pplayer, vision_site_owner(pdcity))
4328 && pdcity->occupied)) {
4329 cancel = TRUE;
4330 break;
4331 }
4332 } circle_iterate_end;
4333
4334 return cancel;
4335}
4336
4337/**********************************************************************/
4345 static inline bool player_is_watching(struct unit *punit, const bool fresh)
4346{
4347 /* The player just sent the orders to the unit. The unit has moves left.
4348 * It is therefore safe to assume that the player already is paying
4349 * attention to the unit. */
4350 return fresh && punit->moves_left > 0;
4351}
4352
4353/**********************************************************************/
4372 bool execute_orders(struct unit *punit, const bool fresh)
4373{
4374 struct act_prob prob;
4375 bool performed;
4376 const char *name;
4377 bool res, last_order;
4378 int unitid = punit->id;
4379 struct player *pplayer = unit_owner(punit);
4380 int moves_made = 0;
4381 const struct civ_map *nmap = &(wld.map);
4382
4383 fc_assert_ret_val(unit_has_orders(punit), TRUE);
4384
4385 if (punit->activity != ACTIVITY_IDLE) {
4386 /* Unit's in the middle of an activity; wait for it to finish. */
4387 punit->done_moving = TRUE;
4388 return TRUE;
4389 }
4390
4391 log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4392
4393 /* Any time the orders are canceled we should give the player a message. */
4394
4395 while (TRUE) {
4396 struct unit_order order;
4397
4398 struct action *oaction;
4399
4400 struct tile *dst_tile;
4401 struct city *tgt_city;
4402 struct unit *tgt_unit;
4403 int tgt_id;
4404 int sub_tgt_id;
4405 struct extra_type *pextra;
4406
4407 if (punit->done_moving) {
4408 log_debug(" stopping because we're done this turn");
4409 return TRUE;
4410 }
4411
4412 if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
4413 /* "Patrol" orders are stopped if an enemy is near. */
4414 cancel_orders(punit, " stopping because of nearby enemy");
4415 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4416 _("Orders for %s aborted as there are units nearby."),
4417 unit_link(punit));
4418 return TRUE;
4419 }
4420
4421 if (moves_made == punit->orders.length) {
4422 /* For repeating orders, don't repeat more than once per turn. */
4423 log_debug(" stopping because we ran a round");
4424 punit->done_moving = TRUE;
4425 send_unit_info(NULL, punit);
4426 return TRUE;
4427 }
4428 moves_made++;
4429
4430 order = punit->orders.list[punit->orders.index];
4431
4432 /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4433 * this far. */
4434 fc_assert_action((order.order != ORDER_PERFORM_ACTION
4435 || action_id_exists(order.action)),
4436 continue);
4437
4438 switch (order.order) {
4439 case ORDER_MOVE:
4440 case ORDER_ACTION_MOVE:
4441 case ORDER_FULL_MP:
4442 if (0 == punit->moves_left) {
4443 log_debug(" stopping because of no more move points");
4444 return TRUE;
4445 }
4446 break;
4447 case ORDER_PERFORM_ACTION:
4448 if (action_mp_full_makes_legal(punit, order.action)) {
4449 log_debug(" stopping. Not enough move points this turn");
4450 return TRUE;
4451 }
4452 break;
4453 case ORDER_ACTIVITY:
4454 case ORDER_LAST:
4455 /* Those actions don't require moves left. */
4456 break;
4457 }
4458
4459 last_order = (!punit->orders.repeat
4460 && punit->orders.index + 1 == punit->orders.length);
4461
4462 if (last_order) {
4463 /* Clear the orders before we engage in the move. That way any
4464 * has_orders checks will yield FALSE and this will be treated as
4465 * a normal move. This is important: for instance a caravan goto
4466 * will popup the caravan dialog on the last move only. */
4467 free_unit_orders(punit);
4468 }
4469
4470 /* Advance the orders one step forward. This is needed because any
4471 * updates sent to the client as a result of the action should include
4472 * the new index value. Note that we have to send_unit_info somewhere
4473 * after this point so that the client is properly updated. */
4474 punit->orders.index++;
4475
4476 switch (order.order) {
4477 case ORDER_FULL_MP:
4478 if (punit->moves_left < unit_move_rate(punit)) {
4479 /* If the unit doesn't have full MP then it just waits until the
4480 * next turn. We assume that the next turn it will have full MP
4481 * (there's no check for that). */
4482 punit->done_moving = TRUE;
4483 log_debug(" waiting this turn");
4484 send_unit_info(NULL, punit);
4485 }
4486 break;
4487 case ORDER_ACTIVITY:
4488 {
4489 enum unit_activity activity = order.activity;
4490
4491 fc_assert(activity == ACTIVITY_SENTRY);
4492
4493 if (can_unit_do_activity(nmap, punit, activity)) {
4494 punit->done_moving = TRUE;
4495 set_unit_activity(punit, activity);
4496 send_unit_info(NULL, punit);
4497
4498 break;
4499 }
4500 }
4501
4502 cancel_orders(punit, " orders canceled because of failed activity");
4503 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4504 _("Orders for %s aborted since they "
4505 "give an invalid activity."),
4506 unit_link(punit));
4507 return TRUE;
4508 case ORDER_MOVE:
4509 case ORDER_ACTION_MOVE:
4510 /* Move unit */
4511 if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4512 cancel_orders(punit, " move order sent us to invalid location");
4513 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4514 _("Orders for %s aborted since they "
4515 "give an invalid location."),
4516 unit_link(punit));
4517 return TRUE;
4518 }
4519
4520 if (order.order != ORDER_ACTION_MOVE
4521 && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
4522 /* Plain move required: no attack, trade route etc. */
4523 cancel_orders(punit, " orders canceled because of enemy");
4524 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4525 _("Orders for %s aborted as there "
4526 "are units in the way."),
4527 unit_link(punit));
4528 return TRUE;
4529 }
4530
4531 log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4532 res = unit_move_handling(punit, dst_tile,
4533 order.order != ORDER_ACTION_MOVE);
4534 if (!player_unit_by_number(pplayer, unitid)) {
4535 log_debug(" unit died while moving.");
4536 /* A player notification should already have been sent. */
4537 return FALSE;
4538 }
4539
4540 if (res && !same_pos(dst_tile, unit_tile(punit))) {
4541 /* Movement succeeded but unit didn't move. */
4542 log_debug(" orders resulted in combat.");
4543 send_unit_info(NULL, punit);
4544 return TRUE;
4545 }
4546
4547 if (!res) {
4548 fc_assert(0 <= punit->moves_left);
4549
4550 /* Movement failed (ZOC, etc.) */
4551 cancel_orders(punit, " attempt to move failed.");
4552
4553 if (!player_is_watching(punit, fresh)
4554 /* The final move "failed" because the unit needs to ask the
4555 * player what action it should take.
4556 *
4557 * The action decision request notifies the player. Its
4558 * location at the unit's last order makes it clear to the
4559 * player who the decision is for. ("The Spy I sent to Berlin
4560 * has arrived.")
4561 *
4562 * A notification message is therefore redundant. */
4563 && !(last_order
4564 && punit->action_decision_want == ACT_DEC_ACTIVE
4565 && punit->action_decision_tile == dst_tile)) {
4566 /* The player may have missed this. No one else will announce it
4567 * in a satisfying manner. Inform the player. */
4568 notify_player(pplayer, unit_tile(punit),
4569 E_UNIT_ORDERS, ftc_server,
4570 _("Orders for %s aborted because of failed move."),
4571 unit_link(punit));
4572 }
4573
4574 return TRUE;
4575 }
4576 break;
4577 case ORDER_PERFORM_ACTION:
4578 oaction = action_by_number(order.action);
4579
4580 /* Checked in unit_order_list_is_sane() */
4581 fc_assert_action(oaction != NULL, continue);
4582
4583 log_debug(" orders: doing action %s", action_rule_name(oaction));
4584
4585 dst_tile = index_to_tile(&(wld.map), order.target);
4586
4587 if (dst_tile == NULL) {
4588 /* Could be at the edge of the map while trying to target a tile
4589 * outside of it. */
4590
4591 cancel_orders(punit, " target location doesn't exist");
4592 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4593 order.action, dst_tile, NULL, NULL);
4594
4595 return TRUE;
4596 }
4597
4598 /* Get the target city from the target tile. */
4599 tgt_city = tile_city(dst_tile);
4600
4601 if (tgt_city == NULL
4602 && action_id_get_target_kind(order.action) == ATK_CITY) {
4603 /* This action targets a city but no city target was found. */
4604
4605 cancel_orders(punit, " perform action vs city with no city");
4606 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4607 order.action, dst_tile, tgt_city, NULL);
4608
4609 return TRUE;
4610 }
4611
4612 /* Get a target unit at the target tile. */
4613 tgt_unit = action_tgt_unit(punit, dst_tile, TRUE);
4614
4615 if (tgt_unit == NULL
4616 && action_id_get_target_kind(order.action) == ATK_UNIT) {
4617 /* This action targets a unit but no target unit was found. */
4618
4619 cancel_orders(punit, " perform action vs unit with no unit");
4620 illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4621 order.action, dst_tile, tgt_city, tgt_unit);
4622
4623 return TRUE;
4624 }
4625
4626 /* Server side sub target assignment */
4627 if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4628 && order.sub_target == NO_TARGET) {
4629 /* Try to find a sub target. */
4630 sub_tgt_id = action_sub_target_id_for_action(oaction, punit);
4631 } else {
4632 /* The client should have specified a sub target if needed */
4633 sub_tgt_id = order.sub_target;
4634 }
4635
4636 /* Get a target extra at the target tile */
4637 pextra = (sub_tgt_id == NO_TARGET ?
4638 NULL :
4639 extra_by_number(sub_tgt_id));
4640
4641 if (action_get_sub_target_kind(oaction) == ASTK_EXTRA_NOT_THERE
4642 && pextra != NULL
4643 && action_creates_extra(oaction, pextra)
4644 && tile_has_extra(dst_tile, pextra)) {
4645 /* Already there. Move on to the next order. */
4646 break;
4647 }
4648
4649 if (action_get_sub_target_kind(oaction) == ASTK_EXTRA
4650 && pextra != NULL
4651 && action_removes_extra(oaction, pextra)
4652 && !tile_has_extra(dst_tile, pextra)) {
4653 /* Already not there. Move on to the next order. */
4654 break;
4655 }
4656
4657 /* No target selected. */
4658 tgt_id = -1;
4659
4660 /* Assume impossible until told otherwise. */
4661 prob = ACTPROB_IMPOSSIBLE;
4662
4663 switch (action_id_get_target_kind(order.action)) {
4664 case ATK_UNITS:
4665 prob = action_prob_vs_units(punit, order.action,
4666 dst_tile);
4667 tgt_id = dst_tile->index;
4668 break;
4669 case ATK_TILE:
4670 prob = action_prob_vs_tile(punit, order.action,
4671 dst_tile, pextra);
4672 tgt_id = dst_tile->index;
4673 break;
4674 case ATK_EXTRAS:
4675 prob = action_prob_vs_extras(punit, order.action,
4676 dst_tile, pextra);
4677 tgt_id = dst_tile->index;
4678 break;
4679 case ATK_CITY:
4680 prob = action_prob_vs_city(nmap, punit, order.action,
4681 tgt_city);
4682 tgt_id = tgt_city->id;
4683 break;
4684 case ATK_UNIT:
4685 prob = action_prob_vs_unit(nmap, punit, order.action,
4686 tgt_unit);
4687
4688 tgt_id = tgt_unit->id;
4689 break;
4690 case ATK_SELF:
4691 prob = action_prob_self(punit, order.action);
4692
4693 tgt_id = unitid;
4694 break;
4695 case ATK_COUNT:
4696 log_error("Invalid action target kind");
4697
4698 /* The check below will abort and cancel the orders because prob
4699 * was initialized to impossible above this switch statement. */
4700
4701 break;
4702 }
4703
4704 if (!action_prob_possible(prob)) {
4705 /* The player has enough information to know that this action is
4706 * against the rules. Don't risk any punishment by trying to
4707 * perform it. */
4708
4709 cancel_orders(punit, " illegal action");
4710 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4711 _("%s could not do %s to %s."),
4712 unit_link(punit),
4713 action_id_name_translation(order.action),
4714 tile_link(dst_tile));
4715
4716 /* Try to explain what rule made it illegal. */
4717 illegal_action_msg(unit_owner(punit), E_BAD_COMMAND, punit,
4718 order.action, dst_tile, tgt_city, tgt_unit);
4719
4720 return TRUE;
4721 }
4722
4723 if (action_id_has_result_safe(order.action, ACTRES_FOUND_CITY)) {
4724 /* This action needs a name. */
4725 name = city_name_suggestion(pplayer, unit_tile(punit));
4726 } else {
4727 /* This action doesn't need a name. */
4728 name = "";
4729 }
4730
4731 performed = unit_perform_action(pplayer,
4732 unitid,
4733 tgt_id,
4734 sub_tgt_id,
4735 name,
4736 order.action,
4737 ACT_REQ_PLAYER);
4738
4739 if (!player_unit_by_number(pplayer, unitid)) {
4740 /* The unit "died" while performing the action. */
4741 return FALSE;
4742 }
4743
4744 if (!performed) {
4745 /* The action wasn't performed as ordered. */
4746
4747 cancel_orders(punit, " failed action");
4748 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4749 _("Orders for %s aborted because "
4750 "doing %s to %s failed."),
4751 unit_link(punit),
4752 action_id_name_translation(order.action),
4753 tile_link(dst_tile));
4754
4755 return TRUE;
4756 }
4757
4758 if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4759 != ACT_TIME_INSTANTANEOUS) {
4760 /* Done at turn change. */
4761 punit->done_moving = TRUE;
4762 send_unit_info(NULL, punit);
4763 break;
4764 }
4765
4766 break;
4767 case ORDER_LAST:
4768 /* Should be caught when loading the unit orders from the savegame or
4769 * when receiving the unit orders from the client. */
4770 fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4771 cancel_orders(punit, " invalid order!");
4772 notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4773 _("Your %s has invalid orders."),
4774 unit_link(punit));
4775 return TRUE;
4776 }
4777
4778 if (last_order) {
4779 fc_assert(!punit->has_orders);
4780 log_debug(" stopping because orders are complete");
4781 return TRUE;
4782 }
4783
4784 if (punit->orders.index == punit->orders.length) {
4785 fc_assert(punit->orders.repeat);
4786 /* Start over. */
4787 log_debug(" repeating orders.");
4788 punit->orders.index = 0;
4789 }
4790 } /* end while */
4791}
4792
4793/**********************************************************************/
4800 static int get_unit_vision_base(struct unit *punit, enum vision_layer vlayer,
4801 const int base)
4802{
4803 switch (vlayer) {
4804 case V_MAIN:
4805 return MAX(0, base);
4806 case V_INVIS:
4807 case V_SUBSURFACE:
4808 return CLIP(0, base, 2);
4809 case V_COUNT:
4810 break;
4811 }
4812
4813 log_error("Unsupported vision layer variant: %d.", vlayer);
4814
4815 return 0;
4816}
4817
4818/**********************************************************************/
4821 static int unit_vision_range_modifiers(struct unit *punit,
4822 const struct tile *ptile)
4823{
4824 const struct unit_type *utype = unit_type_get(punit);
4825
4826 return (utype->vision_radius_sq
4827 + get_unittype_bonus(unit_owner(punit), ptile,
4828 utype, NULL,
4829 EFT_UNIT_VISION_RADIUS_SQ));
4830}
4831
4832/**********************************************************************/
4839 int get_unit_vision_at(struct unit *punit, const struct tile *ptile,
4840 enum vision_layer vlayer)
4841{
4842 return get_unit_vision_base(punit, vlayer,
4843 unit_vision_range_modifiers(punit, ptile));
4844}
4845
4846/**********************************************************************/
4852 void unit_refresh_vision(struct unit *punit)
4853{
4854 struct vision *uvision = punit->server.vision;
4855 const struct tile *utile = unit_tile(punit);
4856 int mod = unit_vision_range_modifiers(punit, utile);
4857 const v_radius_t radius_sq =
4858 V_RADIUS(get_unit_vision_base(punit, V_MAIN, mod),
4859 get_unit_vision_base(punit, V_INVIS, mod),
4860 get_unit_vision_base(punit, V_SUBSURFACE, mod));
4861
4862 vision_change_sight(uvision, radius_sq);
4863 ASSERT_VISION(uvision);
4864}
4865
4866/**********************************************************************/
4869 void unit_list_refresh_vision(struct unit_list *punitlist)
4870{
4871 unit_list_iterate(punitlist, punit) {
4872 unit_refresh_vision(punit);
4873 } unit_list_iterate_end;
4874}
4875
4876/**********************************************************************/
4880 bool unit_can_do_action_now(const struct unit *punit)
4881{
4882 time_t dt;
4883
4884 if (!punit) {
4885 return FALSE;
4886 }
4887
4888 if (game.server.unitwaittime <= 0) {
4889 return TRUE;
4890 }
4891
4892 if (punit->server.action_turn != game.info.turn - 1) {
4893 return TRUE;
4894 }
4895
4896 dt = time(NULL) - punit->server.action_timestamp;
4897 if (dt < game.server.unitwaittime) {
4898 char buf[64];
4899 format_time_duration(game.server.unitwaittime - dt, buf, sizeof(buf));
4900 notify_player(unit_owner(punit), unit_tile(punit), E_BAD_COMMAND,
4901 ftc_server, _("Your unit may not act for another %s "
4902 "this turn. See /help unitwaittime."), buf);
4903 return FALSE;
4904 }
4905
4906 return TRUE;
4907}
4908
4909/**********************************************************************/
4913 void unit_did_action(struct unit *punit)
4914{
4915 if (!punit) {
4916 return;
4917 }
4918
4919 punit->server.action_timestamp = time(NULL);
4920 punit->server.action_turn = game.info.turn;
4921}
4922
4923/**********************************************************************/
4928 bool unit_can_be_retired(struct unit *punit)
4929{
4930 /* check if there is enemy nearby */
4931 square_iterate(&(wld.map), unit_tile(punit), 3, ptile) {
4932 if (is_enemy_city_tile(ptile, unit_owner(punit))
4933 || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4934 return FALSE;
4935 }
4936 }
4937 square_iterate_end;
4938
4939 return TRUE;
4940}
action_removes_extra
bool action_removes_extra(const struct action *paction, const struct extra_type *pextra)
Definition actions.c:2312
action_name_translation
const char * action_name_translation(const struct action *action)
Definition actions.c:1890
action_mp_full_makes_legal
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Definition actions.c:7224
action_id_name_translation
const char * action_id_name_translation(action_id act_id)
Definition actions.c:1910
action_prob_self
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Definition actions.c:6380
action_prob_possible
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6707
action_rule_name
const char * action_rule_name(const struct action *action)
Definition actions.c:1876
action_get_sub_target_kind
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Definition actions.c:1751
action_prob_vs_tile
struct act_prob action_prob_vs_tile(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6225
action_prob_vs_units
struct act_prob action_prob_vs_units(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Definition actions.c:6141
action_prob_vs_city
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:5870
action_prob_vs_extras
struct act_prob action_prob_vs_extras(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile, const struct extra_type *target_extra)
Definition actions.c:6309
action_id_exists
bool action_id_exists(const action_id act_id)
Definition actions.c:1697
action_creates_extra
bool action_creates_extra(const struct action *paction, const struct extra_type *pextra)
Definition actions.c:2224
action_prob_cmp_pessimist
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Definition actions.c:6767
action_prob_vs_unit
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:5953
action_prob_to_0_to_1_pessimist
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Definition actions.c:6818
action_by_number
static struct action * action_by_number(action_id act_id)
Definition actions.h:638
action_has_result
#define action_has_result(_act_, _res_)
Definition actions.h:448
action_id_get_act_time
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition actions.h:683
ACTPROB_IMPOSSIBLE
#define ACTPROB_IMPOSSIBLE
Definition actions.h:927
action_id_get_target_kind
#define action_id_get_target_kind(act_id)
Definition actions.h:655
action_id_has_result_safe
#define action_id_has_result_safe(act_id, result)
Definition actions.h:668
action_consequence_complete
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)
Definition actiontools.c:570
action_consequence_caught
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)
Definition actiontools.c:372
action_auto_perf_unit_prob
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)
Definition actiontools.c:1095
action_auto_perf_unit_do
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)
Definition actiontools.c:993
action_tgt_unit
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Definition actiontools.c:705
action_consequence_success
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)
Definition actiontools.c:549
action_tgt_city
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Definition actiontools.c:638
action_sub_target_id_for_action
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
Definition actiontools.c:883
actiontools.h
adv_follow_path
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
advgoto.h
CALL_FUNC_EACH_AI
#define CALL_FUNC_EACH_AI(_func,...)
Definition ai.h:384
CALL_PLR_AI_FUNC
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition ai.h:374
aiiface.h
n
#define n
Definition astring.c:77
manage_auto_explorer
enum unit_move_result manage_auto_explorer(struct unit *punit)
Definition autoexplorer.c:273
autoexplorer.h
adv_unit_new_task
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
Definition autosettlers.c:1267
autosettlers.h
barbarian.h
base.h
bitvector.h
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
BV_CLR
#define BV_CLR(bv, bit)
Definition bitvector.h:86
city_exists_within_max_city_map
bool city_exists_within_max_city_map(const struct tile *ptile, bool may_be_on_center)
Definition city.c:2080
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1111
is_friendly_city_near
bool is_friendly_city_near(const struct civ_map *nmap, const struct player *owner, const struct tile *ptile)
Definition city.c:2061
city.h
city_list_iterate_safe
#define city_list_iterate_safe(citylist, _city)
Definition city.h:502
is_non_allied_city_tile
static bool is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:741
city_list_iterate
#define city_list_iterate(citylist, pcity)
Definition city.h:488
city_tile
#define city_tile(_pcity_)
Definition city.h:544
is_enemy_city_tile
static bool is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:705
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
is_allied_city_tile
static bool is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Definition city.h:717
output_type_iterate
#define output_type_iterate(output)
Definition city.h:812
city_owner
#define city_owner(_pcity_)
Definition city.h:543
city_list_iterate_end
#define city_list_iterate_end
Definition city.h:490
city_list_iterate_safe_end
#define city_list_iterate_safe_end
Definition city.h:524
output_type_iterate_end
#define output_type_iterate_end
Definition city.h:818
city_map_update_tile_now
bool city_map_update_tile_now(struct tile *ptile)
Definition citytools.c:3222
city_name_suggestion
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Definition citytools.c:451
send_city_info
void send_city_info(struct player *dest, struct city *pcity)
Definition citytools.c:2320
find_closest_city
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:849
refresh_dumb_city
void refresh_dumb_city(struct city *pcity)
Definition citytools.c:2181
sync_cities
void sync_cities(void)
Definition citytools.c:3231
unit_conquer_city
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Definition citytools.c:1956
city_units_upkeep
void city_units_upkeep(const struct city *pcity)
Definition citytools.c:3019
transfer_city
bool transfer_city(struct player *ptaker, struct city *pcity, int kill_outside, bool transfer_unit_verbose, bool resolve_stack, bool raze, bool build_free)
Definition citytools.c:1065
citytools.h
city_reduce_size
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Definition cityturn.c:807
city_refresh
bool city_refresh(struct city *pcity)
Definition cityturn.c:161
cityturn.h
unit_info
Definition citydlg.h:197
is_unit_reachable_at
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Definition combat.c:85
is_stack_vulnerable
bool is_stack_vulnerable(const struct tile *ptile)
Definition combat.c:928
get_virtual_defense_power
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:657
unit_bombard_rate
int unit_bombard_rate(struct unit *punit)
Definition combat.c:959
get_total_defense_power
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:712
get_total_attack_power
int get_total_attack_power(const struct unit *attacker, const struct unit *defender)
Definition combat.c:567
unit_win_chance
double unit_win_chance(const struct civ_map *nmap, const struct unit *attacker, const struct unit *defender)
Definition combat.c:438
get_defender
struct unit * get_defender(const struct civ_map *nmap, const struct unit *attacker, const struct tile *ptile)
Definition combat.c:781
get_modified_firepower
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:369
combat.h
conn_get_player
struct player * conn_get_player(const struct connection *pconn)
Definition connection.c:760
conn_list_do_unbuffer
void conn_list_do_unbuffer(struct conn_list *dest)
Definition connection.c:365
conn_list_do_buffer
void conn_list_do_buffer(struct conn_list *dest)
Definition connection.c:355
conn_is_global_observer
bool conn_is_global_observer(const struct connection *pconn)
Definition connection.c:750
conn_list_iterate
#define conn_list_iterate(connlist, pconn)
Definition connection.h:113
conn_list_iterate_end
#define conn_list_iterate_end
Definition connection.h:115
base
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2839
enter_hut
static void enter_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2570
frighten_hut
static void frighten_hut(QVariant data1, QVariant data2)
Definition dialogs.cpp:2600
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
diplhand.h
get_unit_bonus
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Definition effects.c:992
get_unittype_bonus
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, const struct action *paction, enum effect_type effect_type)
Definition effects.c:957
get_player_bonus
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Definition effects.c:771
events.h
rand_extra_for_tile
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Definition extras.c:267
prev_extra_in_tile
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:765
extra_by_number
struct extra_type * extra_by_number(int id)
Definition extras.c:175
extras
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
extra_rule_name
const char * extra_rule_name(const struct extra_type *pextra)
Definition extras.c:195
extra_type_list_iterate
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:159
extra_type_by_rmcause_iterate_end
#define extra_type_by_rmcause_iterate_end
Definition extras.h:334
extra_index
#define extra_index(_e_)
Definition extras.h:177
extra_type_by_rmcause_iterate
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition extras.h:329
EXTRA_NONE
#define EXTRA_NONE
Definition extras.h:82
extra_type_list_iterate_end
#define extra_type_list_iterate_end
Definition extras.h:161
NO_TARGET
#define NO_TARGET
Definition fc_types.h:324
Tech_type_id
int Tech_type_id
Definition fc_types.h:347
ACT_TIME_INSTANTANEOUS
#define ACT_TIME_INSTANTANEOUS
Definition fc_types.h:319
RPT_CERTAIN
@ RPT_CERTAIN
Definition fc_types.h:586
AUT_NONE
@ AUT_NONE
Definition fc_types.h:340
HB_DISABLED
@ HB_DISABLED
Definition fc_types.h:1142
IDENTITY_NUMBER_ZERO
#define IDENTITY_NUMBER_ZERO
Definition fc_types.h:82
fcintl.h
PL_
#define PL_(String1, String2, n)
Definition fcintl.h:71
_
#define _(String)
Definition fcintl.h:67
tile_link
const char * tile_link(const struct tile *ptile)
Definition featured_text.c:1106
ftc_server
const struct ft_color ftc_server
Definition featured_text.c:77
city_link
const char * city_link(const struct city *pcity)
Definition featured_text.c:1072
unit_link
const char * unit_link(const struct unit *punit)
Definition featured_text.c:1200
unit_tile_link
const char * unit_tile_link(const struct unit *punit)
Definition featured_text.c:1217
MAX_LEN_LINK
#define MAX_LEN_LINK
Definition featured_text.h:138
game
struct civ_game game
Definition game.c:57
current_turn_timeout
int current_turn_timeout(void)
Definition game.c:828
wld
struct world wld
Definition game.c:58
game_remove_unit
void game_remove_unit(struct world *gworld, struct unit *punit)
Definition game.c:119
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:111
game_city_by_number
struct city * game_city_by_number(int id)
Definition game.c:102
game.h
increase_timeout_because_unit_moved
void increase_timeout_because_unit_moved(void)
Definition gamehand.c:1034
gamehand.h
government.h
owner
struct city * owner
Definition citydlg.c:219
type
GType type
Definition repodlgs.c:1312
has_handicap
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
handicaps.h
H_MAP
@ H_MAP
Definition handicaps.h:28
H_LIMITEDHUTS
@ H_LIMITEDHUTS
Definition handicaps.h:20
idex_register_unit
void idex_register_unit(struct world *iworld, struct unit *punit)
Definition idex.c:81
idex.h
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_msg
#define fc_assert_msg(condition, message,...)
Definition log.h:181
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert_exit_msg
#define fc_assert_exit_msg(condition, message,...)
Definition log.h:211
log_test
#define log_test
Definition log.h:136
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
fc_assert_action
#define fc_assert_action(condition, action)
Definition log.h:187
log_debug
#define log_debug(message,...)
Definition log.h:115
log_error
#define log_error(message,...)
Definition log.h:103
luascript_signal.h
luascript_types.h
sq_map_distance
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:639
is_safe_ocean
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:665
index_to_tile
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:454
same_pos
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
mapstep
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Definition map.c:369
base_get_direction_for_step
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:1326
map.h
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:427
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:422
square_iterate_end
#define square_iterate_end
Definition map.h:388
map_move_cost_unit
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition map.h:287
circle_iterate
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition map.h:395
circle_iterate_end
#define circle_iterate_end
Definition map.h:398
vision_clear_sight
void vision_clear_sight(struct vision *vision)
Definition maphand.c:2517
destroy_extra
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Definition maphand.c:2605
bounce_units_on_terrain_change
void bounce_units_on_terrain_change(struct tile *ptile)
Definition maphand.c:1903
tile_claim_bases
void tile_claim_bases(struct tile *ptile, struct player *powner)
Definition maphand.c:2204
create_extra
void create_extra(struct tile *ptile, struct extra_type *pextra, struct player *pplayer)
Definition maphand.c:2540
tile_change_side_effects
void tile_change_side_effects(struct tile *ptile, bool refresh_city)
Definition maphand.c:2708
map_is_known_and_seen
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Definition maphand.c:900
map_show_circle
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Definition maphand.c:856
update_tile_knowledge
void update_tile_knowledge(struct tile *ptile)
Definition maphand.c:1427
check_terrain_change
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Definition maphand.c:1979
give_distorted_map
bool give_distorted_map(struct player *pfrom, struct player *pto, int prob, bool reveal_cities)
Definition maphand.c:2680
map_get_player_site
struct vision_site * map_get_player_site(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1359
map_get_player_tile
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Definition maphand.c:1370
vision_change_sight
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Definition maphand.c:2505
maphand.h
mem.h
FC_FREE
#define FC_FREE(ptr)
Definition mem.h:41
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
can_exist_at_tile
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:275
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:316
unit_move_rate
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
unit_could_load_at
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:869
is_native_to_class
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:327
can_unit_survive_at_tile
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:476
movement.h
MR_OK
@ MR_OK
Definition movement.h:33
MR_NOT_ALLOWED
@ MR_NOT_ALLOWED
Definition movement.h:50
MR_DEATH
@ MR_DEATH
Definition movement.h:34
name_translation_get
static const char * name_translation_get(const struct name_translation *ptrans)
Definition name_translation.h:121
nation_rule_name
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
nation_of_unit
struct nation_type * nation_of_unit(const struct unit *punit)
Definition nation.c:462
nation_adjective_for_player
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:168
nation_plural_for_player
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:177
notify_player
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:292
notify_conn
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:239
notify.h
packets.h
unit_info_use
unit_info_use
Definition packets.h:81
UNIT_INFO_IDENTITY
@ UNIT_INFO_IDENTITY
Definition packets.h:82
send_packet_unit_remove
int send_packet_unit_remove(struct connection *pc, const struct packet_unit_remove *packet)
Definition packets_gen.c:37984
lsend_packet_unit_remove
void lsend_packet_unit_remove(struct conn_list *dest, const struct packet_unit_remove *packet)
Definition packets_gen.c:37996
send_packet_unit_short_info
int send_packet_unit_short_info(struct connection *pc, const struct packet_unit_short_info *packet, bool force_to_send)
Definition packets_gen.c:42114
send_packet_unit_info
int send_packet_unit_info(struct connection *pc, const struct packet_unit_info *packet)
Definition packets_gen.c:40947
dlsend_packet_unit_remove
void dlsend_packet_unit_remove(struct conn_list *dest, int unit_id16, int unit_id32)
Definition packets_gen.c:38013
pf_path_destroy
void pf_path_destroy(struct pf_path *path)
Definition path_finding.c:3411
pf_map_new
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
Definition path_finding.c:3182
pf_map_path
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
Definition path_finding.c:3235
pf_map_destroy
void pf_map_destroy(struct pf_map *pfm)
Definition path_finding.c:3206
path_finding.h
pf_map_move_costs_iterate_end
#define pf_map_move_costs_iterate_end
Definition path_finding.h:592
pf_map_move_costs_iterate
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
Definition path_finding.h:582
pft_fill_unit_parameter
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
pf_tools.h
player_unit_by_number
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
Definition player.c:1205
player_by_number
struct player * player_by_number(const int player_id)
Definition player.c:840
can_player_see_unit_at
bool can_player_see_unit_at(const struct player *pplayer, const struct unit *punit, const struct tile *ptile, bool is_transported)
Definition player.c:1025
player_slot_count
int player_slot_count(void)
Definition player.c:411
player_number
int player_number(const struct player *pplayer)
Definition player.c:828
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:886
can_player_see_unit
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Definition player.c:1084
pplayers_at_war
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1364
player_index
int player_index(const struct player *pplayer)
Definition player.c:820
player_diplstate_get
struct player_diplstate * player_diplstate_get(const struct player *plr1, const struct player *plr2)
Definition player.c:317
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
slots
struct player_slot * slots
Definition player.c:50
pplayers_non_attack
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1435
player.h
players_iterate_end
#define players_iterate_end
Definition player.h:535
players_iterate
#define players_iterate(_pplayer)
Definition player.h:530
is_barbarian
static bool is_barbarian(const struct player *pplayer)
Definition player.h:488
is_ai
#define is_ai(plr)
Definition player.h:234
is_human
#define is_human(plr)
Definition player.h:233
player_update_last_war_action
void player_update_last_war_action(struct player *pplayer)
Definition plrhand.c:746
player_status_add
void player_status_add(struct player *plr, enum player_status pstatus)
Definition plrhand.c:3042
maybe_make_contact
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Definition plrhand.c:2191
send_player_info_c
void send_player_info_c(struct player *src, struct conn_list *dest)
Definition plrhand.c:1000
player_reply_dest
struct conn_list * player_reply_dest(struct player *pplayer)
Definition plrhand.c:1425
plrhand.h
phase_players_iterate
#define phase_players_iterate(pplayer)
Definition plrhand.h:111
phase_players_iterate_end
#define phase_players_iterate_end
Definition plrhand.h:116
rand.h
fc_rand
#define fc_rand(_size)
Definition rand.h:34
are_reqs_active
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)
Definition requirements.c:4361
research_advance_rule_name
const char * research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Definition research.c:238
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:126
research.h
sanitycheck.h
script_server_signal_emit
void script_server_signal_emit(const char *signal_name,...)
Definition script_server.c:408
script_server_remove_exported_object
void script_server_remove_exported_object(void *object)
Definition script_server.c:207
script_server.h
flush_packets
void flush_packets(void)
Definition sernet.c:379
sernet.h
format_time_duration
void format_time_duration(time_t t, char *buf, int maxlen)
Definition shared.c:1954
shared.h
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MIN
#define MIN(x, y)
Definition shared.h:55
MAX
#define MAX(x, y)
Definition shared.h:54
speclist.h
identity_number
int identity_number(void)
Definition srv_main.c:1952
srv_main.h
act_prob
Definition fc_types.h:1092
action
Definition actions.h:379
action::result
enum action_result result
Definition actions.h:382
action::sub_results
bv_action_sub_results sub_results
Definition actions.h:383
action::target_complexity
enum act_tgt_compl target_complexity
Definition actions.h:390
autoattack_prob
Definition unittools.c:113
autoattack_prob::unit_id
int unit_id
Definition unittools.c:114
autoattack_prob::prob
struct act_prob prob
Definition unittools.c:115
callback
Definition gui_main.c:2187
city
Definition city.h:309
city::id
int id
Definition city.h:315
city::owner
struct player * owner
Definition city.h:312
city::airlift
int airlift
Definition city.h:365
city::tile
struct tile * tile
Definition city.h:311
city::units_supported
struct unit_list * units_supported
Definition city.h:391
civ_game::unitwaittime
int unitwaittime
Definition game.h:197
civ_game::server
struct civ_game::@30::@34 server
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::autoupgrade_veteran_loss
int autoupgrade_veteran_loss
Definition game.h:131
civ_game::killunhomed
int killunhomed
Definition game.h:153
civ_game::savepalace
bool savepalace
Definition game.h:186
civ_game::ransom_gold
int ransom_gold
Definition game.h:174
civ_game::autoattack
bool autoattack
Definition game.h:130
civ_game::timeoutaddenemymove
int timeoutaddenemymove
Definition game.h:207
civ_map
Definition map_types.h:71
extra_type
Definition extras.h:85
packet_game_info::gameloss_style
enum gameloss_style gameloss_style
Definition packets_gen.h:232
packet_game_info::goods_selection
enum goods_selection_method goods_selection
Definition packets_gen.h:161
packet_game_info::happyborders
enum happyborders_type happyborders
Definition packets_gen.h:177
packet_game_info::nuke_pop_loss_pct
int nuke_pop_loss_pct
Definition packets_gen.h:197
packet_game_info::nuke_defender_survival_chance_pct
int nuke_defender_survival_chance_pct
Definition packets_gen.h:198
packet_game_info::only_real_fight_makes_veteran
bool only_real_fight_makes_veteran
Definition packets_gen.h:190
packet_game_info::airlifting_style
enum airlifting_style airlifting_style
Definition packets_gen.h:123
packet_game_info::only_killing_makes_veteran
bool only_killing_makes_veteran
Definition packets_gen.h:189
packet_game_info::turn
int turn
Definition packets_gen.h:241
packet_game_info::combat_odds_scaled_veterancy
bool combat_odds_scaled_veterancy
Definition packets_gen.h:191
packet_unit_info
Definition packets_gen.h:642
packet_unit_info::movesleft
int movesleft
Definition packets_gen.h:663
packet_unit_info::upkeep
int upkeep[O_LAST]
Definition packets_gen.h:651
packet_unit_info::carrying
int carrying
Definition packets_gen.h:662
packet_unit_info::action_decision_want
enum action_decision action_decision_want
Definition packets_gen.h:680
packet_unit_info::homecity32
int homecity32
Definition packets_gen.h:650
packet_unit_info::owner
int owner
Definition packets_gen.h:645
packet_unit_info::id16
int id16
Definition packets_gen.h:643
packet_unit_info::has_orders
bool has_orders
Definition packets_gen.h:674
packet_unit_info::orders
struct unit_order orders[MAX_LEN_ROUTE]
Definition packets_gen.h:679
packet_unit_info::fuel
int fuel
Definition packets_gen.h:665
packet_unit_info::activity
enum unit_activity activity
Definition packets_gen.h:669
packet_unit_info::activity_tgt
int activity_tgt
Definition packets_gen.h:670
packet_unit_info::nationality
int nationality
Definition packets_gen.h:646
packet_unit_info::transported
bool transported
Definition packets_gen.h:656
packet_unit_info::goto_tile
int goto_tile
Definition packets_gen.h:668
packet_unit_info::transported_by16
int transported_by16
Definition packets_gen.h:660
packet_unit_info::orders_index
int orders_index
Definition packets_gen.h:676
packet_unit_info::type
Unit_type_id type
Definition packets_gen.h:659
packet_unit_info::changed_from
enum unit_activity changed_from
Definition packets_gen.h:671
packet_unit_info::orders_length
int orders_length
Definition packets_gen.h:675
packet_unit_info::id32
int id32
Definition packets_gen.h:644
packet_unit_info::veteran
int veteran
Definition packets_gen.h:652
packet_unit_info::orders_repeat
bool orders_repeat
Definition packets_gen.h:677
packet_unit_info::activity_count
int activity_count
Definition packets_gen.h:666
packet_unit_info::occupied
bool occupied
Definition packets_gen.h:655
packet_unit_info::action_decision_tile
int action_decision_tile
Definition packets_gen.h:681
packet_unit_info::transported_by32
int transported_by32
Definition packets_gen.h:661
packet_unit_info::battlegroup
int battlegroup
Definition packets_gen.h:673
packet_unit_info::facing
enum direction8 facing
Definition packets_gen.h:648
packet_unit_info::orders_vigilant
bool orders_vigilant
Definition packets_gen.h:678
packet_unit_info::hp
int hp
Definition packets_gen.h:664
packet_unit_info::changed_from_count
int changed_from_count
Definition packets_gen.h:667
packet_unit_info::stay
bool stay
Definition packets_gen.h:658
packet_unit_info::tile
int tile
Definition packets_gen.h:647
packet_unit_info::homecity16
int homecity16
Definition packets_gen.h:649
packet_unit_info::ssa_controller
enum server_side_agent ssa_controller
Definition packets_gen.h:653
packet_unit_info::done_moving
bool done_moving
Definition packets_gen.h:657
packet_unit_info::paradropped
bool paradropped
Definition packets_gen.h:654
packet_unit_info::changed_from_tgt
int changed_from_tgt
Definition packets_gen.h:672
packet_unit_remove
Definition packets_gen.h:637
packet_unit_remove::unit_id16
int unit_id16
Definition packets_gen.h:638
packet_unit_remove::unit_id32
int unit_id32
Definition packets_gen.h:639
packet_unit_short_info
Definition packets_gen.h:684
packet_unit_short_info::id16
int id16
Definition packets_gen.h:685
packet_unit_short_info::activity
int activity
Definition packets_gen.h:695
packet_unit_short_info::packet_use
int packet_use
Definition packets_gen.h:699
packet_unit_short_info::tile
int tile
Definition packets_gen.h:688
packet_unit_short_info::transported
bool transported
Definition packets_gen.h:693
packet_unit_short_info::transported_by32
int transported_by32
Definition packets_gen.h:698
packet_unit_short_info::hp
int hp
Definition packets_gen.h:694
packet_unit_short_info::veteran
int veteran
Definition packets_gen.h:691
packet_unit_short_info::type
Unit_type_id type
Definition packets_gen.h:690
packet_unit_short_info::owner
int owner
Definition packets_gen.h:687
packet_unit_short_info::occupied
bool occupied
Definition packets_gen.h:692
packet_unit_short_info::info_city_id32
int info_city_id32
Definition packets_gen.h:701
packet_unit_short_info::info_city_id16
int info_city_id16
Definition packets_gen.h:700
packet_unit_short_info::facing
enum direction8 facing
Definition packets_gen.h:689
packet_unit_short_info::transported_by16
int transported_by16
Definition packets_gen.h:697
packet_unit_short_info::id32
int id32
Definition packets_gen.h:686
packet_unit_short_info::activity_tgt
int activity_tgt
Definition packets_gen.h:696
pf_map
Definition path_finding.c:78
pf_parameter
Definition path_finding.h:357
pf_parameter::omniscience
bool omniscience
Definition path_finding.h:376
pf_path
Definition path_finding.h:344
player_diplstate::type
enum diplstate_type type
Definition player.h:201
player_economic::gold
int gold
Definition player.h:70
player_score::units_killed
int units_killed
Definition player.h:112
player_score::units_lost
int units_lost
Definition player.h:113
player_tile
Definition maphand.h:30
player_tile::extras
bv_extras extras
Definition maphand.h:36
player_tile::site
struct vision_site * site
Definition maphand.h:31
player_tile::terrain
struct terrain * terrain
Definition maphand.h:33
player_tile::owner
struct player * owner
Definition maphand.h:34
player
Definition player.h:249
player::cities
struct city_list * cities
Definition player.h:281
player::units
struct unit_list * units
Definition player.h:282
player::connections
struct conn_list * connections
Definition player.h:298
player::huts
int huts
Definition player.h:349
player::is_alive
bool is_alive
Definition player.h:268
player::economic
struct player_economic economic
Definition player.h:284
player::score
struct player_score score
Definition player.h:283
player::server
struct player::@69::@71 server
req_context
Definition requirements.h:99
req_context::player
const struct player * player
Definition requirements.h:100
terrain
Definition terrain.h:176
tile
Definition tile.h:49
tile::index
int index
Definition tile.h:50
tile::units
struct unit_list * units
Definition tile.h:57
unit_class
Definition unittype.h:136
unit_class::cache
struct unit_class::@85 cache
unit_class::refuel_extras
struct extra_type_list * refuel_extras
Definition unittype.h:155
unit_move_data
Definition unittools.c:91
unit_move_data::can_see_unit
bv_player can_see_unit
Definition unittools.c:95
unit_move_data::ref_count
int ref_count
Definition unittools.c:92
unit_move_data::powner
struct player * powner
Definition unittools.c:94
unit_move_data::can_see_move
bv_player can_see_move
Definition unittools.c:96
unit_move_data::punit
struct unit * punit
Definition unittools.c:93
unit_move_data::old_vision
struct vision * old_vision
Definition unittools.c:97
unit_order
Definition unit.h:92
unit_order::activity
enum unit_activity activity
Definition unit.h:94
unit_order::order
enum unit_orders order
Definition unit.h:93
unit_order::action
int action
Definition unit.h:100
unit_order::dir
enum direction8 dir
Definition unit.h:102
unit_order::target
int target
Definition unit.h:97
unit_order::sub_target
int sub_target
Definition unit.h:98
unit_type
Definition unittype.h:481
unit_type::vision_radius_sq
int vision_radius_sq
Definition unittype.h:503
unit_type::vlayer
enum vision_layer vlayer
Definition unittype.h:550
unit_type::hp
int hp
Definition unittype.h:505
unit_type::converted_to
const struct unit_type * converted_to
Definition unittype.h:511
unit
Definition unit.h:138
unit::action_timestamp
time_t action_timestamp
Definition unit.h:243
unit::length
int length
Definition unit.h:195
unit::upkeep
int upkeep[O_LAST]
Definition unit.h:148
unit::has_orders
bool has_orders
Definition unit.h:193
unit::action_decision_want
enum action_decision action_decision_want
Definition unit.h:202
unit::battlegroup
int battlegroup
Definition unit.h:191
unit::activity
enum unit_activity activity
Definition unit.h:157
unit::moves_left
int moves_left
Definition unit.h:150
unit::id
int id
Definition unit.h:145
unit::moved
bool moved
Definition unit.h:173
unit::index
int index
Definition unit.h:195
unit::vision
struct vision * vision
Definition unit.h:242
unit::vigilant
bool vigilant
Definition unit.h:197
unit::hp
int hp
Definition unit.h:151
unit::orders
struct unit::@79 orders
unit::fuel
int fuel
Definition unit.h:153
unit::changed_from_target
struct extra_type * changed_from_target
Definition unit.h:170
unit::stay
bool stay
Definition unit.h:205
unit::facing
enum direction8 facing
Definition unit.h:142
unit::tile
struct tile * tile
Definition unit.h:140
unit::activity_target
struct extra_type * activity_target
Definition unit.h:164
unit::activity_count
int activity_count
Definition unit.h:162
unit::list
struct unit_order * list
Definition unit.h:198
unit::changed_from
enum unit_activity changed_from
Definition unit.h:168
unit::nationality
struct player * nationality
Definition unit.h:144
unit::repeat
bool repeat
Definition unit.h:196
unit::removal_callback
void(* removal_callback)(struct unit *punit)
Definition unit.h:251
unit::moving
struct unit_move_data * moving
Definition unit.h:245
unit::action_turn
int action_turn
Definition unit.h:244
unit::server
struct unit::@80::@83 server
unit::homecity
int homecity
Definition unit.h:146
unit::paradropped
bool paradropped
Definition unit.h:174
unit::done_moving
bool done_moving
Definition unit.h:181
unit::birth_turn
int birth_turn
Definition unit.h:235
unit::carrying
struct goods_type * carrying
Definition unit.h:186
unit::goto_tile
struct tile * goto_tile
Definition unit.h:155
unit::action_decision_tile
struct tile * action_decision_tile
Definition unit.h:203
unit::utype
const struct unit_type * utype
Definition unit.h:139
unit::veteran
int veteran
Definition unit.h:152
unit::changed_from_count
int changed_from_count
Definition unit.h:169
unit::dying
bool dying
Definition unit.h:248
unit::ssa_controller
enum server_side_agent ssa_controller
Definition unit.h:172
veteran_level
Definition unittype.h:467
veteran_level::base_raise_chance
int base_raise_chance
Definition unittype.h:471
veteran_level::name
struct name_translation name
Definition unittype.h:468
veteran_level::work_raise_chance
int work_raise_chance
Definition unittype.h:472
veteran_system
Definition unittype.h:475
veteran_system::levels
int levels
Definition unittype.h:476
vision_site
Definition vision.h:109
vision_site::occupied
bool occupied
Definition vision.h:117
vision
Definition vision.h:85
world::map
struct civ_map map
Definition world_object.h:38
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:161
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
fc__fallthrough
#define fc__fallthrough
Definition support.h:109
A_NONE
#define A_NONE
Definition tech.h:43
A_UNSET
#define A_UNSET
Definition tech.h:48
steal_a_tech
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
Definition techtools.c:1207
techtools.h
terrain_name_translation
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:226
get_preferred_pillage
struct extra_type * get_preferred_pillage(bv_extras extras)
Definition terrain.c:538
terrain.h
tile_add_extra
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Definition tile.c:940
tile_has_not_aggressive_extra_for_unit
bool tile_has_not_aggressive_extra_for_unit(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:193
tile_has_claimable_base
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:209
tile_apply_activity
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Definition tile.c:658
tile_extras_defense_bonus
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Definition tile.c:227
tile_activity_time
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Definition tile.c:412
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_index
#define tile_index(_pt_)
Definition tile.h:87
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:109
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:42
tile_extras
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:119
tile_continent
#define tile_continent(_tile)
Definition tile.h:91
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
tile_owner
#define tile_owner(_tile)
Definition tile.h:95
goods_from_city_to_unit
struct goods_type * goods_from_city_to_unit(struct city *src, struct unit *punit)
Definition traderoutes.c:720
goods_index
Goods_type_id goods_index(const struct goods_type *pgood)
Definition traderoutes.c:592
tile_non_allied_unit
struct unit * tile_non_allied_unit(const struct tile *ptile, const struct player *pplayer)
Definition unit.c:1333
get_transporter_occupancy
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1769
free_unit_orders
void free_unit_orders(struct unit *punit)
Definition unit.c:1755
unit_is_alive
bool unit_is_alive(int id)
Definition unit.c:2239
get_activity_rate_this_turn
int get_activity_rate_this_turn(const struct unit *punit)
Definition unit.c:505
unit_transport_load
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Definition unit.c:2356
set_unit_activity
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Definition unit.c:1108
unit_nationality
struct player * unit_nationality(const struct unit *punit)
Definition unit.c:1272
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2427
unit_transport_unload
bool unit_transport_unload(struct unit *pcargo)
Definition unit.c:2376
unit_gain_hitpoints
int unit_gain_hitpoints(const struct unit *punit)
Definition unit.c:2169
can_unit_continue_current_activity
bool can_unit_continue_current_activity(const struct civ_map *nmap, struct unit *punit)
Definition unit.c:846
unit_virtual_create
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Definition unit.c:1619
can_unit_do_activity
bool can_unit_do_activity(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity)
Definition unit.c:873
unit_virtual_destroy
void unit_virtual_destroy(struct unit *punit)
Definition unit.c:1715
unit_tile_set
void unit_tile_set(struct unit *punit, struct tile *ptile)
Definition unit.c:1282
unit_upgrade_test
enum unit_upgrade_result unit_upgrade_test(const struct civ_map *nmap, const struct unit *punit, bool is_free)
Definition unit.c:1974
unit_transported
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2411
can_unit_unload
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:771
unit_transport_cargo
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Definition unit.c:2437
unit_has_orders
bool unit_has_orders(const struct unit *punit)
Definition unit.c:207
transporter_for_unit
struct unit * transporter_for_unit(const struct unit *pcargo)
Definition unit.c:1898
unit_can_convert
bool unit_can_convert(const struct civ_map *nmap, const struct unit *punit)
Definition unit.c:2021
activity_requires_target
bool activity_requires_target(enum unit_activity activity)
Definition unit.c:541
can_unit_do_activity_targeted
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:912
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
is_enemy_unit_tile
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:411
unit_cargo_iterate_end
#define unit_cargo_iterate_end
Definition unit.h:562
ORDER_ACTION_MOVE
@ ORDER_ACTION_MOVE
Definition unit.h:45
ORDER_ACTIVITY
@ ORDER_ACTIVITY
Definition unit.h:41
ORDER_FULL_MP
@ ORDER_FULL_MP
Definition unit.h:43
ORDER_MOVE
@ ORDER_MOVE
Definition unit.h:39
ORDER_LAST
@ ORDER_LAST
Definition unit.h:49
ORDER_PERFORM_ACTION
@ ORDER_PERFORM_ACTION
Definition unit.h:47
is_allied_unit_tile
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:399
unit_cargo_iterate
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition unit.h:559
CHECK_UNIT
#define CHECK_UNIT(punit)
Definition unit.h:268
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
UU_OK
@ UU_OK
Definition unit.h:61
unit_home
#define unit_home(_pu_)
Definition unit.h:386
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:423
illegal_action_msg
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:2352
unit_activity_handling
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6176
unit_perform_action
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:3173
unit_move_handling
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool move_do_not_act)
Definition unithand.c:5237
unithand.h
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_safe
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_list_iterate_safe_end
#define unit_list_iterate_safe_end
Definition unitlist.h:61
unit_did_action
void unit_did_action(struct unit *punit)
Definition unittools.c:4913
autoattack_prob_free
static void autoattack_prob_free(struct autoattack_prob *prob)
Definition unittools.c:3348
do_airline
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Definition unittools.c:2967
place_partisans
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Definition unittools.c:1181
try_to_save_unit
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:2263
unit_move_by_data
static void unit_move_by_data(struct unit_move_data *pdata, struct tile *psrctile, struct tile *pdesttile)
Definition unittools.c:3805
execute_orders
bool execute_orders(struct unit *punit, const bool fresh)
Definition unittools.c:4372
unit_convert
static void unit_convert(struct unit *punit)
Definition unittools.c:766
update_unit_activities
void update_unit_activities(struct player *pplayer)
Definition unittools.c:658
throw_units_from_illegal_cities
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Definition unittools.c:1324
unit_move_data_list_iterate_rev_end
#define unit_move_data_list_iterate_rev_end
Definition unittools.c:107
transform_unit
void transform_unit(struct unit *punit, const struct unit_type *to_unit, int vet_loss)
Definition unittools.c:1569
server_remove_unit_full
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
Definition unittools.c:1808
get_units_seen_via_ally
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Definition unittools.c:1433
is_refuel_tile
static bool is_refuel_tile(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1505
unit_lost_with_transport
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Definition unittools.c:1938
remove_allied_visibility
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
Definition unittools.c:1468
maybe_cancel_goto_due_to_enemy
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Definition unittools.c:4303
combat_veterans
void combat_veterans(struct unit *attacker, struct unit *defender, bool powerless, int att_vet, int def_vet)
Definition unittools.c:392
unit_vision_range_modifiers
static int unit_vision_range_modifiers(struct unit *punit, const struct tile *ptile)
Definition unittools.c:4821
resolve_unit_stacks
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1418
unit_move_data_unref
static void unit_move_data_unref(struct unit_move_data *pdata)
Definition unittools.c:3855
unit_set_removal_callback
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Definition unittools.c:1785
unit_bombs_unit
void unit_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp)
Definition unittools.c:352
unit_enter_hut
static void unit_enter_hut(struct unit *punit, bool frighten_hut)
Definition unittools.c:3225
package_unit
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Definition unittools.c:2654
unit_move_data_list_iterate_end
#define unit_move_data_list_iterate_end
Definition unittools.c:104
unit_goes_out_of_sight
void unit_goes_out_of_sight(struct player *pplayer, struct unit *punit)
Definition unittools.c:2785
unit_restore_movepoints
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Definition unittools.c:649
wakeup_neighbor_sentries
static void wakeup_neighbor_sentries(struct unit *punit)
Definition unittools.c:3547
total_activity
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:706
unit_activities_cancel_all_illegal_plr
void unit_activities_cancel_all_illegal_plr(const struct player *pplayer)
Definition unittools.c:810
unit_transport_load_tp_status
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Definition unittools.c:3306
autoattack_prob_list_iterate_safe_end
#define autoattack_prob_list_iterate_safe_end
Definition unittools.c:131
unit_survive_autoattack
static bool unit_survive_autoattack(struct unit *punit)
Definition unittools.c:3404
finalize_unit_phase_beginning
void finalize_unit_phase_beginning(struct player *pplayer)
Definition unittools.c:690
execute_unit_orders
void execute_unit_orders(struct player *pplayer)
Definition unittools.c:668
find_a_good_partisan_spot
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:1133
send_unit_info
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2798
wipe_unit_full
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:1962
resolve_stack_conflicts
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
Definition unittools.c:1389
check_unit_activity
static void check_unit_activity(struct unit *punit)
Definition unittools.c:3734
unit_restore_hitpoints
static void unit_restore_hitpoints(struct unit *punit)
Definition unittools.c:622
do_upgrade_effects
static void do_upgrade_effects(struct player *pplayer)
Definition unittools.c:416
get_unit_vision_at
int get_unit_vision_at(struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Definition unittools.c:4839
unit_versus_unit
bool unit_versus_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp, int *att_vet, int *def_vet)
Definition unittools.c:286
place_unit
bool place_unit(struct unit *punit, struct player *pplayer, struct city *pcity, struct unit *ptrans, bool force)
Definition unittools.c:1727
notify_unit_experience
void notify_unit_experience(struct unit *punit)
Definition unittools.c:735
unit_activities_cancel
void unit_activities_cancel(struct unit *punit)
Definition unittools.c:792
package_short_unit
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:2737
unit_virtual_prepare
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:1679
give_allied_visibility
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Definition unittools.c:1492
unit_forget_last_activity
void unit_forget_last_activity(struct unit *punit)
Definition unittools.c:1073
unit_move_data_list_iterate
#define unit_move_data_list_iterate(_plist, _pdata)
Definition unittools.c:102
create_unit_full
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:1646
server_remove_unit
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
Definition unittools.c:1929
unit_unset_removal_callback
void unit_unset_removal_callback(struct unit *punit)
Definition unittools.c:1799
maybe_make_veteran
bool maybe_make_veteran(struct unit *punit, int base_chance)
Definition unittools.c:217
unit_refresh_vision
void unit_refresh_vision(struct unit *punit)
Definition unittools.c:4852
create_unit
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:1619
do_explore
void do_explore(struct unit *punit)
Definition unittools.c:3000
unit_transport_load_send
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Definition unittools.c:3276
unit_can_do_action_now
bool unit_can_do_action_now(const struct unit *punit)
Definition unittools.c:4880
autoattack_prob_list_iterate_safe
#define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, _unit_)
Definition unittools.c:122
wipe_unit
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2251
unit_tc_effect_refresh
void unit_tc_effect_refresh(struct player *pplayer)
Definition unittools.c:680
do_paradrop
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Definition unittools.c:3036
player_is_watching
static bool player_is_watching(struct unit *punit, const bool fresh)
Definition unittools.c:4345
player_restore_units
void player_restore_units(struct player *pplayer)
Definition unittools.c:469
do_nuclear_explosion
void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
Definition unittools.c:2950
do_nuke_tile
static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
Definition unittools.c:2870
is_refuel_point
bool is_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Definition unittools.c:1547
update_unit_activity
static void update_unit_activity(struct unit *punit)
Definition unittools.c:852
unit_move_data_list_iterate_rev
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition unittools.c:105
unit_transport_unload_send
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3328
is_unit_being_refueled
bool is_unit_being_refueled(const struct unit *punit)
Definition unittools.c:1538
find_a_unit_type
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Definition unittools.c:174
cancel_orders
static void cancel_orders(struct unit *punit, char *dbg_msg)
Definition unittools.c:3536
unit_can_be_retired
bool unit_can_be_retired(struct unit *punit)
Definition unittools.c:4928
total_activity_done
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Definition unittools.c:726
unit_activities_cancel_all_illegal_tile
void unit_activities_cancel_all_illegal_tile(const struct tile *ptile)
Definition unittools.c:822
unit_change_owner
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
Definition unittools.c:2311
teleport_unit_to_city
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Definition unittools.c:1207
get_unit_vision_base
static int get_unit_vision_base(struct unit *punit, enum vision_layer vlayer, const int base)
Definition unittools.c:4800
hut_get_limited
static bool hut_get_limited(struct unit *punit)
Definition unittools.c:3194
unit_assign_specific_activity_target
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
Definition unittools.c:1102
compare_units
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
Definition unittools.c:3362
unit_activities_cancel_all_illegal_area
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Definition unittools.c:837
unit_move_consequences
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:3617
unit_get_goods
void unit_get_goods(struct unit *punit)
Definition unittools.c:1630
send_all_known_units
void send_all_known_units(struct conn_list *dest)
Definition unittools.c:2842
maybe_become_veteran_real
static bool maybe_become_veteran_real(struct unit *punit, int base_chance, bool settler)
Definition unittools.c:235
maybe_cancel_patrol_due_to_enemy
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Definition unittools.c:4316
unit_move
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:3884
unit_list_refresh_vision
void unit_list_refresh_vision(struct unit_list *punitlist)
Definition unittools.c:4869
kill_unit
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Definition unittools.c:2377
bounce_unit
void bounce_unit(struct unit *punit, bool verbose)
Definition unittools.c:1245
unit_activity_needs_target_from_client
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Definition unittools.c:1082
unittools.h
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
unit_name_translation
const char * unit_name_translation(const struct unit *punit)
Definition unittype.c:1621
get_role_unit
struct unit_type * get_role_unit(int role, int role_index)
Definition unittype.c:2301
unit_rule_name
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1639
utype_veteran_system
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Definition unittype.c:2615
num_role_units
int num_role_units(int role)
Definition unittype.c:2251
utype_player_already_has_this_unique
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Definition unittype.c:1979
can_upgrade_unittype
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Definition unittype.c:1755
can_player_build_unit_direct
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype)
Definition unittype.c:2015
unit_class_get
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2546
unit_has_type_role
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:202
utype_veteran_level
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2631
unit_has_type_flag
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
utype_number
Unit_type_id utype_number(const struct unit_type *punittype)
Definition unittype.c:100
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
unittype.h
uclass_has_flag
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:753
utype_class
#define utype_class(_t_)
Definition unittype.h:736
utype_fuel
#define utype_fuel(ptype)
Definition unittype.h:822
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604
U_LAST
#define U_LAST
Definition unittype.h:40
vision_new
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Definition vision.c:33
vision_free
void vision_free(struct vision *vision)
Definition vision.c:50
ASSERT_VISION
#define ASSERT_VISION(v)
Definition vision.h:98
V_RADIUS
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition vision.h:96
vision_site_owner
#define vision_site_owner(v)
Definition vision.h:128
v_radius_t
short int v_radius_t[V_COUNT]
Definition vision.h:83