Freeciv-3.2: /fast/freeciv/nightly/S3_2/server/unittools.c Source File

Freeciv-3.2

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