Freeciv21
Develop your civilization from humble roots to a global empire
pf_tools.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 1996-2020 Freeciv21 and Freeciv contributors. This file is
3  __ __ part of Freeciv21. Freeciv21 is free software: you can
4 / \\..// \ redistribute it and/or modify it under the terms of the GNU
5  ( oo ) General Public License as published by the Free Software
6  \__/ Foundation, either version 3 of the License, or (at your
7  option) any later version. You should have received
8  a copy of the GNU General Public License along with Freeciv21. If not,
9  see https://www.gnu.org/licenses/.
10  */
11 
12 #include <cstring>
13 
14 // utility
15 #include "bitvector.h"
16 #include "log.h"
17 
18 // common
19 #include "base.h"
20 #include "game.h"
21 #include "movement.h"
22 #include "tile.h"
23 #include "unit.h"
24 #include "unittype.h"
25 
26 // aicore
27 #include "aiactions.h"
28 
29 #include "pf_tools.h"
30 
31 // ===================== Capability Functions ========================
32 
37 static inline bool pf_attack_possible(const struct tile *ptile,
38  enum known_type known,
39  const struct pf_parameter *param)
40 {
41  bool attack_any;
42 
43  if (!can_attack_non_native(param->utype)
44  && !is_native_tile(param->utype, ptile)) {
45  return false;
46  }
47 
48  if (TILE_KNOWN_SEEN != known) {
49  // We cannot see units, let's assume we can attack.
50  return true;
51  }
52 
53  attack_any = false;
54  unit_list_iterate(ptile->units, punit)
55  {
56  if (!pplayers_at_war(unit_owner(punit), param->owner)) {
57  return false;
58  }
59 
60  // Unit reachability test.
61  if (BV_ISSET(param->utype->targets, uclass_index(unit_class_get(punit)))
62  || tile_has_native_base(ptile, unit_type_get(punit))) {
63  attack_any = true;
64  } else if (game.info.unreachable_protects) {
65  // We would need to be able to attack all, this is not the case.
66  return false;
67  }
68  }
70 
71  return attack_any;
72 }
73 
80 static enum pf_action pf_get_action(const struct tile *ptile,
81  enum known_type known,
82  const struct pf_parameter *param)
83 {
84  bool non_allied_city =
85  (nullptr != is_non_allied_city_tile(ptile, param->owner));
86 
87  if (non_allied_city) {
88  if (PF_AA_TRADE_ROUTE & param->actions) {
89  return PF_ACTION_TRADE_ROUTE;
90  }
91 
92  if (PF_AA_DIPLOMAT & param->actions) {
93  return PF_ACTION_DIPLOMAT;
94  }
95  }
96 
97  if (is_non_allied_unit_tile(ptile, param->owner)) {
98  if (PF_AA_DIPLOMAT & param->actions) {
99  return PF_ACTION_DIPLOMAT;
100  }
101 
102  if (PF_AA_UNIT_ATTACK & param->actions) {
103  return (pf_attack_possible(ptile, known, param)
106  }
107  }
108 
109  if (non_allied_city && PF_AA_CITY_ATTACK & param->actions) {
110  /* Consider that there are potentially units, even if
111  * is_non_allied_unit_tile() returned nullptr (usually when
112  * '!param->omniscience'). */
113  return ((utype_can_take_over(param->utype)
114  || pf_attack_possible(ptile, TILE_KNOWN_UNSEEN, param))
117  }
118 
119  return PF_ACTION_NONE;
120 }
121 
126 static bool pf_action_possible(const struct tile *src,
127  enum pf_move_scope src_scope,
128  const struct tile *dst, enum pf_action action,
129  const struct pf_parameter *param)
130 {
131  Q_UNUSED(src)
132  Q_UNUSED(dst)
133  if (PF_ACTION_ATTACK == action) {
134  return (PF_MS_NATIVE & src_scope
135  || can_attack_from_non_native(param->utype));
136 
137  } else if (PF_ACTION_DIPLOMAT == action
139  /* Don't try to act when inside of a transport over non native terrain
140  * when all actions the unit type can do requires the unit to be on
141  * native terrain. */
142  if (can_unit_act_when_ustate_is(param->utype, USP_LIVABLE_TILE, false)) {
143  return (PF_MS_NATIVE | PF_MS_CITY | PF_MS_TRANSPORT) & src_scope;
144  } else {
145  return (PF_MS_NATIVE | PF_MS_CITY) & src_scope;
146  }
147  }
148  return true;
149 }
150 
155 static enum pf_action pf_reverse_get_action(const struct tile *ptile,
156  enum known_type known,
157  const struct pf_parameter *param)
158 {
159  Q_UNUSED(known)
160  return (ptile == param->data ? PF_ACTION_ATTACK : PF_ACTION_NONE);
161 }
162 
166 static inline bool pf_transport_check(const struct pf_parameter *param,
167  const struct unit *ptrans,
168  const struct unit_type *trans_utype)
169 {
170  if (!pplayers_allied(unit_owner(ptrans), param->owner)
171  || unit_has_orders(ptrans) || param->utype == trans_utype
172  || !can_unit_type_transport(trans_utype, utype_class(param->utype))
173  || can_unit_type_transport(param->utype, utype_class(trans_utype))
175  < 1 + unit_transport_depth(ptrans) + param->cargo_depth)) {
176  return false;
177  }
178 
179  if (1 <= param->cargo_depth) {
180  unit_type_iterate(cargo_utype)
181  {
182  if (BV_ISSET(param->cargo_types, utype_index(cargo_utype))
183  && (cargo_utype == trans_utype
184  || can_unit_type_transport(cargo_utype,
185  utype_class(trans_utype)))) {
186  return false;
187  }
188  }
190  }
191 
192  unit_transports_iterate(ptrans, pparent)
193  {
194  if (unit_has_orders(pparent)
195  || param->utype == (trans_utype = unit_type_get(pparent))
196  || can_unit_type_transport(param->utype, utype_class(trans_utype))) {
197  return false;
198  }
199 
200  if (1 <= param->cargo_depth) {
201  unit_type_iterate(cargo_utype)
202  {
203  if (BV_ISSET(param->cargo_types, utype_index(cargo_utype))
204  && (cargo_utype == trans_utype
205  || can_unit_type_transport(cargo_utype,
206  utype_class(trans_utype)))) {
207  return false;
208  }
209  }
211  }
212  }
214 
215  return true;
216 }
217 
222 static enum pf_move_scope
223 pf_get_move_scope(const struct tile *ptile, bool *can_disembark,
224  enum pf_move_scope previous_scope,
225  const struct pf_parameter *param)
226 {
227  int scope = PF_MS_NONE;
228  const struct unit_class *uclass = utype_class(param->utype);
229  struct city *pcity = tile_city(ptile);
230 
231  if ((is_native_tile_to_class(uclass, ptile)
232  && (!utype_has_flag(param->utype, UTYF_COAST_STRICT)
233  || is_safe_ocean(param->map, ptile)))) {
234  scope |= PF_MS_NATIVE;
235  }
236 
237  if (nullptr != pcity
238  && (utype_can_take_over(param->utype)
239  || pplayers_allied(param->owner, city_owner(pcity)))
240  && ((previous_scope & PF_MS_CITY) // City channel previously tested
241  || uclass_has_flag(uclass, UCF_BUILD_ANYWHERE)
242  || is_native_near_tile(param->map, uclass, ptile)
243  || (1 == game.info.citymindist
244  && is_city_channel_tile(uclass, ptile, nullptr)))) {
245  scope |= PF_MS_CITY;
246  }
247 
248  if (PF_MS_NONE == scope) {
249  /* Check for transporters. Useless if we already got another way to
250  * move. */
251  bool allied_city_tile =
252  (nullptr != pcity
253  && pplayers_allied(param->owner, city_owner(pcity)));
254  const struct unit_type *utype;
255 
256  *can_disembark = false;
257 
258  unit_list_iterate(ptile->units, punit)
259  {
260  utype = unit_type_get(punit);
261 
262  if (!pf_transport_check(param, punit, utype)) {
263  continue;
264  }
265 
266  if (allied_city_tile || tile_has_native_base(ptile, utype)) {
267  scope |= PF_MS_TRANSPORT;
268  *can_disembark = true;
269  break;
270  }
271 
272  if (!utype_can_freely_load(param->utype, utype)) {
273  continue;
274  }
275 
276  scope |= PF_MS_TRANSPORT;
277 
278  if (utype_can_freely_unload(param->utype, utype)) {
279  *can_disembark = true;
280  break;
281  }
282  }
284  }
285 
286  return pf_move_scope(scope);
287 }
288 
292 static enum pf_move_scope
293 amphibious_move_scope(const struct tile *ptile, bool *can_disembark,
294  enum pf_move_scope previous_scope,
295  const struct pf_parameter *param)
296 {
297  pft_amphibious *amphibious = static_cast<pft_amphibious *>(param->data);
298  int land_scope, sea_scope;
299  bool dumb;
300 
301  land_scope =
302  pf_get_move_scope(ptile, &dumb, previous_scope, &amphibious->land);
303  sea_scope = pf_get_move_scope(ptile, &dumb, pf_move_scope(land_scope),
304  &amphibious->sea);
305 
306  if ((PF_MS_NATIVE | PF_MS_CITY) & sea_scope) {
307  *can_disembark = (PF_MS_CITY & sea_scope
308  || utype_can_freely_unload(amphibious->land.utype,
309  amphibious->sea.utype)
310  || tile_has_native_base(ptile, amphibious->sea.utype));
311  return pf_move_scope(PF_MS_TRANSPORT | land_scope);
312  }
313  return pf_move_scope(~PF_MS_TRANSPORT & land_scope);
314 }
315 
324 static inline bool pf_move_possible(const struct tile *src,
325  enum pf_move_scope src_scope,
326  const struct tile *dst,
327  enum pf_move_scope dst_scope,
328  const struct pf_parameter *param)
329 {
330  fc_assert(PF_MS_NONE != src_scope);
331 
332  if (PF_MS_NONE == dst_scope) {
333  return false;
334  }
335 
336  if (PF_MS_NATIVE == dst_scope && (PF_MS_NATIVE & src_scope)
337  && !is_native_move(utype_class(param->utype), src, dst)) {
338  return false;
339  }
340 
341  return true;
342 }
343 
344 // ===================== Move Cost Callbacks =========================
345 
351 static int normal_move(const struct tile *src, enum pf_move_scope src_scope,
352  const struct tile *dst, enum pf_move_scope dst_scope,
353  const struct pf_parameter *param)
354 {
355  if (pf_move_possible(src, src_scope, dst, dst_scope, param)) {
356  return map_move_cost(param->map, param->owner, param->utype, src, dst);
357  }
358  return PF_IMPOSSIBLE_MC;
359 }
360 
368 static int overlap_move(const struct tile *src, enum pf_move_scope src_scope,
369  const struct tile *dst, enum pf_move_scope dst_scope,
370  const struct pf_parameter *param)
371 {
372  if (pf_move_possible(src, src_scope, dst, dst_scope, param)) {
373  return map_move_cost(param->map, param->owner, param->utype, src, dst);
374  } else if (!(PF_MS_NATIVE & dst_scope)) {
375  // This should always be the last tile reached.
376  return param->move_rate;
377  }
378  return PF_IMPOSSIBLE_MC;
379 }
380 
384 static int amphibious_move(const struct tile *ptile,
385  enum pf_move_scope src_scope,
386  const struct tile *ptile1,
387  enum pf_move_scope dst_scope,
388  const struct pf_parameter *param)
389 {
390  pft_amphibious *amphibious = static_cast<pft_amphibious *>(param->data);
391  int cost, scale;
392 
393  if (PF_MS_TRANSPORT & src_scope) {
394  if (PF_MS_TRANSPORT & dst_scope) {
395  // Sea move, moving from native terrain to a city, or leaving port.
396  cost = amphibious->sea.get_MC(
397  ptile, pf_move_scope((PF_MS_CITY & src_scope) | PF_MS_NATIVE),
398  ptile1, pf_move_scope((PF_MS_CITY & dst_scope) | PF_MS_NATIVE),
399  &amphibious->sea);
400  scale = amphibious->sea_scale;
401  } else if (PF_MS_NATIVE & dst_scope) {
402  /* Disembark; use land movement function to handle non-native attacks.
403  */
404  cost = amphibious->land.get_MC(ptile, PF_MS_TRANSPORT, ptile1,
405  PF_MS_NATIVE, &amphibious->land);
406  scale = amphibious->land_scale;
407  } else {
408  // Neither ferry nor passenger can enter tile.
409  return PF_IMPOSSIBLE_MC;
410  }
411  } else if ((PF_MS_NATIVE | PF_MS_CITY) & dst_scope) {
412  // Land move
413  cost = amphibious->land.get_MC(ptile, PF_MS_NATIVE, ptile1, PF_MS_NATIVE,
414  &amphibious->land);
415  scale = amphibious->land_scale;
416  } else {
417  /* Now we have disembarked, our ferry can not help us - we have to
418  * stay on the land. */
419  return PF_IMPOSSIBLE_MC;
420  }
421  if (cost != PF_IMPOSSIBLE_MC && cost < FC_INFINITY) {
422  cost *= scale;
423  }
424  return cost;
425 }
426 
427 // ===================== Extra Cost Callbacks ========================
428 
432 static int amphibious_extra_cost(const struct tile *ptile,
433  enum known_type known,
434  const struct pf_parameter *param)
435 {
436  pft_amphibious *amphibious = static_cast<pft_amphibious *>(param->data);
437  const bool ferry_move = is_native_tile(amphibious->sea.utype, ptile);
438  int cost, scale;
439 
440  if (known == TILE_UNKNOWN) {
441  // We can travel almost anywhere
442  cost = SINGLE_MOVE;
443  scale = MAX(amphibious->sea_scale, amphibious->land_scale);
444  } else if (ferry_move && amphibious->sea.get_EC) {
445  // Do the EC callback for sea moves.
446  cost = amphibious->sea.get_EC(ptile, known, &amphibious->sea);
447  scale = amphibious->sea_scale;
448  } else if (!ferry_move && amphibious->land.get_EC) {
449  // Do the EC callback for land moves.
450  cost = amphibious->land.get_EC(ptile, known, &amphibious->land);
451  scale = amphibious->land_scale;
452  } else {
453  cost = 0;
454  scale = 1;
455  }
456 
457  if (cost != PF_IMPOSSIBLE_MC) {
458  cost *= scale;
459  }
460  return cost;
461 }
462 
463 // ===================== Tile Behaviour Callbacks ====================
464 
469 enum tile_behavior no_fights_or_unknown(const struct tile *ptile,
470  enum known_type known,
471  const struct pf_parameter *param)
472 {
473  if (known == TILE_UNKNOWN || is_non_allied_unit_tile(ptile, param->owner)
474  || is_non_allied_city_tile(ptile, param->owner)) {
475  // Can't attack
476  return TB_IGNORE;
477  }
478  return TB_NORMAL;
479 }
480 
484 enum tile_behavior no_fights(const struct tile *ptile, enum known_type known,
485  const struct pf_parameter *param)
486 {
487  Q_UNUSED(known)
488  if (is_non_allied_unit_tile(ptile, param->owner)
489  || is_non_allied_city_tile(ptile, param->owner)) {
490  // Can't attack
491  return TB_IGNORE;
492  }
493  return TB_NORMAL;
494 }
495 
499 enum tile_behavior no_intermediate_fights(const struct tile *ptile,
500  enum known_type known,
501  const struct pf_parameter *param)
502 {
503  Q_UNUSED(known)
504  if (is_non_allied_unit_tile(ptile, param->owner)
505  || is_non_allied_city_tile(ptile, param->owner)) {
506  return TB_DONT_LEAVE;
507  }
508  return TB_NORMAL;
509 }
510 
514 static enum tile_behavior
515 amphibious_behaviour(const struct tile *ptile, enum known_type known,
516  const struct pf_parameter *param)
517 {
518  pft_amphibious *amphibious = static_cast<pft_amphibious *>(param->data);
519  const bool ferry_move = is_native_tile(amphibious->sea.utype, ptile);
520 
521  // Simply a wrapper for the sea or land tile_behavior callbacks.
522  if (ferry_move && amphibious->sea.get_TB) {
523  return amphibious->sea.get_TB(ptile, known, &amphibious->sea);
524  } else if (!ferry_move && amphibious->land.get_TB) {
525  return amphibious->land.get_TB(ptile, known, &amphibious->land);
526  }
527  return TB_NORMAL;
528 }
529 
530 // ===================== Required Moves Lefts Callbacks =================
531 
535 static bool is_possible_base_fuel(const struct tile *ptile,
536  const struct pf_parameter *param)
537 {
538  const struct unit_class *uclass;
539  enum known_type tile_known =
540  (param->omniscience ? TILE_KNOWN_SEEN
541  : tile_get_known(ptile, param->owner));
542 
543  if (tile_known == TILE_UNKNOWN) {
544  // Cannot guess if it is
545  return false;
546  }
547 
548  if (is_allied_city_tile(ptile, param->owner)) {
549  return true;
550  }
551 
552  uclass = utype_class(param->utype);
554  {
555  // All airbases are considered possible, simply attack enemies.
556  if (tile_has_extra(ptile, pextra)) {
557  return true;
558  }
559  }
561 
562  if (utype_has_flag(param->utype, UTYF_COAST)) {
563  return is_safe_ocean(param->map, ptile);
564  }
565 
566  if (tile_known == TILE_KNOWN_UNSEEN) {
567  // Cannot see units
568  return false;
569  }
570 
571  // Check for carriers
572  unit_list_iterate(ptile->units, ptrans)
573  {
574  const struct unit_type *trans_utype = unit_type_get(ptrans);
575 
576  if (pf_transport_check(param, ptrans, trans_utype)
577  && (utype_can_freely_load(param->utype, trans_utype)
578  || tile_has_native_base(ptile, trans_utype))) {
579  return true;
580  }
581  }
583 
584  return false;
585 }
586 
590 static int get_closest_safe_tile_distance(const struct tile *src_tile,
591  const struct pf_parameter *param,
592  int max_distance)
593 {
594  /* This iteration should, according to the documentation in map.h iterate
595  * tiles from the center tile, so we stop the iteration to the first found
596  * refuel point (as it should be the closest). */
597  iterate_outward_dxy(param->map, src_tile, max_distance, ptile, x, y)
598  {
599  if (tile_get_known(ptile, param->owner) == TILE_UNKNOWN) {
600  // Cannot guess if the tile is safe
601  continue;
602  }
603  if (is_possible_base_fuel(ptile, param)) {
604  return map_vector_to_real_distance(x, y);
605  }
606  }
608 
609  return -1;
610 }
611 
612 // ==================== Postion Dangerous Callbacks ===================
613 
617 static int get_fuel_moves_left_req(const struct tile *ptile,
618  enum known_type known,
619  const struct pf_parameter *param)
620 {
621  Q_UNUSED(known)
622  int dist, max;
623 
624  if (is_possible_base_fuel(ptile, param)) {
625  return 0;
626  }
627 
628  /* Upper bound for search for refuel point. Sometimes unit can have more
629  * moves left than its own move rate due to wonder transfer. Compare
630  * pf_moves_left_initially(). */
631  max = MAX(param->moves_left_initially
632  + (param->fuel_left_initially - 1) * param->move_rate,
633  param->move_rate * param->fuel);
634  dist = get_closest_safe_tile_distance(ptile, param, max / SINGLE_MOVE);
635 
636  return dist != -1 ? dist * SINGLE_MOVE : PF_IMPOSSIBLE_MC;
637 }
638 
642 static bool amphibious_is_pos_dangerous(const struct tile *ptile,
643  enum known_type known,
644  const struct pf_parameter *param)
645 {
646  pft_amphibious *amphibious = static_cast<pft_amphibious *>(param->data);
647  const bool ferry_move = is_native_tile(amphibious->sea.utype, ptile);
648 
649  // Simply a wrapper for the sea or land danger callbacks.
650  if (ferry_move && amphibious->sea.is_pos_dangerous) {
651  return amphibious->sea.is_pos_dangerous(ptile, known, param);
652  } else if (!ferry_move && amphibious->land.is_pos_dangerous) {
653  return amphibious->land.is_pos_dangerous(ptile, known, param);
654  }
655  return false;
656 }
657 
658 // ======================= Tools for filling parameters =================
659 
663 static inline void
665  const struct unit_type *punittype)
666 {
667  parameter->map = &(wld.map);
668  parameter->get_TB = nullptr;
669  parameter->get_EC = nullptr;
670  parameter->is_pos_dangerous = nullptr;
671  parameter->get_moves_left_req = nullptr;
672  parameter->get_costs = nullptr;
673  parameter->get_zoc = nullptr;
674  parameter->get_move_scope = pf_get_move_scope;
675  parameter->get_action = nullptr;
676  parameter->is_action_possible = nullptr;
677  parameter->actions = PF_AA_NONE;
678 
679  parameter->utype = punittype;
680 }
681 
685 static inline void pft_enable_default_actions(struct pf_parameter *parameter)
686 {
687  if (!utype_has_flag(parameter->utype, UTYF_CIVILIAN)) {
688  parameter->actions =
690  parameter->get_action = pf_get_action;
692  if (!parameter->omniscience) {
693  // Consider units hided in cities.
694  parameter->actions =
696  }
697  }
698  if (utype_may_act_at_all(parameter->utype)) {
699  // FIXME: it should consider action enablers.
701  parameter->actions =
703  }
704  if (aia_utype_is_considered_spy(parameter->utype)) {
705  parameter->actions =
707  }
708  parameter->get_action = pf_get_action;
710  }
711 }
712 
717  struct pf_parameter *parameter, const struct unit_type *punittype,
718  struct tile *pstart_tile, struct player *powner)
719 {
720  int veteran_level =
721  get_unittype_bonus(powner, pstart_tile, punittype, EFT_VETERAN_BUILD);
722 
723  if (veteran_level >= utype_veteran_levels(punittype)) {
724  veteran_level = utype_veteran_levels(punittype) - 1;
725  }
726 
727  pft_fill_default_parameter(parameter, punittype);
728 
729  parameter->start_tile = pstart_tile;
730  parameter->moves_left_initially = punittype->move_rate;
731  parameter->move_rate = utype_move_rate(punittype, pstart_tile, powner,
732  veteran_level, punittype->hp);
733  if (utype_fuel(punittype)) {
734  parameter->fuel_left_initially = utype_fuel(punittype);
735  parameter->fuel = utype_fuel(punittype);
736  } else {
737  parameter->fuel = 1;
738  parameter->fuel_left_initially = 1;
739  }
740  parameter->transported_by_initially = nullptr;
741  parameter->cargo_depth = 0;
742  BV_CLR_ALL(parameter->cargo_types);
743  parameter->owner = powner;
744 
745  parameter->omniscience = false;
746 }
747 
751 static inline void
753  const struct unit *punit)
754 {
755  const struct unit *ptrans = unit_transport_get(punit);
756  const struct unit_type *ptype = unit_type_get(punit);
757 
758  pft_fill_default_parameter(parameter, ptype);
759 
760  parameter->start_tile = unit_tile(punit);
761  parameter->moves_left_initially = punit->moves_left;
762  parameter->move_rate = unit_move_rate(punit);
763  if (utype_fuel(ptype)) {
764  parameter->fuel_left_initially = punit->fuel;
765  parameter->fuel = utype_fuel(ptype);
766  } else {
767  parameter->fuel = 1;
768  parameter->fuel_left_initially = 1;
769  }
770  parameter->transported_by_initially =
771  (nullptr != ptrans ? unit_type_get(ptrans) : nullptr);
772  parameter->cargo_depth = unit_cargo_depth(punit);
773  BV_CLR_ALL(parameter->cargo_types);
774  unit_cargo_iterate(punit, pcargo)
775  {
776  BV_SET(parameter->cargo_types, utype_index(unit_type_get(pcargo)));
777  }
779  parameter->owner = unit_owner(punit);
780 
781  parameter->omniscience = false;
782 }
783 
787 static inline void pft_fill_parameter(struct pf_parameter *parameter,
788  const struct unit_type *punittype)
789 {
790  parameter->get_MC = normal_move;
791  parameter->ignore_none_scopes = true;
792  pft_enable_default_actions(parameter);
793 
794  if (!parameter->get_moves_left_req && utype_fuel(punittype)) {
795  // Unit needs fuel
797  }
798 
799  if (!unit_type_really_ignores_zoc(punittype)) {
800  parameter->get_zoc = is_my_zoc;
801  } else {
802  parameter->get_zoc = nullptr;
803  }
804 }
805 
809 void pft_fill_utype_parameter(struct pf_parameter *parameter,
810  const struct unit_type *punittype,
811  struct tile *pstart_tile,
812  struct player *pplayer)
813 {
814  pft_fill_utype_default_parameter(parameter, punittype, pstart_tile,
815  pplayer);
816  pft_fill_parameter(parameter, punittype);
817 }
818 
822 void pft_fill_unit_parameter(struct pf_parameter *parameter,
823  const struct unit *punit)
824 {
825  pft_fill_unit_default_parameter(parameter, punit);
826  pft_fill_parameter(parameter, unit_type_get(punit));
827 }
828 
835 static void pft_fill_overlap_param(struct pf_parameter *parameter,
836  const struct unit_type *punittype)
837 {
838  parameter->get_MC = overlap_move;
839  parameter->ignore_none_scopes = false;
840 
841  if (!unit_type_really_ignores_zoc(punittype)) {
842  parameter->get_zoc = is_my_zoc;
843  } else {
844  parameter->get_zoc = nullptr;
845  }
846 
847  if (!parameter->get_moves_left_req && utype_fuel(punittype)) {
848  // Unit needs fuel
850  }
851 }
852 
858  const struct unit_type *punittype,
859  struct tile *pstart_tile,
860  struct player *pplayer)
861 {
862  pft_fill_utype_default_parameter(parameter, punittype, pstart_tile,
863  pplayer);
864  pft_fill_overlap_param(parameter, punittype);
865 }
866 
872  const struct unit *punit)
873 {
874  pft_fill_unit_default_parameter(parameter, punit);
875  pft_fill_overlap_param(parameter, unit_type_get(punit));
876 }
877 
883 static void pft_fill_attack_param(struct pf_parameter *parameter,
884  const struct unit_type *punittype)
885 {
886  parameter->get_MC = normal_move;
887  parameter->ignore_none_scopes = true;
888  pft_enable_default_actions(parameter);
889  // We want known units!
890  parameter->actions =
892 
893  if (!unit_type_really_ignores_zoc(punittype)) {
894  parameter->get_zoc = is_my_zoc;
895  } else {
896  parameter->get_zoc = nullptr;
897  }
898 
899  // It is too complicated to work with danger here
900  parameter->is_pos_dangerous = nullptr;
901 
902  if (!parameter->get_moves_left_req && utype_fuel(punittype)) {
903  // Unit needs fuel
905  }
906 }
907 
914  const struct unit *punit)
915 {
916  pft_fill_unit_default_parameter(parameter, punit);
917  pft_fill_attack_param(parameter, unit_type_get(punit));
918 }
919 
924  struct tile *target_tile)
925 {
926  memset(parameter, 0, sizeof(*parameter));
927 
928  parameter->map = &(wld.map);
929 
930  // We ignore refuel bases in reverse mode.
931  parameter->fuel = 1;
932  parameter->fuel_left_initially = 1;
933 
934  parameter->get_MC = normal_move;
935  parameter->get_move_scope = pf_get_move_scope;
936  parameter->ignore_none_scopes = true;
937 
938  parameter->get_action = pf_reverse_get_action;
939  parameter->data = target_tile;
940 
941  // Other data may stay at zero.
942 }
943 
956 {
957  const int move_rate = parameter->land.move_rate * parameter->sea.move_rate;
958 
959  parameter->sea.cargo_depth = 1;
960  BV_SET(parameter->sea.cargo_types, utype_index(parameter->land.utype));
961 
962  parameter->combined = parameter->sea;
963  parameter->land_scale = move_rate / parameter->land.move_rate;
964  parameter->sea_scale = move_rate / parameter->sea.move_rate;
965  parameter->combined.moves_left_initially *= parameter->sea_scale;
966  parameter->combined.move_rate = move_rate;
967  parameter->combined.get_MC = amphibious_move;
969  parameter->combined.get_TB = amphibious_behaviour;
971  if (nullptr != parameter->land.is_pos_dangerous
972  || nullptr != parameter->sea.is_pos_dangerous) {
974  } else {
975  parameter->combined.is_pos_dangerous = nullptr;
976  }
977  if (parameter->sea.get_moves_left_req != nullptr) {
978  parameter->combined.get_moves_left_req =
979  parameter->sea.get_moves_left_req;
980  } else if (parameter->land.get_moves_left_req != nullptr) {
981  parameter->combined.get_moves_left_req =
982  parameter->land.get_moves_left_req;
983  } else {
984  parameter->combined.get_moves_left_req = nullptr;
985  }
986  parameter->combined.get_action = nullptr;
987  parameter->combined.is_action_possible = nullptr;
988 
989  parameter->combined.data = parameter;
990 }
bool aia_utype_is_considered_caravan_trade(const struct unit_type *putype)
Returns TRUE if the specified unit type is able to perform trade caravan actions.
Definition: aiactions.cpp:57
bool aia_utype_is_considered_spy(const struct unit_type *putype)
Returns TRUE if the specified unit type is able to perform diplomatic actions.
Definition: aiactions.cpp:45
#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
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 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
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
#define extra_type_list_iterate(extralist, pextra)
Definition: extras.h:145
#define extra_type_list_iterate_end
Definition: extras.h:147
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
#define GAME_TRANSPORT_MAX_RECURSIVE
Definition: game.h:695
#define fc_assert(condition)
Definition: log.h:89
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Return TRUE if this ocean terrain is adjacent to a safe coastline.
Definition: map.cpp:636
int map_vector_to_real_distance(int dx, int dy)
Return the "real" distance for a given vector.
Definition: map.cpp:549
#define iterate_outward_dxy_end
Definition: map.h:283
#define iterate_outward_dxy(nmap, start_tile, max_dist, _tile, _x, _y)
Definition: map.h:260
static int map_move_cost(const struct civ_map *nmap, const struct player *pplayer, const struct unit_type *punittype, const struct tile *src_tile, const struct tile *dst_tile)
Definition: map.h:232
bool is_city_channel_tile(const struct unit_class *punitclass, const struct tile *ptile, const struct tile *pexclude)
Check for a city channel.
Definition: movement.cpp:192
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 can_attack_from_non_native(const struct unit_type *utype)
This unit can attack from non-native tiles (Marines can attack from transport, ships from harbour cit...
Definition: movement.cpp:177
int utype_move_rate(const struct unit_type *utype, const struct tile *ptile, const struct player *pplayer, int veteran_level, int hitpoints)
This function calculates the move rate of the unit, taking into account the penalty for reduced hitpo...
Definition: movement.cpp:38
bool is_native_near_tile(const struct civ_map *nmap, const struct unit_class *uclass, const struct tile *ptile)
Is there native tile adjacent to given tile.
Definition: movement.cpp:424
bool can_unit_type_transport(const struct unit_type *transporter, const struct unit_class *transported)
Return TRUE iff transporter type has ability to transport transported class.
Definition: movement.cpp:698
bool is_native_move(const struct unit_class *punitclass, const struct tile *src_tile, const struct tile *dst_tile)
Is the move under consideration a native move? Note that this function does not check for possible mo...
Definition: movement.cpp:322
bool can_attack_non_native(const struct unit_type *utype)
This unit can attack non-native tiles (eg.
Definition: movement.cpp:164
#define SINGLE_MOVE
Definition: movement.h:17
static bool is_native_tile_to_class(const struct unit_class *punitclass, const struct tile *ptile)
Definition: movement.h:73
#define PF_IMPOSSIBLE_MC
Definition: path_finding.h:244
pf_action
Definition: path_finding.h:255
@ PF_ACTION_ATTACK
Definition: path_finding.h:257
@ PF_ACTION_DIPLOMAT
Definition: path_finding.h:258
@ PF_ACTION_TRADE_ROUTE
Definition: path_finding.h:259
@ PF_ACTION_IMPOSSIBLE
Definition: path_finding.h:260
@ PF_ACTION_NONE
Definition: path_finding.h:256
pf_move_scope
Definition: path_finding.h:287
@ PF_MS_TRANSPORT
Definition: path_finding.h:291
@ PF_MS_CITY
Definition: path_finding.h:290
@ PF_MS_NATIVE
Definition: path_finding.h:289
@ PF_MS_NONE
Definition: path_finding.h:288
pf_action_account
Definition: path_finding.h:264
@ PF_AA_CITY_ATTACK
Definition: path_finding.h:270
@ PF_AA_UNIT_ATTACK
Definition: path_finding.h:266
@ PF_AA_NONE
Definition: path_finding.h:265
@ PF_AA_DIPLOMAT
Definition: path_finding.h:271
@ PF_AA_TRADE_ROUTE
Definition: path_finding.h:272
tile_behavior
Definition: path_finding.h:276
@ TB_NORMAL
Definition: path_finding.h:277
@ TB_DONT_LEAVE
Definition: path_finding.h:279
@ TB_IGNORE
Definition: path_finding.h:278
static int amphibious_extra_cost(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Extra cost call back for amphibious movement.
Definition: pf_tools.cpp:432
void pft_fill_reverse_parameter(struct pf_parameter *parameter, struct tile *target_tile)
Fill default parameters for reverse map.
Definition: pf_tools.cpp:923
static void pft_fill_overlap_param(struct pf_parameter *parameter, const struct unit_type *punittype)
pft_fill_*_overlap_param() base function.
Definition: pf_tools.cpp:835
static bool pf_action_possible(const struct tile *src, enum pf_move_scope src_scope, const struct tile *dst, enum pf_action action, const struct pf_parameter *param)
Determines if an action is possible from 'src' to 'dst': attack, diplomat action, or caravan action.
Definition: pf_tools.cpp:126
static void pft_fill_default_parameter(struct pf_parameter *parameter, const struct unit_type *punittype)
Fill general use parameters to defaults.
Definition: pf_tools.cpp:664
static int get_fuel_moves_left_req(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Position-dangerous callback for air units.
Definition: pf_tools.cpp:617
static int normal_move(const struct tile *src, enum pf_move_scope src_scope, const struct tile *dst, enum pf_move_scope dst_scope, const struct pf_parameter *param)
A cost function for regular movement.
Definition: pf_tools.cpp:351
static enum pf_move_scope pf_get_move_scope(const struct tile *ptile, bool *can_disembark, enum pf_move_scope previous_scope, const struct pf_parameter *param)
Determine how it is possible to move from/to 'ptile'.
Definition: pf_tools.cpp:223
static bool pf_transport_check(const struct pf_parameter *param, const struct unit *ptrans, const struct unit_type *trans_utype)
Determine if we could load into 'ptrans' and its parents.
Definition: pf_tools.cpp:166
void pft_fill_utype_overlap_param(struct pf_parameter *parameter, const struct unit_type *punittype, struct tile *pstart_tile, struct player *pplayer)
Switch on one tile overlapping into the non-native terrain.
Definition: pf_tools.cpp:857
static enum pf_action pf_get_action(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Determines if a path to 'ptile' would be considered as action rather than normal move: attack,...
Definition: pf_tools.cpp:80
enum tile_behavior no_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
PF callback to prohibit attacking anyone.
Definition: pf_tools.cpp:484
static void pft_fill_attack_param(struct pf_parameter *parameter, const struct unit_type *punittype)
pft_fill_*_attack_param() base function.
Definition: pf_tools.cpp:883
static void pft_fill_unit_default_parameter(struct pf_parameter *parameter, const struct unit *punit)
Fill general use parameters to defaults for an unit.
Definition: pf_tools.cpp:752
static enum pf_action pf_reverse_get_action(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Special case for reverse maps.
Definition: pf_tools.cpp:155
void pft_fill_unit_overlap_param(struct pf_parameter *parameter, const struct unit *punit)
Switch on one tile overlapping into the non-native terrain.
Definition: pf_tools.cpp:871
static bool pf_attack_possible(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Can we attack 'ptile'? At this point, it assumes there are non-allied units on the tile.
Definition: pf_tools.cpp:37
static void pft_enable_default_actions(struct pf_parameter *parameter)
Enable default actions.
Definition: pf_tools.cpp:685
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct unit *punit)
Fill classic parameters for an unit.
Definition: pf_tools.cpp:822
static enum tile_behavior amphibious_behaviour(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
A callback for amphibious movement.
Definition: pf_tools.cpp:515
static int amphibious_move(const struct tile *ptile, enum pf_move_scope src_scope, const struct tile *ptile1, enum pf_move_scope dst_scope, const struct pf_parameter *param)
A cost function for amphibious movement.
Definition: pf_tools.cpp:384
static void pft_fill_utype_default_parameter(struct pf_parameter *parameter, const struct unit_type *punittype, struct tile *pstart_tile, struct player *powner)
Fill general use parameters to defaults for an unit type.
Definition: pf_tools.cpp:716
static bool pf_move_possible(const struct tile *src, enum pf_move_scope src_scope, const struct tile *dst, enum pf_move_scope dst_scope, const struct pf_parameter *param)
Determines if the move between two tiles is possible.
Definition: pf_tools.cpp:324
enum tile_behavior no_intermediate_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
PF callback to prohibit attacking anyone, except at the destination.
Definition: pf_tools.cpp:499
void pft_fill_unit_attack_param(struct pf_parameter *parameter, const struct unit *punit)
pft_fill_*_attack_param() base function.
Definition: pf_tools.cpp:913
static bool is_possible_base_fuel(const struct tile *ptile, const struct pf_parameter *param)
Refueling base for air units.
Definition: pf_tools.cpp:535
static int get_closest_safe_tile_distance(const struct tile *src_tile, const struct pf_parameter *param, int max_distance)
Check if there is a safe position to move.
Definition: pf_tools.cpp:590
void pft_fill_utype_parameter(struct pf_parameter *parameter, const struct unit_type *punittype, struct tile *pstart_tile, struct player *pplayer)
Fill classic parameters for an unit type.
Definition: pf_tools.cpp:809
static bool amphibious_is_pos_dangerous(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Position-dangerous callback for amphibious movement.
Definition: pf_tools.cpp:642
enum tile_behavior no_fights_or_unknown(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
PF callback to prohibit going into the unknown.
Definition: pf_tools.cpp:469
static enum pf_move_scope amphibious_move_scope(const struct tile *ptile, bool *can_disembark, enum pf_move_scope previous_scope, const struct pf_parameter *param)
A cost function for amphibious movement.
Definition: pf_tools.cpp:293
void pft_fill_amphibious_parameter(struct pft_amphibious *parameter)
Fill parameters for combined sea-land movement.
Definition: pf_tools.cpp:955
static int overlap_move(const struct tile *src, enum pf_move_scope src_scope, const struct tile *dst, enum pf_move_scope dst_scope, const struct pf_parameter *param)
A cost function for overlap movement.
Definition: pf_tools.cpp:368
static void pft_fill_parameter(struct pf_parameter *parameter, const struct unit_type *punittype)
Base function to fill classic parameters.
Definition: pf_tools.cpp:787
bool pplayers_at_war(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players can attack each other.
Definition: player.cpp:1317
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Returns true iff players are allied.
Definition: player.cpp:1334
#define FC_INFINITY
Definition: shared.h:32
#define MAX(x, y)
Definition: shared.h:48
Definition: city.h:291
struct packet_game_info info
Definition: game.h:80
int fuel_left_initially
Definition: path_finding.h:344
const struct unit_type * transported_by_initially
Definition: path_finding.h:346
enum pf_action(* get_action)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition: path_finding.h:392
enum pf_move_scope(* get_move_scope)(const struct tile *ptile, bool *can_disembark, enum pf_move_scope previous_scope, const struct pf_parameter *param)
Definition: path_finding.h:371
bool ignore_none_scopes
Definition: path_finding.h:375
const struct civ_map * map
Definition: path_finding.h:340
enum tile_behavior(* get_TB)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition: path_finding.h:380
int(* get_EC)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition: path_finding.h:387
enum pf_action_account actions
Definition: path_finding.h:395
const struct player * owner
Definition: path_finding.h:356
bool(* is_pos_dangerous)(const struct tile *ptile, enum known_type, const struct pf_parameter *param)
Definition: path_finding.h:418
int(* get_moves_left_req)(const struct tile *ptile, enum known_type, const struct pf_parameter *param)
Definition: path_finding.h:423
int moves_left_initially
Definition: path_finding.h:343
bool(* get_zoc)(const struct player *pplayer, const struct tile *ptile, const struct civ_map *zmap)
Definition: path_finding.h:412
int(* get_MC)(const struct tile *from_tile, enum pf_move_scope src_move_scope, const struct tile *to_tile, enum pf_move_scope dst_move_scope, const struct pf_parameter *param)
Definition: path_finding.h:364
int(* get_costs)(const struct tile *from_tile, enum direction8 dir, const struct tile *to_tile, int from_cost, int from_extra, int *to_cost, int *to_extra, const struct pf_parameter *param)
Definition: path_finding.h:445
const struct unit_type * utype
Definition: path_finding.h:355
bool(* is_action_possible)(const struct tile *from_tile, enum pf_move_scope src_move_scope, const struct tile *to_tile, enum pf_action action, const struct pf_parameter *param)
Definition: path_finding.h:399
bv_unit_types cargo_types
Definition: path_finding.h:350
struct tile * start_tile
Definition: path_finding.h:341
int land_scale
Definition: pf_tools.h:32
struct pf_parameter combined
Definition: pf_tools.h:33
struct pf_parameter land sea
Definition: pf_tools.h:29
Definition: player.h:231
Definition: tile.h:42
struct unit_list * units
Definition: tile.h:50
struct unit_class::@81 cache
struct extra_type_list * refuel_bases
Definition: unittype.h:140
int move_rate
Definition: unittype.h:481
bv_unit_classes targets
Definition: unittype.h:524
int hp
Definition: unittype.h:489
Definition: unit.h:134
int moves_left
Definition: unit.h:147
int fuel
Definition: unit.h:150
struct civ_map map
Definition: world_object.h:21
bool tile_has_native_base(const struct tile *ptile, const struct unit_type *punittype)
Check if tile contains base native for unit.
Definition: tile.cpp:327
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
known_type
Definition: tile.h:28
@ TILE_KNOWN_UNSEEN
Definition: tile.h:30
@ TILE_UNKNOWN
Definition: tile.h:29
@ TILE_KNOWN_SEEN
Definition: tile.h:31
#define tile_has_extra(ptile, pextra)
Definition: tile.h:130
bool unit_type_really_ignores_zoc(const struct unit_type *punittype)
Takes into account unit class flag UCF_ZOC as well as IGZOC.
Definition: unit.cpp:1385
bool is_my_zoc(const struct player *pplayer, const struct tile *ptile0, const struct civ_map *zmap)
Is this square controlled by the pplayer?
Definition: unit.cpp:1341
int unit_transport_depth(const struct unit *pcargo)
Returns the number of unit transport layers which carry unit 'pcargo'.
Definition: unit.cpp:2307
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
int unit_cargo_depth(const struct unit *ptrans)
Returns the number of unit cargo layers within transport 'ptrans'.
Definition: unit.cpp:2289
bool unit_has_orders(const struct unit *punit)
Return TRUE iff the unit is following client-side orders.
Definition: unit.cpp:195
#define unit_tile(_pu)
Definition: unit.h:371
#define unit_transports_iterate_end
Definition: unit.h:452
#define unit_cargo_iterate_end
Definition: unit.h:464
#define unit_cargo_iterate(_ptrans, _pcargo)
Definition: unit.h:461
#define unit_owner(_pu)
Definition: unit.h:370
#define unit_transports_iterate(_pcargo, _ptrans)
Definition: unit.h:447
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_end
Definition: unitlist.h:27
bool can_unit_act_when_ustate_is(const struct unit_type *punit_type, const enum ustate_prop prop, const bool is_there)
Return TRUE iff there exists an (action enabler controlled) action that a unit of the type punit_type...
Definition: unittype.cpp:733
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
Definition: unittype.cpp:114
bool utype_can_freely_unload(const struct unit_type *pcargotype, const struct unit_type *ptranstype)
Return TRUE iff the given cargo type has no restrictions on when it can unload from the given transpo...
Definition: unittype.cpp:239
bool utype_may_act_at_all(const struct unit_type *putype)
Return TRUE iff units of this type can do actions controlled by generalized (ruleset defined) action ...
Definition: unittype.cpp:374
bool utype_can_freely_load(const struct unit_type *pcargotype, const struct unit_type *ptranstype)
Return TRUE iff the given cargo type has no restrictions on when it can load onto the given transport...
Definition: unittype.cpp:227
struct unit_class * unit_class_get(const struct unit *punit)
Returns unit class pointer for a unit.
Definition: unittype.cpp:2151
int utype_veteran_levels(const struct unit_type *punittype)
Return veteran levels of the given unit type.
Definition: unittype.cpp:2254
Unit_type_id utype_index(const struct unit_type *punittype)
Return the unit type index.
Definition: unittype.cpp:82
bool utype_can_take_over(const struct unit_type *punittype)
Return whether the unit type can take over enemy cities.
Definition: unittype.cpp:215
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
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition: unittype.h:584
#define unit_type_iterate(_p)
Definition: unittype.h:785
#define uclass_index(_c_)
Definition: unittype.h:684
#define unit_type_iterate_end
Definition: unittype.h:791