Freeciv-3.4
Loading...
Searching...
No Matches
daiferry.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "log.h"
20
21/* common */
22#include "game.h"
23#include "movement.h"
24#include "unit.h"
25#include "unitlist.h"
26
27/* aicore */
28#include "path_finding.h"
29#include "pf_tools.h"
30
31/* server/advisors */
32#include "advgoto.h"
33#include "autoexplorer.h"
34
35/* server */
36#include "hand_gen.h"
37#include "srv_log.h"
38#include "unithand.h"
39#include "unittools.h"
40
41/* server/advisors */
42#include "advdata.h"
43
44/* ai */
45#include "handicaps.h"
46
47/* ai/default */
48#include "daicity.h"
49#include "daidata.h"
50#include "daiguard.h"
51#include "daiplayer.h"
52#include "daitools.h"
53#include "daiunit.h"
54
55#include "daiferry.h"
56
57
58/* =================== constants with special meaning =================== */
59
60/*
61 * This one is used only by ferryboats in ai.passenger field
62 */
63#define FERRY_AVAILABLE (-1) /* Boat is looking for a passenger */
64#define FERRY_ABANDON_BOSS (-2) /* Passenger is assigned for boat, but boat
65 * might take another passenger. Probably
66 * passenger already left the boat*/
67
68/*
69 * The below is used only by passengers in ai.ferryboat field
70 */
71#define FERRY_WANTED (-1) /* Needs a boat */
72#define FERRY_NONE 0 /* Has no boat and doesn't need one */
73
74
75/* =================== Group log levels, debug options ================= */
77/* Logging in ferry management functions */
78#define LOGLEVEL_FERRY LOG_DEBUG
79/* Logging in go_by_boat functions */
80#define LOGLEVEL_GOBYBOAT LOG_DEBUG
81/* Logging in find_ferry functions */
82#define LOGLEVEL_FINDFERRY LOG_DEBUG
83/* Extra consistency checks */
84#ifdef FREECIV_DEBUG
85#define LOGLEVEL_FERRY_STATS LOG_NORMAL
86#endif
87
88
89/* ========= Managing statistics and boat/passenger assignments ======== */
90
91/**********************************************************************/
94void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
95{
96 /* def_ai_player_data() instead of dai_plr_data_get() is deliberate.
97 We are only initializing player data structures and dai_plr_data_get()
98 would try to use it uninitialized. We are only setting values to
99 data structure, not reading them, so we have no need for extra
100 arrangements dai_plr_data_get() would do compared to def_ai_player_data()
101 */
102 struct ai_plr *ai = def_ai_player_data(pplayer, ait);
103
104 ai->stats.passengers = 0;
105 ai->stats.boats = 0;
106 ai->stats.available_boats = 0;
107
108 unit_list_iterate(pplayer->units, punit) {
109 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
110
111 if (dai_is_ferry(punit, ait)) {
112 ai->stats.boats++;
113 if (unit_data->passenger == FERRY_AVAILABLE) {
115 }
116 }
117 if (unit_data->ferryboat == FERRY_WANTED) {
118 UNIT_LOG(LOG_DEBUG, punit, "wants a boat.");
119 ai->stats.passengers++;
120 }
122}
123
124/**********************************************************************/
127#ifdef LOGLEVEL_FERRY_STATS
128static void aiferry_print_stats(struct ai_type *ait, struct player *pplayer)
129{
130 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, nullptr);
131 int n = 1;
132
133 log_base(LOGLEVEL_FERRY_STATS, "Boat stats for %s[%d]",
134 player_name(pplayer), player_number(pplayer));
135 log_base(LOGLEVEL_FERRY_STATS, "Registered: %d free out of total %d",
137 unit_list_iterate(pplayer->units, punit) {
138 if (dai_is_ferry(punit, ait)) {
139 log_base(LOGLEVEL_FERRY_STATS, "#%d. %s[%d], psngr=%d", n,
141 def_ai_unit_data(punit, ait)->passenger);
142 n++;
143 }
145}
146#endif /* LOGLEVEL_FERRY_STATS */
147
148/**********************************************************************/
151bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
152{
153 struct unit_type_ai *utai = utype_ai_data(pferry, ait);
154
155 return utai->ferry;
156}
157
158/**********************************************************************/
161bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
162{
164}
165
166/**********************************************************************/
169void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
170{
171 if (dai_is_ferry(ferry, ait)) {
172 bool caller_closes;
173 struct player *pplayer = unit_owner(ferry);
174 struct unit_ai *unit_data = def_ai_unit_data(ferry, ait);
175 struct ai_plr *ai = dai_plr_data_get(ait, pplayer,
177
178 unit_data->passenger = FERRY_AVAILABLE;
179 ai->stats.boats++;
181
182 if (caller_closes) {
183 dai_data_phase_finished(ait, pplayer);
184 }
185 }
186}
187
188/**********************************************************************/
191void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry,
192 const struct unit_type *old)
193{
194 bool old_f = dai_is_ferry_type(old, ait);
195 bool new_f = dai_is_ferry(ferry, ait);
196
197 if (old_f && !new_f) {
198 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(ferry), nullptr);
199 struct unit_ai *unit_data = def_ai_unit_data(ferry, ait);
200
201 ai->stats.boats--;
202
203 if (unit_data->passenger == FERRY_AVAILABLE) {
205 } else if (unit_data->passenger > 0) {
206 struct unit *passenger = game_unit_by_number(unit_data->passenger);
207
208 if (passenger != nullptr) {
209 aiferry_clear_boat(ait, passenger);
210 }
211 }
212 } else if (!old_f && new_f) {
213 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(ferry), nullptr);
214
215 ai->stats.boats++;
217 }
218}
219
220/**********************************************************************/
223void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
224{
225 /* Ignore virtual units. */
226 if (punit->id != 0 && is_ai_data_phase_open(ait, unit_owner(punit))) {
227 bool close_here;
228 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
229 struct player *pplayer = unit_owner(punit);
230 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, &close_here);
231
232 if (dai_is_ferry(punit, ait)) {
233 ai->stats.boats--;
234 if (unit_data->passenger == FERRY_AVAILABLE) {
236 }
237 } else {
238 /* Not a ferry */
239 if (unit_data->ferryboat > 0) {
241 }
242 }
243
244 if (close_here) {
245 dai_data_phase_finished(ait, pplayer);
246 }
247 }
248}
249
250/**********************************************************************/
253void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
254{
255 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
256
257 if (unit_data->ferryboat == FERRY_WANTED) {
258 struct player *pplayer = unit_owner(punit);
259
260 if (is_ai_data_phase_open(ait, pplayer)) {
261 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, nullptr);
262
263 ai->stats.passengers--;
264 }
265 } else {
266 struct unit *ferry = game_unit_by_number(unit_data->ferryboat);
267
268 if (ferry) {
269 struct unit_ai *ferry_data = def_ai_unit_data(ferry, ait);
270
271 if (ferry_data->passenger == punit->id) {
272 /* punit doesn't want us anymore */
273 struct player *pplayer = unit_owner(ferry);
274
275 if (is_ai_data_phase_open(ait, pplayer)) {
276 dai_plr_data_get(ait, pplayer, nullptr)->stats.available_boats++;
277 }
278 ferry_data->passenger = FERRY_AVAILABLE;
279 }
280 }
281 }
282
283 unit_data->ferryboat = FERRY_NONE;
284}
285
286/**********************************************************************/
290static void aiferry_request_boat(struct ai_type *ait, struct unit *punit)
291{
292 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(punit), nullptr);
293 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
294
295 /* First clear the previous assignments (just in case there are).
296 * Subtract virtual units or already counted */
297 if ((punit->id == 0) ||
298 ((ai->stats.passengers > 0) &&
299 (unit_data->ferryboat == FERRY_WANTED))) {
301 }
302
303 /* Now add ourselves to the list of potential passengers */
304 ai->stats.passengers++;
305 UNIT_LOG(LOG_DEBUG, punit, "requests a boat (total passengers=%d).",
306 ai->stats.passengers);
307 unit_data->ferryboat = FERRY_WANTED;
308
309 /* Lastly, wait for ferry. */
310 unit_data->done = TRUE;
311}
312
313/**********************************************************************/
316static void aiferry_psngr_meet_boat(struct ai_type *ait,
317 struct unit *punit, struct unit *pferry)
318{
321
323
324 /* First delete the unit from the list of passengers and
325 * release its previous ferry */
327
328 /* If ferry was available, update the stats */
329 if (ferry_data->passenger == FERRY_AVAILABLE) {
331 }
332
333 /* Exchange the phone numbers */
335 ferry_data->passenger = punit->id;
336}
337
338/**********************************************************************/
341static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
342{
344
345 if (ferry_data->passenger != FERRY_AVAILABLE) {
347 ferry_data->passenger = FERRY_AVAILABLE;
348 }
349}
350
351/**********************************************************************/
355int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
356{
357 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, nullptr);
358
359 /* To developer: Switch this checking on when testing some new
360 * ferry code. */
361#ifdef LOGLEVEL_FERRY_STATS
362 int boats = 0;
363
364 unit_list_iterate(pplayer->units, punit) {
365 if (dai_is_ferry(punit, ait)
366 && def_ai_unit_data(punit, ait)->passenger == FERRY_AVAILABLE) {
367 boats++;
368 }
370
371 if (boats != ai->stats.available_boats) {
372 log_error("Player[%d] in turn %d: boats miscounted.",
373 player_number(pplayer), game.info.turn);
374 aiferry_print_stats(ait, pplayer);
375 }
376#endif /* LOGLEVEL_FERRY_STATS */
377
378 return ai->stats.available_boats;
379}
380
381/* ================== functions to find a boat ========================= */
382
383/**********************************************************************/
396static unsigned combined_land_sea_move(const struct tile *src_tile,
398 const struct tile *tgt_tile,
400 const struct pf_parameter *param)
401{
402 unsigned move_cost;
403
404 if (!((PF_MS_NATIVE | PF_MS_CITY) & dst_scope)) {
405 /* Any-to-Sea */
406 move_cost = 0;
407 } else if (!((PF_MS_NATIVE | PF_MS_CITY) & src_scope)) {
408 /* Sea-to-Land */
409 move_cost = PF_IMPOSSIBLE_MC;
410 } else {
411 /* Land-to-Land */
412 move_cost = map_move_cost(&(wld.map), param->owner, param->utype,
413 src_tile, tgt_tile);
414 }
415
416 return move_cost;
417}
418
419/**********************************************************************/
423static unsigned sea_move(const struct tile *ptile, enum known_type known,
424 const struct pf_parameter *param)
425{
426 if (is_ocean_tile(ptile)) {
427 /* Approximately TURN_FACTOR / average ferry move rate
428 * we can pass a better guess of the move rate through param->data
429 * but we don't know which boat we will find out there */
430 return SINGLE_MOVE * PF_TURN_FACTOR / 12;
431 } else {
432 return 0;
433 }
434}
435
436/**********************************************************************/
440bool is_boat_free(struct ai_type *ait, struct unit *boat,
441 struct unit *punit, int cap)
442{
443 /* - Only transporters capable of transporting this unit are eligible.
444 * - Units with orders are skipped (the AI doesn't control units with
445 * orders).
446 * - Only boats that we own are eligible.
447 * - Only available boats or boats that are already dedicated to this unit
448 * are eligible.
449 * - Only boats with enough remaining capacity are eligible.
450 * - Only units that can travel at sea are eligible.
451 * - Units that require fuel, except "Coast" ones, or lose hitpoints are
452 * not eligible.
453 */
455 const struct unit_type *ferry_type = unit_type_get(boat);
456 struct unit_ai *boat_data = def_ai_unit_data(boat, ait);
457
461 && (boat_data->passenger == FERRY_AVAILABLE
462 || boat_data->passenger == punit->id)
465 && ferry_class->adv.sea_move != MOVE_NONE
466 && !is_losing_hp(boat)
467 && (ferry_type->fuel == 0 || utype_has_flag(ferry_type, UTYF_COAST)));
468}
469
470/**********************************************************************/
473bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
474{
475 if (!unit_transported(punit)) {
476 /* Not even in boat */
477 return FALSE;
478 }
479
482 == punit->id) {
483 return TRUE;
484 }
485
486 return FALSE;
487}
488
489/**********************************************************************/
497int aiferry_find_boat(struct ai_type *ait, struct unit *punit,
498 int cap, struct pf_path **path)
499{
501 int best_id = 0;
502 struct pf_parameter param;
503 struct pf_map *search_map;
504 struct player *pplayer = unit_owner(punit);
505 const struct civ_map *nmap = &(wld.map);
506
507 /* currently assigned ferry */
508 int ferryboat = def_ai_unit_data(punit, ait)->ferryboat;
509
510 /* We may end calling pf_destroy_path for *path if it's not nullptr.
511 * Most likely you are passing garbage or path you don't want
512 * destroyed if this assertion fails.
513 * Don't try to be clever and pass 'fallback' path that will be returned
514 * if no path is found. Instead check for nullptr return value and then
515 * use fallback path in calling function. */
516 fc_assert_ret_val(path == nullptr || *path == nullptr, 0);
517
518 fc_assert_ret_val(0 < ferryboat
519 || FERRY_NONE == ferryboat
520 || FERRY_WANTED == ferryboat, 0);
521 UNIT_LOG(LOGLEVEL_FINDFERRY, punit, "asked aiferry_find_boat for a boat");
522
523 if (aiferry_avail_boats(ait, pplayer) <= 0
524 && ferryboat <= 0) {
525 /* No boats to be found (the second check is to ensure that we are not
526 * the ones keeping the last boat busy) */
527 return 0;
528 }
529
531 param.omniscience = !has_handicap(pplayer, H_MAP);
533 param.get_EC = sea_move;
536
537 search_map = pf_map_new(&param);
538
540 /* Should this be !can_unit_exist_at_tile() instead of is_ocean() some day?
541 * That would allow special units to wade in shallow coast waters to meet
542 * ferry where deep sea starts. */
543 int radius = (is_ocean_tile(pos.tile) ? 1 : 0);
544
545 if (pos.turn + pos.total_EC/PF_TURN_FACTOR > best_turns) {
546 /* Won't find anything better */
547 /* FIXME: This condition is somewhat dodgy */
548 break;
549 }
550
551 square_iterate(&(wld.map), pos.tile, radius, ptile) {
552 unit_list_iterate(ptile->units, aunit) {
553 if (is_boat_free(ait, aunit, punit, cap)) {
554 /* Turns for the unit to get to rendezvous pnt */
555 int u_turns = pos.turn;
556 /* Turns for the boat to get to the rendezvous pnt */
557 int f_turns = ((pos.total_EC / PF_TURN_FACTOR * 16
558 - aunit->moves_left)
560 int turns = MAX(u_turns, f_turns);
561
562 if (turns < best_turns) {
564 "Found a potential boat %s[%d](%d,%d)(moves left: %d)",
566 TILE_XY(unit_tile(aunit)), aunit->moves_left);
567 if (path) {
568 if (*path) {
569 pf_path_destroy(*path);
570 }
572 }
573 best_turns = turns;
574 best_id = aunit->id;
575 }
576 }
581
582 return best_id;
583}
584
585/**********************************************************************/
588static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit,
589 int cap)
590{
591 UNIT_LOG(LOGLEVEL_FINDFERRY, punit, "asked find_ferry_nearby for a boat");
592
593 square_iterate(&(wld.map), unit_tile(punit), 1, ptile) {
594 unit_list_iterate(ptile->units, aunit) {
595 if (is_boat_free(ait, aunit, punit, cap)) {
596 return aunit->id;
597 }
600
601 return 0;
602}
603
604
605/* ============================= go by boat ============================== */
606
607/**********************************************************************/
612static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
613{
614 struct player *ferry_owner = unit_owner(ferry);
615
617 if (unit_transport_get(aunit) == ferry) {
620
621 if (unit_owner(aunit) == ferry_owner) {
622 /* Move it only if it's our own. */
624 }
625 }
627}
628
629/**********************************************************************/
637 struct unit *ferry,
638 struct unit *passenger,
639 struct tile *ptile,
640 struct pft_amphibious *parameter)
641{
642 bool alive = TRUE;
643 struct pf_map *pfm;
644 struct pf_path *path;
645 int pass_id = passenger->id;
646
649 fc_assert_ret_val(unit_tile(ferry) == unit_tile(passenger), TRUE);
650
651 ptile = immediate_destination(passenger, ptile);
652
653 if (same_pos(unit_tile(passenger), ptile)) {
654 /* Not an error; sometimes immediate_destination instructs the unit
655 * to stay here. For example, to refuel.*/
656 send_unit_info(nullptr, passenger);
657 return TRUE;
658 } else if (passenger->moves_left == 0 && ferry->moves_left == 0) {
659 send_unit_info(nullptr, passenger);
660 return TRUE;
661 }
662
663 pfm = pf_map_new(&parameter->combined);
664 path = pf_map_path(pfm, ptile);
665
666 if (path) {
667 dai_log_path(passenger, path, &parameter->combined);
668 /* Sea leg */
669 alive = adv_follow_path(ferry, path, ptile);
670 if (alive && unit_tile(passenger) != ptile) {
671 /* Ferry has stopped; it is at the landing beach or
672 * has run out of movement points */
673 struct tile *next_tile;
674
675 if (!pf_path_advance(path, unit_tile(passenger))) {
676 /* Somehow we got thrown away from our route.
677 * This can happen if our movement caused alliance breakup. */
678 return unit_is_alive(pass_id);
679 }
680 next_tile = path->positions[1].tile;
681 if (!is_ocean_tile(next_tile)) {
682 int ferry_id = ferry->id;
683
684 UNIT_LOG(LOG_DEBUG, passenger, "Our boat has arrived "
685 "[%d](moves left: %d)", ferry->id, ferry->moves_left);
686 UNIT_LOG(LOG_DEBUG, passenger, "Disembarking to (%d,%d)",
688 /* Land leg */
689 alive = adv_follow_path(passenger, path, ptile);
690 /* Movement of the passenger outside the ferry can cause also
691 * ferry to die. That has happened at least when passenger
692 * destroyed city cutting the civ1-style channel (cities in
693 * a chain) ferry was in. */
694 if (unit_is_alive(ferry_id) && 0 < ferry->moves_left
695 && (!alive || unit_tile(ferry) != unit_tile(passenger))) {
696 /* The passenger is no longer on the ferry,
697 * and the ferry can still act.
698 * Give a chance for another passenger to take command
699 * of the ferry.
700 */
701 UNIT_LOG(LOG_DEBUG, ferry, "Activating passengers");
702 dai_activate_passengers(ait, ferry);
703
704 /* It is theoretically possible passenger died here due to
705 * autoattack against another passing unit at its location. */
707 }
708 }
709 /* else at sea */
710 } else if (alive) {
711 /* Arrived all the way to the destination by boat. Deboard. */
712 if (can_unit_exist_at_tile(parameter->land.map, passenger, ptile)) {
714 }
715 }
716 /* else dead */
717 } else {
718 /* Not always an error; enemy units might block all paths. */
719 UNIT_LOG(LOG_DEBUG, passenger, "no path to destination");
720 }
721
722 pf_path_destroy(path);
724
725 return alive;
726}
727
728/**********************************************************************/
732bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry,
733 struct unit *passenger, struct tile *ptile)
734{
735 struct pft_amphibious parameter;
738
739 dai_fill_unit_param(ait, &parameter.land, &land_risk_cost, passenger, ptile);
740 if (parameter.land.get_TB != no_fights) {
741 /* Use the ferry to go around danger areas: */
742 parameter.land.get_TB = no_intermediate_fights;
743 }
744 dai_fill_unit_param(ait, &parameter.sea, &sea_risk_cost, ferry, ptile);
746
747 /* Move as far along the path to the destination as we can;
748 * that is, ignore the presence of enemy units when computing the
749 * path */
750 parameter.combined.get_zoc = nullptr;
751
752 return dai_amphibious_goto_constrained(ait, ferry, passenger, ptile,
753 &parameter);
754}
755
756/**********************************************************************/
766bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer,
767 struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
768{
769 struct civ_map *nmap = &(wld.map);
770
771 if (!unit_transported(punit)) {
772 /* We are not on a boat and we cannot walk */
773 int boatid;
774 struct unit *ferryboat = nullptr;
775 int cap = with_bodyguard ? 2 : 1;
776 bool board_success = FALSE;
777
778 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "will have to go to (%d,%d) by boat",
779 TILE_XY(dest_tile));
780
782 struct pf_path *path_to_ferry = nullptr;
783
785 if (boatid <= 0) {
787 "in ai_gothere cannot find any boats.");
788 def_ai_unit_data(punit, ait)->done = TRUE; /* Nothing to do */
789 return FALSE;
790 }
791
792 ferryboat = game_unit_by_number(boatid);
793 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "found boat[%d](%d,%d), going there",
794 boatid, TILE_XY(unit_tile(ferryboat)));
795 /* The path can be amphibious so we will stop at the coast.
796 * It might not lead _onto_ the boat. */
798 /* Died. */
800
801 return FALSE;
802 }
804 }
805
807 /* Still haven't reached the coast */
808 return FALSE;
809 }
810
811 /* We are on the coast, look around for a boat */
813 if (boatid <= 0) {
814 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "requesting a boat.");
816 return FALSE;
817 }
818
819 /* Ok, a boat found, try boarding it */
820 ferryboat = game_unit_by_number(boatid);
821 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "found a nearby boat[%d](%d,%d)",
822 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
823 /* Setting ferry now in hope it won't run away even
824 * if we can't board it right now */
825 aiferry_psngr_meet_boat(ait, punit, ferryboat);
826
827 if (is_tiles_adjacent(unit_tile(punit), unit_tile(ferryboat))) {
828 (void) dai_unit_move(ait, punit, unit_tile(ferryboat));
829 }
830
831 /* FIXME: check if action is enabled. */
832 if (!can_unit_load(punit, ferryboat)) {
833 /* Something prevented us from boarding */
834 /* FIXME: this is probably a serious bug, but we just skip past
835 * it and continue. */
836 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "couldn't board boat[%d](%d,%d)",
837 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
838 return FALSE;
839 }
840
842 enum gen_action act_id = action_id(paction);
843
845 ferryboat))) {
846 if (unit_perform_action(pplayer,
847 punit->id, ferryboat->id, 0, "",
848 act_id, ACT_REQ_PLAYER)) {
850 break;
851 }
852 }
854
855 if (!board_success) {
856 /* No action enabler active.
857 * TODO: Try to predict this failure so that the units wouldn't
858 * waste turns to travel to the rendezvous point. */
859 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "boarding boat[%d](%d,%d) not enabled",
860 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
861
862 return FALSE;
863 }
864
866 }
867
868 if (unit_transported(punit)) {
869 /* We are on a boat, ride it! */
870 struct unit *ferryboat = unit_transport_get(punit);
871
872 /* Check if we are the passenger-in-charge */
873 if (is_boat_free(ait, ferryboat, punit, 0)) {
874 struct unit *bodyguard = aiguard_guard_of(ait, punit);
875
877 "got boat[%d](moves left: %d), going (%d,%d)",
878 ferryboat->id, ferryboat->moves_left, TILE_XY(dest_tile));
879 aiferry_psngr_meet_boat(ait, punit, ferryboat);
880
881 punit->goto_tile = dest_tile;
882 /* Grab bodyguard */
883 if (bodyguard
884 && !same_pos(unit_tile(punit), unit_tile(bodyguard))) {
885 if (!goto_is_sane(bodyguard, unit_tile(punit))
886 || !dai_unit_goto(ait, bodyguard, unit_tile(punit))) {
887 /* Bodyguard can't get there or died en route */
889 bodyguard = nullptr;
890 } else if (bodyguard->moves_left <= 0) {
891 /* Wait for me, I'm cooooming!! */
892 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "waiting for bodyguard");
894 return FALSE;
895 } else {
896 /* Crap bodyguard. Got stuck somewhere. Ditch it! */
897 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "ditching useless bodyguard");
899 dai_unit_new_task(ait, bodyguard, AIUNIT_NONE, nullptr);
900 bodyguard = nullptr;
901 }
902 }
903 if (bodyguard) {
905
906 /* Bodyguard either uses the same boat or none at all. */
908 enum gen_action act_id = action_id(paction);
909
911 act_id,
912 ferryboat))) {
913 if (unit_perform_action(pplayer,
914 bodyguard->id, ferryboat->id, 0, "",
915 act_id, ACT_REQ_PLAYER)) {
916 break;
917 }
918 }
920 }
921
922 if (!aiferry_goto_amphibious(ait, ferryboat, punit, dest_tile)) {
923 /* Died */
924 return FALSE;
925 }
926 if (same_pos(unit_tile(punit), dest_tile)) {
927 /* Arrived */
929 } else {
930 /* We are in still transit */
932
933 return FALSE;
934 }
935 } else {
936 /* Waiting for the boss to load and move us */
937 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "Cannot command boat [%d],"
938 " its boss is [%d]",
939 ferryboat->id, def_ai_unit_data(ferryboat, ait)->passenger);
940
941 return FALSE;
942 }
943 }
944
945 return TRUE;
946}
947
948
949/* ===================== Boat management ================================= */
950
951/**********************************************************************/
958static bool aiferry_findcargo(struct ai_type *ait, struct unit *pferry)
959{
960 /* Path-finding stuff */
961 struct pf_map *pfm;
962 struct pf_parameter parameter;
963 int passengers = dai_plr_data_get(ait, unit_owner(pferry),
964 nullptr)->stats.passengers;
965 struct player *pplayer;
966 const struct civ_map *nmap = &(wld.map);
967
968 if (passengers <= 0) {
969 /* No passengers anywhere */
970 return FALSE;
971 }
972
973 UNIT_LOG(LOGLEVEL_FERRY, pferry, "Ferryboat is looking for cargo.");
974
975 pplayer = unit_owner(pferry);
977 parameter.omniscience = !has_handicap(pplayer, H_MAP);
978 /* If we have omniscience, we use it, since paths to some places
979 * might be "blocked" by unknown. We don't want to fight though */
980 parameter.get_TB = no_fights;
981
982 pfm = pf_map_new(&parameter);
983 pf_map_tiles_iterate(pfm, ptile, TRUE) {
984 unit_list_iterate(ptile->units, aunit) {
985 struct unit_ai *unit_data = def_ai_unit_data(aunit, ait);
986
988 && (unit_data->ferryboat == FERRY_WANTED
989 || unit_data->ferryboat == pferry->id)) {
991 "Found a potential cargo %s[%d](%d,%d), going there",
993 aunit->id,
995 pferry->goto_tile = unit_tile(aunit);
996 /* Exchange phone numbers */
999
1000 return TRUE;
1001 }
1004
1005 /* False positive can happen if we cannot find a route to the passenger
1006 * because of an internal sea or enemy blocking the route */
1008 "AI Passengers counting reported false positive %d", passengers);
1010
1011 return FALSE;
1012}
1013
1014/**********************************************************************/
1026static bool aiferry_find_interested_city(struct ai_type *ait,
1027 struct unit *pferry)
1028{
1029 /* Path-finding stuff */
1030 struct pf_map *pfm;
1031 struct pf_parameter parameter;
1032 /* Early termination condition */
1034 /* Future return value */
1035 bool needed = FALSE;
1036 const struct civ_map *nmap = &(wld.map);
1037
1038 UNIT_LOG(LOGLEVEL_FERRY, pferry, "Ferry looking for a city that needs it");
1039
1040 pft_fill_unit_parameter(&parameter, nmap, pferry);
1041 /* We are looking for our own cities, no need to look into the unknown */
1042 parameter.get_TB = no_fights_or_unknown;
1043 parameter.omniscience = FALSE;
1044 pfm = pf_map_new(&parameter);
1045
1047 struct city *pcity;
1048
1049 if (pos.turn >= turns_horizon) {
1050 /* Won't be able to find anything better than what we have */
1051 break;
1052 }
1053
1054 pcity = tile_city(pos.tile);
1055
1057 && (def_ai_city_data(pcity, ait)->choice.need_boat
1058 || (VUT_UTYPE == pcity->production.kind
1059 && utype_has_role(pcity->production.value.utype,
1060 L_FERRYBOAT)))) {
1061 bool really_needed = TRUE;
1063
1064 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s (%d, %d) looks promising...",
1066
1067 if (pos.turn > turns
1068 && VUT_UTYPE == pcity->production.kind
1069 && utype_has_role(pcity->production.value.utype, L_FERRYBOAT)) {
1070 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1071 "will finish building its own ferry too soon",
1073 continue;
1074 }
1075
1076 if (turns >= turns_horizon) {
1077 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1078 "has just started building",
1080 continue;
1081 }
1082
1086
1087 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1088 "has another ferry",
1091 break;
1092 }
1094
1095 if (really_needed) {
1096 UNIT_LOG(LOGLEVEL_FERRY, pferry, "will go to %s unless we "
1097 "find something better",
1099 pferry->goto_tile = pos.tile;
1100 turns_horizon = turns;
1101 needed = TRUE;
1102 }
1103 }
1105
1107
1108 return needed;
1109}
1110
1111/**********************************************************************/
1121void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer,
1122 struct unit *punit)
1123{
1124 struct city *pcity;
1125 int sanity = punit->id;
1126 struct unit_ai *unit_data;
1127 int bossid;
1128 const struct unit_type *ptype;
1129 const struct civ_map *nmap = &(wld.map);
1130
1132
1133 /* Try to recover hitpoints if we are in a city, before we do anything */
1134 if (punit->hp < unit_type_get(punit)->hp
1135 && (pcity = tile_city(unit_tile(punit)))) {
1136 UNIT_LOG(LOGLEVEL_FERRY, punit, "waiting in %s to recover hitpoints",
1139 return;
1140 }
1141
1142 /* Check if we are an empty barbarian boat and so not needed */
1143 if (is_barbarian(pplayer) && get_transporter_occupancy(punit) == 0) {
1144 wipe_unit(punit, ULR_RETIRED, nullptr);
1145 return;
1146 }
1147
1149
1150 bossid = unit_data->passenger; /* Old boss */
1151
1152 do {
1153 /* Do we have the passenger-in-charge on board? */
1154 if (unit_data->passenger > 0) {
1155 struct unit *psngr = game_unit_by_number(unit_data->passenger);
1156
1157 /* If the passenger-in-charge is adjacent, we should wait for it to
1158 * board. We will pass control to it later. */
1159 if (!psngr
1162 "recorded passenger[%d] is not on board, checking for "
1163 "others", unit_data->passenger);
1164 unit_data->passenger = FERRY_ABANDON_BOSS;
1165 }
1166 }
1167
1168 if (unit_data->passenger == FERRY_AVAILABLE
1169 || unit_data->passenger == FERRY_ABANDON_BOSS) {
1170 struct unit *candidate = nullptr;
1171
1172 /* Try to select passenger-in-charge from among our passengers */
1174 if (unit_owner(aunit) != pplayer) {
1175 /* We used to check if ferryboat was set to us or to
1176 * FERRY_WANTED too, but this was a bit strict. Especially
1177 * when we don't save these values in a savegame. */
1178 continue;
1179 }
1180
1181 if (def_ai_unit_data(aunit, ait)->task != AIUNIT_ESCORT) {
1182 candidate = aunit;
1183 break;
1184 } else {
1185 /* Bodyguards shouldn't be in charge of boats so continue looking */
1186 candidate = aunit;
1187 }
1189
1190 if (candidate) {
1192 "appointed %s[%d] our passenger-in-charge",
1194 candidate->id);
1195 bossid = candidate->id;
1197 }
1198 }
1199
1200 if (unit_data->passenger > 0) {
1202
1203 fc_assert_ret(boss != nullptr);
1204
1207 /* Temporary hack: workers all go in the end, forcing them
1208 * earlier might mean uninitialised cache, so just wait for them */
1209 return;
1210 }
1211
1212 UNIT_LOG(LOGLEVEL_FERRY, punit, "passing control to %s[%d]",
1214 boss->id);
1215 dai_manage_unit(ait, pplayer, boss);
1216
1217 if (!game_unit_by_number(sanity) || punit->moves_left <= 0) {
1218 return;
1219 }
1222 /* The boss decided to stay put on the ferry. We aren't moving. */
1223 UNIT_LOG(LOG_DEBUG, boss, "drove ferry - done for now");
1224 def_ai_unit_data(boss, ait)->done = TRUE;
1225 return;
1226 } else if (unit_data->passenger == bossid
1228 /* The boss isn't on the ferry, has not passed control away,
1229 * and we have other passengers?
1230 * Forget about the boss. */
1231 unit_data->passenger = FERRY_ABANDON_BOSS;
1232 }
1233 }
1234 if (unit_data->passenger != bossid
1235 && unit_data->passenger != FERRY_ABANDON_BOSS) {
1236 /* Boss handling resulted in boss change. Run next round with new boss. */
1237 bossid = unit_data->passenger;
1238 }
1239 } else {
1240 /* Cannot select a passenger-in-charge */
1241 break;
1242 }
1243 } while (get_transporter_occupancy(punit) != 0);
1244
1245 if (unit_data->passenger == FERRY_ABANDON_BOSS) {
1246 /* As nobody else wanted the control, restore it to old boss. */
1247 unit_data->passenger = bossid;
1248 }
1249
1250 /* Not carrying anyone, even the ferryman */
1251
1253
1254 if (IS_ATTACKER(ptype) && punit->moves_left > 0) {
1255 /* AI used to build frigates to attack and then use them as ferries
1256 * -- Syela */
1257 dai_unit_new_task(ait, punit, AIUNIT_NONE, nullptr);
1258 UNIT_LOG(LOGLEVEL_FERRY, punit, "passing ferry over to attack code");
1259 dai_manage_military(ait, nmap, pplayer, punit);
1260 return;
1261 }
1262
1263 UNIT_LOG(LOGLEVEL_FERRY, punit, "Ferryboat is not carrying anyone "
1264 "(moves left: %d).", punit->moves_left);
1267 dai_unit_new_task(ait, punit, AIUNIT_NONE, nullptr);
1269
1270 /* Try to find passengers */
1271 if (aiferry_findcargo(ait, punit)) {
1272 UNIT_LOG(LOGLEVEL_FERRY, punit, "picking up cargo (moves left: %d)",
1273 punit->moves_left);
1274 if (dai_unit_goto(ait, punit, punit->goto_tile)) {
1277 struct unit *cargo = game_unit_by_number(unit_data->passenger);
1278
1279 /* See if passenger can jump on board! */
1280 fc_assert_ret(cargo != punit);
1281 dai_manage_unit(ait, pplayer, cargo);
1282 }
1283 }
1284
1285 return;
1286 }
1287
1288 /* Try to find a city that needs a ferry */
1291 UNIT_LOG(LOGLEVEL_FERRY, punit, "staying in city that needs us");
1292 unit_data->done = TRUE;
1293
1294 return;
1295 } else {
1296 UNIT_LOG(LOGLEVEL_FERRY, punit, "going to city that needs us");
1299 unit_data->done = TRUE; /* Save some CPU */
1300 }
1301
1302 return;
1303 }
1304 }
1305
1306 UNIT_LOG(LOGLEVEL_FERRY, punit, "Passing control of ferry to explorer code");
1307 switch (manage_auto_explorer(punit)) {
1308 case MR_DEATH:
1309 /* Don't use punit! */
1310 return;
1311 case MR_OK:
1312 /* FIXME: Continue moving? */
1313 break;
1314 default:
1315 unit_data->done = TRUE;
1316 break;
1317 };
1318
1319 if (punit->moves_left > 0) {
1321
1322 if (safe_city != nullptr) {
1323 punit->goto_tile = safe_city->tile;
1324 UNIT_LOG(LOGLEVEL_FERRY, punit, "No work, going home");
1325 unit_data->done = TRUE;
1326 dai_unit_new_task(ait, punit, AIUNIT_NONE, nullptr);
1328 }
1329 }
1330
1331 return;
1332}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5306
struct act_prob action_prob_vs_unit(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:4552
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:245
#define action_by_result_iterate_end
Definition actions.h:249
#define action_id(_act_)
Definition actions.h:426
#define ACTION_NONE
Definition actions.h:59
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
bool adv_unit_execute_path(struct unit *punit, struct pf_path *path)
Definition advgoto.c:86
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:820
#define city_owner(_pcity_)
Definition city.h:563
char * incite_cost
Definition comments.c:76
bool is_ai_data_phase_open(struct ai_type *ait, struct player *pplayer)
Definition daidata.c:132
struct ai_plr * dai_plr_data_get(struct ai_type *ait, struct player *pplayer, bool *caller_closes)
Definition daidata.c:308
void dai_data_phase_finished(struct ai_type *ait, struct player *pplayer)
Definition daidata.c:285
static bool aiferry_findcargo(struct ai_type *ait, struct unit *pferry)
Definition daiferry.c:956
static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
Definition daiferry.c:610
#define FERRY_WANTED
Definition daiferry.c:69
bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
Definition daiferry.c:764
int aiferry_find_boat(struct ai_type *ait, struct unit *punit, int cap, struct pf_path **path)
Definition daiferry.c:495
#define FERRY_NONE
Definition daiferry.c:70
void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition daiferry.c:1119
bool is_boat_free(struct ai_type *ait, struct unit *boat, struct unit *punit, int cap)
Definition daiferry.c:438
bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
Definition daiferry.c:149
void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
Definition daiferry.c:92
static bool aiferry_find_interested_city(struct ai_type *ait, struct unit *pferry)
Definition daiferry.c:1024
#define LOGLEVEL_FINDFERRY
Definition daiferry.c:80
void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
Definition daiferry.c:221
void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry, const struct unit_type *old)
Definition daiferry.c:189
bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile)
Definition daiferry.c:730
bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
Definition daiferry.c:471
static void aiferry_psngr_meet_boat(struct ai_type *ait, struct unit *punit, struct unit *pferry)
Definition daiferry.c:314
static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
Definition daiferry.c:339
static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit, int cap)
Definition daiferry.c:586
static unsigned sea_move(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition daiferry.c:421
int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
Definition daiferry.c:353
#define LOGLEVEL_GOBYBOAT
Definition daiferry.c:78
bool dai_amphibious_goto_constrained(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile, struct pft_amphibious *parameter)
Definition daiferry.c:634
bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
Definition daiferry.c:159
#define FERRY_ABANDON_BOSS
Definition daiferry.c:64
void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
Definition daiferry.c:167
void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
Definition daiferry.c:251
static unsigned combined_land_sea_move(const struct tile *src_tile, enum pf_move_scope src_scope, const struct tile *tgt_tile, enum pf_move_scope dst_scope, const struct pf_parameter *param)
Definition daiferry.c:394
#define FERRY_AVAILABLE
Definition daiferry.c:63
static void aiferry_request_boat(struct ai_type *ait, struct unit *punit)
Definition daiferry.c:288
#define LOGLEVEL_FERRY
Definition daiferry.c:76
void aiguard_request_guard(struct ai_type *ait, struct unit *punit)
Definition daiguard.c:227
struct unit * aiguard_guard_of(struct ai_type *ait, struct unit *charge)
Definition daiguard.c:269
static struct ai_plr * def_ai_player_data(const struct player *pplayer, struct ai_type *deftype)
Definition daiplayer.h:54
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition daiplayer.h:42
static struct unit_ai * def_ai_unit_data(const struct unit *punit, struct ai_type *deftype)
Definition daiplayer.h:48
void dai_fill_unit_param(struct ai_type *ait, struct pf_parameter *parameter, struct adv_risk_cost *risk_cost, struct unit *punit, struct tile *ptile)
Definition daitools.c:469
bool goto_is_sane(struct unit *punit, struct tile *ptile)
Definition daitools.c:429
struct tile * immediate_destination(struct unit *punit, struct tile *dest_tile)
Definition daitools.c:302
bool dai_unit_goto(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition daitools.c:605
void dai_log_path(struct unit *punit, struct pf_path *path, struct pf_parameter *parameter)
Definition daitools.c:356
void dai_unit_new_task(struct ai_type *ait, struct unit *punit, enum ai_unit_task task, struct tile *ptile)
Definition daitools.c:643
bool dai_unit_move(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition daitools.c:1086
void dai_manage_military(struct ai_type *ait, const struct civ_map *nmap, struct player *pplayer, struct unit *punit)
Definition daiunit.c:2517
void dai_manage_unit(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition daiunit.c:2672
struct city * find_nearest_safe_city(struct unit *punit)
Definition daiunit.c:1644
@ AIUNIT_NONE
Definition daiunit.h:27
@ AIUNIT_ESCORT
Definition daiunit.h:28
#define IS_ATTACKER(ptype)
Definition daiunit.h:70
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
static struct tile * pos
Definition finddlg.c:53
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_base(level, message,...)
Definition log.h:95
@ LOG_DEBUG
Definition log.h:35
#define log_error(message,...)
Definition log.h:104
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:1067
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:1076
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:675
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:388
#define square_iterate_end
Definition map.h:391
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:302
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
bool can_unit_transport(const struct unit *transporter, const struct unit *transported)
Definition movement.c:888
#define SINGLE_MOVE
Definition movement.h:26
@ MR_OK
Definition movement.h:35
@ MR_DEATH
Definition movement.h:36
void pf_path_destroy(struct pf_path *path)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
struct pf_path * pf_map_iter_path(struct pf_map *pfm)
void pf_map_destroy(struct pf_map *pfm)
bool pf_path_advance(struct pf_path *path, struct tile *ptile)
#define PF_IMPOSSIBLE_MC
pf_move_scope
@ PF_MS_CITY
@ PF_MS_NATIVE
#define pf_map_positions_iterate_end
#define PF_TURN_FACTOR
#define pf_map_tiles_iterate(ARG_pfm, NAME_tile, COND_from_start)
#define pf_map_positions_iterate(ARG_pfm, NAME_pos, COND_from_start)
#define pf_map_tiles_iterate_end
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:843
void pft_fill_unit_overlap_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:894
enum tile_behavior no_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:510
enum tile_behavior no_intermediate_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:526
enum tile_behavior no_fights_or_unknown(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:493
void pft_fill_amphibious_parameter(struct pft_amphibious *parameter)
Definition pf_tools.c:997
int player_number(const struct player *pplayer)
Definition player.c:839
const char * player_name(const struct player *pplayer)
Definition player.c:900
static bool is_barbarian(const struct player *pplayer)
Definition player.h:491
#define is_ai(plr)
Definition player.h:232
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
#define UNIT_LOG(loglevel, punit, msg,...)
Definition srv_log.h:98
int passengers
Definition daidata.h:78
struct ai_plr::@282 stats
int boats
Definition daidata.h:79
int available_boats
Definition daidata.h:80
Definition ai.h:50
Definition city.h:318
struct packet_game_info info
Definition game.h:89
bool ignore_none_scopes
enum tile_behavior(* get_TB)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
const struct player * owner
bool(* get_zoc)(const struct player *pplayer, const struct tile *ptile, const struct civ_map *zmap)
unsigned(* 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)
unsigned(* get_EC)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
const struct unit_type * utype
struct pf_position * positions
struct tile * tile
struct pf_parameter combined
Definition pf_tools.h:42
struct pf_parameter land sea
Definition pf_tools.h:38
struct unit_list * units
Definition player.h:282
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
bool done
Definition daiunit.h:44
int ferryboat
Definition daiunit.h:34
int passenger
Definition daiunit.h:35
bool ferry
Definition daiunit.h:52
int move_rate
Definition unittype.h:524
Definition unit.h:140
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
struct unit_list * transporting
Definition unit.h:187
int hp
Definition unit.h:153
struct tile * tile
Definition unit.h:142
struct tile * goto_tile
Definition unit.h:157
const struct unit_type * utype
Definition unit.h:141
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:616
#define is_ocean_tile(ptile)
Definition terrain.h:196
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
known_type
Definition tile.h:35
#define TILE_XY(ptile)
Definition tile.h:43
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1847
bool unit_is_alive(int id)
Definition unit.c:2317
bool is_losing_hp(const struct unit *punit)
Definition unit.c:2292
bool can_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:768
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2545
bool unit_is_cityfounder(const struct unit *punit)
Definition unit.c:2745
int get_transporter_capacity(const struct unit *punit)
Definition unit.c:316
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2529
bool unit_has_orders(const struct unit *punit)
Definition unit.c:221
#define unit_tile(_pu)
Definition unit.h:407
#define CHECK_UNIT(punit)
Definition unit.h:273
#define unit_owner(_pu)
Definition unit.h:406
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity, enum gen_action trigger_action)
Definition unithand.c:6707
bool unit_perform_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id_incoming, const char *name, const action_id action_type, const enum action_requester requester)
Definition unithand.c:3369
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2882
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2144
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3446
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1613
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:224
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2530
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:233
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:215
void * utype_ai_data(const struct unit_type *ptype, const struct ai_type *ai)
Definition unittype.c:2771
@ MOVE_NONE
Definition unittype.h:144
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:624