Freeciv21
Develop your civilization from humble roots to a global empire
unittools.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <QDateTime>
15 
16 #include <cstdlib>
17 #include <cstring>
18 
19 // utility
20 #include "bitvector.h"
21 #include "effects.h"
22 #include "extras.h"
23 #include "fcintl.h"
24 #include "hand_gen.h"
25 #include "log.h"
26 #include "path_finder.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 "unit_utils.h"
47 #include "unitlist.h"
48 #include "unittype.h"
49 
50 // aicore
51 #include "path_finding.h"
52 #include "pf_tools.h"
53 
54 /* server/scripting */
55 #include "script_server.h"
56 
57 // server
58 #include "actiontools.h"
59 #include "aiiface.h"
60 #include "citytools.h"
61 #include "cityturn.h"
62 #include "gamehand.h"
63 #include "maphand.h"
64 #include "notify.h"
65 #include "plrhand.h"
66 #include "sernet.h"
67 #include "srv_main.h"
68 #include "techtools.h"
69 #include "unithand.h"
70 
71 /* server/advisors */
72 #include "advgoto.h"
73 #include "autoexplorer.h"
74 #include "autosettlers.h"
75 
76 // ai
77 #include "handicaps.h"
78 
79 #include "unittools.h"
80 
81 /* Tools for controlling the client vision of every unit when a unit
82  * moves + script effects. See unit_move(). You can access this data with
83  * punit->server.moving; it may be nullptr if the unit is not moving). */
85  int ref_count;
86  struct unit *punit; // nullptr for invalidating.
87  struct player *powner;
88  bv_player can_see_unit;
89  bv_player can_see_move;
90  struct vision *old_vision;
91 };
92 
93 #define SPECLIST_TAG unit_move_data
94 #include "speclist.h"
95 #define unit_move_data_list_iterate(_plist, _pdata) \
96  TYPED_LIST_ITERATE(struct unit_move_data, _plist, _pdata)
97 #define unit_move_data_list_iterate_end LIST_ITERATE_END
98 #define unit_move_data_list_iterate_rev(_plist, _pdata) \
99  TYPED_LIST_ITERATE_REV(struct unit_move_data, _plist, _pdata)
100 #define unit_move_data_list_iterate_rev_end LIST_ITERATE_REV_END
101 
102 /* This data structure lets the auto attack code cache each potential
103  * attacker unit's probability of success against the target unit during
104  * the checks if the unit can do autoattack. It is then reused when the
105  * list of potential attackers is sorted by probability of success. */
107  int unit_id;
108  struct act_prob prob;
109 };
110 
111 #define SPECLIST_TAG autoattack_prob
112 #define SPECLIST_TYPE struct autoattack_prob
113 #include "speclist.h"
114 
115 #define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, \
116  _unit_) \
117  TYPED_LIST_ITERATE(struct autoattack_prob, autoattack_prob_list, _aap_) \
118  struct unit *_unit_ = game_unit_by_number(_aap_->unit_id); \
119  \
120  if (_unit_ == nullptr) { \
121  continue; \
122  }
123 
124 #define autoattack_prob_list_iterate_safe_end LIST_ITERATE_END
125 
126 static void unit_restore_movepoints(struct player *pplayer,
127  struct unit *punit);
128 static void update_unit_activity(struct unit *punit, time_t now);
129 static bool try_to_save_unit(struct unit *punit,
130  const struct unit_type *pttype, bool helpless,
131  bool teleporting, const struct city *pexclcity);
132 static void wakeup_neighbor_sentries(struct unit *punit);
133 static void do_upgrade_effects(struct player *pplayer);
134 
135 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit);
136 static bool maybe_become_veteran_real(struct unit *punit, bool settler);
137 
138 static void unit_transport_load_tp_status(struct unit *punit,
139  struct unit *ptrans, bool force);
140 
141 static void wipe_unit_full(struct unit *punit, bool transported,
142  enum unit_loss_reason reason,
143  struct player *killer);
144 
159 struct unit_type *find_a_unit_type(enum unit_role_id role,
160  enum unit_role_id role_tech)
161 {
162  struct unit_type *which[U_LAST];
163  int i, num = 0;
164 
165  if (role_tech != -1) {
166  for (i = 0; i < num_role_units(role_tech); i++) {
167  struct unit_type *iunit = get_role_unit(role_tech, i);
168  const int minplayers = 2;
169  int players = 0;
170 
171  /* Note, if there's only one player in the game this check will always
172  * fail. */
173  players_iterate(pplayer)
174  {
175  if (!is_barbarian(pplayer)
176  && can_player_build_unit_direct(pplayer, iunit)) {
177  players++;
178  }
179  }
181  if (players > minplayers) {
182  which[num++] = iunit;
183  }
184  }
185  }
186  if (num == 0) {
187  for (i = 0; i < num_role_units(role); i++) {
188  which[num++] = get_role_unit(role, i);
189  }
190  }
191 
192  /* Ruleset code should ensure there is at least one unit for each
193  * possibly-required role, or check before calling this function. */
194  fc_assert_exit_msg(0 < num, "No unit types in find_a_unit_type(%d, %d)!",
195  role, role_tech);
196 
197  return which[fc_rand(num)];
198 }
199 
204 bool maybe_make_veteran(struct unit *punit)
205 {
206  return maybe_become_veteran_real(punit, false);
207 }
208 
220 static bool maybe_become_veteran_real(struct unit *punit, bool settler)
221 {
222  const struct veteran_system *vsystem;
223  const struct veteran_level *vlevel;
224  int chance;
225 
226  fc_assert_ret_val(punit != nullptr, false);
227 
228  vsystem = utype_veteran_system(unit_type_get(punit));
229  fc_assert_ret_val(vsystem != nullptr, false);
230  fc_assert_ret_val(vsystem->levels > punit->veteran, false);
231 
232  vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
233  fc_assert_ret_val(vlevel != nullptr, false);
234 
235  if (punit->veteran + 1 >= vsystem->levels
236  || unit_has_type_flag(punit, UTYF_NO_VETERAN)) {
237  return false;
238  } else if (!settler) {
239  int mod = 100 + get_unit_bonus(punit, EFT_VETERAN_COMBAT);
240 
241  /* The modification is tacked on as a multiplier to the base chance.
242  * For example with a base chance of 50% for green units and a modifier
243  * of +50% the end chance is 75%. */
244  chance = vlevel->base_raise_chance * mod / 100;
245  } else if (settler && unit_has_type_flag(punit, UTYF_SETTLERS)) {
246  chance = vlevel->work_raise_chance;
247  } else {
248  // No battle and no work done.
249  return false;
250  }
251 
252  if (fc_rand(100) < chance) {
253  punit->veteran++;
254  return true;
255  }
256 
257  return false;
258 }
259 
268 void unit_versus_unit(struct unit *attacker, struct unit *defender,
269  int *att_hp, int *def_hp)
270 {
271  int attackpower = get_total_attack_power(attacker, defender);
272  int defensepower = get_total_defense_power(attacker, defender);
273  int attack_firepower, defense_firepower;
274  struct player *plr1 = unit_owner(attacker);
275  struct player *plr2 = unit_owner(defender);
276  int max_rounds;
277  int rounds;
278 
279  *att_hp = attacker->hp;
280  *def_hp = defender->hp;
281  get_modified_firepower(attacker, defender, &attack_firepower,
282  &defense_firepower);
283 
284  qDebug("attack:%d, defense:%d, attack firepower:%d, "
285  "defense firepower:%d",
286  attackpower, defensepower, attack_firepower, defense_firepower);
287 
290 
291  max_rounds = get_unit_bonus(attacker, EFT_COMBAT_ROUNDS);
292  if (max_rounds <= 0) {
293  if (attackpower == 0 || attack_firepower == 0) {
294  *att_hp = 0;
295  } else if (defensepower == 0 || defense_firepower == 0) {
296  *def_hp = 0;
297  }
298  }
299  for (rounds = 0; *att_hp > 0 && *def_hp > 0
300  && (max_rounds <= 0 || max_rounds > rounds);
301  rounds++) {
302  if (fc_rand(attackpower + defensepower) >= defensepower) {
303  *def_hp -= attack_firepower;
304  } else {
305  *att_hp -= defense_firepower;
306  }
307  }
308  if (*att_hp < 0) {
309  *att_hp = 0;
310  }
311  if (*def_hp < 0) {
312  *def_hp = 0;
313  }
314 }
315 
321 void unit_bombs_unit(struct unit *attacker, struct unit *defender,
322  int *att_hp, int *def_hp)
323 {
324  int i;
325  int old_def_hp, bomb_limit_hp, bomb_limit_pct;
326  int rate = unit_type_get(attacker)->bombard_rate;
327 
328  int attackpower = get_total_attack_power(attacker, defender);
329  int defensepower = get_total_defense_power(attacker, defender);
330  int attack_firepower, defense_firepower;
331  struct player *plr1 = unit_owner(attacker);
332  struct player *plr2 = unit_owner(defender);
333 
334  *att_hp = attacker->hp;
335  old_def_hp = *def_hp = defender->hp;
336  // don't reduce below maxHP * Bombard_Limit_Pct%, rounded up
337  bomb_limit_pct = get_unit_bonus(defender, EFT_BOMBARD_LIMIT_PCT);
338  if (bomb_limit_pct > 0)
339  bomb_limit_hp =
340  (unit_type_get(defender)->hp - 1) * bomb_limit_pct / 100 + 1;
341  else
342  bomb_limit_hp = 0;
343  // if unit was already below limit, don't heal it back up to the limit
344  bomb_limit_hp = MIN(bomb_limit_hp, old_def_hp);
345  get_modified_firepower(attacker, defender, &attack_firepower,
346  &defense_firepower);
347 
348  qDebug("attack:%d, defense:%d, attack firepower:%d, "
349  "defense firepower:%d, bomb limit:%d",
350  attackpower, defensepower, attack_firepower, defense_firepower,
351  bomb_limit_hp);
352 
355 
356  for (i = 0; i < rate; i++) {
357  if (fc_rand(attackpower + defensepower) >= defensepower) {
358  *def_hp -= attack_firepower;
359  }
360  }
361 
362  // Don't kill the target.
363  if (*def_hp < bomb_limit_hp) {
364  *def_hp = bomb_limit_hp;
365  }
366 }
367 
371 void combat_veterans(struct unit *attacker, struct unit *defender)
372 {
373  if (attacker->hp <= 0 || defender->hp <= 0
374  || !game.info.only_killing_makes_veteran) {
375  if (attacker->hp > 0) {
376  maybe_make_veteran(attacker);
377  }
378  if (defender->hp > 0) {
379  maybe_make_veteran(defender);
380  }
381  }
382 }
383 
388 static void do_upgrade_effects(struct player *pplayer)
389 {
390  int upgrades = get_player_bonus(pplayer, EFT_UPGRADE_UNIT);
391  struct unit_list *candidates;
392 
393  if (upgrades <= 0) {
394  return;
395  }
396  candidates = unit_list_new();
397 
398  unit_list_iterate(pplayer->units, punit)
399  {
400  /* We have to be careful not to strand units at sea, for example by
401  * upgrading a frigate to an ironclad while it was carrying a unit. */
402  if (UU_OK == unit_upgrade_test(punit, true)) {
403  unit_list_prepend(candidates, punit); // Potential candidate :)
404  }
405  }
407 
408  while (upgrades > 0 && unit_list_size(candidates) > 0) {
409  /* Upgrade one unit. The unit is chosen at random from the list of
410  * available candidates. */
411  int candidate_to_upgrade = fc_rand(unit_list_size(candidates));
412  struct unit *punit = unit_list_get(candidates, candidate_to_upgrade);
413  const struct unit_type *type_from = unit_type_get(punit);
414  const struct unit_type *type_to =
415  can_upgrade_unittype(pplayer, type_from);
416 
417  if (type_to == nullptr) {
418  /* This is unlikely but it can happen with unique units. If the target
419  * unit type is a unique unit and some other unit has been upgraded
420  * first, punit can no longer be upgraded and can_upgrade_unittype
421  * returns nullptr. Thus punit is no longer a good candidate and we
422  * just remove it from the list. */
423  unit_list_remove(candidates, punit);
424  continue;
425  }
426 
427  transform_unit(punit, type_to, true);
428  notify_player(pplayer, unit_tile(punit), E_UNIT_UPGRADED, ftc_server,
429  _("%s was upgraded for free to %s."),
430  utype_name_translation(type_from), unit_link(punit));
431  unit_list_remove(candidates, punit);
432  upgrades--;
433  }
434 
435  unit_list_destroy(candidates);
436 }
437 
442 static bool converting_fuel_rescue(struct unit *punit)
443 {
444  const struct unit_type *from_type, *to_type;
445 
446  if (punit->activity != ACTIVITY_CONVERT)
447  /* not converting */
448  return false;
449  if (punit->activity_count + get_activity_rate_this_turn(punit)
450  < action_id_get_act_time(ACTION_CONVERT, punit, unit_tile(punit),
451  punit->activity_target))
452  /* won't be finished in time */
453  return false;
454  if (!unit_can_convert(punit))
455  /* can't actually convert */
456  return false;
457  from_type = unit_type_get(punit);
458  to_type = from_type->converted_to;
459  if (utype_fuel(to_type) && utype_fuel(to_type) <= utype_fuel(from_type))
460  /* to_type doesn't have more fuel, so conversion doesn't help */
461  return false;
462  /* we're saved! */
463  return true;
464 }
465 
481 void player_restore_units(struct player *pplayer)
482 {
483  // 1) get Leonardo out of the way first:
484  do_upgrade_effects(pplayer);
485 
486  unit_list_iterate_safe(pplayer->units, punit)
487  {
488  // 2) Modify unit hitpoints. Helicopters can even lose them.
489  unit_restore_hitpoints(punit);
490 
491  // 3) Check that unit has hitpoints
492  if (punit->hp <= 0) {
493  /* This should usually only happen for heli units, but if any other
494  * units get 0 hp somehow, catch them too. --dwp */
495  /* if 'game.server.killunhomed' is activated unhomed units are slowly
496  * killed; notify player here */
497  if (!punit->homecity && 0 < game.info.killunhomed) {
498  notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
499  ftc_server,
500  _("Your %s has run out of hit points "
501  "because it was not supported by a city."),
502  unit_tile_link(punit));
503  } else {
504  notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC,
505  ftc_server, _("Your %s has run out of hit points."),
506  unit_tile_link(punit));
507  }
508 
509  wipe_unit(punit, ULR_HP_LOSS, nullptr);
510  continue; // Continue iterating...
511  }
512 
513  // 4) Rescue planes if needed
514  if (utype_fuel(unit_type_get(punit))) {
515  // Shall we emergency return home on the last vapors?
516 
517  /* I think this is strongly against the spirit of client goto.
518  * The problem is (again) that here we know too much. -- Zamar */
519 
520  if (punit->fuel <= 1 && !is_unit_being_refueled(punit)
521  && !converting_fuel_rescue(punit)) {
522  struct unit *carrier;
523 
524  carrier = transporter_for_unit(punit);
525  if (carrier) {
526  unit_transport_load_tp_status(punit, carrier, false);
527  } else {
528  bool alive = true;
529 
530  struct pf_map *pfm;
531  struct pf_parameter parameter;
532 
533  pft_fill_unit_parameter(&parameter, punit);
534  parameter.omniscience = !has_handicap(pplayer, H_MAP);
535  pfm = pf_map_new(&parameter);
536 
537  pf_map_move_costs_iterate(pfm, ptile, move_cost, true)
538  {
539  if (move_cost > punit->moves_left) {
540  // Too far
541  break;
542  }
543 
544  if (is_airunit_refuel_point(ptile, pplayer, punit)) {
545  PFPath path;
546  int id = punit->id;
547 
548  /* Client orders may be running for this unit - if so
549  * we free them before engaging goto. */
550  free_unit_orders(punit);
551 
552  path = pf_map_path(pfm, ptile);
553 
554  alive = adv_follow_path(punit, path, ptile);
555 
556  if (!alive) {
557  qCritical("rescue plane: unit %d died enroute!", id);
558  } else if (!same_pos(unit_tile(punit), ptile)) {
559  /* Enemy units probably blocked our route
560  * FIXME: We should try find alternative route around
561  * the enemy unit instead of just giving up and crashing. */
562  log_debug("rescue plane: unit %d could not move to "
563  "refuel point!",
564  punit->id);
565  }
566 
567  if (alive) {
568  /* Clear activity. Unit info will be sent in the end of
569  * the function. */
570  unit_activity_handling(punit, ACTIVITY_IDLE);
571  adv_unit_new_task(punit, AUT_NONE, nullptr);
572  punit->goto_tile = nullptr;
573 
574  if (!is_unit_being_refueled(punit)) {
575  carrier = transporter_for_unit(punit);
576  if (carrier) {
577  unit_transport_load_tp_status(punit, carrier, false);
578  }
579  }
580 
582  pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
583  _("Your %s has returned to refuel."), unit_link(punit));
584  }
585  break;
586  }
587  }
589  pf_map_destroy(pfm);
590 
591  if (!alive) {
592  // Unit died trying to move to refuel point.
593  return;
594  }
595  }
596  }
597 
598  // 5) Update fuel
599  punit->fuel--;
600 
601  /* 6) Automatically refuel air units in cities, airbases, and
602  * transporters (carriers). */
603  if (is_unit_being_refueled(punit)) {
604  punit->fuel = utype_fuel(unit_type_get(punit));
605  }
606  }
607  }
609 
610  // 7) Check if there are air units without fuel
611  unit_list_iterate_safe(pplayer->units, punit)
612  {
613  if (punit->fuel <= 0 && utype_fuel(unit_type_get(punit))
614  && !converting_fuel_rescue(punit)) {
615  notify_player(pplayer, unit_tile(punit), E_UNIT_LOST_MISC, ftc_server,
616  _("Your %s has run out of fuel."),
617  unit_tile_link(punit));
618  wipe_unit(punit, ULR_FUEL, nullptr);
619  }
620  }
622 
623  // Send all updates.
624  unit_list_iterate(pplayer->units, punit)
625  {
626  send_unit_info(nullptr, punit);
627  }
629 }
630 
636 static void unit_restore_movepoints(struct player *pplayer,
637  struct unit *punit)
638 {
639  punit->moves_left = unit_move_rate(punit);
640  punit->done_moving = false;
641 }
642 
646 void update_unit_activities(struct player *pplayer)
647 {
648  auto now = time(nullptr);
649  unit_list_iterate_safe(pplayer->units, punit)
650  {
651  update_unit_activity(punit, now);
652  }
654 }
655 
659 void execute_unit_orders(struct player *pplayer)
660 {
661  unit_list_iterate_safe(pplayer->units, punit)
662  {
663  if (unit_has_orders(punit)) {
664  execute_orders(punit, false);
665  }
666  }
668 }
669 
674 {
675  /* Remember activities only after all knock-on effects of unit activities
676  * on other units have been resolved */
677  unit_list_iterate(pplayer->units, punit)
678  {
679  punit->changed_from = punit->activity;
680  punit->changed_from_target = punit->activity_target;
681  punit->changed_from_count = punit->activity_count;
682  send_unit_info(nullptr, punit);
683  }
685 }
686 
691 static int total_activity(struct tile *ptile, enum unit_activity act,
692  struct extra_type *tgt)
693 {
694  int total = 0;
695  bool tgt_matters = activity_requires_target(act);
696 
697  unit_list_iterate(ptile->units, punit)
698  {
699  if (punit->activity == act
700  && (!tgt_matters || punit->activity_target == tgt)) {
701  total += punit->activity_count;
702  }
703  }
705 
706  return total;
707 }
708 
713 static bool total_activity_done(struct tile *ptile, enum unit_activity act,
714  struct extra_type *tgt)
715 {
716  return total_activity(ptile, act, tgt)
717  >= tile_activity_time(act, ptile, tgt);
718 }
719 
723 void notify_unit_experience(struct unit *punit)
724 {
725  const struct veteran_system *vsystem;
726  const struct veteran_level *vlevel;
727 
728  if (!punit) {
729  return;
730  }
731 
732  vsystem = utype_veteran_system(unit_type_get(punit));
733  fc_assert_ret(vsystem != nullptr);
734  fc_assert_ret(vsystem->levels > punit->veteran);
735 
736  vlevel = utype_veteran_level(unit_type_get(punit), punit->veteran);
737  fc_assert_ret(vlevel != nullptr);
738 
739  notify_player(unit_owner(punit), unit_tile(punit), E_UNIT_BECAME_VET,
740  ftc_server,
741  // TRANS: Your <unit> became ... rank of <veteran level>.
742  _("Your %s became more experienced and achieved the rank "
743  "of %s."),
744  unit_link(punit), name_translation_get(&vlevel->name));
745 }
746 
750 static void unit_convert(struct unit *punit)
751 {
752  const struct unit_type *to_type;
753  const struct unit_type *from_type;
754 
755  from_type = unit_type_get(punit);
756  to_type = from_type->converted_to;
757 
758  if (unit_can_convert(punit)) {
759  transform_unit(punit, to_type, true);
760  notify_player(unit_owner(punit), unit_tile(punit), E_UNIT_UPGRADED,
761  ftc_server, _("%s converted to %s."),
762  utype_name_translation(from_type),
763  utype_name_translation(to_type));
764  } else {
765  notify_player(unit_owner(punit), unit_tile(punit), E_UNIT_UPGRADED,
766  ftc_server, _("%s cannot be converted."),
767  utype_name_translation(from_type));
768  }
769 }
770 
774 void unit_activities_cancel_all_illegal(const struct tile *ptile)
775 {
776  unit_list_iterate(ptile->units, punit2)
777  {
778  if (!can_unit_continue_current_activity(punit2)) {
779  if (unit_has_orders(punit2)) {
780  notify_player(unit_owner(punit2), unit_tile(punit2), E_UNIT_ORDERS,
781  ftc_server,
782  _("Orders for %s aborted because activity "
783  "is no longer available."),
784  unit_link(punit2));
785  free_unit_orders(punit2);
786  }
787 
788  set_unit_activity(punit2, ACTIVITY_IDLE);
789  send_unit_info(nullptr, punit2);
790  }
791  }
793 }
794 
802 {
804  adjc_iterate(&wld.map, ptile, ptile2)
805  {
807  }
809 }
810 
817 static void unit_activity_complete(struct unit *punit)
818 {
819  bool unit_activity_done = false;
820  enum unit_activity activity = punit->activity;
821  struct tile *ptile = unit_tile(punit);
822 
823  switch (activity) {
824  case ACTIVITY_IDLE:
825  case ACTIVITY_FORTIFIED:
826  case ACTIVITY_SENTRY:
827  case ACTIVITY_GOTO:
828  case ACTIVITY_UNKNOWN:
829  case ACTIVITY_FORTIFYING:
830  case ACTIVITY_CONVERT:
831  case ACTIVITY_PATROL_UNUSED:
832  case ACTIVITY_LAST:
833  // no default, ensure all handled
834  break;
835 
836  case ACTIVITY_EXPLORE:
837  do_explore(punit);
838  return;
839 
840  case ACTIVITY_PILLAGE:
841  if (total_activity_done(ptile, ACTIVITY_PILLAGE,
842  punit->activity_target)) {
843  destroy_extra(ptile, punit->activity_target);
844  unit_activity_done = true;
845 
847 
848  // Change vision if effects have changed.
850  }
851  break;
852 
853  case ACTIVITY_POLLUTION:
854  /* TODO: Remove this fallback target setting when target always correctly
855  * set */
856  if (punit->activity_target == nullptr) {
857  punit->activity_target =
858  prev_extra_in_tile(ptile, ERM_CLEANPOLLUTION, nullptr, punit);
859  }
860  if (total_activity_done(ptile, ACTIVITY_POLLUTION,
861  punit->activity_target)) {
862  destroy_extra(ptile, punit->activity_target);
863  unit_activity_done = true;
864  }
865  break;
866 
867  case ACTIVITY_FALLOUT:
868  /* TODO: Remove this fallback target setting when target always correctly
869  * set */
870  if (punit->activity_target == nullptr) {
871  punit->activity_target =
872  prev_extra_in_tile(ptile, ERM_CLEANFALLOUT, nullptr, punit);
873  }
874  if (total_activity_done(ptile, ACTIVITY_FALLOUT,
875  punit->activity_target)) {
876  destroy_extra(ptile, punit->activity_target);
877  unit_activity_done = true;
878  }
879  break;
880 
881  case ACTIVITY_BASE: {
882  if (total_activity(ptile, ACTIVITY_BASE, punit->activity_target)
883  >= tile_activity_time(ACTIVITY_BASE, ptile,
884  punit->activity_target)) {
885  create_extra(ptile, punit->activity_target, unit_owner(punit));
886  unit_activity_done = true;
887  }
888  } break;
889 
890  case ACTIVITY_GEN_ROAD: {
891  if (total_activity(ptile, ACTIVITY_GEN_ROAD, punit->activity_target)
892  >= tile_activity_time(ACTIVITY_GEN_ROAD, ptile,
893  punit->activity_target)) {
894  create_extra(ptile, punit->activity_target, unit_owner(punit));
895  unit_activity_done = true;
896  }
897  } break;
898 
899  case ACTIVITY_IRRIGATE:
900  case ACTIVITY_MINE:
901  case ACTIVITY_CULTIVATE:
902  case ACTIVITY_PLANT:
903  case ACTIVITY_TRANSFORM:
904  if (total_activity_done(ptile, activity, punit->activity_target)) {
905  struct terrain *old = tile_terrain(ptile);
906 
907  /* The function below could change the terrain. Therefore, we have to
908  * check the terrain (which will also do a sanity check for the tile).
909  */
910  tile_apply_activity(ptile, activity, punit->activity_target);
911  check_terrain_change(ptile, old);
912  unit_activity_done = true;
913  }
914  break;
915 
916  case ACTIVITY_OLD_ROAD:
917  case ACTIVITY_OLD_RAILROAD:
918  case ACTIVITY_FORTRESS:
919  case ACTIVITY_AIRBASE:
920  fc_assert(false);
921  break;
922  }
923 
924  if (unit_activity_done) {
925  update_tile_knowledge(ptile);
926  if (ACTIVITY_IRRIGATE == activity || ACTIVITY_MINE == activity
927  || ACTIVITY_CULTIVATE == activity || ACTIVITY_PLANT == activity
928  || ACTIVITY_TRANSFORM == activity) {
929  /* FIXME: As we might probably do the activity again, because of the
930  * terrain change cycles, we need to treat these cases separatly.
931  * Probably ACTIVITY_TRANSFORM should be associated to its terrain
932  * target, whereas ACTIVITY_IRRIGATE and ACTIVITY_MINE should only
933  * used for extras. */
934  unit_list_iterate(ptile->units, punit2)
935  {
936  if (punit2->activity == activity) {
937  set_unit_activity(punit2, ACTIVITY_IDLE);
938  send_unit_info(nullptr, punit2);
939  }
940  }
942  } else {
943  unit_list_iterate(ptile->units, punit2)
944  {
945  if (!can_unit_continue_current_activity(punit2)) {
946  set_unit_activity(punit2, ACTIVITY_IDLE);
947  send_unit_info(nullptr, punit2);
948  }
949  }
951  }
952 
953  // Some units nearby may not be able to continue their action,
954  // such as building irrigation if we removed the only source
955  // of water from them.
957  }
958 
959  if (activity == ACTIVITY_FORTIFYING) {
961  ACTION_FORTIFY, punit, ptile, punit->activity_target)) {
962  set_unit_activity(punit, ACTIVITY_FORTIFIED);
963  unit_activity_done = true;
964  }
965  }
966 
967  if (activity == ACTIVITY_CONVERT) {
969  ACTION_CONVERT, punit, ptile, punit->activity_target)) {
970  unit_convert(punit);
971  set_unit_activity(punit, ACTIVITY_IDLE);
972  unit_activity_done = true;
973  }
974  }
975 
976  if (unit_activity_done) {
977  if (activity == ACTIVITY_PILLAGE) {
978  // Casus Belli for when the action is completed.
979  /* TODO: is it more logical to put Casus_Belli_Success here, change
980  * Casus_Belli_Complete to Casus_Belli_Successful_Beginning and
981  * trigger it when an activity successfully has began? */
983  action_by_number(ACTION_PILLAGE), unit_owner(punit),
984  tile_owner(unit_tile(punit)), unit_tile(punit),
985  tile_link(unit_tile(punit)));
986  }
987  }
988 }
989 
995 static void update_unit_activity(struct unit *punit, time_t now)
996 {
997  struct player *pplayer = unit_owner(punit);
998  enum unit_activity activity = punit->activity;
999  int activity_rate = get_activity_rate_this_turn(punit);
1000  struct unit_wait *wait;
1001  time_t wake_up = punit->action_timestamp + game.server.unitwaittime;
1002 
1003  unit_restore_movepoints(pplayer, punit);
1004 
1005  switch (activity) {
1006  case ACTIVITY_IDLE:
1007  case ACTIVITY_EXPLORE:
1008  case ACTIVITY_FORTIFIED:
1009  case ACTIVITY_SENTRY:
1010  case ACTIVITY_GOTO:
1011  case ACTIVITY_PATROL_UNUSED:
1012  case ACTIVITY_UNKNOWN:
1013  case ACTIVITY_LAST:
1014  // These activities do not do anything interesting at turn change.
1015  break;
1016 
1017  case ACTIVITY_POLLUTION:
1018  case ACTIVITY_MINE:
1019  case ACTIVITY_CULTIVATE:
1020  case ACTIVITY_IRRIGATE:
1021  case ACTIVITY_PILLAGE:
1022  case ACTIVITY_PLANT:
1023  case ACTIVITY_TRANSFORM:
1024  case ACTIVITY_FALLOUT:
1025  case ACTIVITY_BASE:
1026  case ACTIVITY_GEN_ROAD:
1027  // settler may become veteran when doing something useful
1028  if (maybe_become_veteran_real(punit, true)) {
1029  notify_unit_experience(punit);
1030  }
1031  // Fallthrough.
1032  case ACTIVITY_FORTIFYING:
1033  case ACTIVITY_CONVERT:
1034  if (game.server.unitwaittime
1035  && (game.server.unitwaittime_style & UWT_ACTIVITIES)
1036  && wake_up > now) {
1037  wait = new unit_wait{};
1038  wait->activity_count = activity_rate;
1039  wait->activity = activity;
1040  wait->id = punit->id;
1041  wait->wake_up = wake_up;
1042  unit_wait_list_append(server.unit_waits, wait);
1043  return;
1044  }
1045 
1046  punit->activity_count += activity_rate;
1047  break;
1048 
1049  case ACTIVITY_OLD_ROAD:
1050  case ACTIVITY_OLD_RAILROAD:
1051  case ACTIVITY_FORTRESS:
1052  case ACTIVITY_AIRBASE:
1053  fc_assert(false);
1054  return;
1055  }
1056 
1057  unit_activity_complete(punit);
1058 }
1059 
1063 void finish_unit_wait(struct unit *punit, int activity_count)
1064 {
1065  punit->activity_count += activity_count;
1066  unit_activity_complete(punit);
1067 }
1068 
1073 void unit_forget_last_activity(struct unit *punit)
1074 {
1075  punit->changed_from = ACTIVITY_IDLE;
1076  if (punit->server.wait) {
1077  unit_wait_list_erase(server.unit_waits, punit->server.wait);
1078  }
1079 }
1080 
1086 {
1087  switch (activity) {
1088  case ACTIVITY_PILLAGE:
1089  // Can be set server side.
1090  return false;
1091  default:
1093  }
1094 }
1095 
1106  enum unit_activity *activity,
1107  struct extra_type **target)
1108 {
1109  if (*activity == ACTIVITY_PILLAGE && *target == nullptr) {
1110  struct tile *ptile = unit_tile(punit);
1111  struct extra_type *tgt;
1112 
1113  bv_extras extras = *tile_extras(ptile);
1114 
1115  while ((tgt = get_preferred_pillage(extras))) {
1116  BV_CLR(extras, extra_index(tgt));
1117 
1118  if (can_unit_do_activity_targeted(punit, *activity, tgt)) {
1119  *target = tgt;
1120  return;
1121  }
1122  }
1123  // Nothing we can pillage here.
1124  *activity = ACTIVITY_IDLE;
1125  }
1126 }
1127 
1132 static bool find_a_good_partisan_spot(struct tile *pcenter,
1133  struct player *powner,
1134  struct unit_type *u_type,
1135  int sq_radius, struct tile **dst_tile)
1136 {
1137  int bestvalue = 0;
1138 
1139  // coords of best tile in arg pointers
1140  circle_iterate(&(wld.map), pcenter, sq_radius, ptile)
1141  {
1142  int value;
1143 
1144  if (!is_native_tile(u_type, ptile)) {
1145  continue;
1146  }
1147 
1148  if (nullptr != tile_city(ptile)) {
1149  continue;
1150  }
1151 
1152  if (0 < unit_list_size(ptile->units)) {
1153  continue;
1154  }
1155 
1156  // City may not have changed hands yet; see place_partisans().
1157  value =
1158  get_virtual_defense_power(nullptr, u_type, powner, ptile, false, 0);
1159  value *= 10;
1160 
1161  if (tile_continent(ptile) != tile_continent(pcenter)) {
1162  value /= 2;
1163  }
1164 
1165  value -= fc_rand(value / 3);
1166 
1167  if (value > bestvalue) {
1168  *dst_tile = ptile;
1169  bestvalue = value;
1170  }
1171  }
1173 
1174  return bestvalue > 0;
1175 }
1176 
1180 void place_partisans(struct tile *pcenter, struct player *powner, int count,
1181  int sq_radius)
1182 {
1183  struct tile *ptile = nullptr;
1184  struct unit_type *u_type = best_role_unit_for_player(powner, L_PARTISAN);
1185  if (!u_type) {
1186  // If the player cannot build any partisan, pick the first one
1187  u_type = get_role_unit(L_PARTISAN, 0);
1188  }
1189  if (!u_type) {
1190  // Cannot do anything.
1191  return;
1192  }
1193 
1194  while (count-- > 0
1195  && find_a_good_partisan_spot(pcenter, powner, u_type, sq_radius,
1196  &ptile)) {
1197  struct unit *punit;
1198 
1199  punit = create_unit(powner, ptile, u_type, 0, 0, -1);
1200  if (can_unit_do_activity(punit, ACTIVITY_FORTIFYING)) {
1201  punit->activity = ACTIVITY_FORTIFIED; // yes; directly fortified
1202  send_unit_info(nullptr, punit);
1203  }
1204  }
1205 }
1206 
1212 bool teleport_unit_to_city(struct unit *punit, struct city *pcity,
1213  int move_cost, bool verbose)
1214 {
1215  struct tile *src_tile = unit_tile(punit), *dst_tile = pcity->tile;
1216 
1217  if (city_owner(pcity) == unit_owner(punit)) {
1218  qDebug("Teleported %s %s from (%d,%d) to %s",
1220  TILE_XY(src_tile), city_name_get(pcity));
1221  if (verbose) {
1222  notify_player(unit_owner(punit), city_tile(pcity), E_UNIT_RELOCATED,
1223  ftc_server, _("Teleported your %s to %s."),
1224  unit_link(punit), city_link(pcity));
1225  }
1226 
1227  // Silently free orders since they won't be applicable anymore.
1228  free_unit_orders(punit);
1229 
1230  if (move_cost == -1) {
1231  move_cost = punit->moves_left;
1232  }
1233  unit_move(punit, dst_tile, move_cost, nullptr, false, false);
1234 
1235  return true;
1236  }
1237  return false;
1238 }
1239 
1240 namespace /* anonymous */ {
1241 
1250 template <bool SAFE> class bounce_destination : public freeciv::destination {
1251 public:
1253  explicit bounce_destination(const unit *unit) : m_unit(unit) {}
1254 
1256  ~bounce_destination() {}
1257 
1258 protected:
1259  bool reached(const freeciv::detail::vertex &vertex) const override;
1260 
1261 private:
1262  const unit *m_unit;
1263 };
1264 
1268 template <bool SAFE>
1269 bool bounce_destination<SAFE>::reached(
1270  const freeciv::detail::vertex &vertex) const
1271 {
1272  if constexpr (SAFE) {
1273  return vertex.location != m_unit->tile
1274  && can_unit_survive_at_tile(&(wld.map), m_unit, vertex.location);
1275  } else {
1276  return vertex.location != m_unit->tile
1277  && can_unit_exist_at_tile(&(wld.map), m_unit, vertex.location);
1278  }
1279 }
1280 
1286 class bounce_path_constraint : public freeciv::step_constraint {
1287 public:
1289  explicit bounce_path_constraint(const player *player,
1290  const tile *start_from, int max_distance)
1291  : m_player(player), m_start(start_from), m_distance(max_distance)
1292  {
1293  }
1294 
1296  virtual ~bounce_path_constraint() = default;
1297 
1298  bool is_allowed(const freeciv::path::step &step) const override;
1299 
1300 private:
1301  const player *m_player;
1302  const tile *m_start;
1303  const int m_distance;
1304 };
1305 
1309 bool bounce_path_constraint::is_allowed(
1310  const freeciv::path::step &step) const
1311 {
1312  return step.order.order != ORDER_FULL_MP
1313  && step.order.order != ORDER_ACTION_MOVE && step.turns < 1
1314  && real_map_distance(m_start, step.location) <= m_distance
1315  && tile_get_known(step.location, m_player) != TILE_UNKNOWN;
1316 }
1317 } // anonymous namespace
1318 
1327 void bounce_unit(struct unit *punit, bool verbose, bounce_reason reason,
1328  int max_distance)
1329 {
1330  if (!punit) {
1331  return;
1332  }
1333 
1334  const auto pplayer = unit_owner(punit);
1335  const auto punit_tile = unit_tile(punit);
1336 
1337  // Cancel whatever the unit has been doing. Needed for the path finding
1338  // code to work.
1339  handle_unit_server_side_agent_set(pplayer, punit->id, SSA_NONE);
1340  unit_activity_handling(punit, ACTIVITY_IDLE);
1341 
1342  auto finder = freeciv::path_finder(punit);
1343  finder.set_constraint(std::make_unique<bounce_path_constraint>(
1344  pplayer, punit_tile, max_distance));
1345 
1346  // Collect possible reactions for the unit. Bouncing units are pushed out
1347  // and need to act on their own, so they pick something at random.
1348  auto paths = finder.find_all(bounce_destination<true>(punit));
1349  if (paths.empty()) {
1350  paths = finder.find_all(bounce_destination<false>(punit));
1351  }
1352 
1353  qDebug() << "Bouncing: found" << paths.size() << "possible paths";
1354 
1355  if (!paths.empty()) {
1356  const auto path = paths[fc_rand(paths.size())];
1357  const auto steps = path.steps();
1358  const auto end_tile = path.steps().back().location;
1359 
1360  if (verbose) {
1361  switch (reason) {
1363  notify_player(pplayer, end_tile, E_UNIT_RELOCATED, ftc_server,
1364  // TRANS: A unit is moved to resolve stack conflicts.
1365  _("Moved your %s."), unit_link(punit));
1366  break;
1368  notify_player(pplayer, end_tile, E_UNIT_RELOCATED, ftc_server,
1369  _("Moved your %s due to changing terrain."),
1370  unit_link(punit));
1371  break;
1372  }
1373  }
1374 
1375  // Execute the orders making up the path. See control.cpp in the client
1376  // (FIXME: write a nice function)
1377  if (steps.size() < MAX_LEN_ROUTE) {
1378  auto packet = packet_unit_orders{};
1379  packet.unit_id = punit->id;
1380  packet.dest_tile = steps.back().location->index;
1381  packet.src_tile = punit->tile->index;
1382  packet.repeat = false;
1383  packet.vigilant = false;
1384 
1385  packet.length = steps.size();
1386 
1387  for (std::size_t i = 0; i < steps.size(); ++i) {
1388  packet.orders[i] = steps[i].order;
1389  }
1390 
1391  // Disable unit wait time since this is a forced action
1392  auto timestamp = punit->action_timestamp;
1393  punit->action_timestamp = 0;
1394 
1395  handle_unit_orders(pplayer, &packet);
1396 
1397  // Restore unit wait time
1398  punit->action_timestamp = timestamp;
1399 
1400  if (punit->tile != punit_tile) {
1401  return;
1402  }
1403  // Do something sensible if the unit fails to move (below). This
1404  // happens, for instance, if it is out of moves for the turn.
1405  }
1406  }
1407 
1408  /* Didn't find a place to bounce the unit, going to disband it.
1409  * Try to bounce transported units. */
1410  if (0 < get_transporter_occupancy(punit)) {
1411  const auto pcargo_units = unit_transport_cargo(punit);
1412  unit_list_iterate(pcargo_units, pcargo) { bounce_unit(pcargo, verbose); }
1414  }
1415 
1416  if (verbose) {
1417  switch (reason) {
1419  notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1420  // TRANS: A unit is disbanded to resolve stack conflicts.
1421  _("Disbanded your %s."), unit_tile_link(punit));
1422  break;
1424  notify_player(pplayer, punit_tile, E_UNIT_LOST_MISC, ftc_server,
1425  _("Disbanded your %s due to changing terrain."),
1426  unit_tile_link(punit));
1427  break;
1428  }
1429  }
1430  wipe_unit(punit, ULR_STACK_CONFLICT, nullptr);
1431 }
1432 
1438 static void throw_units_from_illegal_cities(struct player *pplayer,
1439  bool verbose)
1440 {
1441  struct tile *ptile;
1442  struct city *pcity;
1443  struct unit *ptrans;
1444  struct unit_list *pcargo_units;
1445 
1446  // Unload undesired units from transports, if possible.
1447  unit_list_iterate(pplayer->units, punit)
1448  {
1449  ptile = unit_tile(punit);
1450  pcity = tile_city(ptile);
1451  if (nullptr != pcity && !pplayers_allied(city_owner(pcity), pplayer)
1452  && 0 < get_transporter_occupancy(punit)) {
1453  pcargo_units = unit_transport_cargo(punit);
1454  unit_list_iterate(pcargo_units, pcargo)
1455  {
1456  if (!pplayers_allied(unit_owner(pcargo), pplayer)) {
1457  if (can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
1459  }
1460  }
1461  }
1463  }
1464  }
1466 
1467  /* Bounce units except transported ones which will be bounced with their
1468  * transport. */
1469  unit_list_iterate_safe(pplayer->units, punit)
1470  {
1471  ptile = unit_tile(punit);
1472  pcity = tile_city(ptile);
1473  if (nullptr != pcity && !pplayers_allied(city_owner(pcity), pplayer)) {
1474  ptrans = unit_transport_get(punit);
1475  if (nullptr == ptrans || pplayer != unit_owner(ptrans)) {
1476  bounce_unit(punit, verbose);
1477  }
1478  }
1479  }
1481 
1482 #ifdef FREECIV_DEBUG
1483  // Sanity check.
1484  unit_list_iterate(pplayer->units, punit)
1485  {
1486  ptile = unit_tile(punit);
1487  pcity = tile_city(ptile);
1488  fc_assert_msg(
1489  nullptr == pcity || pplayers_allied(city_owner(pcity), pplayer),
1490  "Failed to throw %s %d from %s %d (%d, %d)", unit_rule_name(punit),
1491  punit->id, city_name_get(pcity), pcity->id, TILE_XY(ptile));
1492  }
1494 #endif // FREECIV_DEBUG
1495 }
1496 
1505 static void resolve_stack_conflicts(struct player *pplayer,
1506  struct player *aplayer, bool verbose)
1507 {
1508  unit_list_iterate_safe(pplayer->units, punit)
1509  {
1510  struct tile *ptile = unit_tile(punit);
1511 
1512  if (is_non_allied_unit_tile(ptile, pplayer)) {
1513  unit_list_iterate_safe(ptile->units, aunit)
1514  {
1515  if (unit_owner(aunit) == pplayer || unit_owner(aunit) == aplayer
1516  || !can_unit_survive_at_tile(&(wld.map), aunit, ptile)) {
1517  bounce_unit(aunit, verbose);
1518  }
1519  }
1521  }
1522  }
1524 }
1525 
1537 void resolve_unit_stacks(struct player *pplayer, struct player *aplayer,
1538  bool verbose)
1539 {
1540  throw_units_from_illegal_cities(pplayer, verbose);
1541  throw_units_from_illegal_cities(aplayer, verbose);
1542 
1543  resolve_stack_conflicts(pplayer, aplayer, verbose);
1544  resolve_stack_conflicts(aplayer, pplayer, verbose);
1545 }
1546 
1552 struct unit_list *get_units_seen_via_ally(const struct player *pplayer,
1553  const struct player *aplayer)
1554 {
1555  struct unit_list *seen_units = unit_list_new();
1556 
1557  // Anybody's units inside ally's cities
1558  city_list_iterate(aplayer->cities, pcity)
1559  {
1560  unit_list_iterate(city_tile(pcity)->units, punit)
1561  {
1562  if (can_player_see_unit(pplayer, punit)) {
1563  unit_list_append(seen_units, punit);
1564  }
1565  }
1567  }
1569 
1570  // Ally's own units inside transports
1571  unit_list_iterate(aplayer->units, punit)
1572  {
1573  if (unit_transported(punit) && can_player_see_unit(pplayer, punit)) {
1574  unit_list_append(seen_units, punit);
1575  }
1576  }
1578 
1579  /* Make sure the same unit is not added in multiple phases
1580  * (unit within transport in a city) */
1581  unit_list_unique(seen_units);
1582 
1583  return seen_units;
1584 }
1585 
1593 void remove_allied_visibility(struct player *pplayer, struct player *aplayer,
1594  const struct unit_list *seen_units)
1595 {
1596  unit_list_iterate(seen_units, punit)
1597  {
1598  // We need to hide units previously seen by the client.
1599  if (!can_player_see_unit(pplayer, punit)) {
1600  unit_goes_out_of_sight(pplayer, punit);
1601  }
1602  }
1604 
1605  city_list_iterate(aplayer->cities, pcity)
1606  {
1607  /* The player used to know what units were in these cities. Now that he
1608  * doesn't, he needs to get a new short city packet updating the
1609  * occupied status. */
1610  if (map_is_known_and_seen(pcity->tile, pplayer, V_MAIN)) {
1611  send_city_info(pplayer, pcity);
1612  }
1613  }
1615 }
1616 
1621 void give_allied_visibility(struct player *pplayer, struct player *aplayer)
1622 {
1623  unit_list_iterate(aplayer->units, punit)
1624  {
1625  if (can_player_see_unit(pplayer, punit)) {
1626  send_unit_info(pplayer->connections, punit);
1627  }
1628  }
1630 }
1631 
1635 bool is_airunit_refuel_point(const struct tile *ptile,
1636  const struct player *pplayer,
1637  const struct unit *punit)
1638 {
1639  const struct unit_class *pclass;
1640 
1641  if (nullptr != is_non_allied_unit_tile(ptile, pplayer)) {
1642  return false;
1643  }
1644 
1645  if (nullptr != is_allied_city_tile(ptile, pplayer)) {
1646  return true;
1647  }
1648 
1649  pclass = unit_class_get(punit);
1650  if (nullptr != pclass->cache.refuel_bases) {
1651  const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1652 
1653  extra_type_list_iterate(pclass->cache.refuel_bases, pextra)
1654  {
1655  if (BV_ISSET(plrtile->extras, extra_index(pextra))) {
1656  return true;
1657  }
1658  }
1660  }
1661 
1662  return unit_could_load_at(punit, ptile);
1663 }
1664 
1676 void transform_unit(struct unit *punit, const struct unit_type *to_unit,
1677  bool is_free)
1678 {
1679  struct player *pplayer = unit_owner(punit);
1680  const struct unit_type *old_type = punit->utype;
1681  int old_mr = unit_move_rate(punit);
1682  int old_hp = unit_type_get(punit)->hp;
1683  bv_player can_see_unit;
1684 
1685  BV_CLR_ALL(can_see_unit);
1686  players_iterate(oplayer)
1687  {
1688  if (can_player_see_unit(oplayer, punit)) {
1689  BV_SET(can_see_unit, player_index(oplayer));
1690  }
1691  }
1693 
1694  if (!is_free) {
1695  pplayer->economic.gold -=
1696  unit_upgrade_price(pplayer, unit_type_get(punit), to_unit);
1697  }
1698 
1699  punit->utype = to_unit;
1700 
1701  /* New type may not have the same veteran system, and we may want to
1702  * knock some levels off. */
1703  punit->veteran =
1704  MIN(punit->veteran, utype_veteran_system(to_unit)->levels - 1);
1705  if (is_free) {
1706  punit->veteran =
1707  MAX(punit->veteran - game.server.autoupgrade_veteran_loss, 0);
1708  } else {
1709  punit->veteran =
1710  MAX(punit->veteran - game.server.upgrade_veteran_loss, 0);
1711  }
1712 
1713  /* Scale HP and MP, rounding down. Be careful with integer arithmetic,
1714  * and don't kill the unit. unit_move_rate() is used to take into account
1715  * global effects like Magellan's Expedition. */
1716  punit->hp = MAX(punit->hp * unit_type_get(punit)->hp / old_hp, 1);
1717  if (old_mr == 0) {
1718  punit->moves_left = unit_move_rate(punit);
1719  } else {
1720  punit->moves_left = punit->moves_left * unit_move_rate(punit) / old_mr;
1721  }
1722 
1723  /* Update unit fuel state */
1724  if (utype_fuel(to_unit) && utype_fuel(old_type)) {
1725  /* Keep the amount of fuel used constant, except don't kill the unit */
1726  int delta = utype_fuel(to_unit) - utype_fuel(old_type);
1727  punit->fuel = MAX(punit->fuel + delta, 1);
1728  } else {
1729  /* When converting from a non-fuel unit, fully refuel */
1730  punit->fuel = utype_fuel(to_unit);
1731  }
1732 
1734 
1735  // update unit upkeep
1737 
1738  conn_list_do_buffer(pplayer->connections);
1739 
1740  unit_refresh_vision(punit);
1741 
1742  // unit may disappear for some players if vlayer changed
1743  players_iterate(oplayer)
1744  {
1745  if (BV_ISSET(can_see_unit, player_index(oplayer))
1746  && !can_player_see_unit(oplayer, punit)) {
1747  unit_goes_out_of_sight(oplayer, punit);
1748  }
1749  }
1751 
1752  CALL_PLR_AI_FUNC(unit_transformed, pplayer, punit, old_type);
1753  CALL_FUNC_EACH_AI(unit_info, punit);
1754 
1755  send_unit_info(nullptr, punit);
1757 }
1758 
1762 struct unit *create_unit(struct player *pplayer, struct tile *ptile,
1763  const struct unit_type *type, int veteran_level,
1764  int homecity_id, int moves_left)
1765 {
1766  return create_unit_full(pplayer, ptile, type, veteran_level, homecity_id,
1767  moves_left, -1, nullptr);
1768 }
1769 
1773 void unit_get_goods(struct unit *punit)
1774 {
1775  if (punit->homecity != 0) {
1776  struct city *home = game_city_by_number(punit->homecity);
1777 
1778  if (home != nullptr && game.info.goods_selection == GSM_LEAVING) {
1779  punit->carrying = goods_from_city_to_unit(home, punit);
1780  }
1781  }
1782 }
1783 
1789 struct unit *create_unit_full(struct player *pplayer, struct tile *ptile,
1790  const struct unit_type *type,
1791  int veteran_level, int homecity_id,
1792  int moves_left, int hp_left,
1793  struct unit *ptrans)
1794 {
1795  struct unit *punit =
1796  unit_virtual_create(pplayer, nullptr, type, veteran_level);
1797  struct city *pcity;
1798 
1799  // Register unit
1800  punit->id = identity_number();
1801  idex_register_unit(&wld, punit);
1802 
1803  fc_assert_ret_val(ptile != nullptr, nullptr);
1804  unit_tile_set(punit, ptile);
1805 
1806  pcity = game_city_by_number(homecity_id);
1807  if (utype_has_flag(type, UTYF_NOHOME)) {
1808  punit->homecity = 0; // none
1809  } else {
1810  punit->homecity = homecity_id;
1811  }
1812 
1813  if (hp_left >= 0) {
1814  // Override default full HP
1815  punit->hp = hp_left;
1816  }
1817 
1818  if (moves_left >= 0) {
1819  // Override default full MP
1820  punit->moves_left = MIN(moves_left, unit_move_rate(punit));
1821  }
1822 
1823  if (ptrans) {
1824  // Set transporter for unit.
1825  unit_transport_load_tp_status(punit, ptrans, false);
1826  } else {
1828  !ptile || can_unit_exist_at_tile(&(wld.map), punit, ptile), nullptr);
1829  }
1830 
1831  /* Assume that if moves_left < 0 then the unit is "fresh",
1832  * and not moved; else the unit has had something happen
1833  * to it (eg, bribed) which we treat as equivalent to moved.
1834  * (Otherwise could pass moved arg too...) --dwp */
1835  punit->moved = (moves_left >= 0);
1836 
1837  unit_list_prepend(pplayer->units, punit);
1838  unit_list_prepend(ptile->units, punit);
1839  if (pcity && !utype_has_flag(type, UTYF_NOHOME)) {
1840  fc_assert(city_owner(pcity) == pplayer);
1841  unit_list_prepend(pcity->units_supported, punit);
1842  // Refresh the unit's homecity.
1843  city_refresh(pcity);
1844  send_city_info(pplayer, pcity);
1845  }
1846 
1847  punit->server.vision = vision_new(pplayer, ptile);
1848  unit_refresh_vision(punit);
1849 
1850  send_unit_info(nullptr, punit);
1851  maybe_make_contact(ptile, unit_owner(punit));
1852  wakeup_neighbor_sentries(punit);
1853 
1854  // update unit upkeep
1855  city_units_upkeep(game_city_by_number(homecity_id));
1856 
1857  // The unit may have changed the available tiles in nearby cities.
1858  city_map_update_tile_now(ptile);
1859  sync_cities();
1860 
1861  unit_get_goods(punit);
1862 
1863  CALL_FUNC_EACH_AI(unit_created, punit);
1864  CALL_PLR_AI_FUNC(unit_got, pplayer, punit);
1865 
1866  return punit;
1867 }
1868 
1872 void unit_set_removal_callback(struct unit *punit,
1873  void (*callback)(struct unit *punit))
1874 {
1875  /* Tried to overwrite another call back. If this assertion is triggered
1876  * in a case where two call back are needed it may be time to support
1877  * more than one unit removal call back at a time. */
1878  fc_assert_ret(punit->server.removal_callback == nullptr);
1879 
1880  punit->server.removal_callback = callback;
1881 }
1882 
1887 {
1888  punit->server.removal_callback = nullptr;
1889 }
1890 
1895 static void server_remove_unit_full(struct unit *punit, bool transported,
1896  enum unit_loss_reason reason)
1897 {
1898  struct packet_unit_remove packet;
1899  struct tile *ptile = unit_tile(punit);
1900  struct city *pcity = tile_city(ptile);
1901  struct city *phomecity = game_city_by_number(punit->homecity);
1902  struct unit *ptrans;
1903  struct player *pplayer = unit_owner(punit);
1904 
1905  // The unit is doomed.
1906  punit->server.dying = true;
1907 
1908 #ifdef FREECIV_DEBUG
1909  unit_list_iterate(ptile->units, pcargo)
1910  {
1911  fc_assert(unit_transport_get(pcargo) != punit);
1912  }
1914 #endif // FREECIV_DEBUG
1915 
1916  CALL_PLR_AI_FUNC(unit_lost, pplayer, punit);
1917  CALL_FUNC_EACH_AI(unit_destroyed, punit);
1918 
1919  // Save transporter for updating below.
1920  ptrans = unit_transport_get(punit);
1921  // Unload unit.
1922  unit_transport_unload(punit);
1923 
1924  /* Since settlers plot in new cities in the minimap before they
1925  are built, so that no two settlers head towards the same city
1926  spot, we need to ensure this reservation is cleared should
1927  the settler disappear on the way. */
1928  adv_unit_new_task(punit, AUT_NONE, nullptr);
1929 
1930  /* Clear the vision before sending unit remove. Else, we might duplicate
1931  * the PACKET_UNIT_REMOVE if we lose vision of the unit tile. */
1932  vision_clear_sight(punit->server.vision);
1933  vision_free(punit->server.vision);
1934  punit->server.vision = nullptr;
1935 
1936  // Clear a unit wait if present.
1937  if (punit->server.wait) {
1938  unit_wait_list_erase(server.unit_waits, punit->server.wait);
1939  }
1940 
1941  packet.unit_id = punit->id;
1942  // Send to onlookers.
1943  players_iterate(aplayer)
1944  {
1945  if (can_player_see_unit_at(aplayer, punit, unit_tile(punit),
1946  transported)) {
1947  lsend_packet_unit_remove(aplayer->connections, &packet);
1948  }
1949  }
1951  // Send to global observers.
1953  {
1954  if (conn_is_global_observer(pconn)) {
1955  send_packet_unit_remove(pconn, &packet);
1956  }
1957  }
1959 
1960  if (punit->server.moving != nullptr) {
1961  // Do not care of this unit for running moves.
1962  punit->server.moving->punit = nullptr;
1963  }
1964 
1965  if (punit->server.removal_callback != nullptr) {
1966  // Run the unit removal call back.
1967  punit->server.removal_callback(punit);
1968  }
1969 
1970  // check if this unit had UTYF_GAMELOSS flag
1971  if (unit_has_type_flag(punit, UTYF_GAMELOSS)
1972  && unit_owner(punit)->is_alive) {
1973  notify_conn(game.est_connections, ptile, E_UNIT_LOST_MISC, ftc_server,
1974  _("Unable to defend %s, %s has lost the game."),
1975  unit_link(punit), player_name(pplayer));
1976  notify_player(pplayer, ptile, E_GAME_END, ftc_server,
1977  _("Losing %s meant losing the game! "
1978  "Be more careful next time!"),
1979  unit_link(punit));
1980  player_status_add(unit_owner(punit), PSTATUS_DYING);
1981  }
1982 
1983  script_server_signal_emit("unit_lost", punit, unit_owner(punit),
1984  unit_loss_reason_name(reason));
1985 
1987  game_remove_unit(&wld, punit);
1988  punit = nullptr;
1989 
1990  if (nullptr != ptrans) {
1991  // Update the occupy info.
1992  send_unit_info(nullptr, ptrans);
1993  }
1994 
1995  // This unit may have blocked tiles of adjacent cities. Update them.
1996  city_map_update_tile_now(ptile);
1997  sync_cities();
1998 
1999  if (phomecity) {
2000  city_refresh(phomecity);
2001  send_city_info(city_owner(phomecity), phomecity);
2002  }
2003 
2004  if (pcity && pcity != phomecity) {
2005  city_refresh(pcity);
2006  send_city_info(city_owner(pcity), pcity);
2007  }
2008 
2009  if (pcity && unit_list_size(ptile->units) == 0) {
2010  // The last unit in the city was killed: update the occupied flag.
2011  send_city_info(nullptr, pcity);
2012  }
2013 }
2014 
2019 static void server_remove_unit(struct unit *punit,
2020  enum unit_loss_reason reason)
2021 {
2022  server_remove_unit_full(punit, unit_transported(punit), reason);
2023 }
2024 
2028 static void unit_lost_with_transport(const struct player *pplayer,
2029  struct unit *pcargo,
2030  const struct unit_type *ptransport,
2031  struct player *killer)
2032 {
2033  notify_player(pplayer, unit_tile(pcargo), E_UNIT_LOST_MISC, ftc_server,
2034  _("%s lost when %s was lost."), unit_tile_link(pcargo),
2035  utype_name_translation(ptransport));
2036  /* Unit is not transported any more at this point, but it has jumped
2037  * off the transport and drowns outside. So it must be removed from
2038  * all clients.
2039  * However, we don't know if given client has received ANY updates
2040  * about the swimming unit, and we can't remove it if it's not there
2041  * in the first place -> we send it once here just to be sure it's
2042  * there. */
2043  send_unit_info(nullptr, pcargo);
2044  wipe_unit_full(pcargo, false, ULR_TRANSPORT_LOST, killer);
2045 }
2046 
2051 static void wipe_unit_full(struct unit *punit, bool transported,
2052  enum unit_loss_reason reason,
2053  struct player *killer)
2054 {
2055  struct tile *ptile = unit_tile(punit);
2056  struct player *pplayer = unit_owner(punit);
2057  const struct unit_type *putype_save =
2058  unit_type_get(punit); // for notify messages
2059  struct unit_list *helpless = unit_list_new();
2060  struct unit_list *imperiled = unit_list_new();
2061  struct unit_list *unsaved = unit_list_new();
2062  struct unit *ptrans = unit_transport_get(punit);
2063  struct city *pexclcity;
2064 
2065  // The unit is doomed.
2066  punit->server.dying = true;
2067 
2068  /* If a unit is being lost due to loss of its city, ensure that we don't
2069  * try to teleport any of its cargo to that city (which may not yet
2070  * have changed hands or disappeared). (It is assumed that the unit's
2071  * home city is always the one that is being lost/transferred/etc.) */
2072  if (reason == ULR_CITY_LOST) {
2073  pexclcity = unit_home(punit);
2074  } else {
2075  pexclcity = nullptr;
2076  }
2077 
2078  // Remove unit itself from its transport
2079  if (ptrans != nullptr) {
2080  unit_transport_unload(punit);
2081  send_unit_info(nullptr, ptrans);
2082  }
2083 
2084  // First pull all units off of the transporter.
2085  if (get_transporter_occupancy(punit) > 0) {
2086  /* Use iterate_safe as unloaded units will be removed from the list
2087  * while iterating. */
2089  {
2090  bool healthy = false;
2091 
2092  if (!can_unit_unload(pcargo, punit)) {
2093  unit_list_prepend(helpless, pcargo);
2094  } else {
2095  if (!can_unit_exist_at_tile(&(wld.map), pcargo, ptile)) {
2096  unit_list_prepend(imperiled, pcargo);
2097  } else {
2098  // These units do not need to be saved.
2099  healthy = true;
2100  }
2101  }
2102 
2103  /* Could use unit_transport_unload_send here, but that would
2104  * call send_unit_info for the transporter unnecessarily.
2105  * Note that this means that unit might to get seen briefly
2106  * by clients other than owner's, for example as a result of
2107  * update of homecity common to this cargo and some other
2108  * destroyed unit. */
2109  unit_transport_unload(pcargo);
2110  if (pcargo->activity == ACTIVITY_SENTRY) {
2111  /* Activate sentried units - like planes on a disbanded carrier.
2112  * Note this will activate ground units even if they just change
2113  * transporter. */
2114  set_unit_activity(pcargo, ACTIVITY_IDLE);
2115  }
2116 
2117  /* Unit info for unhealthy units will be sent when they are
2118  * assigned new transport or removed. */
2119  if (healthy) {
2120  send_unit_info(nullptr, pcargo);
2121  }
2122  }
2124  }
2125 
2126  // Now remove the unit.
2127  server_remove_unit_full(punit, transported, reason);
2128 
2129  switch (reason) {
2130  case ULR_KILLED:
2131  case ULR_EXECUTED:
2132  case ULR_SDI:
2133  case ULR_NUKE:
2134  case ULR_BRIBED:
2135  case ULR_CAPTURED:
2136  case ULR_CAUGHT:
2137  case ULR_ELIMINATED:
2138  case ULR_TRANSPORT_LOST:
2139  if (killer != nullptr) {
2140  killer->score.units_killed++;
2141  }
2142  pplayer->score.units_lost++;
2143  break;
2144  case ULR_BARB_UNLEASH:
2145  case ULR_CITY_LOST:
2146  case ULR_STARVED:
2147  case ULR_NONNATIVE_TERR:
2148  case ULR_ARMISTICE:
2149  case ULR_HP_LOSS:
2150  case ULR_FUEL:
2151  case ULR_STACK_CONFLICT:
2152  case ULR_SOLD:
2153  pplayer->score.units_lost++;
2154  break;
2155  case ULR_RETIRED:
2156  case ULR_DISBANDED:
2157  case ULR_USED:
2158  case ULR_EDITOR:
2159  case ULR_PLAYER_DIED:
2160  case ULR_DETONATED:
2161  case ULR_MISSILE:
2162  break;
2163  }
2164 
2165  // First, sort out helpless cargo.
2166  if (unit_list_size(helpless) > 0) {
2167  struct unit_list *remaining = unit_list_new();
2168 
2169  /* Grant priority to gameloss units and units with the EvacuateFirst
2170  * unit type flag. */
2171  unit_list_iterate_safe(helpless, pcargo)
2172  {
2173  if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
2174  || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
2175  if (!try_to_save_unit(pcargo, putype_save, true,
2176  unit_has_type_flag(pcargo, UTYF_EVAC_FIRST),
2177  pexclcity)) {
2178  unit_list_prepend(unsaved, pcargo);
2179  }
2180  } else {
2181  unit_list_prepend(remaining, pcargo);
2182  }
2183  }
2185 
2186  // Handle non-priority units.
2187  unit_list_iterate_safe(remaining, pcargo)
2188  {
2189  if (!try_to_save_unit(pcargo, putype_save, true, false, pexclcity)) {
2190  unit_list_prepend(unsaved, pcargo);
2191  }
2192  }
2194 
2195  unit_list_destroy(remaining);
2196  }
2197  unit_list_destroy(helpless);
2198 
2199  // Then, save any imperiled cargo.
2200  if (unit_list_size(imperiled) > 0) {
2201  struct unit_list *remaining = unit_list_new();
2202 
2203  /* Grant priority to gameloss units and units with the EvacuateFirst
2204  * unit type flag. */
2205  unit_list_iterate_safe(imperiled, pcargo)
2206  {
2207  if (unit_has_type_flag(pcargo, UTYF_EVAC_FIRST)
2208  || unit_has_type_flag(pcargo, UTYF_GAMELOSS)) {
2209  if (!try_to_save_unit(pcargo, putype_save, false,
2210  unit_has_type_flag(pcargo, UTYF_EVAC_FIRST),
2211  pexclcity)) {
2212  unit_list_prepend(unsaved, pcargo);
2213  }
2214  } else {
2215  unit_list_prepend(remaining, pcargo);
2216  }
2217  }
2219 
2220  // Handle non-priority units.
2221  unit_list_iterate_safe(remaining, pcargo)
2222  {
2223  if (!try_to_save_unit(pcargo, putype_save, false, false, pexclcity)) {
2224  unit_list_prepend(unsaved, pcargo);
2225  }
2226  }
2228 
2229  unit_list_destroy(remaining);
2230  }
2231  unit_list_destroy(imperiled);
2232 
2233  // Finally, kill off the unsaved units.
2234  if (unit_list_size(unsaved) > 0) {
2235  unit_list_iterate_safe(unsaved, dying_unit)
2236  {
2237  unit_lost_with_transport(pplayer, dying_unit, putype_save, killer);
2238  }
2240  }
2241  unit_list_destroy(unsaved);
2242 }
2243 
2248 void wipe_unit(struct unit *punit, enum unit_loss_reason reason,
2249  struct player *killer)
2250 {
2251  wipe_unit_full(punit, unit_transported(punit), reason, killer);
2252 }
2253 
2260 static bool try_to_save_unit(struct unit *punit,
2261  const struct unit_type *pttype, bool helpless,
2262  bool teleporting, const struct city *pexclcity)
2263 {
2264  struct tile *ptile = unit_tile(punit);
2265  struct player *pplayer = unit_owner(punit);
2266  struct unit *ptransport = transporter_for_unit(punit);
2267 
2268  // Helpless units cannot board a transport in their current state.
2269  if (!helpless && ptransport != nullptr) {
2270  unit_transport_load_tp_status(punit, ptransport, false);
2271  send_unit_info(nullptr, punit);
2272  return true;
2273  } else {
2274  // Only units that cannot find transport are considered for teleport.
2275  if (teleporting) {
2276  struct city *pcity =
2277  find_closest_city(ptile, pexclcity, unit_owner(punit), false,
2278  false, false, true, false, utype_class(pttype));
2279  if (pcity != nullptr) {
2280  char tplink[MAX_LEN_LINK]; // In case unit dies when teleported
2281 
2282  sz_strlcpy(tplink, unit_link(punit));
2283 
2284  if (teleport_unit_to_city(punit, pcity, 0, false)) {
2285  notify_player(
2286  pplayer, ptile, E_UNIT_RELOCATED, ftc_server,
2287  _("%s escaped the destruction of %s, and fled to %s."), tplink,
2288  utype_name_translation(pttype), city_link(pcity));
2289  return true;
2290  }
2291  }
2292  }
2293  }
2294  // The unit could not use transport on the tile, and could not teleport.
2295  return false;
2296 }
2297 
2302 struct unit *unit_change_owner(struct unit *punit, struct player *pplayer,
2303  int homecity, enum unit_loss_reason reason)
2304 {
2305  struct unit *gained_unit;
2306 
2307  fc_assert(
2309 
2310  /* Convert the unit to your cause. Fog is lifted in the create algorithm.
2311  */
2312  gained_unit = create_unit_full(
2313  pplayer, unit_tile(punit), unit_type_get(punit), punit->veteran,
2314  homecity, punit->moves_left, punit->hp, nullptr);
2315 
2316  // Owner changes, nationality not.
2317  gained_unit->nationality = punit->nationality;
2318 
2319  // Copy some more unit fields
2320  gained_unit->fuel = punit->fuel;
2321  gained_unit->paradropped = punit->paradropped;
2322  gained_unit->server.birth_turn = punit->server.birth_turn;
2323 
2324  if (game.server.unitwaittime_extended) {
2325  // Counts as an action for unitwaittime
2326  unit_did_action(gained_unit);
2327  }
2328 
2329  send_unit_info(nullptr, gained_unit);
2330 
2331  // update unit upkeep in the homecity of the victim
2332  if (punit->homecity > 0) {
2333  // update unit upkeep
2335  }
2336  // update unit upkeep in the new homecity
2337  if (homecity > 0) {
2339  }
2340 
2341  // Be sure to wipe the converted unit!
2342  wipe_unit(punit, reason, nullptr);
2343 
2344  return gained_unit; // Returns the replacement.
2345 }
2346 
2358 void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
2359 {
2360  char pkiller_link[MAX_LEN_LINK], punit_link[MAX_LEN_LINK];
2361  struct player *pvictim = unit_owner(punit);
2362  struct player *pvictor = unit_owner(pkiller);
2363  int ransom, unitcount = 0;
2364  bool escaped;
2365 
2366  sz_strlcpy(pkiller_link, unit_link(pkiller));
2367  sz_strlcpy(punit_link, unit_tile_link(punit));
2368 
2369  // The unit is doomed.
2370  punit->server.dying = true;
2371 
2372  if ((game.info.gameloss_style & GAMELOSS_STYLE_LOOT)
2373  && unit_has_type_flag(punit, UTYF_GAMELOSS)) {
2374  ransom = fc_rand(1 + pvictim->economic.gold);
2375  int n;
2376 
2377  // give map
2378  give_distorted_map(pvictim, pvictor, 50, true);
2379 
2380  log_debug("victim has money: %d", pvictim->economic.gold);
2381  pvictor->economic.gold += ransom;
2382  pvictim->economic.gold -= ransom;
2383 
2384  n = 1 + fc_rand(3);
2385 
2386  while (n > 0) {
2387  Tech_type_id ttid = steal_a_tech(pvictor, pvictim, A_UNSET);
2388 
2389  if (ttid == A_NONE) {
2390  log_debug("Worthless enemy doesn't have more techs to steal.");
2391  break;
2392  } else {
2393  log_debug("Pressed tech %s from captured enemy",
2394  qUtf8Printable(research_advance_rule_name(
2395  research_get(pvictor), ttid)));
2396  if (!fc_rand(3)) {
2397  break; // out of luck
2398  }
2399  n--;
2400  }
2401  }
2402 
2403  { // try to submit some cities
2404  int vcsize = city_list_size(pvictim->cities);
2405  int evcsize = vcsize;
2406  int conqsize = evcsize;
2407 
2408  if (evcsize < 3) {
2409  evcsize = 0;
2410  } else {
2411  evcsize -= 3;
2412  }
2413  // about a quarter on average with high numbers less probable
2414  conqsize = fc_rand(fc_rand(evcsize));
2415 
2416  log_debug("conqsize=%d", conqsize);
2417 
2418  if (conqsize > 0) {
2419  bool palace = game.server.savepalace;
2420  bool submit = false;
2421 
2422  game.server.savepalace = false; // moving it around is dumb
2423 
2424  city_list_iterate_safe(pvictim->cities, pcity)
2425  {
2426  // kindly ask the citizens to submit
2427  if (fc_rand(vcsize) < conqsize) {
2428  submit = true;
2429  }
2430  vcsize--;
2431  if (submit) {
2432  conqsize--;
2433  /* Transfer city to the victorious player
2434  * kill all its units outside of a radius of 7,
2435  * give verbose messages of every unit transferred,
2436  * and raze buildings according to raze chance
2437  * (also removes palace) */
2438  (void) transfer_city(pvictor, pcity, 7, true, true, true,
2439  !is_barbarian(pvictor));
2440  submit = false;
2441  }
2442  if (conqsize <= 0) {
2443  break;
2444  }
2445  }
2447  game.server.savepalace = palace;
2448  }
2449  }
2450  }
2451 
2452  // barbarian leader ransom hack
2453  if (is_barbarian(pvictim) && unit_has_type_role(punit, L_BARBARIAN_LEADER)
2454  && (unit_list_size(unit_tile(punit)->units) == 1)
2455  && uclass_has_flag(unit_class_get(pkiller), UCF_COLLECT_RANSOM)) {
2456  // Occupying units can collect ransom if leader is alone in the tile
2457  ransom = (pvictim->economic.gold >= game.server.ransom_gold)
2458  ? game.server.ransom_gold
2459  : pvictim->economic.gold;
2460  notify_player(pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2461  PL_("Barbarian leader captured; %d gold ransom paid.",
2462  "Barbarian leader captured; %d gold ransom paid.",
2463  ransom),
2464  ransom);
2465  pvictor->economic.gold += ransom;
2466  pvictim->economic.gold -= ransom;
2467  send_player_info_c(pvictor, nullptr); // let me see my new gold :-)
2468  unitcount = 1;
2469  }
2470 
2471  if (unitcount == 0) {
2472  unit_list_iterate(unit_tile(punit)->units, vunit)
2473  {
2474  if (pplayers_at_war(pvictor, unit_owner(vunit))) {
2475  unitcount++;
2476  }
2477  }
2479  }
2480 
2481  if (!is_stack_vulnerable(unit_tile(punit)) || unitcount == 1) {
2482  wipe_unit(punit, ULR_KILLED, pvictor);
2483  } else { // unitcount > 1
2484  int i;
2485  int num_killed[MAX_NUM_PLAYER_SLOTS];
2486  int num_escaped[MAX_NUM_PLAYER_SLOTS];
2487  struct unit *other_killed[MAX_NUM_PLAYER_SLOTS];
2488  struct tile *ptile = unit_tile(punit);
2489 
2490  fc_assert(unitcount > 1);
2491 
2492  // initialize
2493  for (i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
2494  num_killed[i] = 0;
2495  other_killed[i] = nullptr;
2496  num_escaped[i] = 0;
2497  }
2498 
2499  // count killed units
2500  unit_list_iterate(ptile->units, vunit)
2501  {
2502  struct player *vplayer = unit_owner(vunit);
2503 
2504  if (pplayers_at_war(pvictor, vplayer)
2505  && is_unit_reachable_at(vunit, pkiller, ptile)) {
2506  escaped = false;
2507 
2508  if (unit_has_type_flag(vunit, UTYF_CANESCAPE)
2509  && !unit_has_type_flag(pkiller, UTYF_CANKILLESCAPING)
2510  && vunit->hp > 0 && vunit->moves_left > pkiller->moves_left
2511  && fc_rand(2)) {
2512  int curr_def_bonus;
2513  int def_bonus = 0;
2514  struct tile *dsttile = nullptr;
2515  int move_cost;
2516 
2517  fc_assert(vunit->hp > 0);
2518 
2519  adjc_iterate(&(wld.map), ptile, ptile2)
2520  {
2521  if (can_exist_at_tile(&(wld.map), vunit->utype, ptile2)
2522  && nullptr == tile_city(ptile2)) {
2523  move_cost = map_move_cost_unit(&(wld.map), vunit, ptile2);
2524  if (pkiller->moves_left <= vunit->moves_left - move_cost
2525  && (is_allied_unit_tile(ptile2, pvictim)
2526  || unit_list_size(ptile2->units))
2527  == 0) {
2528  curr_def_bonus =
2529  tile_extras_defense_bonus(ptile2, vunit->utype);
2530  if (def_bonus <= curr_def_bonus) {
2531  def_bonus = curr_def_bonus;
2532  dsttile = ptile2;
2533  }
2534  }
2535  }
2536  }
2538 
2539  if (dsttile != nullptr) {
2540  /* TODO: Consider if forcing the unit to perform actions that
2541  * includes a move, like "Transport Embark", should be done when
2542  * a regular move is illegal or rather than a regular move. If
2543  * yes: remember to set action_requester to ACT_REQ_RULES. */
2544  move_cost = map_move_cost_unit(&(wld.map), vunit, dsttile);
2545  /* FIXME: Shouldn't unit_move_handling() be used here? This is
2546  * the unit escaping by moving itself. It should therefore
2547  * respect movement rules. */
2548  unit_move(vunit, dsttile, move_cost, nullptr, true, false);
2549  num_escaped[player_index(vplayer)]++;
2550  escaped = true;
2551  unitcount--;
2552  }
2553  }
2554 
2555  if (!escaped) {
2556  num_killed[player_index(vplayer)]++;
2557  if (vunit != punit) {
2558  other_killed[player_index(vplayer)] = vunit;
2559  other_killed[player_index(pvictor)] = vunit;
2560  }
2561  }
2562  }
2563  }
2565 
2566  /* Inform the destroyer again if more than one unit was killed */
2567  if (unitcount > 1) {
2568  notify_player(
2569  pvictor, unit_tile(pkiller), E_UNIT_WIN_ATT, ftc_server,
2570  /* TRANS: "Another unit was eliminated by..." */
2571  PL_("Another unit was eliminated by your attacking %s!",
2572  "Another %2$d units were eliminated by your attacking %1$s!",
2573  unitcount - 1),
2574  pkiller_link, unitcount - 1);
2575  }
2576 
2577  /* inform the owners: this only tells about owned units that were killed.
2578  * there may have been 20 units who died but if only 2 belonged to the
2579  * particular player they'll only learn about those.
2580  *
2581  * Also if a large number of units die you don't find out what type
2582  * they all are. */
2583  for (i = 0; i < MAX_NUM_PLAYER_SLOTS; i++) {
2584  /* The owner can get two extra messages.
2585  * One if more units of their own died
2586  * One if allied units died as well. */
2587  if (i == player_index(pvictim)) {
2588  if (num_killed[i] > 1) {
2589  fc_assert(other_killed[i] != punit);
2590  notify_player(
2591  player_by_number(i), ptile, E_UNIT_LOST_DEF, ftc_server,
2592  /* TRANS: "One other unit lost when the celtiberian armor
2593  defeated your mech inf. */
2594  PL_("One other unit lost when the %s %s defeated your %s.",
2595  "%4$d other units lost when the %1$s %2$s defeated your "
2596  "%3$s.",
2597  num_killed[i] - 1),
2598  nation_adjective_for_player(pvictor), pkiller_link, punit_link,
2599  num_killed[i] - 1);
2600  }
2601  if ((unitcount - 1) > num_killed[i]) {
2602  notify_player(
2603  player_by_number(i), ptile, E_UNIT_LOST_DEF, ftc_server,
2604  /* TRANS: "One allied unit lost when the celtiberian armor
2605  defeated your mech inf. */
2606  PL_("One allied unit lost when the %s %s defeated your %s.",
2607  "%4$d allied units lost when the %1$s %2$s defeated your "
2608  "%3$s.",
2609  unitcount),
2610  nation_adjective_for_player(pvictor), pkiller_link, punit_link,
2611  unitcount);
2612  }
2613  } else {
2614  if (num_killed[i] >= 1) {
2615  notify_player(
2616  player_by_number(i), ptile, E_UNIT_LOST_DEF, ftc_server,
2617  /* TRANS: "One unit lost when the celtiberian armor
2618  defeated the roman mech inf. */
2619  PL_("One unit lost when the %s %s defeated the %s %s.",
2620  "%5$d units lost when the %1$s %2$s defeated the %3$s "
2621  "%4$s.",
2622  num_killed[i]),
2623  nation_adjective_for_player(pvictor), pkiller_link,
2624  nation_adjective_for_player(pvictim), punit_link,
2625  num_killed[i]);
2626  }
2627  }
2628  }
2629 
2630  // Inform the owner of the units that escaped.
2631  for (i = 0; i < MAX_NUM_PLAYER_SLOTS; ++i) {
2632  if (0 < num_escaped[i]) {
2633  notify_player(player_by_number(i), unit_tile(punit), E_UNIT_ESCAPED,
2634  ftc_server,
2635  PL_("%d unit escaped from attack by %s %s",
2636  "%d units escaped from attack by %s %s",
2637  num_escaped[i]),
2638  num_escaped[i], pkiller_link,
2640  }
2641  }
2642 
2643  /* remove the units - note the logic of which units actually die
2644  * must be mimiced exactly in at least one place up above. */
2645  punit = nullptr; // wiped during following iteration so unsafe to use
2646 
2647  unit_list_iterate_safe(ptile->units, punit2)
2648  {
2649  if (pplayers_at_war(pvictor, unit_owner(punit2))
2650  && is_unit_reachable_at(punit2, pkiller, ptile)) {
2651  wipe_unit(punit2, ULR_KILLED, pvictor);
2652  }
2653  }
2655  }
2656 }
2657 
2662 void package_unit(struct unit *punit, struct packet_unit_info *packet)
2663 {
2664  packet->id = punit->id;
2665  packet->owner = player_number(unit_owner(punit));
2666  packet->nationality = player_number(unit_nationality(punit));
2667  packet->tile = tile_index(unit_tile(punit));
2668  packet->facing = punit->facing;
2669  packet->homecity = punit->homecity;
2670  fc_strlcpy(packet->name, punit->name.toUtf8(), ARRAY_SIZE(packet->name));
2671  output_type_iterate(o) { packet->upkeep[o] = punit->upkeep[o]; }
2673  packet->veteran = punit->veteran;
2674  packet->type = utype_number(unit_type_get(punit));
2675  packet->movesleft = punit->moves_left;
2676  packet->hp = punit->hp;
2677  packet->activity = punit->activity;
2678  packet->activity_count = punit->activity_count;
2679 
2680  if (punit->activity_target != nullptr) {
2681  packet->activity_tgt = extra_index(punit->activity_target);
2682  } else {
2683  packet->activity_tgt = EXTRA_NONE;
2684  }
2685 
2686  packet->changed_from = punit->changed_from;
2687  packet->changed_from_count = punit->changed_from_count;
2688 
2689  if (punit->changed_from_target != nullptr) {
2690  packet->changed_from_tgt = extra_index(punit->changed_from_target);
2691  } else {
2692  packet->changed_from_tgt = EXTRA_NONE;
2693  }
2694 
2695  packet->ssa_controller = punit->ssa_controller;
2696  packet->fuel = punit->fuel;
2697  packet->goto_tile =
2698  (nullptr != punit->goto_tile ? tile_index(punit->goto_tile) : -1);
2699  packet->paradropped = punit->paradropped;
2700  packet->done_moving = punit->done_moving;
2701  packet->stay = punit->stay;
2702  if (!unit_transported(punit)) {
2703  packet->transported = false;
2704  packet->transported_by = 0;
2705  } else {
2706  packet->transported = true;
2707  packet->transported_by = unit_transport_get(punit)->id;
2708  }
2709  if (punit->carrying != nullptr) {
2710  packet->carrying = goods_index(punit->carrying);
2711  } else {
2712  packet->carrying = -1;
2713  }
2714  packet->occupied = (get_transporter_occupancy(punit) > 0);
2715  packet->battlegroup = punit->battlegroup;
2716  packet->has_orders = punit->has_orders;
2717  if (punit->has_orders) {
2718  packet->orders_length = punit->orders.length;
2719  packet->orders_index = punit->orders.index;
2720  packet->orders_repeat = punit->orders.repeat;
2721  packet->orders_vigilant = punit->orders.vigilant;
2722  memcpy(packet->orders, punit->orders.list,
2723  punit->orders.length * sizeof(struct unit_order));
2724  } else {
2725  packet->orders_length = packet->orders_index = 0;
2726  packet->orders_repeat = packet->orders_vigilant = false;
2727  // No need to initialize array.
2728  }
2729  packet->action_turn = punit->action_turn;
2730  // client doesnt have access to game.server.unitwaittime, so use release
2731  // time
2732  time_t gotime = game.server.unitwaittime + punit->action_timestamp;
2733  // convert to UTC using Qt
2734  QDateTime localtime;
2735  localtime.setSecsSinceEpoch(gotime);
2736  QDateTime utctime(localtime.toUTC());
2737  gotime = utctime.toSecsSinceEpoch();
2738  packet->action_timestamp = gotime;
2739  packet->action_decision_want = punit->action_decision_want;
2740  packet->action_decision_tile =
2743 }
2744 
2750 void package_short_unit(struct unit *punit,
2751  struct packet_unit_short_info *packet,
2752  enum unit_info_use packet_use, int info_city_id)
2753 {
2754  packet->packet_use = packet_use;
2755  packet->info_city_id = info_city_id;
2756 
2757  packet->id = punit->id;
2758  packet->owner = player_number(unit_owner(punit));
2759  packet->tile = tile_index(unit_tile(punit));
2760  packet->facing = punit->facing;
2761  packet->veteran = punit->veteran;
2762  packet->type = utype_number(unit_type_get(punit));
2763  packet->hp = punit->hp;
2764  packet->occupied = (get_transporter_occupancy(punit) > 0);
2765  fc_strlcpy(packet->name, punit->name.toUtf8(), ARRAY_SIZE(packet->name));
2766  if (punit->activity == ACTIVITY_EXPLORE
2767  || punit->activity == ACTIVITY_GOTO) {
2768  packet->activity = ACTIVITY_IDLE;
2769  } else {
2770  packet->activity = punit->activity;
2771  }
2772 
2773  if (punit->activity_target == nullptr) {
2774  packet->activity_tgt = EXTRA_NONE;
2775  } else {
2776  packet->activity_tgt = extra_index(punit->activity_target);
2777  }
2778 
2779  /* Transported_by information is sent to the client even for units that
2780  * aren't fully known. Note that for non-allied players, any transported
2781  * unit can't be seen at all. For allied players we have to know if
2782  * transporters have room in them so that we can load units properly. */
2783  if (!unit_transported(punit)) {
2784  packet->transported = false;
2785  packet->transported_by = 0;
2786  } else {
2787  packet->transported = true;
2788  packet->transported_by = unit_transport_get(punit)->id;
2789  }
2790 }
2791 
2795 void unit_goes_out_of_sight(struct player *pplayer, const unit *punit)
2796 {
2797  dlsend_packet_unit_remove(pplayer->connections, punit->id);
2798  if (punit->server.moving != nullptr) {
2799  // Update status of 'pplayer' vision for 'punit'.
2800  BV_CLR(punit->server.moving->can_see_unit, player_index(pplayer));
2801  }
2802 }
2803 
2808 void send_unit_info(struct conn_list *dest, struct unit *punit)
2809 {
2810  const struct player *powner;
2811  struct packet_unit_info info;
2812  struct packet_unit_short_info sinfo;
2813  struct unit_move_data *pdata;
2814 
2815  if (dest == nullptr) {
2816  dest = game.est_connections;
2817  }
2818 
2819  CHECK_UNIT(punit);
2820 
2821  powner = unit_owner(punit);
2822  package_unit(punit, &info);
2824  pdata = punit->server.moving;
2825 
2826  conn_list_iterate(dest, pconn)
2827  {
2828  struct player *pplayer = conn_get_player(pconn);
2829 
2830  // Be careful to consider all cases where pplayer is nullptr...
2831  if (pplayer == nullptr) {
2832  if (pconn->observer) {
2833  send_packet_unit_info(pconn, &info);
2834  }
2835  } else if (pplayer == powner) {
2836  send_packet_unit_info(pconn, &info);
2837  if (pdata != nullptr) {
2838  BV_SET(pdata->can_see_unit, player_index(pplayer));
2839  }
2840  } else if (players_on_same_team(pplayer, powner)) {
2841  send_packet_unit_info(pconn, &info);
2842  if (pdata != nullptr) {
2843  BV_SET(pdata->can_see_unit, player_index(pplayer));
2844  }
2845  } else if (can_player_see_unit(pplayer, punit)) {
2846  send_packet_unit_short_info(pconn, &sinfo, false);
2847  if (pdata != nullptr) {
2848  BV_SET(pdata->can_see_unit, player_index(pplayer));
2849  }
2850  }
2851  }
2853 }
2854 
2859 void send_all_known_units(struct conn_list *dest)
2860 {
2861  conn_list_do_buffer(dest);
2862  conn_list_iterate(dest, pconn)
2863  {
2864  struct player *pplayer = pconn->playing;
2865 
2866  if (nullptr == pplayer && !pconn->observer) {
2867  continue;
2868  }
2869 
2870  players_iterate(unitowner)
2871  {
2872  unit_list_iterate(unitowner->units, punit)
2873  {
2874  send_unit_info(dest, punit);
2875  }
2877  }
2879  }
2881  conn_list_do_unbuffer(dest);
2882  flush_packets();
2883 }
2884 
2892 static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
2893 {
2894  struct city *pcity = nullptr;
2895  int pop_loss;
2896 
2897  pcity = tile_city(ptile);
2898 
2899  unit_list_iterate_safe(ptile->units, punit)
2900  {
2901  // unit in a city may survive
2902  if (pcity
2903  && fc_rand(100) < game.info.nuke_defender_survival_chance_pct) {
2904  continue;
2905  }
2906  notify_player(unit_owner(punit), ptile, E_UNIT_LOST_MISC, ftc_server,
2907  _("Your %s was nuked by %s."), unit_tile_link(punit),
2908  pplayer == unit_owner(punit)
2909  ? _("yourself")
2910  : nation_plural_for_player(pplayer));
2911  if (unit_owner(punit) != pplayer) {
2912  notify_player(pplayer, ptile, E_UNIT_WIN_ATT, ftc_server,
2913  _("The %s %s was nuked."),
2915  unit_tile_link(punit));
2916  }
2917  wipe_unit(punit, ULR_NUKE, pplayer);
2918  }
2920 
2921  if (pcity) {
2922  notify_player(city_owner(pcity), ptile, E_CITY_NUKED, ftc_server,
2923  _("%s was nuked by %s."), city_link(pcity),
2924  pplayer == city_owner(pcity)
2925  ? _("yourself")
2926  : nation_plural_for_player(pplayer));
2927 
2928  if (city_owner(pcity) != pplayer) {
2929  notify_player(pplayer, ptile, E_CITY_NUKED, ftc_server,
2930  _("You nuked %s."), city_link(pcity));
2931  }
2932 
2933  city_built_iterate(pcity, pimprove)
2934  {
2935  /* only destroy regular improvements, not wonders, and not those
2936  * that are especially protected from sabotage (e.g. Walls) */
2937  if (is_improvement(pimprove) && pimprove->sabotage == 100
2938  && fc_rand(100) < (float(
2939  get_player_bonus(pplayer, EFT_NUKE_IMPROVEMENT_PCT)))) {
2940  notify_player(city_owner(pcity), city_tile(pcity), E_CITY_NUKED,
2941  ftc_server, _("%s destroyed in nuclear explosion!"),
2942  improvement_name_translation(pimprove));
2943  city_remove_improvement(pcity, pimprove);
2944  }
2945  }
2947 
2948  pop_loss = (game.info.nuke_pop_loss_pct * city_size_get(pcity)) / 100;
2949  city_reduce_size(pcity, pop_loss, pplayer, "nuke");
2950 
2951  send_city_info(nullptr, pcity);
2952  }
2953 
2954  // Nuke tile extras
2955  const auto chance = get_target_bonus_effects(
2956  nullptr, pplayer, extra_owner(ptile), pcity, nullptr, nullptr, nullptr,
2957  nullptr, nullptr, nullptr, nullptr, EFT_NUKE_INFRASTRUCTURE_PCT);
2958  if (chance > 0) {
2959  extra_type_iterate(extra)
2960  {
2961  // Only destroy Infra
2962  if (extra->category != ECAT_INFRA) {
2963  continue;
2964  }
2965 
2966  // Only destroy what the tile has
2967  if (!tile_has_extra(ptile, extra)) {
2968  continue;
2969  }
2970 
2971  // Only destroy if allowed
2972  if (!player_can_remove_extra(extra, pplayer, ptile)) {
2973  continue;
2974  }
2975 
2976  if (fc_rand(100) <= chance) {
2977  // Destroy it
2978  destroy_extra(ptile, extra);
2979  }
2980  }
2982  }
2983 
2984  if (fc_rand(2) == 1) {
2985  struct extra_type *pextra;
2986 
2987  pextra = rand_extra_for_tile(ptile, EC_FALLOUT, false);
2988  if (pextra != nullptr && !tile_has_extra(ptile, pextra)) {
2989  tile_add_extra(ptile, pextra);
2990  update_tile_knowledge(ptile);
2991  }
2992  }
2993 }
2994 
2999 void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
3000 {
3001  square_iterate(&(wld.map), ptile, 1, ptile1)
3002  {
3003  do_nuke_tile(pplayer, ptile1);
3004  }
3006 
3007  script_server_signal_emit("nuke_exploded", 2, API_TYPE_TILE, ptile,
3008  API_TYPE_PLAYER, pplayer);
3009  notify_conn(nullptr, ptile, E_NUKE, ftc_server,
3010  _("The %s detonated a nuke!"),
3011  nation_plural_for_player(pplayer));
3012 }
3013 
3018 bool do_airline(struct unit *punit, struct city *pdest_city,
3019  const struct action *paction)
3020 {
3021  struct city *psrc_city = tile_city(unit_tile(punit));
3022 
3023  notify_player(unit_owner(punit), city_tile(pdest_city), E_UNIT_RELOCATED,
3024  ftc_server, _("%s transported successfully."),
3025  unit_link(punit));
3026 
3027  unit_move(punit, pdest_city->tile, punit->moves_left, nullptr,
3028  // Can only airlift to allied and domestic cities
3029  false, false);
3030 
3031  // Update airlift fields.
3032  if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
3033  psrc_city->airlift--;
3034  send_city_info(city_owner(psrc_city), psrc_city);
3035  }
3036  if (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
3037  pdest_city->airlift--;
3038  send_city_info(city_owner(pdest_city), pdest_city);
3039  }
3040 
3041  return true;
3042 }
3043 
3047 void do_explore(struct unit *punit)
3048 {
3049  switch (manage_auto_explorer(punit)) {
3050  case MR_DEATH:
3051  // don't use punit!
3052  return;
3053  case MR_NOT_ALLOWED:
3054  // Needed for something else
3055  return;
3056  case MR_OK:
3057  /* FIXME: manage_auto_explorer() isn't supposed to change the activity,
3058  * but don't count on this. See PR#39792.
3059  */
3060  if (punit->activity == ACTIVITY_EXPLORE) {
3061  break;
3062  }
3063  // fallthru
3064  default:
3065  unit_activity_handling(punit, ACTIVITY_IDLE);
3066 
3067  /* FIXME: When the manage_auto_explorer() call changes the activity from
3068  * EXPLORE to IDLE, in unit_activity_handling() ai.control is left
3069  * alone. We reset it here. See PR#12931. */
3070  punit->ssa_controller = SSA_NONE;
3071  break;
3072  }
3073 
3074  send_unit_info(nullptr, punit); // probably duplicate
3075 }
3076 
3082 bool do_paradrop(struct unit *punit, struct tile *ptile,
3083  const struct action *paction)
3084 {
3085  struct player *pplayer = unit_owner(punit);
3086 
3087  // Hard requirements
3088  /* FIXME: hard requirements belong in common/actions's
3089  * is_action_possible() and the explanation texts belong in
3090  * server/unithand's action not enabled system (expl_act_not_enabl(),
3091  * ane_kind, explain_why_no_action_enabled(), etc)
3092  */
3093  if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
3094  // Only take in account values from player map.
3095  const struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
3096 
3097  if (nullptr == plrtile->site
3098  && !is_native_to_class(unit_class_get(punit), plrtile->terrain,
3099  &(plrtile->extras))) {
3100  notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3101  _("This unit cannot paradrop into %s."),
3102  terrain_name_translation(plrtile->terrain));
3103  return false;
3104  }
3105 
3106  if (nullptr != plrtile->site && plrtile->owner != nullptr
3107  && pplayers_non_attack(pplayer, plrtile->owner)) {
3108  notify_player(pplayer, ptile, E_BAD_COMMAND, ftc_server,
3109  _("Cannot attack unless you declare war first."));
3110  return false;
3111  }
3112  }
3113 
3114  // Kill the unit when the landing goes wrong.
3115 
3116  // Safe terrain, really? Not transformed since player last saw it.
3117  if (!can_unit_exist_at_tile(&(wld.map), punit, ptile)
3118  && (!game.info.paradrop_to_transport
3119  || !unit_could_load_at(punit, ptile))) {
3120  map_show_circle(pplayer, ptile, unit_type_get(punit)->vision_radius_sq);
3121  notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3122  _("Your %s paradropped into the %s and was lost."),
3123  unit_tile_link(punit),
3125  pplayer->score.units_lost++;
3126  server_remove_unit(punit, ULR_NONNATIVE_TERR);
3127  return true;
3128  }
3129 
3130  if (is_non_attack_city_tile(ptile, pplayer)
3131  || (is_non_allied_city_tile(ptile, pplayer)
3132  && (pplayer->ai_common.barbarian_type == ANIMAL_BARBARIAN
3133  || !uclass_has_flag(unit_class_get(punit), UCF_CAN_OCCUPY_CITY)
3134  || unit_has_type_flag(punit, UTYF_CIVILIAN)))
3135  || is_non_allied_unit_tile(ptile, pplayer)) {
3136  map_show_circle(pplayer, ptile, unit_type_get(punit)->vision_radius_sq);
3137  maybe_make_contact(ptile, pplayer);
3138  notify_player(pplayer, ptile, E_UNIT_LOST_MISC, ftc_server,
3139  _("Your %s was killed by enemy units at the "
3140  "paradrop destination."),
3141  unit_tile_link(punit));
3142  /* TODO: Should defender score.units_killed get increased too?
3143  * What if there's units of several allied players? Should the
3144  * city owner or owner of the first/random unit get the kill? */
3145  pplayer->score.units_lost++;
3146  server_remove_unit(punit, ULR_KILLED);
3147  return true;
3148  }
3149 
3150  // All ok
3151  punit->paradropped = true;
3152  if (unit_move(
3153  punit, ptile,
3154  // Done by Action_Success_Actor_Move_Cost
3155  0, nullptr, game.info.paradrop_to_transport,
3156  /* A paradrop into a non allied city results in a city
3157  * occupation. */
3158  /* FIXME: move the following actor requirements to the
3159  * ruleset. One alternative is to split "Paradrop Unit".
3160  * Another is to use different enablers. */
3161  (pplayer->ai_common.barbarian_type != ANIMAL_BARBARIAN
3162  && uclass_has_flag(unit_class_get(punit), UCF_CAN_OCCUPY_CITY)
3163  && !unit_has_type_flag(punit, UTYF_CIVILIAN)
3164  && is_non_allied_city_tile(ptile, pplayer)))) {
3165  // Ensure we finished on valid state.
3166  fc_assert(can_unit_exist_at_tile(&(wld.map), punit, unit_tile(punit))
3167  || unit_transported(punit));
3168  }
3169 
3170  return true;
3171 }
3172 
3177 static bool hut_get_limited(struct unit *punit)
3178 {
3179  bool ok = true;
3180  int hut_chance = fc_rand(12);
3181  struct player *pplayer = unit_owner(punit);
3182  // 1 in 12 to get barbarians
3183  if (hut_chance != 0) {
3184  int cred = 25;
3185  notify_player(pplayer, unit_tile(punit), E_HUT_GOLD, ftc_server,
3186  PL_("You found %d gold.", "You found %d gold.", cred),
3187  cred);
3188  pplayer->economic.gold += cred;
3189  } else if (city_exists_within_max_city_map(unit_tile(punit), true)
3190  || unit_has_type_flag(punit, UTYF_GAMELOSS)) {
3191  notify_player(pplayer, unit_tile(punit), E_HUT_BARB_CITY_NEAR,
3192  ftc_server, _("An abandoned village is here."));
3193  } else {
3194  notify_player(pplayer, unit_tile(punit), E_HUT_BARB_KILLED, ftc_server,
3195  _("Your %s has been killed by barbarians!"),
3196  unit_tile_link(punit));
3197  wipe_unit(punit, ULR_BARB_UNLEASH, nullptr);
3198  ok = false;
3199  }
3200  return ok;
3201 }
3202 
3207 static void unit_enter_hut(struct unit *punit)
3208 {
3209  struct player *pplayer = unit_owner(punit);
3210  int id = punit->id;
3211  enum hut_behavior behavior = unit_class_get(punit)->hut_behavior;
3212  struct tile *ptile = unit_tile(punit);
3213  bool hut = false;
3214 
3215  if (behavior == HUT_NOTHING) {
3216  return;
3217  }
3218 
3219  extra_type_by_rmcause_iterate(ERM_ENTER, pextra)
3220  {
3221  if (tile_has_extra(ptile, pextra)
3222  && are_reqs_active(pplayer, tile_owner(ptile), nullptr, nullptr,
3223  ptile, nullptr, nullptr, nullptr, nullptr,
3224  nullptr, &pextra->rmreqs, RPT_CERTAIN)) {
3225  hut = true;
3226  // FIXME: are all enter-removes extras worth counting?
3227  pplayer->server.huts++;
3228 
3229  destroy_extra(ptile, pextra);
3231 
3232  /* FIXME: enable different classes
3233  * to behave differently with different huts */
3234  if (behavior == HUT_FRIGHTEN) {
3235  script_server_signal_emit("hut_frighten", punit,
3236  extra_rule_name(pextra));
3237  } else if (is_ai(pplayer) && has_handicap(pplayer, H_LIMITEDHUTS)) {
3238  // AI with H_LIMITEDHUTS only gets 25 gold (or barbs if unlucky)
3239  (void) hut_get_limited(punit);
3240  } else {
3241  script_server_signal_emit("hut_enter", punit,
3242  extra_rule_name(pextra));
3243  }
3244 
3245  // We need punit for the callbacks, can't continue if the unit died
3246  if (!unit_is_alive(id)) {
3247  break;
3248  }
3249  }
3250  }
3252 
3253  if (hut) {
3254  send_player_info_c(pplayer, pplayer->connections); // eg, gold
3255  }
3256 }
3257 
3261 void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
3262 {
3263  bv_player can_see_unit;
3264 
3265  fc_assert_ret(punit != nullptr);
3266  fc_assert_ret(ptrans != nullptr);
3267 
3268  BV_CLR_ALL(can_see_unit);
3269  players_iterate(pplayer)
3270  {
3271  if (can_player_see_unit(pplayer, punit)) {
3272  BV_SET(can_see_unit, player_index(pplayer));
3273  }
3274  }
3276 
3277  unit_transport_load(punit, ptrans, false);
3278 
3279  players_iterate(pplayer)
3280  {
3281  if (BV_ISSET(can_see_unit, player_index(pplayer))
3282  && !can_player_see_unit(pplayer, punit)) {
3283  unit_goes_out_of_sight(pplayer, punit);
3284  }
3285  }
3287 
3288  send_unit_info(nullptr, punit);
3289  send_unit_info(nullptr, ptrans);
3290 }
3291 
3295 static void unit_transport_load_tp_status(struct unit *punit,
3296  struct unit *ptrans, bool force)
3297 {
3298  bool had_cargo;
3299 
3300  fc_assert_ret(punit != nullptr);
3301  fc_assert_ret(ptrans != nullptr);
3302 
3303  had_cargo = get_transporter_occupancy(ptrans) > 0;
3304 
3305  unit_transport_load(punit, ptrans, force);
3306 
3307  if (!had_cargo) {
3308  // Transport's loaded status changed
3309  send_unit_info(nullptr, ptrans);
3310  }
3311 }
3312 
3317 {
3318  struct unit *ptrans;
3319 
3320  fc_assert_ret(punit);
3321 
3322  ptrans = unit_transport_get(punit);
3323 
3324  fc_assert_ret(ptrans);
3325 
3326  unit_transport_unload(punit);
3327 
3328  send_unit_info(nullptr, punit);
3329  send_unit_info(nullptr, ptrans);
3330 }
3331 
3336 static void autoattack_prob_free(struct autoattack_prob *prob)
3337 {
3338  delete prob;
3339 }
3340 
3350 static int compare_units(const struct autoattack_prob *const *p1,
3351  const struct autoattack_prob *const *q1)
3352 {
3353  const struct unit *p1unit = game_unit_by_number((*p1)->unit_id);
3354  const struct unit *q1unit = game_unit_by_number((*q1)->unit_id);
3355 
3356  /* Sort by transport depth first. This makes sure that no transport
3357  * attacks before its cargo does -- cargo sorts earlier in the list. */
3358  {
3359  const struct unit *p1trans = p1unit, *q1trans = q1unit;
3360 
3361  /* Walk the transport stacks in parallel, so as to bail out as soon as
3362  * one of them is empty (avoid walking deep stacks more often than
3363  * necessary). */
3364  while (p1trans && q1trans) {
3365  p1trans = unit_transport_get(p1trans);
3366  q1trans = unit_transport_get(q1trans);
3367  }
3368  if (!p1trans && q1trans) {
3369  /* q1 is at greater depth (perhaps it's p1's cargo). It should sort
3370  * earlier in the list (p1 > q1). */
3371  return 1;
3372  } else if (p1trans && !q1trans) {
3373  // p1 is at greater depth, so should sort earlier (p1 < q1).
3374  return -1;
3375  }
3376  // else same depth, so move on to checking win chance:
3377  }
3378 
3379  /* Put the units with the highest probability of success first. The up
3380  * side of this is that units with bonuses against the victim attacks
3381  * before other units. The downside is that strong units can be led
3382  * away by sacrificial units. */
3383  return (-1
3384  // Assume the worst.
3385  * action_prob_cmp_pessimist((*p1)->prob, (*q1)->prob));
3386 }
3387 
3392 static bool unit_survive_autoattack(struct unit *punit)
3393 {
3394  struct autoattack_prob_list *autoattack;
3395  int moves = punit->moves_left;
3396  int sanity1 = punit->id;
3397 
3398  if (!game.server.autoattack) {
3399  return true;
3400  }
3401 
3402  autoattack = autoattack_prob_list_new_full(autoattack_prob_free);
3403 
3404  // Kludge to prevent attack power from dropping to zero during calc
3405  punit->moves_left = MAX(punit->moves_left, 1);
3406 
3407  adjc_iterate(&(wld.map), unit_tile(punit), ptile)
3408  {
3409  // First add all eligible units to a autoattack list
3410  unit_list_iterate(ptile->units, penemy)
3411  {
3412  auto *probability = new autoattack_prob;
3413  struct tile *tgt_tile = unit_tile(punit);
3414 
3415  fc_assert_action(tgt_tile, continue);
3416 
3417  probability->prob = action_auto_perf_unit_prob(
3418  AAPC_UNIT_MOVED_ADJ, penemy, unit_owner(punit), nullptr, tgt_tile,
3419  tile_city(tgt_tile), punit, nullptr);
3420 
3421  if (action_prob_possible(probability->prob)) {
3422  probability->unit_id = penemy->id;
3423  autoattack_prob_list_prepend(autoattack, probability);
3424  } else {
3425  delete probability;
3426  probability = nullptr;
3427  }
3428  }
3430  }
3432 
3433  /* Sort the potential attackers from highest to lowest success
3434  * probability. */
3435  if (autoattack_prob_list_size(autoattack) >= 2) {
3436  autoattack_prob_list_sort(autoattack, &compare_units);
3437  }
3438 
3439  autoattack_prob_list_iterate_safe(autoattack, peprob, penemy)
3440  {
3441  int sanity2 = penemy->id;
3442  struct tile *ptile = unit_tile(penemy);
3443  struct unit *enemy_defender = get_defender(punit, ptile);
3444  double punitwin, penemywin;
3445  double threshold = 0.25;
3446  struct tile *tgt_tile = unit_tile(punit);
3447 
3448  fc_assert(tgt_tile);
3449 
3450  if (tile_city(ptile) && unit_list_size(ptile->units) == 1) {
3451  // Don't leave city defenseless
3452  threshold = 0.90;
3453  }
3454 
3455  if (nullptr != enemy_defender) {
3456  punitwin = unit_win_chance(punit, enemy_defender);
3457  } else {
3458  // 'penemy' can attack 'punit' but it may be not reciproque.
3459  punitwin = 1.0;
3460  }
3461 
3462  // Previous attacks may have changed the odds. Recalculate.
3463  peprob->prob = action_auto_perf_unit_prob(
3464  AAPC_UNIT_MOVED_ADJ, penemy, unit_owner(punit), nullptr, tgt_tile,
3465  tile_city(tgt_tile), punit, nullptr);
3466 
3467  if (!action_prob_possible(peprob->prob)) {
3468  // No longer legal.
3469  continue;
3470  }
3471 
3472  // Assume the worst.
3473  penemywin = action_prob_to_0_to_1_pessimist(peprob->prob);
3474 
3475  if ((penemywin > 1.0 - punitwin
3476  || unit_has_type_flag(punit, UTYF_PROVOKING))
3477  && penemywin > threshold) {
3478 #ifdef REALLY_DEBUG_THIS
3479  log_test("AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3480  unit_rule_name(penemy), unit_rule_name(punit),
3481  TILE_XY(unit_tile(punit)), penemywin, 1.0 - punitwin,
3482  threshold);
3483 #endif
3484 
3485  unit_activity_handling(penemy, ACTIVITY_IDLE);
3486  action_auto_perf_unit_do(AAPC_UNIT_MOVED_ADJ, penemy,
3487  unit_owner(punit), nullptr, tgt_tile,
3488  tile_city(tgt_tile), punit, nullptr);
3489  } else {
3490 #ifdef REALLY_DEBUG_THIS
3491  log_test("!AA %s -> %s (%d,%d) %.2f > %.2f && > %.2f",
3492  unit_rule_name(penemy), unit_rule_name(punit),
3493  TILE_XY(unit_tile(punit)), penemywin, 1.0 - punitwin,
3494  threshold);
3495 #endif
3496  continue;
3497  }
3498 
3499  if (game_unit_by_number(sanity2)) {
3500  send_unit_info(nullptr, penemy);
3501  }
3502  if (game_unit_by_number(sanity1)) {
3503  send_unit_info(nullptr, punit);
3504  } else {
3505  autoattack_prob_list_destroy(autoattack);
3506  return false; // moving unit dead
3507  }
3508  }
3510 
3511  autoattack_prob_list_destroy(autoattack);
3512  if (game_unit_by_number(sanity1)) {
3513  // We could have lost movement in combat
3514  punit->moves_left = MIN(punit->moves_left, moves);
3515  send_unit_info(nullptr, punit);
3516  return true;
3517  } else {
3518  return false;
3519  }
3520 }
3521 
3525 static void cancel_orders(struct unit *punit, const char *dbg_msg)
3526 {
3527  free_unit_orders(punit);
3528  send_unit_info(nullptr, punit);
3529  log_debug("%s", dbg_msg);
3530 }
3531 
3536 static void wakeup_neighbor_sentries(struct unit *punit)
3537 {
3538  bool alone_in_city;
3539 
3540  if (nullptr != tile_city(unit_tile(punit))) {
3541  int count = 0;
3542 
3543  unit_list_iterate(unit_tile(punit)->units, aunit)
3544  {
3545  // Consider only units not transported.
3546  if (!unit_transported(aunit)) {
3547  count++;
3548  }
3549  }
3551 
3552  alone_in_city = (1 == count);
3553  } else {
3554  alone_in_city = false;
3555  }
3556 
3557  // There may be sentried units with a sightrange > sentry_range, but we
3558  // don't wake them up.
3559  square_iterate(&(wld.map), unit_tile(punit), game.control.sentry_range,
3560  ptile)
3561  {
3562  unit_list_iterate(ptile->units, penemy)
3563  {
3564  int distance_sq = sq_map_distance(unit_tile(punit), ptile);
3565  int radius_sq = get_unit_vision_at(penemy, unit_tile(penemy), V_MAIN);
3566 
3567  if (!pplayers_allied(unit_owner(punit), unit_owner(penemy))
3568  && penemy->activity == ACTIVITY_SENTRY
3569  && radius_sq >= distance_sq
3570  /* If the unit moved on a city, and the unit is alone, consider
3571  * it is visible. */
3572  && (alone_in_city
3573  || can_player_see_unit(unit_owner(penemy), punit))
3574  // on board transport; don't awaken
3575  && can_unit_exist_at_tile(&(wld.map), penemy, unit_tile(penemy))) {
3576  set_unit_activity(penemy, ACTIVITY_IDLE);
3577  send_unit_info(nullptr, penemy);
3578  notify_player(
3579  unit_owner(penemy), unit_tile(punit), E_UNIT_ORDERS, ftc_server,
3580  _("Your sentried %s spotted a %s %s %s [id:%d, %s, hp:%d] at "
3581  "%s."),
3582  unit_link(penemy),
3585  punit->id, unit_veteran_level_and_bonus(punit), punit->hp,
3586  tile_link(punit->tile));
3587  }
3588  }
3590  }
3592 
3593  // Wakeup patrolling units we bump into.
3594  square_iterate(&(wld.map), unit_tile(punit), game.control.sentry_range,
3595  ptile)
3596  {
3597  unit_list_iterate(ptile->units, ppatrol)
3598  {
3599  if (punit != ppatrol && unit_has_orders(ppatrol)
3600  && ppatrol->orders.vigilant) {
3601  if (maybe_cancel_patrol_due_to_enemy(ppatrol)) {
3602  cancel_orders(ppatrol, " stopping because of nearby enemy");
3603  notify_player(unit_owner(ppatrol), unit_tile(ppatrol),
3604  E_UNIT_ORDERS, ftc_server,
3605  _("Orders for %s aborted after enemy movement was "
3606  "spotted."),
3607  unit_link(ppatrol));
3608  }
3609  }
3610  }
3612  }
3614 }
3615 
3625 static bool unit_move_consequences(struct unit *punit, struct tile *src_tile,
3626  struct tile *dst_tile, bool passenger,
3627  bool conquer_city_allowed)
3628 {
3629  struct city *fromcity = tile_city(src_tile);
3630  struct city *tocity = tile_city(dst_tile);
3631  struct city *homecity_start_pos = nullptr;
3632  struct city *homecity_end_pos = nullptr;
3633  int homecity_id_start_pos = punit->homecity;
3634  int homecity_id_end_pos = punit->homecity;
3635  struct player *pplayer_start_pos = unit_owner(punit);
3636  struct player *pplayer_end_pos = pplayer_start_pos;
3637  const struct unit_type *type_start_pos = unit_type_get(punit);
3638  const struct unit_type *type_end_pos = type_start_pos;
3639  bool refresh_homecity_start_pos = false;
3640  bool refresh_homecity_end_pos = false;
3641  int saved_id = punit->id;
3642  bool alive = true;
3643 
3644  if (tocity && conquer_city_allowed) {
3645  if (!passenger) {
3646  // The unit that does the move may conquer.
3647  unit_conquer_city(punit, tocity);
3648  }
3649 
3650  /* Run for passengers too. A passenger may have been killed when its
3651  * transport conquered a city. (unit_conquer_city() can cause Lua code
3652  * to run) */
3653 
3654  alive = unit_is_alive(saved_id);
3655  if (alive) {
3656  // In case script has changed something about unit
3657  pplayer_end_pos = unit_owner(punit);
3658  type_end_pos = unit_type_get(punit);
3659  homecity_id_end_pos = punit->homecity;
3660  }
3661  }
3662 
3663  if (homecity_id_start_pos != 0) {
3664  homecity_start_pos = game_city_by_number(homecity_id_start_pos);
3665  }
3666  if (homecity_id_start_pos != homecity_id_end_pos) {
3667  homecity_end_pos = game_city_by_number(homecity_id_end_pos);
3668  } else {
3669  homecity_end_pos = homecity_start_pos;
3670  }
3671 
3672  /* We only do refreshes for non-AI players to now make sure the AI turns
3673  doesn't take too long. Perhaps we should make a special refresh_city
3674  functions that only refreshed happines. */
3675 
3676  // might have changed owners or may be destroyed
3677  tocity = tile_city(dst_tile);
3678 
3679  if (tocity) { // entering a city
3680  if (tocity->owner == pplayer_end_pos) {
3681  if (tocity != homecity_end_pos && is_human(pplayer_end_pos)) {
3682  city_refresh(tocity);
3683  send_city_info(pplayer_end_pos, tocity);
3684  }
3685  }
3686  if (homecity_start_pos) {
3687  refresh_homecity_start_pos = true;
3688  }
3689  }
3690 
3691  if (fromcity) { // leaving a city
3692  if (homecity_start_pos) {
3693  refresh_homecity_start_pos = true;
3694  }
3695  if (fromcity != homecity_start_pos
3696  && fromcity->owner == pplayer_start_pos
3697  && is_human(pplayer_start_pos)) {
3698  city_refresh(fromcity);
3699  send_city_info(pplayer_start_pos, fromcity);
3700  }
3701  }
3702 
3703  /* entering/leaving a fortress or friendly territory */
3704  if (homecity_start_pos || homecity_end_pos) {
3705  if ((game.info.happyborders != HB_DISABLED
3706  && tile_owner(src_tile) != tile_owner(dst_tile))
3707  || (tile_has_base_flag_for_unit(dst_tile, type_end_pos,
3708  BF_NOT_AGGRESSIVE)
3709  && is_friendly_city_near(pplayer_end_pos, dst_tile))
3710  || (tile_has_base_flag_for_unit(src_tile, type_start_pos,
3711  BF_NOT_AGGRESSIVE)
3712  && is_friendly_city_near(pplayer_start_pos, src_tile))) {
3713  refresh_homecity_start_pos = true;
3714  refresh_homecity_end_pos = true;
3715  }
3716  }
3717 
3718  if (refresh_homecity_start_pos && is_human(pplayer_start_pos)) {
3719  city_refresh(homecity_start_pos);
3720  send_city_info(pplayer_start_pos, homecity_start_pos);
3721  }
3722  if (refresh_homecity_end_pos
3723  && (!refresh_homecity_start_pos
3724  || homecity_start_pos != homecity_end_pos)
3725  && is_human(pplayer_end_pos)) {
3726  city_refresh(homecity_end_pos);
3727  send_city_info(pplayer_end_pos, homecity_end_pos);
3728  }
3729 
3730  city_map_update_tile_now(dst_tile);
3731  sync_cities();
3732 
3733  return alive;
3734 }
3735 
3740 static void check_unit_activity(struct unit *punit)
3741 {
3742  switch (punit->activity) {
3743  case ACTIVITY_IDLE:
3744  case ACTIVITY_SENTRY:
3745  case ACTIVITY_EXPLORE:
3746  case ACTIVITY_GOTO:
3747  break;
3748  case ACTIVITY_POLLUTION:
3749  case ACTIVITY_MINE:
3750  case ACTIVITY_IRRIGATE:
3751  case ACTIVITY_CULTIVATE:
3752  case ACTIVITY_PLANT:
3753  case ACTIVITY_FORTIFIED:
3754  case ACTIVITY_FORTRESS:
3755  case ACTIVITY_PILLAGE:
3756  case ACTIVITY_TRANSFORM:
3757  case ACTIVITY_UNKNOWN:
3758  case ACTIVITY_AIRBASE:
3759  case ACTIVITY_FORTIFYING:
3760  case ACTIVITY_FALLOUT:
3761  case ACTIVITY_PATROL_UNUSED:
3762  case ACTIVITY_BASE:
3763  case ACTIVITY_GEN_ROAD:
3764  case ACTIVITY_CONVERT:
3765  case ACTIVITY_OLD_ROAD:
3766  case ACTIVITY_OLD_RAILROAD:
3767  case ACTIVITY_LAST:
3768  set_unit_activity(punit, ACTIVITY_IDLE);
3769  break;
3770  };
3771 }
3772 
3776 static struct unit_move_data *unit_move_data(struct unit *punit,
3777  struct tile *psrctile,
3778  struct tile *pdesttile)
3779 {
3780  struct unit_move_data *pdata;
3781  struct player *powner = unit_owner(punit);
3782  const v_radius_t radius_sq =
3783  V_RADIUS(get_unit_vision_at(punit, pdesttile, V_MAIN),
3784  get_unit_vision_at(punit, pdesttile, V_INVIS),
3785  get_unit_vision_at(punit, pdesttile, V_SUBSURFACE));
3786  struct vision *new_vision;
3787  bool success;
3788 
3789  if (punit->server.moving) {
3790  // Recursive moving (probably due to a script).
3791  pdata = punit->server.moving;
3792  pdata->ref_count++;
3793  fc_assert_msg(pdata->punit == punit,
3794  "Unit number %d (%p) was going to die, but "
3795  "server attempts to move it.",
3796  punit->id, punit);
3797  fc_assert_msg(pdata->old_vision == nullptr,
3798  "Unit number %d (%p) has done an incomplete move.",
3799  punit->id, punit);
3800  } else {
3801  pdata = new struct unit_move_data;
3802  pdata->ref_count = 1;
3803  pdata->punit = punit;
3804  punit->server.moving = pdata;
3805  BV_CLR_ALL(pdata->can_see_unit);
3806  }
3807  pdata->powner = powner;
3808  BV_CLR_ALL(pdata->can_see_move);
3809  pdata->old_vision = punit->server.vision;
3810 
3811  // Remove unit from the source tile.
3812  fc_assert(unit_tile(punit) == psrctile);
3813  success = unit_list_remove(psrctile->units, punit);
3814  fc_assert(success == true);
3815 
3816  // Set new tile.
3817  unit_tile_set(punit, pdesttile);
3818  unit_list_prepend(pdesttile->units, punit);
3819 
3820  if (unit_transported(punit)) {
3821  // Silently free orders since they won't be applicable anymore.
3823  }
3824 
3825  // Check unit activity.
3829 
3830  /* We first unfog the destination, then send the move,
3831  * and then fog the old territory. This means that the player
3832  * gets a chance to see the newly explored territory while the
3833  * client moves the unit, and both areas are visible during the
3834  * move */
3835 
3836  // Enhance vision if unit steps into a fortress
3837  new_vision = vision_new(powner, pdesttile);
3838  punit->server.vision = new_vision;
3839  vision_change_sight(new_vision, radius_sq);
3840  ASSERT_VISION(new_vision);
3841 
3842  return pdata;
3843 }
3844 
3848 static void unit_move_data_unref(struct unit_move_data *pdata)
3849 {
3850  fc_assert_ret(pdata != nullptr);
3851  fc_assert_ret(pdata->ref_count > 0);
3852  fc_assert_msg(pdata->old_vision == nullptr,
3853  "Unit number %d (%p) has done an incomplete move.",
3854  pdata->punit != nullptr ? pdata->punit->id : -1,
3855  pdata->punit);
3856 
3857  pdata->ref_count--;
3858  if (pdata->ref_count == 0) {
3859  if (pdata->punit != nullptr) {
3860  fc_assert(pdata->punit->server.moving == pdata);
3861  pdata->punit->server.moving = nullptr;
3862  }
3863  delete pdata;
3864  }
3865 }
3866 
3878 bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost,
3879  struct unit *embark_to, bool find_embark_target,
3880  bool conquer_city_allowed)
3881 {
3882  struct player *pplayer;
3883  struct tile *psrctile;
3884  struct city *pcity;
3885  struct unit *ptransporter;
3886  struct packet_unit_info src_info, dest_info;
3887  struct packet_unit_short_info src_sinfo, dest_sinfo;
3888  struct unit_move_data_list *plist;
3889  struct unit_move_data *pdata;
3890  int saved_id;
3891  bool unit_lives;
3892  bool adj;
3893  enum direction8 facing;
3894  struct player *bowner;
3895 
3896  // Some checks.
3897  fc_assert_ret_val(punit != nullptr, false);
3898  fc_assert_ret_val(pdesttile != nullptr, false);
3899 
3900  plist = unit_move_data_list_new_full(unit_move_data_unref);
3901  pplayer = unit_owner(punit);
3902  saved_id = punit->id;
3903  psrctile = unit_tile(punit);
3904  adj =
3905  base_get_direction_for_step(&(wld.map), psrctile, pdesttile, &facing);
3906 
3908 
3909  // Unload the unit if on a transport.
3910  ptransporter = unit_transport_get(punit);
3911  if (ptransporter != nullptr) {
3912  // Unload unit _before_ setting the new tile!
3913  unit_transport_unload(punit);
3914  /* Send updated information to anyone watching that transporter
3915  * was unloading cargo. */
3916  send_unit_info(nullptr, ptransporter);
3917  }
3918 
3919  // Wakup units next to us before we move.
3920  wakeup_neighbor_sentries(punit);
3921 
3922  // Make info packets at 'psrctile'.
3923  if (adj) {
3924  /* If tiles are adjacent, we will show the move to users able
3925  * to see it. */
3926  package_unit(punit, &src_info);
3927  package_short_unit(punit, &src_sinfo, UNIT_INFO_IDENTITY, 0);
3928  }
3929 
3930  // Make new data for 'punit'.
3931  pdata = unit_move_data(punit, psrctile, pdesttile);
3932  unit_move_data_list_prepend(plist, pdata);
3933 
3934  // Set unit orientation
3935  if (adj) {
3936  // Only change orientation when moving to adjacent tile
3937  punit->facing = facing;
3938  }
3939 
3940  // Move magic.
3941  punit->moved = true;
3942  punit->moves_left = MAX(0, punit->moves_left - move_cost);
3943  if (punit->moves_left == 0 && !unit_has_orders(punit)) {
3944  // The next order may not require any remaining move fragments.
3945  punit->done_moving = true;
3946  }
3947 
3948  // No longer relevant.
3949  punit->action_decision_tile = nullptr;
3950  punit->action_decision_want = ACT_DEC_NOTHING;
3951 
3952  if (!adj && action_tgt_city(punit, pdesttile, false)) {
3953  /* The unit can perform an action to the city at the destination tile.
3954  * A long distance move (like an airlift) doesn't ask what action to
3955  * perform before moving. Ask now. */
3956 
3957  punit->action_decision_want = ACT_DEC_PASSIVE;
3958  punit->action_decision_tile = pdesttile;
3959  }
3960 
3961  // Claim ownership of fortress?
3962  bowner = extra_owner(pdesttile);
3963  if ((bowner == nullptr || pplayers_at_war(bowner, pplayer))
3964  && tile_has_claimable_base(pdesttile, unit_type_get(punit))) {
3965  /* Yes. We claim *all* bases if there's *any* claimable base(s).
3966  * Even if original unit cannot claim other kind of bases, the
3967  * first claimed base will have influence over other bases,
3968  * or something like that. */
3969  tile_claim_bases(pdesttile, pplayer);
3970  }
3971 
3972  // Move all contained units.
3973  unit_cargo_iterate(punit, pcargo)
3974  {
3975  pdata = unit_move_data(pcargo, psrctile, pdesttile);
3976  unit_move_data_list_append(plist, pdata);
3977  }
3979 
3980  // Get data for 'punit'.
3981  pdata = unit_move_data_list_front(plist);
3982 
3983  /* Determine the players able to see the move(s), now that the player
3984  * vision has been increased. */
3985  if (adj) {
3986  /* Main unit for adjacent move: the move is visible for every player
3987  * able to see on the matching unit layer. */
3988  enum vision_layer vlayer = unit_type_get(punit)->vlayer;
3989 
3990  players_iterate(oplayer)
3991  {
3992  if (map_is_known_and_seen(psrctile, oplayer, vlayer)
3993  || map_is_known_and_seen(pdesttile, oplayer, vlayer)) {
3994  BV_SET(pdata->can_see_unit, player_index(oplayer));
3995  BV_SET(pdata->can_see_move, player_index(oplayer));
3996  }
3997  }
3999  }
4000  unit_move_data_list_iterate(plist, pmove_data)
4001  {
4002  if (adj && pmove_data == pdata) {
4003  /* If positions are adjacent, we have already handled 'punit'. See
4004  * above. */
4005  continue;
4006  }
4007 
4008  players_iterate(oplayer)
4009  {
4010  if ((adj
4011  && can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
4012  pmove_data != pdata))
4013  || can_player_see_unit_at(oplayer, pmove_data->punit, pdesttile,
4014  pmove_data != pdata)) {
4015  BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4016  BV_SET(pmove_data->can_see_move, player_index(oplayer));
4017  }
4018  if (can_player_see_unit_at(oplayer, pmove_data->punit, psrctile,
4019  pmove_data != pdata)) {
4020  /* The unit was seen with its source tile even if it was
4021  * teleported. */
4022  BV_SET(pmove_data->can_see_unit, player_index(oplayer));
4023  }
4024  }
4026  }
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  {
4035  /* Increase the timeout if an enemy unit moves and the
4036  * timeoutaddenemymove setting is in use. */
4037  if (penemy->is_connected && 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  }
4045 
4046  if (new_information_for_enemy) {
4048  }
4049  }
4050 
4051  // Notifications of the move to the clients.
4052  if (adj) {
4053  /* Special case: 'punit' is moving to adjacent position. Then we show
4054  * 'punit' move to all users able to see 'psrctile' or 'pdesttile'. */
4055 
4056  // Make info packets at 'pdesttile'.
4057  package_unit(punit, &dest_info);
4058  package_short_unit(punit, &dest_sinfo, UNIT_INFO_IDENTITY, 0);
4059 
4061  {
4062  struct player *aplayer = conn_get_player(pconn);
4063 
4064  if (aplayer == nullptr) {
4065  if (pconn->observer) {
4066  // Global observers see all...
4067  send_packet_unit_info(pconn, &src_info);
4068  send_packet_unit_info(pconn, &dest_info);
4069  }
4070  } else if (BV_ISSET(pdata->can_see_move, player_index(aplayer))) {
4071  if (aplayer == pplayer) {
4072  send_packet_unit_info(pconn, &src_info);
4073  send_packet_unit_info(pconn, &dest_info);
4074  } else {
4075  send_packet_unit_short_info(pconn, &src_sinfo, false);
4076  send_packet_unit_short_info(pconn, &dest_sinfo, false);
4077  }
4078  }
4079  }
4081  }
4082 
4083  // Other moves.
4084  unit_move_data_list_iterate(plist, pmove_data)
4085  {
4086  if (adj && pmove_data == pdata) {
4087  /* If positions are adjacent, we have already shown 'punit' move.
4088  * See above. */
4089  continue;
4090  }
4091 
4092  // Make info packets at 'pdesttile'.
4093  package_unit(pmove_data->punit, &dest_info);
4094  package_short_unit(pmove_data->punit, &dest_sinfo, UNIT_INFO_IDENTITY,
4095  0);
4096 
4098  {
4099  struct player *aplayer = conn_get_player(pconn);
4100 
4101  if (aplayer == nullptr) {
4102  if (pconn->observer) {
4103  // Global observers see all...
4104  send_packet_unit_info(pconn, &dest_info);
4105  }
4106  } else if (BV_ISSET(pmove_data->can_see_move, player_index(aplayer))) {
4107  if (aplayer == pmove_data->powner) {
4108  send_packet_unit_info(pconn, &dest_info);
4109  } else {
4110  send_packet_unit_short_info(pconn, &dest_sinfo, false);
4111  }
4112  }
4113  }
4115  }
4117 
4118  // Clear old vision.
4119  unit_move_data_list_iterate(plist, pmove_data)
4120  {
4121  vision_clear_sight(pmove_data->old_vision);
4122  vision_free(pmove_data->old_vision);
4123  pmove_data->old_vision = nullptr;
4124  }
4126 
4127  // Move consequences.
4128  unit_move_data_list_iterate(plist, pmove_data)
4129  {
4130  struct unit *aunit = pmove_data->punit;
4131 
4132  if (aunit != nullptr && unit_owner(aunit) == pmove_data->powner
4133  && unit_tile(aunit) == pdesttile) {
4134  (void) unit_move_consequences(aunit, psrctile, pdesttile,
4135  pdata != pmove_data,
4136  conquer_city_allowed);
4137  }
4138  }
4140 
4141  unit_lives = (pdata->punit == punit);
4142 
4143  // Wakeup units and make contact.
4144  if (unit_lives) {
4145  wakeup_neighbor_sentries(punit);
4146  }
4147  maybe_make_contact(pdesttile, pplayer);
4148 
4149  if (unit_lives) {
4150  // Special checks for ground units in the ocean.
4151  if (embark_to
4152  || !can_unit_survive_at_tile(&(wld.map), punit, pdesttile)) {
4153  if (embark_to != nullptr) {
4154  ptransporter = embark_to;
4155  } else if (find_embark_target) {
4156  /* TODO: Consider to stop supporting find_embark_target and make all
4157  * callers that wants auto loading set embark_to. */
4158  ptransporter = transporter_for_unit(punit);
4159  } else {
4160  ptransporter = nullptr;
4161  }
4162  if (ptransporter) {
4163  unit_transport_load_tp_status(punit, ptransporter, false);
4164 
4165  // Set activity to sentry if boarding a ship.
4166  if (is_human(pplayer) && !unit_has_orders(punit)
4167  && punit->ssa_controller == SSA_NONE
4168  && !can_unit_exist_at_tile(&(wld.map), punit, pdesttile)) {
4169  set_unit_activity(punit, ACTIVITY_SENTRY);
4170  }
4171 
4172  send_unit_info(nullptr, punit);
4173  }
4174  }
4175  }
4176 
4177  // Remove units going out of sight.
4178  unit_move_data_list_iterate_rev(plist, pmove_data)
4179  {
4180  struct unit *aunit = pmove_data->punit;
4181 
4182  if (aunit == nullptr) {
4183  continue; // Died!
4184  }
4185 
4186  players_iterate(aplayer)
4187  {
4188  if (BV_ISSET(pmove_data->can_see_unit, player_index(aplayer))
4189  && !can_player_see_unit(aplayer, aunit)) {
4190  unit_goes_out_of_sight(aplayer, aunit);
4191  }
4192  }
4194  }
4196 
4197  /* Inform the owner's client about actor unit arrival. Can, depending on
4198  * the client settings, cause the client to start the process that makes
4199  * the action selection dialog pop up. */
4200  if ((pcity = tile_city(pdesttile))) {
4201  // Arrival in a city counts.
4202 
4203  unit_move_data_list_iterate(plist, pmove_data)
4204  {
4205  struct unit *ptrans;
4206  bool ok;
4207  struct unit *act_unit;
4208  struct player *act_player;
4209 
4210  act_unit = pmove_data->punit;
4211  act_player = unit_owner(act_unit);
4212 
4213  if (act_unit == nullptr || !unit_is_alive(act_unit->id)) {
4214  // The unit died before reaching this point.
4215  continue;
4216  }
4217 
4218  if (unit_tile(act_unit) != pdesttile) {
4219  // The unit didn't arrive at the destination tile.
4220  continue;
4221  }
4222 
4223  if (!is_human(act_player)) {
4224  // Only humans need reminders.
4225  continue;
4226  }
4227 
4228  if (!unit_transported(act_unit)) {
4229  /* Don't show the action selection dialog again. Non transported
4230  * units are handled before they move to the tile. */
4231  continue;
4232  }
4233 
4234  /* Open action dialog only if 'act_unit' and all its transporters
4235  * (recursively) don't have orders. */
4236  if (unit_has_orders(act_unit)) {
4237  // The unit it self has orders.
4238  continue;
4239  }
4240 
4241  for (ptrans = unit_transport_get(act_unit);;
4242  ptrans = unit_transport_get(ptrans)) {
4243  if (nullptr == ptrans) {
4244  // No (recursive) transport has orders.
4245  ok = true;
4246  break;
4247  } else if (unit_has_orders(ptrans)) {
4248  // A unit transporting the unit has orders
4249  ok = false;
4250  break;
4251  }
4252  }
4253 
4254  if (!ok) {
4255  // A unit transporting act_unit has orders.
4256  continue;
4257  }
4258 
4259  if (action_tgt_city(act_unit, pdesttile, false)) {
4260  // There is a valid target.
4261 
4262  act_unit->action_decision_want = ACT_DEC_PASSIVE;
4263  act_unit->action_decision_tile = pdesttile;
4264 
4265  /* Let the client know that this unit wants the player to decide
4266  * what to do. */
4267  send_unit_info(player_reply_dest(act_player), act_unit);
4268  }
4269  }
4271  }
4272 
4273  unit_move_data_list_destroy(plist);
4274 
4275  // Check cities at source and destination.
4276  if ((pcity = tile_city(psrctile))) {
4277  refresh_dumb_city(pcity);
4278  }
4279  if ((pcity = tile_city(pdesttile))) {
4280  refresh_dumb_city(pcity);
4281  }
4282 
4283  if (unit_lives) {
4284  // Let the scripts run ...
4285  script_server_signal_emit("unit_moved", punit, psrctile, pdesttile);
4286  unit_lives = unit_is_alive(saved_id);
4287  }
4288 
4289  if (unit_lives) {
4290  // Autoattack.
4291  unit_lives = unit_survive_autoattack(punit);
4292  }
4293 
4294  if (unit_lives) {
4295  // Is there a hut?
4296  unit_enter_hut(punit);
4297  unit_lives = unit_is_alive(saved_id);
4298  }
4299 
4301 
4302  if (unit_lives) {
4303  CALL_FUNC_EACH_AI(unit_move_seen, punit);
4304  }
4305 
4306  return unit_lives;
4307 }
4308 
4312 static bool maybe_cancel_goto_due_to_enemy(struct unit *punit,
4313  struct tile *ptile)
4314 {
4315  return (is_non_allied_unit_tile(ptile, unit_owner(punit))
4316  || is_non_allied_city_tile(ptile, unit_owner(punit)));
4317 }
4318 
4325 static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
4326 {
4327  bool cancel = false;
4328  int radius_sq = get_unit_vision_at(punit, unit_tile(punit), V_MAIN);
4329  struct player *pplayer = unit_owner(punit);
4330 
4331  circle_iterate(&(wld.map), unit_tile(punit), radius_sq, ptile)
4332  {
4333  struct unit *penemy = is_non_allied_unit_tile(ptile, pplayer);
4334 
4335  const vision_site *pdcity = map_get_player_site(ptile, pplayer);
4336 
4337  if ((penemy && can_player_see_unit(pplayer, penemy))
4338  || (pdcity && !pplayers_allied(pplayer, vision_site_owner(pdcity))
4339  && pdcity->occupied)) {
4340  cancel = true;
4341  break;
4342  }
4343  }
4345 
4346  return cancel;
4347 }
4348 
4357 static inline bool player_is_watching(struct unit *punit, const bool fresh)
4358 {
4359  /* The player just sent the orders to the unit. The unit has moves left.
4360  * It is therefore safe to assume that the player already is paying
4361  * attention to the unit. */
4362  return fresh && punit->moves_left > 0;
4363 }
4364 
4384 bool execute_orders(struct unit *punit, const bool fresh)
4385 {
4386  struct act_prob prob;
4387  bool performed;
4388  const char *name;
4389  bool res, last_order;
4390  int unitid = punit->id;
4391  struct player *pplayer = unit_owner(punit);
4392  int moves_made = 0;
4393 
4394  fc_assert_ret_val(unit_has_orders(punit), true);
4395 
4396  if (punit->activity != ACTIVITY_IDLE) {
4397  // Unit's in the middle of an activity; wait for it to finish.
4398  punit->done_moving = true;
4399  return true;
4400  }
4401 
4402  log_debug("Executing orders for %s %d", unit_rule_name(punit), punit->id);
4403 
4404  // Any time the orders are canceled we should give the player a message.
4405 
4406  while (true) {
4407  struct unit_order order;
4408 
4409  struct action *oaction;
4410 
4411  struct tile *dst_tile;
4412  struct city *tgt_city;
4413  struct unit *tgt_unit;
4414  int tgt_id;
4415  int sub_tgt_id;
4416  struct extra_type *pextra;
4417 
4418  if (punit->done_moving) {
4419  log_debug(" stopping because we're done this turn");
4420  return true;
4421  }
4422 
4423  if (punit->orders.vigilant && maybe_cancel_patrol_due_to_enemy(punit)) {
4424  // "Patrol" orders are stopped if an enemy is near.
4425  cancel_orders(punit, " stopping because of nearby enemy");
4426  notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4427  _("Orders for %s aborted as there are units nearby."),
4428  unit_link(punit));
4429  return true;
4430  }
4431 
4432  if (moves_made == punit->orders.length) {
4433  // For repeating orders, don't repeat more than once per turn.
4434  log_debug(" stopping because we ran a round");
4435  punit->done_moving = true;
4436  send_unit_info(nullptr, punit);
4437  return true;
4438  }
4439  moves_made++;
4440 
4441  order = punit->orders.list[punit->orders.index];
4442 
4443  /* An ORDER_PERFORM_ACTION that doesn't specify an action should not get
4444  * this far. */
4446  || action_id_exists(order.action)),
4447  continue);
4448 
4449  switch (order.order) {
4450  case ORDER_MOVE:
4451  case ORDER_ACTION_MOVE:
4452  case ORDER_FULL_MP:
4453  if (0 == punit->moves_left) {
4454  log_debug(" stopping because of no more move points");
4455  return true;
4456  }
4457  break;
4458  case ORDER_PERFORM_ACTION:
4459  if (action_mp_full_makes_legal(punit, order.action)) {
4460  log_debug(" stopping. Not enough move points this turn");
4461  return true;
4462  }
4463  break;
4464  case ORDER_ACTIVITY:
4465  case ORDER_LAST:
4466  // Those actions don't require moves left.
4467  break;
4468  }
4469 
4470  last_order = (!punit->orders.repeat
4471  && punit->orders.index + 1 == punit->orders.length);
4472 
4473  if (last_order) {
4474  /* Clear the orders before we engage in the move. That way any
4475  * has_orders checks will yield FALSE and this will be treated as
4476  * a normal move. This is important: for instance a caravan goto
4477  * will popup the caravan dialog on the last move only. */
4478  free_unit_orders(punit);
4479  }
4480 
4481  /* Advance the orders one step forward. This is needed because any
4482  * updates sent to the client as a result of the action should include
4483  * the new index value. Note that we have to send_unit_info somewhere
4484  * after this point so that the client is properly updated. */
4485  punit->orders.index++;
4486 
4487  switch (order.order) {
4488  case ORDER_FULL_MP:
4489  if (punit->moves_left < unit_move_rate(punit)) {
4490  /* If the unit doesn't have full MP then it just waits until the
4491  * next turn. We assume that the next turn it will have full MP
4492  * (there's no check for that). */
4493  punit->done_moving = true;
4494  log_debug(" waiting this turn");
4495  send_unit_info(nullptr, punit);
4496  }
4497  break;
4498  case ORDER_ACTIVITY: {
4499  enum unit_activity activity = order.activity;
4500 
4501  fc_assert(activity == ACTIVITY_SENTRY);
4502 
4503  if (can_unit_do_activity(punit, activity)) {
4504  punit->done_moving = true;
4505  set_unit_activity(punit, activity);
4506  send_unit_info(nullptr, punit);
4507 
4508  break;
4509  }
4510  }
4511 
4512  cancel_orders(punit, " orders canceled because of failed activity");
4513  notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4514  _("Orders for %s aborted since they "
4515  "give an invalid activity."),
4516  unit_link(punit));
4517  return true;
4518  case ORDER_MOVE:
4519  case ORDER_ACTION_MOVE:
4520  // Move unit
4521  if (!(dst_tile = mapstep(&(wld.map), unit_tile(punit), order.dir))) {
4522  cancel_orders(punit, " move order sent us to invalid location");
4523  notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4524  _("Orders for %s aborted since they "
4525  "give an invalid location."),
4526  unit_link(punit));
4527  return true;
4528  }
4529 
4530  if (order.order != ORDER_ACTION_MOVE
4531  && maybe_cancel_goto_due_to_enemy(punit, dst_tile)) {
4532  // Plain move required: no attack, trade route etc.
4533  cancel_orders(punit, " orders canceled because of enemy");
4534  notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4535  _("Orders for %s aborted as there "
4536  "are units in the way."),
4537  unit_link(punit));
4538  return true;
4539  }
4540 
4541  log_debug(" moving to %d,%d", TILE_XY(dst_tile));
4542  res = unit_move_handling(punit, dst_tile, false,
4543  order.order != ORDER_ACTION_MOVE);
4544  if (!player_unit_by_number(pplayer, unitid)) {
4545  log_debug(" unit died while moving.");
4546  // A player notification should already have been sent.
4547  return false;
4548  }
4549 
4550  if (res && !same_pos(dst_tile, unit_tile(punit))) {
4551  // Movement succeeded but unit didn't move.
4552  log_debug(" orders resulted in combat.");
4553  send_unit_info(nullptr, punit);
4554  return true;
4555  }
4556 
4557  if (!res) {
4558  fc_assert(0 <= punit->moves_left);
4559 
4560  // Movement failed (ZOC, etc.)
4561  cancel_orders(punit, " attempt to move failed.");
4562 
4563  if (!player_is_watching(punit, fresh)
4564  /* The final move "failed" because the unit needs to ask the
4565  * player what action it should take.
4566  *
4567  * The action decision request notifies the player. Its
4568  * location at the unit's last order makes it clear to the
4569  * player who the decision is for. ("The Spy I sent to Berlin
4570  * has arrived.")
4571  *
4572  * A notification message is therefore redundant. */
4573  && !(last_order && punit->action_decision_want == ACT_DEC_ACTIVE
4574  && punit->action_decision_tile == dst_tile)) {
4575  /* The player may have missed this. No one else will announce it
4576  * in a satisfying manner. Inform the player. */
4577  notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4578  _("Orders for %s aborted because of failed move."),
4579  unit_link(punit));
4580  }
4581 
4582  return true;
4583  }
4584  break;
4585  case ORDER_PERFORM_ACTION:
4586  oaction = action_by_number(order.action);
4587 
4588  // Checked in unit_order_list_is_sane()
4589  fc_assert_action(oaction != nullptr, continue);
4590 
4591  log_debug(" orders: doing action %s", action_rule_name(oaction));
4592 
4593  dst_tile = index_to_tile(&(wld.map), order.target);
4594 
4595  if (dst_tile == nullptr) {
4596  /* Could be at the edge of the map while trying to target a tile
4597  * outside of it. */
4598 
4599  cancel_orders(punit, " target location doesn't exist");
4600  illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4601  order.action, dst_tile, nullptr, nullptr);
4602 
4603  return true;
4604  }
4605 
4606  // Get the target city from the target tile.
4607  tgt_city = tile_city(dst_tile);
4608 
4609  if (tgt_city == nullptr
4610  && action_id_get_target_kind(order.action) == ATK_CITY) {
4611  // This action targets a city but no city target was found.
4612 
4613  cancel_orders(punit, " perform action vs city with no city");
4614  illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4615  order.action, dst_tile, tgt_city, nullptr);
4616 
4617  return true;
4618  }
4619 
4620  // Get a target unit at the target tile.
4621  tgt_unit = action_tgt_unit(punit, dst_tile, true);
4622 
4623  if (tgt_unit == nullptr
4624  && action_id_get_target_kind(order.action) == ATK_UNIT) {
4625  // This action targets a unit but no target unit was found.
4626 
4627  cancel_orders(punit, " perform action vs unit with no unit");
4628  illegal_action_msg(unit_owner(punit), E_UNIT_ORDERS, punit,
4629  order.action, dst_tile, tgt_city, tgt_unit);
4630 
4631  return true;
4632  }
4633 
4634  // Server side sub target assignment
4635  if (oaction->target_complexity == ACT_TGT_COMPL_FLEXIBLE
4636  && order.sub_target == NO_TARGET) {
4637  // Try to find a sub target.
4638  sub_tgt_id = action_sub_target_id_for_action(oaction, punit);
4639  } else {
4640  // The client should have specified a sub target if needed
4641  sub_tgt_id = order.sub_target;
4642  }
4643 
4644  // Get a target extra at the target tile
4645  pextra =
4646  (sub_tgt_id == NO_TARGET ? nullptr : extra_by_number(sub_tgt_id));
4647 
4648  if (action_get_sub_target_kind(oaction) == ASTK_EXTRA_NOT_THERE
4649  && pextra != nullptr && action_creates_extra(oaction, pextra)
4650  && tile_has_extra(dst_tile, pextra)) {
4651  // Already there. Move on to the next order.
4652  break;
4653  }
4654 
4655  if (action_get_sub_target_kind(oaction) == ASTK_EXTRA
4656  && pextra != nullptr && action_removes_extra(oaction, pextra)
4657  && !tile_has_extra(dst_tile, pextra)) {
4658  // Already not there. Move on to the next order.
4659  break;
4660  }
4661 
4662  // No target selected.
4663  tgt_id = -1;
4664 
4665  // Assume impossible until told otherwise.
4666  prob = ACTPROB_IMPOSSIBLE;
4667 
4668  switch (action_id_get_target_kind(order.action)) {
4669  case ATK_UNITS:
4670  prob = action_prob_vs_units(punit, order.action, dst_tile);
4671  tgt_id = dst_tile->index;
4672  break;
4673  case ATK_TILE:
4674  prob = action_prob_vs_tile(punit, order.action, dst_tile, pextra);
4675  tgt_id = dst_tile->index;
4676  break;
4677  case ATK_CITY:
4678  prob = action_prob_vs_city(punit, order.action, tgt_city);
4679  tgt_id = tgt_city->id;
4680  break;
4681  case ATK_UNIT:
4682  prob = action_prob_vs_unit(punit, order.action, tgt_unit);
4683 
4684  tgt_id = tgt_unit->id;
4685  break;
4686  case ATK_SELF:
4687  prob = action_prob_self(punit, order.action);
4688 
4689  tgt_id = unitid;
4690  break;
4691  case ATK_COUNT:
4692  qCritical("Invalid action target kind");
4693 
4694  /* The check below will abort and cancel the orders because prob
4695  * was initialized to impossible above this switch statement. */
4696 
4697  break;
4698  }
4699 
4700  if (!action_prob_possible(prob)) {
4701  /* The player has enough information to know that this action is
4702  * against the rules. Don't risk any punishment by trying to
4703  * perform it. */
4704 
4705  cancel_orders(punit, " illegal action");
4706  notify_player(
4707  pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4708  _("%s could not do %s to %s."), unit_link(punit),
4709  qUtf8Printable(action_id_name_translation(order.action)),
4710  tile_link(dst_tile));
4711 
4712  // Try to explain what rule made it illegal.
4713  illegal_action_msg(unit_owner(punit), E_BAD_COMMAND, punit,
4714  order.action, dst_tile, tgt_city, tgt_unit);
4715 
4716  return true;
4717  }
4718 
4719  if (action_id_has_result_safe(order.action, ACTRES_FOUND_CITY)) {
4720  // This action needs a name.
4721  name = city_name_suggestion(pplayer, unit_tile(punit));
4722  } else {
4723  // This action doesn't need a name.
4724  name = "";
4725  }
4726 
4727  performed = unit_perform_action(pplayer, unitid, tgt_id, sub_tgt_id,
4728  name, order.action, ACT_REQ_PLAYER);
4729 
4730  if (!player_unit_by_number(pplayer, unitid)) {
4731  // The unit "died" while performing the action.
4732  return false;
4733  }
4734 
4735  if (!performed) {
4736  // The action wasn't performed as ordered.
4737 
4738  cancel_orders(punit, " failed action");
4739  notify_player(
4740  pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4741  _("Orders for %s aborted because "
4742  "doing %s to %s failed."),
4743  unit_link(punit),
4744  qUtf8Printable(action_id_name_translation(order.action)),
4745  tile_link(dst_tile));
4746 
4747  return true;
4748  }
4749 
4750  if (action_id_get_act_time(order.action, punit, dst_tile, pextra)
4752  // Done at turn change.
4753  punit->done_moving = true;
4754  send_unit_info(nullptr, punit);
4755  break;
4756  }
4757 
4758  break;
4759  case ORDER_LAST:
4760  /* Should be caught when loading the unit orders from the savegame or
4761  * when receiving the unit orders from the client. */
4762  fc_assert_msg(order.order != ORDER_LAST, "Invalid order: last.");
4763  cancel_orders(punit, " invalid order!");
4764  notify_player(pplayer, unit_tile(punit), E_UNIT_ORDERS, ftc_server,
4765  _("Your %s has invalid orders."), unit_link(punit));
4766  return true;
4767  }
4768 
4769  if (last_order) {
4770  fc_assert(punit->has_orders == false);
4771  log_debug(" stopping because orders are complete");
4772  return true;
4773  }
4774 
4775  if (punit->orders.index == punit->orders.length) {
4776  fc_assert(punit->orders.repeat);
4777  // Start over.
4778  log_debug(" repeating orders.");
4779  punit->orders.index = 0;
4780  }
4781  } // end while
4782 }
4783 
4791 int get_unit_vision_at(struct unit *punit, const struct tile *ptile,
4792  enum vision_layer vlayer)
4793 {
4794  const int base = unit_type_get(punit)->vision_radius_sq;
4795  const int bonus =
4796  get_unittype_bonus(unit_owner(punit), ptile, unit_type_get(punit),
4797  EFT_UNIT_VISION_RADIUS_SQ, vlayer);
4798  switch (vlayer) {
4799  case V_MAIN:
4800  return MAX(0, base) + MAX(0, bonus);
4801  case V_INVIS:
4802  case V_SUBSURFACE:
4803  return CLIP(0, base, 2) + MAX(0, bonus);
4804  case V_COUNT:
4805  break;
4806  }
4807 
4808  qCritical("Unsupported vision layer variant: %d.", vlayer);
4809  return 0;
4810 }
4811 
4818 void unit_refresh_vision(struct unit *punit)
4819 {
4820  struct vision *uvision = punit->server.vision;
4821  const struct tile *utile = unit_tile(punit);
4822  const v_radius_t radius_sq =
4823  V_RADIUS(get_unit_vision_at(punit, utile, V_MAIN),
4824  get_unit_vision_at(punit, utile, V_INVIS),
4825  get_unit_vision_at(punit, utile, V_SUBSURFACE));
4826 
4827  vision_change_sight(uvision, radius_sq);
4828  ASSERT_VISION(uvision);
4829 }
4830 
4834 void unit_list_refresh_vision(struct unit_list *punitlist)
4835 {
4836  unit_list_iterate(punitlist, punit) { unit_refresh_vision(punit); }
4838 }
4839 
4844 bool unit_can_do_action_now(const struct unit *punit)
4845 {
4846  time_t dt;
4847 
4848  if (!punit) {
4849  return false;
4850  }
4851 
4852  if (game.server.unitwaittime <= 0) {
4853  return true;
4854  }
4855 
4856  if (punit->action_turn != game.info.turn - 1) {
4857  return true;
4858  }
4859 
4860  dt = time(nullptr) - punit->action_timestamp;
4861  if (dt < game.server.unitwaittime) {
4862  char buf[64];
4863  format_time_duration(game.server.unitwaittime - dt, buf, sizeof(buf));
4864  notify_player(unit_owner(punit), unit_tile(punit), E_BAD_COMMAND,
4865  ftc_server,
4866  _("Your unit may not act for another %s "
4867  "this turn. See /help unitwaittime."),
4868  buf);
4869  return false;
4870  }
4871 
4872  return true;
4873 }
4874 
4879 void unit_did_action(struct unit *punit)
4880 {
4881  // Dont spam network with unitwaitime changes if its disabled
4882  if (!punit || !game.server.unitwaittime) {
4883  return;
4884  }
4885 
4886  const auto now = time(nullptr);
4887 
4888  // Units can do UWT-protected actions while under UWT when forced by the
4889  // game to do so, for instance when an alliance is broken and the unit gets
4890  // bounced off a city or transport. In this case, the original UWT stays in
4891  // effect.
4892  if (punit->action_turn == game.info.turn - 1
4893  && now < punit->action_timestamp + game.server.unitwaittime) {
4894  return;
4895  }
4896 
4897  punit->action_timestamp = now;
4898  punit->action_turn = game.info.turn;
4899 }
4900 
4906 bool unit_can_be_retired(struct unit *punit)
4907 {
4908  // check if there is enemy nearby
4909  square_iterate(&(wld.map), unit_tile(punit), 3, ptile)
4910  {
4911  if (is_enemy_city_tile(ptile, unit_owner(punit))
4912  || is_enemy_unit_tile(ptile, unit_owner(punit))) {
4913  return false;
4914  }
4915  }
4917 
4918  return true;
4919 }
4920 
4924 bool unit_order_list_is_sane(int length, const struct unit_order *orders)
4925 {
4926  int i;
4927 
4928  for (i = 0; i < length; i++) {
4929  struct action *paction;
4930  struct extra_type *pextra;
4931 
4932  if (orders[i].order > ORDER_LAST) {
4933  qCritical("invalid order %d at index %d", orders[i].order, i);
4934  return false;
4935  }
4936  switch (orders[i].order) {
4937  case ORDER_MOVE:
4938  case ORDER_ACTION_MOVE:
4939  if (!map_untrusted_dir_is_valid(orders[i].dir)) {
4940  qCritical("in order %d, invalid move direction %d.", i,
4941  orders[i].dir);
4942  return false;
4943  }
4944  break;
4945  case ORDER_ACTIVITY:
4946  switch (orders[i].activity) {
4947  case ACTIVITY_SENTRY:
4948  if (i != length - 1) {
4949  // Only allowed as the last order.
4950  qCritical("activity %d is not allowed at index %d.",
4951  orders[i].activity, i);
4952  return false;
4953  }
4954  break;
4955  // Replaced by action orders
4956  case ACTIVITY_BASE:
4957  case ACTIVITY_GEN_ROAD:
4958  case ACTIVITY_FALLOUT:
4959  case ACTIVITY_POLLUTION:
4960  case ACTIVITY_PILLAGE:
4961  case ACTIVITY_MINE:
4962  case ACTIVITY_IRRIGATE:
4963  case ACTIVITY_PLANT:
4964  case ACTIVITY_CULTIVATE:
4965  case ACTIVITY_TRANSFORM:
4966  case ACTIVITY_CONVERT:
4967  case ACTIVITY_FORTIFYING:
4968  qCritical("at index %d, use action rather than activity %d.", i,
4969  orders[i].activity);
4970  return false;
4971  // Not supported.
4972  case ACTIVITY_EXPLORE:
4973  case ACTIVITY_IDLE:
4974  // Not set from the client.
4975  case ACTIVITY_GOTO:
4976  case ACTIVITY_FORTIFIED:
4977  // Compatiblity, used in savegames.
4978  case ACTIVITY_OLD_ROAD:
4979  case ACTIVITY_OLD_RAILROAD:
4980  case ACTIVITY_FORTRESS:
4981  case ACTIVITY_AIRBASE:
4982  // Unused.
4983  case ACTIVITY_PATROL_UNUSED:
4984  case ACTIVITY_LAST:
4985  case ACTIVITY_UNKNOWN:
4986  qCritical("at index %d, unsupported activity %d.", i,
4987  orders[i].activity);
4988  return false;
4989  }
4990 
4991  break;
4992  case ORDER_PERFORM_ACTION:
4993  if (!action_id_exists(orders[i].action)) {
4994  // Non-existent action.
4995  qCritical("at index %d, the action %d doesn't exist.", i,
4996  orders[i].action);
4997  return false;
4998  }
4999 
5000  paction = action_by_number(orders[i].action);
5001 
5002  // Validate main target.
5003  if (index_to_tile(&(wld.map), orders[i].target) == nullptr) {
5004  qCritical("at index %d, invalid tile target %d for the action %d.",
5005  i, orders[i].target, orders[i].action);
5006  return false;
5007  }
5008 
5009  if (orders[i].dir != DIR8_ORIGIN) {
5010  qCritical("at index %d, the action %d sets the outdated target"
5011  " specification dir.",
5012  i, orders[i].action);
5013  }
5014 
5015  // Validate sub target.
5016  switch (action_id_get_sub_target_kind(orders[i].action)) {
5017  case ASTK_BUILDING:
5018  // Sub target is a building.
5019  if (!improvement_by_number(orders[i].sub_target)) {
5020  // Sub target is invalid.
5021  qCritical("at index %d, cannot do %s without a target.", i,
5022  action_id_rule_name(orders[i].action));
5023  return false;
5024  }
5025  break;
5026  case ASTK_TECH:
5027  // Sub target is a technology.
5028  if (orders[i].sub_target == A_NONE
5029  || (!valid_advance_by_number(orders[i].sub_target)
5030  && orders[i].sub_target != A_FUTURE)) {
5031  // Target tech is invalid.
5032  qCritical("at index %d, cannot do %s without a target.", i,
5033  action_id_rule_name(orders[i].action));
5034  return false;
5035  }
5036  break;
5037  case ASTK_EXTRA:
5038  case ASTK_EXTRA_NOT_THERE:
5039  // Sub target is an extra.
5040  pextra = (!(orders[i].sub_target == NO_TARGET
5041  || (orders[i].sub_target < 0
5042  || (orders[i].sub_target
5043  >= game.control.num_extra_types)))
5044  ? extra_by_number(orders[i].sub_target)
5045  : nullptr);
5046  fc_assert(pextra == nullptr || !(pextra->ruledit_disabled));
5047  if (pextra == nullptr) {
5048  if (paction->target_complexity != ACT_TGT_COMPL_FLEXIBLE) {
5049  // Target extra is invalid.
5050  qCritical("at index %d, cannot do %s without a target.", i,
5051  action_id_rule_name(orders[i].action));
5052  return false;
5053  }
5054  } else {
5055  if (!(action_removes_extra(paction, pextra)
5056  || action_creates_extra(paction, pextra))) {
5057  // Target extra is irrelevant for the action.
5058  qCritical("at index %d, cannot do %s to %s.", i,
5059  action_id_rule_name(orders[i].action),
5060  extra_rule_name(pextra));
5061  return false;
5062  }
5063  }
5064  break;
5065  case ASTK_NONE:
5066  // No validation required.
5067  break;
5068  // Invalid action?
5069  case ASTK_COUNT:
5071  action_id_get_sub_target_kind(orders[i].action) != ASTK_COUNT,
5072  false, "Bad action %d in order number %d.", orders[i].action, i);
5073  }
5074 
5075  // Some action orders are sane only in the last order.
5076  if (i != length - 1) {
5077  // If the unit is dead,
5078  if (utype_is_consumed_by_action(paction, nullptr)
5079  /* or if Freeciv21 has no idea where the unit will end up after
5080  * it has performed this action, */
5081  || !(utype_is_unmoved_by_action(paction, nullptr)
5082  || utype_is_moved_to_tgt_by_action(paction, nullptr))
5083  // or if the unit will end up standing still,
5084  || action_has_result(paction, ACTRES_FORTIFY)) {
5085  /* than having this action in the middle of a unit's orders is
5086  * probably wrong. */
5087  qCritical("action %d is not allowed at index %d.",
5088  orders[i].action, i);
5089  return false;
5090  }
5091  }
5092 
5093  /* Don't validate that the target tile really contains a target or
5094  * that the actor player's map think the target tile has one.
5095  * The player may target a something from his player map that isn't
5096  * there any more, a target he thinks is there even if his player map
5097  * doesn't have it or even a target he assumes will be there when the
5098  * unit reaches the target tile.
5099  *
5100  * With that said: The client should probably at least have an
5101  * option to only aim city targeted actions at cities. */
5102 
5103  break;
5104  case ORDER_FULL_MP:
5105  break;
5106  case ORDER_LAST:
5107  // An invalid order. This is handled above.
5108  break;
5109  }
5110  }
5111 
5112  return true;
5113 }
5114 
5119 struct unit_order *create_unit_orders(int length,
5120  const struct unit_order *orders)
5121 {
5122  if (!unit_order_list_is_sane(length, orders)) {
5123  return nullptr;
5124  }
5125 
5126  auto *unit_orders = new unit_order[length];
5127  memcpy(unit_orders, orders, length * sizeof(*(unit_orders)));
5128 
5129  return unit_orders;
5130 }
bool action_removes_extra(const struct action *paction, const struct extra_type *pextra)
Returns TRUE iff the specified action can remove the specified extra.
Definition: actions.cpp:1732
bool action_mp_full_makes_legal(const struct unit *actor, const action_id act_id)
Returns TRUE if the specified action can't be done now but would have been legal if the unit had full...
Definition: actions.cpp:5817
const char * action_rule_name(const struct action *action)
Get the rule name of the action.
Definition: actions.cpp:1343
struct act_prob action_prob_self(const struct unit *actor_unit, const action_id act_id)
Get the actor unit's probability of successfully performing the chosen action on itself.
Definition: actions.cpp:5145
bool action_prob_possible(const struct act_prob probability)
Returns TRUE iff the given action probability belongs to an action that may be possible.
Definition: actions.cpp:5380
struct unit * action_tgt_unit(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Find a unit to target for an action at the specified tile.
Definition: actions.cpp:7050
struct city * action_tgt_city(struct unit *actor, struct tile *target_tile, bool accept_all_actions)
Find a city to target for an action on the specified tile.
Definition: actions.cpp:6983
struct act_prob action_prob_vs_city(const struct unit *actor_unit, const action_id act_id, const struct city *target_city)
Get the actor unit's probability of successfully performing the chosen action on the target city.
Definition: actions.cpp:4809
struct act_prob action_prob_vs_unit(const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Get the actor unit's probability of successfully performing the chosen action on the target unit.
Definition: actions.cpp:4871
enum action_sub_target_kind action_get_sub_target_kind(const struct action *paction)
Get the sub target kind of an action.
Definition: actions.cpp:1209
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)
Get the actor unit's probability of successfully performing the chosen action on the target tile.
Definition: actions.cpp:5090
struct act_prob action_prob_vs_units(const struct unit *actor_unit, const action_id act_id, const struct tile *target_tile)
Get the actor unit's probability of successfully performing the chosen action on all units at the tar...
Definition: actions.cpp:5029
const QString action_id_name_translation(action_id act_id)
Get the action name used when displaying the action in the UI.
Definition: actions.cpp:1373
struct action * action_by_number(action_id act_id)
Return the action with the given id.
Definition: actions.cpp:1149
bool action_id_exists(const action_id act_id)
Returns TRUE iff the specified action ID refers to a valid action.
Definition: actions.cpp:1138
bool action_has_result(const struct action *paction, enum action_result result)
Returns TRUE iff performing the specified action has the specified result.
Definition: actions.cpp:1248
bool action_creates_extra(const struct action *paction, const struct extra_type *pextra)
Returns TRUE iff the specified action can create the specified extra.
Definition: actions.cpp:1649
int action_prob_cmp_pessimist(const struct act_prob ap1, const struct act_prob ap2)
Compare action probabilities.
Definition: actions.cpp:5428
double action_prob_to_0_to_1_pessimist(const struct act_prob ap)
Returns double in the range [0-1] representing the minimum of the given action probability.
Definition: actions.cpp:5479
const char * action_id_rule_name(action_id act_id)
Get the rule name of the action.
Definition: actions.cpp:1362
#define action_id_get_sub_target_kind(act_id)
Definition: actions.h:526
#define action_id_get_act_time(act_id, actor_unit, tgt_tile, tgt_extra)
Definition: actions.h:552
#define ACTPROB_IMPOSSIBLE
Definition: actions.h:732
#define action_id_get_target_kind(act_id)
Definition: actions.h:522
#define action_id_has_result_safe(act_id, result)
Definition: actions.h:537
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 *output, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
Returns the probability for the specified actor unit to be forced to perform an action by the specifi...
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 *output, const struct tile *target_tile, const struct city *target_city, const struct unit *target_unit, const struct extra_type *target_extra)
Make the specified actor unit perform an action because of cause.
void action_consequence_complete(const struct action *paction, struct player *offender, struct player *victim_player, const struct tile *victim_tile, const char *victim_link)
Take care of any consequences (like casus belli) of successfully completing the given action.
int action_sub_target_id_for_action(const struct action *paction, struct unit *actor_unit)
Find an sub target for the specified action.
bool adv_follow_path(struct unit *punit, const PFPath &path, struct tile *ptile)
Move a unit along a path without disturbing its activity, role or assigned destination Return FALSE i...
Definition: advgoto.cpp:43
#define CALL_FUNC_EACH_AI(_func,...)
Definition: ai.h:393
#define CALL_PLR_AI_FUNC(_func, _player,...)
Definition: ai.h:383
enum unit_move_result manage_auto_explorer(struct unit *punit)
Handle eXplore mode of a unit (explorers are always in eXplore mode for AI) - explores unknown territ...
void adv_unit_new_task(struct unit *punit, enum adv_unit_task task, struct tile *ptile)
Change unit's advisor task.
#define BV_CLR_ALL(bv)
Definition: bitvector.h:62
#define BV_SET(bv, bit)
Definition: bitvector.h:44
bool BV_ISSET(const BV &bv, int bit)
Definition: bitvector.h:37
#define BV_CLR(bv, bit)
Definition: bitvector.h:49
bool city_exists_within_max_city_map(const struct tile *ptile, bool may_be_on_center)
Return TRUE iff a city exists within a city radius of the given location.
Definition: city.cpp:2013
struct city * is_non_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Is there an non_allied city on this tile?
Definition: city.cpp:1968
struct city * is_enemy_city_tile(const struct tile *ptile, const struct player *pplayer)
Is there an enemy city on this tile?
Definition: city.cpp:1923
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
struct city * is_allied_city_tile(const struct tile *ptile, const struct player *pplayer)
Is there an friendly city on this tile?
Definition: city.cpp:1938
struct city * is_non_attack_city_tile(const struct tile *ptile, const struct player *pplayer)
Is there an enemy city on this tile?
Definition: city.cpp:1953
void city_remove_improvement(struct city *pcity, const struct impr_type *pimprove)
Removes an improvement (and its effects) from a city.
Definition: city.cpp:3287
struct tile * city_tile(const struct city *pcity)
Return the tile location of the city.
Definition: city.cpp:1095
const char * city_name_get(const struct city *pcity)
Return the name of the city.
Definition: city.cpp:1077
citizens city_size_get(const struct city *pcity)
Get the city size.
Definition: city.cpp:1101
bool is_friendly_city_near(const struct player *owner, const struct tile *ptile)
Return TRUE if there is a friendly city near to this tile (within 3 steps).
Definition: city.cpp:1993
#define city_list_iterate_safe(citylist, _city)
Definition: city.h:500
#define city_list_iterate(citylist, pcity)
Definition: city.h:482
#define output_type_iterate(output)
Definition: city.h:764
#define city_list_iterate_end
Definition: city.h:484
#define city_list_iterate_safe_end
Definition: city.h:521
#define city_built_iterate(_pcity, _p)
Definition: city.h:752
#define city_built_iterate_end
Definition: city.h:759
#define output_type_iterate_end
Definition: city.h:771
bool city_map_update_tile_now(struct tile *ptile)
Updates the worked status of a tile immediately.
Definition: citytools.cpp:3141
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)
Find the city closest to 'ptile'.
Definition: citytools.cpp:849
void send_city_info(struct player *dest, struct city *pcity)
A wrapper, accessing either broadcast_city_info() (dest == nullptr), or a convenience case of send_ci...
Definition: citytools.cpp:2295
const char * city_name_suggestion(struct player *pplayer, struct tile *ptile)
Come up with a default name when a new city is about to be built.
Definition: citytools.cpp:451
void refresh_dumb_city(struct city *pcity)
Update plrtile information about the city, and send out information to the clients if it has changed.
Definition: citytools.cpp:2163
bool unit_conquer_city(struct unit *punit, struct city *pcity)
Handle unit conquering a city.
Definition: citytools.cpp:1961
void city_units_upkeep(const struct city *pcity)
Recalculate the upkeep needed for all units supported by the city.
Definition: citytools.cpp:2927
bool transfer_city(struct player *ptaker, struct city *pcity, int kill_outside, bool transfer_unit_verbose, bool resolve_stack, bool raze, bool build_free)
Handles all transactions in relation to transferring a city.
Definition: citytools.cpp:1084
void sync_cities()
Make sure all players (clients) have up-to-date information about all their cities.
Definition: citytools.cpp:3150
bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason)
Reduce the city size.
Definition: cityturn.cpp:815
bool city_refresh(struct city *pcity)
Updates unit upkeeps and city internal cached data.
Definition: cityturn.cpp:147
Abstraction for path finding destinations.
Definition: path_finder.h:148
A path is a succession of moves and actions to go from one location to another.
Definition: path_finder.h:55
Allows one to limit the scope a path finding search.
Definition: path_finder.h:258
struct unit * get_defender(const struct unit *attacker, const struct tile *ptile)
Finds the best defender on the tile, given an attacker.
Definition: combat.cpp:721
bool is_unit_reachable_at(const struct unit *defender, const struct unit *attacker, const struct tile *location)
Can unit attack other at given location.
Definition: combat.cpp:83
bool is_stack_vulnerable(const struct tile *ptile)
Is it a city/fortress/air base or will the whole stack die in an attack.
Definition: combat.cpp:839
int get_total_defense_power(const struct unit *attacker, const struct unit *defender)
return the modified defense power of a unit.
Definition: combat.cpp:654
int get_virtual_defense_power(const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, struct tile *ptile, bool fortified, int veteran)
May be called with a non-existing att_type to avoid any effects which depend on the attacker.
Definition: combat.cpp:601
int get_total_attack_power(const struct unit *attacker, const struct unit *defender)
Return the modified attack power of a unit.
Definition: combat.cpp:526
double unit_win_chance(const struct unit *attacker, const struct unit *defender)
Returns a double in the range [0;1] indicating the attackers chance of winning.
Definition: combat.cpp:408
void get_modified_firepower(const struct unit *attacker, const struct unit *defender, int *att_fp, int *def_fp)
A unit's effective firepower depend on the situation.
Definition: combat.cpp:352
char * extras
Definition: comments.cpp:34
void unit_restore_hitpoints(struct unit *punit)
add hitpoints to the unit, hp_gain_coord returns the amount to add united nations will speed up the p...
Definition: unit_utils.cpp:45
void conn_list_do_unbuffer(struct conn_list *dest)
Convenience functions to unbuffer a list of connections.
Definition: connection.cpp:319
struct player * conn_get_player(const struct connection *pconn)
Returns the player that this connection is attached to, or nullptr.
Definition: connection.cpp:693
void conn_list_do_buffer(struct conn_list *dest)
Convenience functions to buffer a list of connections.
Definition: connection.cpp:310
bool conn_is_global_observer(const struct connection *pconn)
Returns TRUE if the given connection is a global observer.
Definition: connection.cpp:683
#define conn_list_iterate(connlist, pconn)
Definition: connection.h:99
#define conn_list_iterate_end
Definition: connection.h:101
static void base(QVariant data1, QVariant data2)
Action "Build Base" for choice dialog.
Definition: dialogs.cpp:2393
int get_target_bonus_effects(struct effect_list *plist, const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, enum effect_type effect_type, enum vision_layer vision_layer, enum national_intelligence nintel)
Returns the effect bonus of a given type for any target.
Definition: effects.cpp:611
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, enum effect_type effect_type, enum vision_layer vision_layer)
Returns the effect bonus that applies at a tile for a given unittype.
Definition: effects.cpp:841
int get_unit_bonus(const struct unit *punit, enum effect_type effect_type)
Returns the effect bonus at a unit.
Definition: effects.cpp:869
int get_player_bonus(const struct player *pplayer, enum effect_type effect_type)
Returns the effect bonus for a player.
Definition: effects.cpp:673
struct extra_type * rand_extra_for_tile(struct tile *ptile, enum extra_cause cause, bool generated)
Return random extra type for given cause that is native to the tile.
Definition: extras.cpp:242
struct extra_type * extra_by_number(int id)
Return extras type of given id.
Definition: extras.cpp:154
struct player * extra_owner(const struct tile *ptile)
Who owns extras on tile.
Definition: extras.cpp:1013
struct extra_type * prev_extra_in_tile(const struct tile *ptile, enum extra_rmcause rmcause, const struct player *pplayer, const struct unit *punit)
Returns prev extra by cause that unit or player can remove from tile.
Definition: extras.cpp:732
bool player_can_remove_extra(const struct extra_type *pextra, const struct player *pplayer, const struct tile *ptile)
Tells if player can remove extra from tile with suitable unit.
Definition: extras.cpp:525
const char * extra_rule_name(const struct extra_type *pextra)
Return the (untranslated) rule name of the extra type.
Definition: extras.cpp:174
#define extra_type_iterate(_p)
Definition: extras.h:279
#define extra_type_list_iterate(extralist, pextra)
Definition: extras.h:145
#define extra_type_iterate_end
Definition: extras.h:285
#define extra_type_by_rmcause_iterate_end
Definition: extras.h:330
#define extra_index(_e_)
Definition: extras.h:163
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition: extras.h:324
#define EXTRA_NONE
Definition: extras.h:72
#define extra_type_list_iterate_end
Definition: extras.h:147
#define NO_TARGET
Definition: fc_types.h:271
int Tech_type_id
Definition: fc_types.h:294
#define ACT_TIME_INSTANTANEOUS
Definition: fc_types.h:266
@ RPT_CERTAIN
Definition: fc_types.h:568
#define DIR8_ORIGIN
Definition: fc_types.h:372
@ AUT_NONE
Definition: fc_types.h:287
#define MAX_NUM_PLAYER_SLOTS
Definition: fc_types.h:24
@ HB_DISABLED
Definition: fc_types.h:1094
#define IDENTITY_NUMBER_ZERO
Definition: fc_types.h:76
#define PL_(String1, String2, n)
Definition: fcintl.h:54
#define _(String)
Definition: fcintl.h:50
const char * unit_veteran_level_and_bonus(const unit *punit)
Get a text of a unit's numerical veteran level and the bonus percentage it confers.
const char * tile_link(const struct tile *ptile)
Get a text link to a tile.
const char * unit_tile_link(const struct unit *punit)
Get a text link to a unit tile (make a clickable link to a tile with the unit type name as text).
const char * unit_veteran_level_string(const struct unit *punit)
Get a text of a unit's vet level.
const struct ft_color ftc_server
const char * city_link(const struct city *pcity)
Get a text link to a city.
const char * unit_link(const struct unit *punit)
Get a text link to an unit.
#define MAX_LEN_LINK
struct unit * game_unit_by_number(int id)
Find unit out of all units in game: now uses fast idex method, instead of looking through all units o...
Definition: game.cpp:112
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
void game_remove_unit(struct world *gworld, struct unit *punit)
In the server call wipe_unit(), and never this function directly.
Definition: game.cpp:120
int current_turn_timeout()
Return timeout value for the current turn.
Definition: game.cpp:808
struct city * game_city_by_number(int id)
Often used function to get a city pointer from a city ID.
Definition: game.cpp:103
void increase_timeout_because_unit_moved()
adjusts game.seconds_to_turn_done when enemy moves a unit, we see it and the remaining timeout is sma...
Definition: gamehand.cpp:1040
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
AI players may have handicaps - allowing them to cheat or preventing them from using certain algorith...
Definition: handicaps.cpp:62
@ H_MAP
Definition: handicaps.h:27
@ H_LIMITEDHUTS
Definition: handicaps.h:19
void idex_register_unit(struct world *iworld, struct unit *punit)
Register a unit into idex, with current punit->id.
Definition: idex.cpp:79
bool is_improvement(const struct impr_type *pimprove)
Is this building a regular improvement?
struct impr_type * improvement_by_number(const Impr_type_id id)
Returns the improvement type for the given index/ID.
const char * improvement_name_translation(const struct impr_type *pimprove)
Return the (translated) name of the given improvement.
const char * name
Definition: inputfile.cpp:118
#define fc_assert_msg(condition, message,...)
Definition: log.h:96
#define fc_assert_ret(condition)
Definition: log.h:112
#define fc_assert_exit_msg(condition, message,...)
Definition: log.h:135
#define log_test
Definition: log.h:71
#define fc_assert(condition)
Definition: log.h:89
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define fc_assert_action(condition, action)
Definition: log.h:104
#define log_debug(message,...)
Definition: log.h:65
#define fc_assert_ret_val_msg(condition, val, message,...)
Definition: log.h:132
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Return squared distance between two tiles.
Definition: map.cpp:610
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Are (x1,y1) and (x2,y2) really the same when adjusted? This function might be necessary ALOT of place...
Definition: map.cpp:887
bool map_untrusted_dir_is_valid(enum direction8 dir)
Returns TRUE iff the given direction is a valid one.
Definition: map.cpp:1212
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Return real distance between two tiles.
Definition: map.cpp:599
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Return the tile for the given index position.
Definition: map.cpp:429
bool base_get_direction_for_step(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile, enum direction8 *dir)
Return TRUE and sets dir to the direction of the step if (end_x, end_y) can be reached from (start_x,...
Definition: map.cpp:1267
struct tile * mapstep(const struct civ_map *nmap, const struct tile *ptile, enum direction8 dir)
Step from the given tile in the given direction.
Definition: map.cpp:342
#define adjc_iterate_end
Definition: map.h:358
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition: map.h:312
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition: map.h:351
#define square_iterate_end
Definition: map.h:315
static int map_move_cost_unit(const struct civ_map *nmap, struct unit *punit, const struct tile *ptile)
Definition: map.h:221
#define circle_iterate(nmap, center_tile, sq_radius, tile_itr)
Definition: map.h:322
#define circle_iterate_end
Definition: map.h:325
void vision_clear_sight(struct vision *vision)
Clear all sight points from this vision source.
Definition: maphand.cpp:2395
void destroy_extra(struct tile *ptile, struct extra_type *pextra)
Remove extra from tile.
Definition: maphand.cpp:2478
void bounce_units_on_terrain_change(struct tile *ptile)
Check ptile and nearby tiles to see if all units can remain at their current locations,...
Definition: maphand.cpp:1802
void give_distorted_map(struct player *pfrom, struct player *pto, int prob, bool reveal_cities)
Transfer (random parts of) player pfrom's world map to pto.
Definition: maphand.cpp:2558
void tile_claim_bases(struct tile *ptile, struct player *powner)
Claim ownership of bases on single tile.
Definition: maphand.cpp:2083
void create_extra(struct tile *ptile, const extra_type *pextra, struct player *pplayer)
Create extra to tile.
Definition: maphand.cpp:2405
bool map_is_known_and_seen(const struct tile *ptile, const struct player *pplayer, enum vision_layer vlayer)
Returns whether the layer 'vlayer' of the tile 'ptile' is known and seen by the player 'pplayer'.
Definition: maphand.cpp:894
void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
Shows the area to the player.
Definition: maphand.cpp:852
void update_tile_knowledge(struct tile *ptile)
Update playermap knowledge for everybody who sees the tile, and send a packet to everyone whose info ...
Definition: maphand.cpp:1395
void check_terrain_change(struct tile *ptile, struct terrain *oldter)
Handles local and global side effects for a terrain change for a single tile.
Definition: maphand.cpp:1875
struct player_tile * map_get_player_tile(const struct tile *ptile, const struct player *pplayer)
Players' information of tiles is tracked so that fogged area can be kept consistent even when the cli...
Definition: maphand.cpp:1341
struct vision_site * map_get_player_site(const struct tile *ptile, const struct player *pplayer)
Returns site located at given tile from player map.
Definition: maphand.cpp:1330
void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
Change the sight points for the vision source, fogging or unfogging tiles as needed.
Definition: maphand.cpp:2383
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Return TRUE iff a unit of the given unit type can "exist" at this location.
Definition: movement.cpp:236
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "exist" at this location.
Definition: movement.cpp:267
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
This tile is native to unit.
Definition: movement.cpp:279
int unit_move_rate(const struct unit *punit)
This function calculates the move rate of the unit.
Definition: movement.cpp:78
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Return whether we could find a suitable transporter for given unit at 'ptile'.
Definition: movement.cpp:743
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
This terrain is native to unit class.
Definition: movement.cpp:290
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Return TRUE iff the unit can "survive" at this location.
Definition: movement.cpp:452
bool is_unit_being_refueled(const struct unit *punit)
Is unit being refueled in its current position.
Definition: movement.cpp:759
@ MR_OK
Definition: movement.h:26
@ MR_NOT_ALLOWED
Definition: movement.h:42
@ MR_DEATH
Definition: movement.h:27
static const char * name_translation_get(const struct name_translation *ptrans)
const char * nation_rule_name(const struct nation_type *pnation)
Return the (untranslated) rule name of the nation (adjective form).
Definition: nation.cpp:115
const char * nation_plural_for_player(const struct player *pplayer)
Return the (translated) plural noun of the given nation of a player.
Definition: nation.cpp:155
struct nation_type * nation_of_unit(const struct unit *punit)
Return the nation of the player who owns the unit.
Definition: nation.cpp:438
const char * nation_adjective_for_player(const struct player *pplayer)
Return the (translated) adjective for the given nation of a player.
Definition: nation.cpp:146
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Similar to notify_conn_packet (see also), but takes player as "destination".
Definition: notify.cpp:284
void notify_conn(struct conn_list *dest, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
See notify_conn_packet - this is just the "non-v" version, with varargs.
Definition: notify.cpp:235
#define MAX_LEN_ROUTE
Definition: packets.h:38
unit_info_use
Definition: packets.h:60
@ UNIT_INFO_IDENTITY
Definition: packets.h:61
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
Factory function to create a new map according to the parameter.
PFPath pf_map_path(struct pf_map *pfm, struct tile *ptile)
CHECK DOCS AFTER FULL CONVERSTION OF pf_path to class PFPath Tries to find the best path in the given...
void pf_map_destroy(struct pf_map *pfm)
After usage the map must be destroyed.
#define pf_map_move_costs_iterate_end
Definition: path_finding.h:542
#define pf_map_move_costs_iterate(ARG_pfm, NAME_tile, NAME_cost, COND_from_start)
Definition: path_finding.h:532
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct unit *punit)
Fill classic parameters for an unit.
Definition: pf_tools.cpp:822
struct unit * player_unit_by_number(const struct player *pplayer, int unit_id)
If the specified player owns the unit with the specified id, return pointer to the unit struct.
Definition: player.cpp:1139
bool players_on_same_team(const struct player *pplayer1, const struct player *pplayer2)
Return TRUE if players are in the same team.
Definition: player.cpp:1405
bool can_player_see_unit_at(const struct player *pplayer, const struct unit *punit, const struct tile *ptile, bool is_transported)
Checks if a unit can be seen by pplayer at (x,y).
Definition: player.cpp:959
struct player * player_by_number(const int player_id)
Return struct player pointer for the given player index.
Definition: player.cpp:768
int player_number(const struct player *pplayer)
Return the player index/number/id.
Definition: player.cpp:756
bool can_player_see_unit(const struct player *pplayer, const struct unit *punit)
Checks if a unit can be seen by pplayer at its current location.
Definition: player.cpp:1016
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players can attack each other.
Definition: player.cpp:1317
int player_index(const struct player *pplayer)
Return the player index.
Definition: player.cpp:748
const char * player_name(const struct player *pplayer)
Return the leader name of the player.
Definition: player.cpp:816
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players are allied.
Definition: player.cpp:1334
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players have peace, cease-fire, or armistice.
Definition: player.cpp:1388
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
static bool is_barbarian(const struct player *pplayer)
Definition: player.h:474
#define is_ai(plr)
Definition: player.h:227
#define is_human(plr)
Definition: player.h:226
struct conn_list * player_reply_dest(struct player *pplayer)
Convenience function to return "reply" destination connection list for player: pplayer->current_conn ...
Definition: plrhand.cpp:1469
void player_update_last_war_action(struct player *pplayer)
Update last war action timestamp (affects player mood).
Definition: plrhand.cpp:730
void player_status_add(struct player *plr, enum player_status pstatus)
Add a status flag to a player.
Definition: plrhand.cpp:3145
void maybe_make_contact(struct tile *ptile, struct player *pplayer)
Check if we make contact with anyone.
Definition: plrhand.cpp:2282
void send_player_info_c(struct player *src, struct conn_list *dest)
Send information about player slot 'src', or all valid (i.e.
Definition: plrhand.cpp:1048
#define phase_players_iterate(pplayer)
Definition: plrhand.h:99
#define phase_players_iterate_end
Definition: plrhand.h:105
#define fc_rand(_size)
Definition: rand.h:16
bool are_reqs_active(const struct player *target_player, const struct player *other_player, const struct city *target_city, const struct impr_type *target_building, const struct tile *target_tile, const struct unit *target_unit, const struct unit_type *target_unittype, const struct output_type *target_output, const struct specialist *target_specialist, const struct action *target_action, const struct requirement_vector *reqs, const enum req_problem_type prob_type, const enum vision_layer vision_layer, const enum national_intelligence nintel)
Checks the requirement(s) to see if they are active on the given target.
struct research * research_get(const struct player *pplayer)
Returns the research structure associated with the player.
Definition: research.cpp:110
QString research_advance_rule_name(const struct research *presearch, Tech_type_id tech)
Store the rule name of the given tech (including A_FUTURE) in 'buf'.
Definition: research.cpp:233
void script_server_signal_emit(const char *signal_name,...)
Invoke all the callback functions attached to a given signal.
void script_server_remove_exported_object(void *object)
Mark any, if exported, full userdata representing 'object' in the current script state as 'Nonexisten...
void flush_packets()
Attempt to flush all information in the send buffers for upto 'netwait' seconds.
Definition: sernet.cpp:187
void format_time_duration(time_t t, char *buf, int maxlen)
Convenience function to nicely format a time_t seconds value in to a string with hours,...
Definition: shared.cpp:1187
#define CLIP(lower, current, upper)
Definition: shared.h:51
#define ARRAY_SIZE(x)
Definition: shared.h:79
#define MIN(x, y)
Definition: shared.h:49
#define MAX(x, y)
Definition: shared.h:48
int step
Definition: specpq.h:83
int identity_number()
Identity ids wrap at IDENTITY_NUMBER_SIZE, skipping IDENTITY_NUMBER_ZERO Setup in server_game_init()
Definition: srv_main.cpp:1993
enum act_tgt_compl target_complexity
Definition: actions.h:315
struct act_prob prob
Definition: unittools.cpp:108
Definition: city.h:291
int id
Definition: city.h:296
struct player * owner
Definition: city.h:294
int airlift
Definition: city.h:349
struct tile * tile
Definition: city.h:293
struct unit_list * units_supported
Definition: city.h:377
struct civ_game::@28::@32 server
struct packet_ruleset_control control
Definition: game.h:74
struct conn_list * est_connections
Definition: game.h:88
struct packet_game_info info
Definition: game.h:80
bool ruledit_disabled
Definition: extras.h:77
A vertex in the path-finding graph.
Definition: path_finder.h:31
tile * location
Where we are.
Definition: path.h:22
enum barbarian_type barbarian_type
Definition: player.h:115
int units_killed
Definition: player.h:99
int units_lost
Definition: player.h:100
bv_extras extras
Definition: maphand.h:33
struct terrain * terrain
Definition: maphand.h:30
std::unique_ptr< vision_site > site
Definition: maphand.h:28
struct player * owner
Definition: maphand.h:31
Definition: player.h:231
struct city_list * cities
Definition: player.h:263
struct player_ai ai_common
Definition: player.h:270
struct player::@65::@67 server
struct unit_list * units
Definition: player.h:264
struct conn_list * connections
Definition: player.h:280
bool is_alive
Definition: player.h:250
struct player_economic economic
Definition: player.h:266
struct player_score score
Definition: player.h:265
Definition: servers.h:55
Definition: tile.h:42
int index
Definition: tile.h:43
struct unit_list * units
Definition: tile.h:50
struct unit_class::@81 cache
enum hut_behavior hut_behavior
Definition: unittype.h:129
struct extra_type_list * refuel_bases
Definition: unittype.h:140
bv_player can_see_unit
Definition: unittools.cpp:88
struct player * powner
Definition: unittools.cpp:87
bv_player can_see_move
Definition: unittools.cpp:89
struct unit * punit
Definition: unittools.cpp:86
struct vision * old_vision
Definition: unittools.cpp:90
enum unit_activity activity
Definition: unit.h:81
enum unit_orders order
Definition: unit.h:80
int action
Definition: unit.h:87
enum direction8 dir
Definition: unit.h:89
int target
Definition: unit.h:84
int sub_target
Definition: unit.h:85
int vision_radius_sq
Definition: unittype.h:487
enum vision_layer vlayer
Definition: unittype.h:532
int bombard_rate
Definition: unittype.h:512
int hp
Definition: unittype.h:489
const struct unit_type * converted_to
Definition: unittype.h:495
time_t wake_up
Definition: unit.h:121
enum unit_activity activity
Definition: unit.h:122
int id
Definition: unit.h:120
int activity_count
Definition: unit.h:123
Definition: unit.h:134
time_t action_timestamp
Definition: unit.h:203
int length
Definition: unit.h:192
int upkeep[O_LAST]
Definition: unit.h:145
bool has_orders
Definition: unit.h:190
enum action_decision action_decision_want
Definition: unit.h:199
int battlegroup
Definition: unit.h:188
enum unit_activity activity
Definition: unit.h:154
int moves_left
Definition: unit.h:147
int id
Definition: unit.h:141
bool moved
Definition: unit.h:170
int index
Definition: unit.h:192
bool vigilant
Definition: unit.h:194
int hp
Definition: unit.h:148
int fuel
Definition: unit.h:150
struct extra_type * changed_from_target
Definition: unit.h:167
bool stay
Definition: unit.h:202
enum direction8 facing
Definition: unit.h:138
struct unit::@76::@79 server
struct tile * tile
Definition: unit.h:136
struct extra_type * activity_target
Definition: unit.h:161
int activity_count
Definition: unit.h:159
struct unit_order * list
Definition: unit.h:195
enum unit_activity changed_from
Definition: unit.h:165
struct player * nationality
Definition: unit.h:140
bool repeat
Definition: unit.h:193
QString name
Definition: unit.h:143
int action_turn
Definition: unit.h:204
int homecity
Definition: unit.h:142
bool paradropped
Definition: unit.h:171
bool done_moving
Definition: unit.h:178
struct goods_type * carrying
Definition: unit.h:183
struct tile * goto_tile
Definition: unit.h:152
struct unit::@75 orders
struct tile * action_decision_tile
Definition: unit.h:200
const struct unit_type * utype
Definition: unit.h:135
int veteran
Definition: unit.h:149
int changed_from_count
Definition: unit.h:166
enum server_side_agent ssa_controller
Definition: unit.h:169
int base_raise_chance
Definition: unittype.h:455
struct name_translation name
Definition: unittype.h:452
int work_raise_chance
Definition: unittype.h:456
bool occupied
Definition: vision.h:121
Definition: vision.h:83
struct civ_map map
Definition: world_object.h:21
size_t fc_strlcpy(char *dest, const char *src, size_t n)
fc_strlcpy() provides utf-8 version of (non-standard) function strlcpy() It is intended as more user-...
Definition: support.cpp:412
#define sz_strlcpy(dest, src)
Definition: support.h:140
struct advance * valid_advance_by_number(const Tech_type_id id)
Returns pointer when the advance "exists" in this game, returns nullptr otherwise.
Definition: tech.cpp:154
#define A_FUTURE
Definition: tech.h:39
#define A_NONE
Definition: tech.h:36
#define A_UNSET
Definition: tech.h:41
Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, Tech_type_id preferred)
If victim has a tech which pplayer doesn't have, pplayer will get it.
Definition: techtools.cpp:1227
struct extra_type * get_preferred_pillage(bv_extras extras)
Returns the highest-priority (best) extra to be pillaged from the terrain set.
Definition: terrain.cpp:439
const char * terrain_name_translation(const struct terrain *pterrain)
Return the (translated) name of the terrain.
Definition: terrain.cpp:175
void tile_add_extra(struct tile *ptile, const struct extra_type *pextra)
Adds extra to tile.
Definition: tile.cpp:974
bool tile_has_claimable_base(const struct tile *ptile, const struct unit_type *punittype)
Check if tile contains base providing effect for unit.
Definition: tile.cpp:203
bool tile_apply_activity(struct tile *ptile, Activity_type_id act, struct extra_type *tgt)
Apply an activity (Activity_type_id, e.g., ACTIVITY_TRANSFORM) to a tile.
Definition: tile.cpp:701
int tile_extras_defense_bonus(const struct tile *ptile, const struct unit_type *punittype)
Calculate defense bonus given for unit type by bases and roads.
Definition: tile.cpp:223
bool tile_has_base_flag_for_unit(const struct tile *ptile, const struct unit_type *punittype, enum base_flag_id flag)
Check if tile contains base providing effect for unit.
Definition: tile.cpp:182
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Time to complete the given activity on the given tile.
Definition: tile.cpp:427
enum known_type tile_get_known(const struct tile *ptile, const struct player *pplayer)
Return a known_type enumeration value for the tile.
Definition: tile.cpp:398
struct city * tile_city(const struct tile *ptile)
Return the city on this tile (or nullptr), checking for city center.
Definition: tile.cpp:72
#define tile_index(_pt_)
Definition: tile.h:70
@ TILE_UNKNOWN
Definition: tile.h:29
#define tile_terrain(_tile)
Definition: tile.h:93
#define TILE_XY(ptile)
Definition: tile.h:36
static const bv_extras * tile_extras(const struct tile *ptile)
Definition: tile.h:102
#define tile_continent(_tile)
Definition: tile.h:74
#define tile_has_extra(ptile, pextra)
Definition: tile.h:130
#define tile_owner(_tile)
Definition: tile.h:78
struct goods_type * goods_from_city_to_unit(struct city *src, struct unit *punit)
Return goods type for the new traderoute between given cities.
Goods_type_id goods_index(const struct goods_type *pgood)
Return the goods index.
int get_transporter_occupancy(const struct unit *ptrans)
Return how many units are in the transport.
Definition: unit.cpp:1647
void free_unit_orders(struct unit *punit)
Free and reset the unit's goto route (punit->pgr).
Definition: unit.cpp:1633
struct unit * transporter_for_unit(const struct unit *pcargo)
Find the best transporter at the given location for the unit.
Definition: unit.cpp:1779
enum unit_upgrade_result unit_upgrade_test(const struct unit *punit, bool is_free)
Tests if the unit could be updated.
Definition: unit.cpp:1826
bool unit_is_alive(int id)
Check if unit with given id is still alive.
Definition: unit.cpp:2014
int get_activity_rate_this_turn(const struct unit *punit)
Returns the amount of work a unit does (will do) on an activity this turn.
Definition: unit.cpp:470
bool unit_transport_load(struct unit *pcargo, struct unit *ptrans, bool force)
Load pcargo onto ptrans.
Definition: unit.cpp:2123
void set_unit_activity(struct unit *punit, enum unit_activity new_activity)
Assign a new untargeted task to a unit.
Definition: unit.cpp:1011
struct unit * is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Returns true if the tile contains an allied unit and only allied units.
Definition: unit.cpp:1211
struct unit * is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Is there an non-allied unit on this tile?
Definition: unit.cpp:1252
struct unit * unit_transport_get(const struct unit *pcargo)
Returns the transporter of the unit or nullptr if it is not transported.
Definition: unit.cpp:2189
bool unit_transport_unload(struct unit *pcargo)
Unload pcargo from ptrans.
Definition: unit.cpp:2144
bool can_unit_continue_current_activity(struct unit *punit)
Check if the unit's current activity is actually legal.
Definition: unit.cpp:780
bool unit_can_convert(const struct unit *punit)
Tests if unit can be converted to another type.
Definition: unit.cpp:1877
bool can_unit_do_activity_targeted(const struct unit *punit, enum unit_activity activity, struct extra_type *target)
Return whether the unit can do the targeted activity at its current location.
Definition: unit.cpp:842
struct unit_list * unit_transport_cargo(const struct unit *ptrans)
Returns the list of cargo units.
Definition: unit.cpp:2199
bool can_unit_do_activity(const struct unit *punit, enum unit_activity activity)
Return TRUE iff the unit can do the given untargeted activity at its current location.
Definition: unit.cpp:806
struct unit * unit_virtual_create(struct player *pplayer, struct city *pcity, const struct unit_type *punittype, int veteran_level)
Create a virtual unit skeleton.
Definition: unit.cpp:1490
void unit_tile_set(struct unit *punit, struct tile *ptile)
Set the tile location of the unit.
Definition: unit.cpp:1200
bool unit_transported(const struct unit *pcargo)
Returns TRUE iff the unit is transported.
Definition: unit.cpp:2176
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Return TRUE iff the given unit can be unloaded from its current transporter.
Definition: unit.cpp:720
bool unit_has_orders(const struct unit *punit)
Return TRUE iff the unit is following client-side orders.
Definition: unit.cpp:195
struct player * unit_nationality(const struct unit *punit)
Return the nationality of the unit.
Definition: unit.cpp:1190
bool activity_requires_target(enum unit_activity activity)
Return TRUE if activity requires some sort of target to be specified.
Definition: unit.cpp:506
struct unit * is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Is there an enemy unit on this tile? Returns the unit or nullptr if none.
Definition: unit.cpp:1235
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_cargo_iterate_end
Definition: unit.h:464
unit_orders
Definition: unit.h:31
@ ORDER_ACTION_MOVE
Definition: unit.h:39
@ ORDER_ACTIVITY
Definition: unit.h:35
@ ORDER_FULL_MP
Definition: unit.h:37
@ ORDER_MOVE
Definition: unit.h:33
@ ORDER_LAST
Definition: unit.h:43
@ ORDER_PERFORM_ACTION
Definition: unit.h:41
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition: unit.h:461
#define CHECK_UNIT(punit)
Definition: unit.h:264
#define unit_owner(_pu)
Definition: unit.h:370
@ UU_OK
Definition: unit.h:49
#define unit_home(_pu_)
Definition: unit.h:369
bool unit_move_handling(struct unit *punit, struct tile *pdesttile, bool igzoc, bool move_do_not_act)
Will try to move to/attack the tile dest_x,dest_y.
Definition: unithand.cpp:4654
void handle_unit_orders(struct player *pplayer, const struct packet_unit_orders *packet)
Receives route packages.
Definition: unithand.cpp:5612
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)
Try to explain to the player why an action is illegal.
Definition: unithand.cpp:2003
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Handle request for changing activity.
Definition: unithand.cpp:5485
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)
Execute a request to perform an action and let the caller know if it was performed or not.
Definition: unithand.cpp:2737
void handle_unit_server_side_agent_set(struct player *pplayer, int unit_id, enum server_side_agent agent)
Handle request to change controlling server side agent.
Definition: unithand.cpp:5340
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_safe(unitlist, _unit)
Definition: unitlist.h:33
#define unit_list_iterate_end
Definition: unitlist.h:27
#define unit_list_iterate_safe_end
Definition: unitlist.h:54
bool unit_move(struct unit *punit, struct tile *pdesttile, int move_cost, struct unit *embark_to, bool find_embark_target, bool conquer_city_allowed)
Moves a unit.
Definition: unittools.cpp:3878
void unit_did_action(struct unit *punit)
Mark a unit as having done something at the current time.
Definition: unittools.cpp:4879
static void autoattack_prob_free(struct autoattack_prob *prob)
Used when unit_survive_autoattack()'s autoattack_prob_list autoattack frees its items.
Definition: unittools.cpp:3336
bool do_airline(struct unit *punit, struct city *pdest_city, const struct action *paction)
Go by airline, if both cities have an airport and neither has been used this turn the unit will be tr...
Definition: unittools.cpp:3018
static void unit_activity_complete(struct unit *punit)
Progress settlers in their current tasks, and units that is pillaging.
Definition: unittools.cpp:817
void place_partisans(struct tile *pcenter, struct player *powner, int count, int sq_radius)
Place partisans for powner around pcenter (normally around a city).
Definition: unittools.cpp:1180
static bool try_to_save_unit(struct unit *punit, const struct unit_type *pttype, bool helpless, bool teleporting, const struct city *pexclcity)
Determine if it is possible to save a given unit, and if so, save them.
Definition: unittools.cpp:2260
bool execute_orders(struct unit *punit, const bool fresh)
Executes a unit's orders stored in punit->orders.
Definition: unittools.cpp:4384
static void unit_convert(struct unit *punit)
Convert a single unit to another type.
Definition: unittools.cpp:750
void update_unit_activities(struct player *pplayer)
Iterate through all units and update them.
Definition: unittools.cpp:646
static void throw_units_from_illegal_cities(struct player *pplayer, bool verbose)
Throw pplayer's units from non allied cities.
Definition: unittools.cpp:1438
#define unit_move_data_list_iterate_rev_end
Definition: unittools.cpp:100
static void server_remove_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason)
We remove the unit and see if it's disappearance has affected the homecity and the city it was in.
Definition: unittools.cpp:1895
static void unit_lost_with_transport(const struct player *pplayer, struct unit *pcargo, const struct unit_type *ptransport, struct player *killer)
Handle units destroyed when their transport is destroyed.
Definition: unittools.cpp:2028
void unit_activities_cancel_all_illegal(const struct tile *ptile)
Cancel all illegal activities done by units at the specified tile.
Definition: unittools.cpp:774
static void cancel_orders(struct unit *punit, const char *dbg_msg)
Cancel orders for the unit.
Definition: unittools.cpp:3525
void remove_allied_visibility(struct player *pplayer, struct player *aplayer, const struct unit_list *seen_units)
When two players cancel an alliance, a lot of units that were visible may no longer be visible (this ...
Definition: unittools.cpp:1593
struct unit * unit_change_owner(struct unit *punit, struct player *pplayer, int homecity, enum unit_loss_reason reason)
We don't really change owner of the unit, but create completely new unit as its copy.
Definition: unittools.cpp:2302
static bool maybe_cancel_goto_due_to_enemy(struct unit *punit, struct tile *ptile)
Maybe cancel the goto if there is an enemy in the way.
Definition: unittools.cpp:4312
struct unit * create_unit(struct player *pplayer, struct tile *ptile, const struct unit_type *type, int veteran_level, int homecity_id, int moves_left)
Wrapper of the below.
Definition: unittools.cpp:1762
void bounce_unit(struct unit *punit, bool verbose, bounce_reason reason, int max_distance)
Move or remove a unit due to stack conflicts.
Definition: unittools.cpp:1327
void resolve_unit_stacks(struct player *pplayer, struct player *aplayer, bool verbose)
When in civil war or an alliance breaks there will potentially be units from both sides coexisting on...
Definition: unittools.cpp:1537
static void unit_move_data_unref(struct unit_move_data *pdata)
Decrease the reference counter and destroy if needed.
Definition: unittools.cpp:3848
void unit_set_removal_callback(struct unit *punit, void(*callback)(struct unit *punit))
Set the call back to run when the server removes the unit.
Definition: unittools.cpp:1872
void unit_bombs_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp)
This is the basic unit versus unit classic bombardment routine.
Definition: unittools.cpp:321
void package_unit(struct unit *punit, struct packet_unit_info *packet)
Package a unit_info packet.
Definition: unittools.cpp:2662
#define unit_move_data_list_iterate_end
Definition: unittools.cpp:97
static void unit_restore_movepoints(struct player *pplayer, struct unit *punit)
Move points are trivial, only modifiers to the base value is if it's sea units and the player has cer...
Definition: unittools.cpp:636
static void wakeup_neighbor_sentries(struct unit *punit)
Will wake up any neighboring enemy sentry units or patrolling units.
Definition: unittools.cpp:3536
static void update_unit_activity(struct unit *punit, time_t now)
Progress settlers in their current tasks, and units that are pillaging.
Definition: unittools.cpp:995
static int total_activity(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Calculate the total amount of activity performed by all units on a tile for a given task and target.
Definition: unittools.cpp:691
void unit_versus_unit(struct unit *attacker, struct unit *defender, int *att_hp, int *def_hp)
This is the basic unit versus unit combat routine.
Definition: unittools.cpp:268
static void unit_transport_load_tp_status(struct unit *punit, struct unit *ptrans, bool force)
Load unit to transport, send transport's loaded status to everyone.
Definition: unittools.cpp:3295
static bool converting_fuel_rescue(struct unit *punit)
Return true if unit is about to finish converting to a unittype with more/no fuel,...
Definition: unittools.cpp:442
#define autoattack_prob_list_iterate_safe_end
Definition: unittools.cpp:124
static bool unit_survive_autoattack(struct unit *punit)
Check if unit survives enemy autoattacks.
Definition: unittools.cpp:3392
void finalize_unit_phase_beginning(struct player *pplayer)
Iterate through all units and remember their current activities.
Definition: unittools.cpp:673
void execute_unit_orders(struct player *pplayer)
Iterate through all units and execute their orders.
Definition: unittools.cpp:659
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)
Find place to place partisans.
Definition: unittools.cpp:1132
void send_unit_info(struct conn_list *dest, struct unit *punit)
Send the unit to the players who need the info.
Definition: unittools.cpp:2808
static void wipe_unit_full(struct unit *punit, bool transported, enum unit_loss_reason reason, struct player *killer)
Remove the unit, and passengers if it is a carrying any.
Definition: unittools.cpp:2051
static void resolve_stack_conflicts(struct player *pplayer, struct player *aplayer, bool verbose)
For each pplayer's unit, check if we stack illegally, if so, bounce both players' units.
Definition: unittools.cpp:1505
void transform_unit(struct unit *punit, const struct unit_type *to_unit, bool is_free)
Really transforms a single unit to another type.
Definition: unittools.cpp:1676
static void check_unit_activity(struct unit *punit)
Check if the units activity is legal for a move , and reset it if it isn't.
Definition: unittools.cpp:3740
static void do_upgrade_effects(struct player *pplayer)
Do unit auto-upgrades to players with the EFT_UNIT_UPGRADE effect (traditionally from Leonardo's Work...
Definition: unittools.cpp:388
int get_unit_vision_at(struct unit *punit, const struct tile *ptile, enum vision_layer vlayer)
Return the vision the unit will have at the given tile.
Definition: unittools.cpp:4791
bool is_airunit_refuel_point(const struct tile *ptile, const struct player *pplayer, const struct unit *punit)
Can unit refuel on tile.
Definition: unittools.cpp:1635
struct unit_order * create_unit_orders(int length, const struct unit_order *orders)
Sanity-check unit order arrays from a packet and create a unit_order array from their contents if val...
Definition: unittools.cpp:5119
void notify_unit_experience(struct unit *punit)
Common notification for all experience levels.
Definition: unittools.cpp:723
void package_short_unit(struct unit *punit, struct packet_unit_short_info *packet, enum unit_info_use packet_use, int info_city_id)
Package a short_unit_info packet.
Definition: unittools.cpp:2750
static bool maybe_become_veteran_real(struct unit *punit, bool settler)
After a battle, after diplomatic aggression and after surviving trireme loss chance,...
Definition: unittools.cpp:220
void give_allied_visibility(struct player *pplayer, struct player *aplayer)
Refresh units visibility of 'aplayer' for 'pplayer' after alliance have been contracted.
Definition: unittools.cpp:1621
void unit_forget_last_activity(struct unit *punit)
Forget the unit's last activity so that it can't be resumed.
Definition: unittools.cpp:1073
#define unit_move_data_list_iterate(_plist, _pdata)
Definition: unittools.cpp:95
void finish_unit_wait(struct unit *punit, int activity_count)
Finish activity of a unit that was deferred by unitwaittime.
Definition: unittools.cpp:1063
static struct unit_move_data * unit_move_data(struct unit *punit, struct tile *psrctile, struct tile *pdesttile)
Create a new unit move data, or use previous one if available.
Definition: unittools.cpp:3776
static void server_remove_unit(struct unit *punit, enum unit_loss_reason reason)
We remove the unit and see if it's disappearance has affected the homecity and the city it was in.
Definition: unittools.cpp:2019
struct unit_type * find_a_unit_type(enum unit_role_id role, enum unit_role_id role_tech)
Returns a unit type that matches the role_tech or role roles.
Definition: unittools.cpp:159
void combat_veterans(struct unit *attacker, struct unit *defender)
Maybe make either side of combat veteran.
Definition: unittools.cpp:371
void unit_unset_removal_callback(struct unit *punit)
Remove the call back so nothing runs when the server removes the unit.
Definition: unittools.cpp:1886
bool maybe_make_veteran(struct unit *punit)
Unit has a chance to become veteran.
Definition: unittools.cpp:204
void unit_refresh_vision(struct unit *punit)
Refresh the unit's vision.
Definition: unittools.cpp:4818
void do_explore(struct unit *punit)
Autoexplore with unit.
Definition: unittools.cpp:3047
void unit_transport_load_send(struct unit *punit, struct unit *ptrans)
Put the unit onto the transporter, and tell everyone.
Definition: unittools.cpp:3261
bool unit_can_do_action_now(const struct unit *punit)
Used to implement the game rule controlled by the unitwaittime setting.
Definition: unittools.cpp:4844
#define autoattack_prob_list_iterate_safe(autoattack_prob_list, _aap_, _unit_)
Definition: unittools.cpp:115
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Remove the unit, and passengers if it is a carrying any.
Definition: unittools.cpp:2248
void unit_goes_out_of_sight(struct player *pplayer, const unit *punit)
Handle situation where unit goes out of player sight.
Definition: unittools.cpp:2795
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)
Creates a unit, and set it's initial values, and put it into the right lists.
Definition: unittools.cpp:1789
bool do_paradrop(struct unit *punit, struct tile *ptile, const struct action *paction)
Returns whether the drop was made or not.
Definition: unittools.cpp:3082
static bool player_is_watching(struct unit *punit, const bool fresh)
Returns TRUE iff it is reasonable to assume that the player is wathing the unit.
Definition: unittools.cpp:4357
bool unit_order_list_is_sane(int length, const struct unit_order *orders)
Returns TRUE iff the unit order array is sane.
Definition: unittools.cpp:4924
void player_restore_units(struct player *pplayer)
Definition: unittools.cpp:481
void do_nuclear_explosion(struct player *pplayer, struct tile *ptile)
Nuke all the squares in a 3x3 square around the center of the explosion pplayer is the player that ca...
Definition: unittools.cpp:2999
static void do_nuke_tile(struct player *pplayer, struct tile *ptile)
Nuke a square: 1) remove all units on the square, and 2) halve the size of the city on the square.
Definition: unittools.cpp:2892
#define unit_move_data_list_iterate_rev(_plist, _pdata)
Definition: unittools.cpp:98
void unit_transport_unload_send(struct unit *punit)
Pull the unit off of the transporter, and tell everyone.
Definition: unittools.cpp:3316
bool unit_can_be_retired(struct unit *punit)
Units (usually barbarian units) may disband spontaneously if they are far from any enemy units or cit...
Definition: unittools.cpp:4906
static bool total_activity_done(struct tile *ptile, enum unit_activity act, struct extra_type *tgt)
Check the total amount of activity performed by all units on a tile for a given task.
Definition: unittools.cpp:713
bool teleport_unit_to_city(struct unit *punit, struct city *pcity, int move_cost, bool verbose)
Teleport punit to city at cost specified.
Definition: unittools.cpp:1212
static bool hut_get_limited(struct unit *punit)
Give 25 Gold or kill the unit.
Definition: unittools.cpp:3177
void unit_assign_specific_activity_target(struct unit *punit, enum unit_activity *activity, struct extra_type **target)
For some activities (currently only pillaging), the precise target can be assigned by the server rath...
Definition: unittools.cpp:1105
static int compare_units(const struct autoattack_prob *const *p1, const struct autoattack_prob *const *q1)
This function is passed to autoattack_prob_list_sort() to sort a list of units and action probabiliti...
Definition: unittools.cpp:3350
void unit_activities_cancel_all_illegal_area(const struct tile *ptile)
Cancel all illegal activities done by units at the specified tile, and surrounding tiles.
Definition: unittools.cpp:801
static bool unit_move_consequences(struct unit *punit, struct tile *src_tile, struct tile *dst_tile, bool passenger, bool conquer_city_allowed)
Does: 1) updates the unit's homecity and the city it enters/leaves (the city's happiness varies).
Definition: unittools.cpp:3625
void unit_get_goods(struct unit *punit)
Set carried goods for unit.
Definition: unittools.cpp:1773
void send_all_known_units(struct conn_list *dest)
For each specified connections, send information about all the units known to that player/conn.
Definition: unittools.cpp:2859
static bool maybe_cancel_patrol_due_to_enemy(struct unit *punit)
Maybe cancel the patrol as there is an enemy near.
Definition: unittools.cpp:4325
void unit_list_refresh_vision(struct unit_list *punitlist)
Refresh the vision of all units in the list - see unit_refresh_vision.
Definition: unittools.cpp:4834
static void unit_enter_hut(struct unit *punit)
Due to the effects in the scripted hut behavior can not be predicted, unit_enter_hut returns nothing.
Definition: unittools.cpp:3207
void kill_unit(struct unit *pkiller, struct unit *punit, bool vet)
Called when one unit kills another in combat (this function is only called in one place).
Definition: unittools.cpp:2358
bool unit_activity_needs_target_from_client(enum unit_activity activity)
Return TRUE iff activity requires some sort of target to be specified by the client.
Definition: unittools.cpp:1085
struct unit_list * get_units_seen_via_ally(const struct player *pplayer, const struct player *aplayer)
Returns the list of the units seen by 'pplayer' potentially seen only thanks to an alliance with 'apl...
Definition: unittools.cpp:1552
bounce_reason
Why do we need to bounce a unit?
Definition: unittools.h:109
@ generic
We just need to do it.
@ terrain_change
We need to do it because of changing terrain.
const char * unit_rule_name(const struct unit *punit)
Return the (untranslated) rule name of the unit.
Definition: unittype.cpp:1283
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
bool utype_is_moved_to_tgt_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff successfully performing the specified action always will move the actor unit of the ...
Definition: unittype.cpp:969
struct unit_type * best_role_unit_for_player(const struct player *pplayer, int role)
Return "best" unit the player can build, with given role/flag.
Definition: unittype.cpp:1950
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Return whether this player can upgrade this unit type (to any other unit type).
Definition: unittype.cpp:1379
int num_role_units(int role)
How many unit types have specified role/flag.
Definition: unittype.cpp:1866
bool utype_player_already_has_this_unique(const struct player *pplayer, const struct unit_type *putype)
Returns TRUE iff the unit type is unique and the player already has one.
Definition: unittype.cpp:1599
struct unit_class * unit_class_get(const struct unit *punit)
Returns unit class pointer for a unit.
Definition: unittype.cpp:2151
bool can_player_build_unit_direct(const struct player *p, const struct unit_type *punittype)
Whether player can build given unit somewhere, ignoring whether unit is obsolete and assuming the pla...
Definition: unittype.cpp:1628
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Return whether the unit has the given role.
Definition: unittype.cpp:195
const struct veteran_system * utype_veteran_system(const struct unit_type *punittype)
Return veteran system used for this unit type.
Definition: unittype.cpp:2208
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Return whether the unit has the given flag.
Definition: unittype.cpp:176
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Definition: unittype.cpp:1256
bool utype_is_consumed_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff performing the specified action will consume an actor unit of the specified type.
Definition: unittype.cpp:936
Unit_type_id utype_number(const struct unit_type *punittype)
Return the unit type index.
Definition: unittype.cpp:91
struct unit_type * get_role_unit(int role, int role_index)
Return index-th unit with specified role/flag.
Definition: unittype.cpp:1900
const char * unit_name_translation(const struct unit *punit)
Return the (translated) name of the unit.
Definition: unittype.cpp:1265
bool utype_is_unmoved_by_action(const struct action *paction, const struct unit_type *utype)
Returns TRUE iff successfully performing the specified action never will move the actor unit from its...
Definition: unittype.cpp:1009
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Return veteran level properties of given unit in given veterancy level.
Definition: unittype.cpp:2224
int unit_upgrade_price(const struct player *pplayer, const struct unit_type *from, const struct unit_type *to)
Return the cost (gold) of upgrading a single unit of the specified type to the new type.
Definition: unittype.cpp:1407
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition: unittype.h:704
#define utype_class(_t_)
Definition: unittype.h:691
#define utype_fuel(ptype)
Definition: unittype.h:772
hut_behavior
Definition: unittype.h:113
@ HUT_FRIGHTEN
Definition: unittype.h:113
@ HUT_NOTHING
Definition: unittype.h:113
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition: unittype.h:584
#define U_LAST
Definition: unittype.h:31
struct vision * vision_new(struct player *pplayer, struct tile *ptile)
Create a new vision source.
Definition: vision.cpp:27
void vision_free(struct vision *vision)
Free the vision source.
Definition: vision.cpp:44
#define ASSERT_VISION(v)
Definition: vision.h:99
#define V_RADIUS(main_sq, invis_sq, subs_sq)
Definition: vision.h:94
#define vision_site_owner(v)
Definition: vision.h:132
short int v_radius_t[V_COUNT]
Definition: vision.h:81