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

Freeciv-3.1

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