Freeciv-3.1
Loading...
Searching...
No Matches
aiferry.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#include "autosettlers.h"
35
36/* server */
37#include "hand_gen.h"
38#include "srv_log.h"
39#include "unithand.h"
40#include "unittools.h"
41
42/* server/advisors */
43#include "advdata.h"
44
45/* ai */
46#include "handicaps.h"
47
48/* ai/default */
49#include "aidata.h"
50#include "aiguard.h"
51#include "ailog.h"
52#include "aiplayer.h"
53#include "aitools.h"
54#include "aiunit.h"
55#include "daicity.h"
56
57#include "aiferry.h"
58
59
60/* =================== constants with special meaning =================== */
61
62/*
63 * This one is used only by ferryboats in ai.passenger field
64 */
65#define FERRY_AVAILABLE (-1) /* Boat is looking for a passenger */
66#define FERRY_ABANDON_BOSS (-2) /* Passenger is assigned for boat, but boat
67 * might take another passenger. Probably
68 * passenger already left the boat*/
69
70/*
71 * The below is used only by passengers in ai.ferryboat field
72 */
73#define FERRY_WANTED (-1) /* Needs a boat */
74#define FERRY_NONE 0 /* Has no boat and doesn't need one */
75
76
77/* =================== group log levels, debug options ================= */
79/* Logging in ferry management functions */
80#define LOGLEVEL_FERRY LOG_DEBUG
81/* Logging in go_by_boat functions */
82#define LOGLEVEL_GOBYBOAT LOG_DEBUG
83/* Logging in find_ferry functions */
84#define LOGLEVEL_FINDFERRY LOG_DEBUG
85/* Extra consistency checks */
86#ifdef FREECIV_DEBUG
87#define LOGLEVEL_FERRY_STATS LOG_NORMAL
88#endif
89
90
91/* ========= managing statistics and boat/passenger assignments ======== */
92
93/**********************************************************************/
96void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
97{
98 /* def_ai_player_data() instead of dai_plr_data_get() is deliberate.
99 We are only initializing player data structures and dai_plr_data_get()
100 would try to use it uninitialized. We are only setting values to
101 data structure, not reading them, so we have no need for extra
102 arrangements dai_plr_data_get() would do compared to def_ai_player_data()
103 */
104 struct ai_plr *ai = def_ai_player_data(pplayer, ait);
105
106 ai->stats.passengers = 0;
107 ai->stats.boats = 0;
108 ai->stats.available_boats = 0;
109
110 unit_list_iterate(pplayer->units, punit) {
111 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
112
113 if (dai_is_ferry(punit, ait)) {
114 ai->stats.boats++;
115 if (unit_data->passenger == FERRY_AVAILABLE) {
117 }
118 }
119 if (unit_data->ferryboat == FERRY_WANTED) {
120 UNIT_LOG(LOG_DEBUG, punit, "wants a boat.");
121 ai->stats.passengers++;
122 }
124}
125
126/**********************************************************************/
129#ifdef LOGLEVEL_FERRY_STATS
130static void aiferry_print_stats(struct ai_type *ait, struct player *pplayer)
131{
132 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, NULL);
133 int n = 1;
134
135 log_base(LOGLEVEL_FERRY_STATS, "Boat stats for %s[%d]",
136 player_name(pplayer), player_number(pplayer));
137 log_base(LOGLEVEL_FERRY_STATS, "Registered: %d free out of total %d",
139 unit_list_iterate(pplayer->units, punit) {
140 if (dai_is_ferry(punit, ait)) {
141 log_base(LOGLEVEL_FERRY_STATS, "#%d. %s[%d], psngr=%d", n,
143 def_ai_unit_data(punit, ait)->passenger);
144 n++;
145 }
147}
148#endif /* LOGLEVEL_FERRY_STATS */
149
150/**********************************************************************/
153bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
154{
155 struct unit_type_ai *utai = utype_ai_data(pferry, ait);
156
157 return utai->ferry;
158}
159
160/**********************************************************************/
163bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
164{
165 return dai_is_ferry_type(unit_type_get(pferry), ait);
166}
167
168/**********************************************************************/
171void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
172{
173 if (dai_is_ferry(ferry, ait)) {
174 bool caller_closes;
175 struct player *pplayer = unit_owner(ferry);
176 struct unit_ai *unit_data = def_ai_unit_data(ferry, ait);
177 struct ai_plr *ai = dai_plr_data_get(ait, pplayer,
178 &caller_closes);
179
180 unit_data->passenger = FERRY_AVAILABLE;
181 ai->stats.boats++;
183
184 if (caller_closes) {
185 dai_data_phase_finished(ait, pplayer);
186 }
187 }
188}
189
190/**********************************************************************/
193void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry,
194 const struct unit_type *old)
195{
196 bool old_f = dai_is_ferry_type(old, ait);
197 bool new_f = dai_is_ferry(ferry, ait);
198
199 if (old_f && !new_f) {
200 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(ferry), NULL);
201 struct unit_ai *unit_data = def_ai_unit_data(ferry, ait);
202
203 ai->stats.boats--;
204
205 if (unit_data->passenger == FERRY_AVAILABLE) {
207 } else if (unit_data->passenger > 0) {
208 struct unit *passenger = game_unit_by_number(unit_data->passenger);
209
210 if (passenger != NULL) {
211 aiferry_clear_boat(ait, passenger);
212 }
213 }
214 } else if (!old_f && new_f) {
215 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(ferry), NULL);
216
217 ai->stats.boats++;
219 }
220}
221
222/**********************************************************************/
225void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
226{
227 /* Ignore virtual units. */
228 if (punit->id != 0 && is_ai_data_phase_open(ait, unit_owner(punit))) {
229 bool close_here;
230 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
231 struct player *pplayer = unit_owner(punit);
232 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, &close_here);
233
234 if (dai_is_ferry(punit, ait)) {
235 ai->stats.boats--;
236 if (unit_data->passenger == FERRY_AVAILABLE) {
238 }
239 } else {
240 /* Not a ferry */
241 if (unit_data->ferryboat > 0) {
243 }
244 }
245
246 if (close_here) {
247 dai_data_phase_finished(ait, pplayer);
248 }
249 }
250}
251
252/**********************************************************************/
255void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
256{
257 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
258
259 if (unit_data->ferryboat == FERRY_WANTED) {
260 struct player *pplayer = unit_owner(punit);
261
262 if (is_ai_data_phase_open(ait, pplayer)) {
263 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, NULL);
264
265 ai->stats.passengers--;
266 }
267 } else {
268 struct unit *ferry = game_unit_by_number(unit_data->ferryboat);
269
270 if (ferry) {
271 struct unit_ai *ferry_data = def_ai_unit_data(ferry, ait);
272
273 if (ferry_data->passenger == punit->id) {
274 /* punit doesn't want us anymore */
275 struct player *pplayer = unit_owner(ferry);
276
277 if (is_ai_data_phase_open(ait, pplayer)) {
278 dai_plr_data_get(ait, pplayer, NULL)->stats.available_boats++;
279 }
280 ferry_data->passenger = FERRY_AVAILABLE;
281 }
282 }
283 }
284
285 unit_data->ferryboat = FERRY_NONE;
286}
287
288/**********************************************************************/
292static void aiferry_request_boat(struct ai_type *ait, struct unit *punit)
293{
294 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(punit), NULL);
295 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
296
297 /* First clear the previous assignments (just in case there are).
298 * Subtract virtual units or already counted */
299 if ((punit->id == 0) ||
300 ((ai->stats.passengers > 0) &&
301 (unit_data->ferryboat == FERRY_WANTED))) {
303 }
304
305 /* Now add ourselves to the list of potential passengers */
306 ai->stats.passengers++;
307 UNIT_LOG(LOG_DEBUG, punit, "requests a boat (total passengers=%d).",
308 ai->stats.passengers);
309 unit_data->ferryboat = FERRY_WANTED;
310
311 /* Lastly, wait for ferry. */
312 unit_data->done = TRUE;
313}
314
315/**********************************************************************/
318static void aiferry_psngr_meet_boat(struct ai_type *ait,
319 struct unit *punit, struct unit *pferry)
320{
321 struct unit_ai *ferry_data = def_ai_unit_data(pferry, ait);
322 struct player *ferry_owner = unit_owner(pferry);
323
324 fc_assert_ret(unit_owner(punit) == ferry_owner);
325
326 /* First delete the unit from the list of passengers and
327 * release its previous ferry */
329
330 /* If ferry was available, update the stats */
331 if (ferry_data->passenger == FERRY_AVAILABLE) {
332 dai_plr_data_get(ait, ferry_owner, NULL)->stats.available_boats--;
333 }
334
335 /* Exchange the phone numbers */
336 def_ai_unit_data(punit, ait)->ferryboat = pferry->id;
337 ferry_data->passenger = punit->id;
338}
339
340/**********************************************************************/
343static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
344{
345 struct unit_ai *ferry_data = def_ai_unit_data(pferry, ait);
346
347 if (ferry_data->passenger != FERRY_AVAILABLE) {
348 dai_plr_data_get(ait, unit_owner(pferry), NULL)->stats.available_boats++;
349 ferry_data->passenger = FERRY_AVAILABLE;
350 }
351}
352
353/**********************************************************************/
357int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
358{
359 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, NULL);
360
361 /* To developer: Switch this checking on when testing some new
362 * ferry code. */
363#ifdef LOGLEVEL_FERRY_STATS
364 int boats = 0;
365
366 unit_list_iterate(pplayer->units, punit) {
367 if (dai_is_ferry(punit, ait)
368 && def_ai_unit_data(punit, ait)->passenger == FERRY_AVAILABLE) {
369 boats++;
370 }
372
373 if (boats != ai->stats.available_boats) {
374 log_error("Player[%d] in turn %d: boats miscounted.",
375 player_number(pplayer), game.info.turn);
376 aiferry_print_stats(ait, pplayer);
377 }
378#endif /* LOGLEVEL_FERRY_STATS */
379
380 return ai->stats.available_boats;
381}
382
383/* ================== functions to find a boat ========================= */
384
385/**********************************************************************/
398static unsigned combined_land_sea_move(const struct tile *src_tile,
399 enum pf_move_scope src_scope,
400 const struct tile *tgt_tile,
401 enum pf_move_scope dst_scope,
402 const struct pf_parameter *param)
403{
404 unsigned move_cost;
405
406 if (!((PF_MS_NATIVE | PF_MS_CITY) & dst_scope)) {
407 /* Any-to-Sea */
408 move_cost = 0;
409 } else if (!((PF_MS_NATIVE | PF_MS_CITY) & src_scope)) {
410 /* Sea-to-Land */
411 move_cost = PF_IMPOSSIBLE_MC;
412 } else {
413 /* Land-to-Land */
414 move_cost = map_move_cost(&(wld.map), param->owner, param->utype,
415 src_tile, tgt_tile);
416 }
417
418 return move_cost;
419}
420
421/**********************************************************************/
425static unsigned sea_move(const struct tile *ptile, enum known_type known,
426 const struct pf_parameter *param)
427{
428 if (is_ocean_tile(ptile)) {
429 /* Approximately TURN_FACTOR / average ferry move rate
430 * we can pass a better guess of the move rate through param->data
431 * but we don't know which boat we will find out there */
432 return SINGLE_MOVE * PF_TURN_FACTOR / 12;
433 } else {
434 return 0;
435 }
436}
437
438/**********************************************************************/
442bool is_boat_free(struct ai_type *ait, struct unit *boat,
443 struct unit *punit, int cap)
444{
445 /* - Only transporters capable of transporting this unit are eligible.
446 * - Units with orders are skipped (the AI doesn't control units with
447 * orders).
448 * - Only boats that we own are eligible.
449 * - Only available boats or boats that are already dedicated to this unit
450 * are eligible.
451 * - Only boats with enough remaining capacity are eligible.
452 * - Only units that can travel at sea are eligible.
453 * - Units that require fuel, except "Coast" ones, or lose hitpoints are
454 * not eligible.
455 */
456 struct unit_class *ferry_class = unit_class_get(boat);
457 const struct unit_type *ferry_type = unit_type_get(boat);
458 struct unit_ai *boat_data = def_ai_unit_data(boat, ait);
459
460 return (can_unit_transport(boat, punit)
461 && !unit_has_orders(boat)
462 && unit_owner(boat) == unit_owner(punit)
463 && (boat_data->passenger == FERRY_AVAILABLE
464 || boat_data->passenger == punit->id)
466 - get_transporter_occupancy(boat) >= cap)
467 && ferry_class->adv.sea_move != MOVE_NONE
468 && !is_losing_hp(boat)
469 && (ferry_type->fuel == 0 || utype_has_flag(ferry_type, UTYF_COAST)));
470}
471
472/**********************************************************************/
475bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
476{
477 if (!unit_transported(punit)) {
478 /* Not even in boat */
479 return FALSE;
480 }
481
484 == punit->id) {
485 return TRUE;
486 }
487
488 return FALSE;
489}
490
491/**********************************************************************/
499int aiferry_find_boat(struct ai_type *ait, struct unit *punit,
500 int cap, struct pf_path **path)
501{
502 int best_turns = FC_INFINITY;
503 int best_id = 0;
504 struct pf_parameter param;
505 struct pf_map *search_map;
506 struct player *pplayer = unit_owner(punit);
507 const struct civ_map *nmap = &(wld.map);
508
509 /* currently assigned ferry */
510 int ferryboat = def_ai_unit_data(punit, ait)->ferryboat;
511
512 /* We may end calling pf_destroy_path for *path if it's not NULL.
513 * Most likely you are passing garbage or path you don't want
514 * destroyed if this assertion fails.
515 * Don't try to be clever and pass 'fallback' path that will be returned
516 * if no path is found. Instead check for NULL return value and then
517 * use fallback path in calling function. */
518 fc_assert_ret_val(path == NULL || *path == NULL, 0);
519
520 fc_assert_ret_val(0 < ferryboat
521 || FERRY_NONE == ferryboat
522 || FERRY_WANTED == ferryboat, 0);
523 UNIT_LOG(LOGLEVEL_FINDFERRY, punit, "asked aiferry_find_boat for a boat");
524
525 if (aiferry_avail_boats(ait, pplayer) <= 0
526 && ferryboat <= 0) {
527 /* No boats to be found (the second check is to ensure that we are not
528 * the ones keeping the last boat busy) */
529 return 0;
530 }
531
532 pft_fill_unit_parameter(&param, nmap, punit);
533 param.omniscience = !has_handicap(pplayer, H_MAP);
535 param.get_EC = sea_move;
538
539 search_map = pf_map_new(&param);
540
541 pf_map_positions_iterate(search_map, pos, TRUE) {
542 /* Should this be !can_unit_exist_at_tile() instead of is_ocean() some day?
543 * That would allow special units to wade in shallow coast waters to meet
544 * ferry where deep sea starts. */
545 int radius = (is_ocean_tile(pos.tile) ? 1 : 0);
546
547 if (pos.turn + pos.total_EC/PF_TURN_FACTOR > best_turns) {
548 /* Won't find anything better */
549 /* FIXME: This condition is somewhat dodgy */
550 break;
551 }
552
553 square_iterate(&(wld.map), pos.tile, radius, ptile) {
554 unit_list_iterate(ptile->units, aunit) {
555 if (is_boat_free(ait, aunit, punit, cap)) {
556 /* Turns for the unit to get to rendezvous pnt */
557 int u_turns = pos.turn;
558 /* Turns for the boat to get to the rendezvous pnt */
559 int f_turns = ((pos.total_EC / PF_TURN_FACTOR * 16
560 - aunit->moves_left)
561 / unit_type_get(aunit)->move_rate);
562 int turns = MAX(u_turns, f_turns);
563
564 if (turns < best_turns) {
566 "Found a potential boat %s[%d](%d,%d)(moves left: %d)",
567 unit_rule_name(aunit), aunit->id,
568 TILE_XY(unit_tile(aunit)), aunit->moves_left);
569 if (path) {
570 if (*path) {
571 pf_path_destroy(*path);
572 }
573 *path = pf_map_iter_path(search_map);
574 }
575 best_turns = turns;
576 best_id = aunit->id;
577 }
578 }
582 pf_map_destroy(search_map);
583
584 return best_id;
585}
586
587/**********************************************************************/
590static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit,
591 int cap)
592{
593 UNIT_LOG(LOGLEVEL_FINDFERRY, punit, "asked find_ferry_nearby for a boat");
594
595 square_iterate(&(wld.map), unit_tile(punit), 1, ptile) {
596 unit_list_iterate(ptile->units, aunit) {
597 if (is_boat_free(ait, aunit, punit, cap)) {
598 return aunit->id;
599 }
602
603 return 0;
604}
605
606
607/* ============================= go by boat ============================== */
608
609/**********************************************************************/
614static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
615{
616 struct player *ferry_owner = unit_owner(ferry);
617
618 unit_list_iterate_safe(unit_tile(ferry)->units, aunit) {
619 if (unit_transport_get(aunit) == ferry) {
620 unit_activity_handling(aunit, ACTIVITY_IDLE);
621 def_ai_unit_data(aunit, ait)->done = FALSE;
622
623 if (unit_owner(aunit) == ferry_owner) {
624 /* Move it only if it's our own. */
625 dai_manage_unit(ait, ferry_owner, aunit);
626 }
627 }
629}
630
631/**********************************************************************/
639 struct unit *ferry,
640 struct unit *passenger,
641 struct tile *ptile,
642 struct pft_amphibious *parameter)
643{
644 bool alive = TRUE;
645 struct pf_map *pfm;
646 struct pf_path *path;
647 int pass_id = passenger->id;
648
651 fc_assert_ret_val(unit_tile(ferry) == unit_tile(passenger), TRUE);
652
653 ptile = immediate_destination(passenger, ptile);
654
655 if (same_pos(unit_tile(passenger), ptile)) {
656 /* Not an error; sometimes immediate_destination instructs the unit
657 * to stay here. For example, to refuel.*/
658 send_unit_info(NULL, passenger);
659 return TRUE;
660 } else if (passenger->moves_left == 0 && ferry->moves_left == 0) {
661 send_unit_info(NULL, passenger);
662 return TRUE;
663 }
664
665 pfm = pf_map_new(&parameter->combined);
666 path = pf_map_path(pfm, ptile);
667
668 if (path) {
669 dai_log_path(passenger, path, &parameter->combined);
670 /* Sea leg */
671 alive = adv_follow_path(ferry, path, ptile);
672 if (alive && unit_tile(passenger) != ptile) {
673 /* Ferry has stopped; it is at the landing beach or
674 * has run out of movement points */
675 struct tile *next_tile;
676
677 if (!pf_path_advance(path, unit_tile(passenger))) {
678 /* Somehow we got thrown away from our route.
679 * This can happen if our movement caused alliance breakup. */
680 return unit_is_alive(pass_id);
681 }
682 next_tile = path->positions[1].tile;
683 if (!is_ocean_tile(next_tile)) {
684 int ferry_id = ferry->id;
685
686 UNIT_LOG(LOG_DEBUG, passenger, "Our boat has arrived "
687 "[%d](moves left: %d)", ferry->id, ferry->moves_left);
688 UNIT_LOG(LOG_DEBUG, passenger, "Disembarking to (%d,%d)",
689 TILE_XY(next_tile));
690 /* Land leg */
691 alive = adv_follow_path(passenger, path, ptile);
692 /* Movement of the passenger outside the ferry can cause also
693 * ferry to die. That has happened at least when passenger
694 * destroyed city cutting the civ1-style channel (cities in
695 * a chain) ferry was in. */
696 if (unit_is_alive(ferry_id) && 0 < ferry->moves_left
697 && (!alive || unit_tile(ferry) != unit_tile(passenger))) {
698 /* The passenger is no longer on the ferry,
699 * and the ferry can still act.
700 * Give a chance for another passenger to take command
701 * of the ferry.
702 */
703 UNIT_LOG(LOG_DEBUG, ferry, "Activating passengers");
704 dai_activate_passengers(ait, ferry);
705
706 /* It is theoretically possible passenger died here due to
707 * autoattack against another passing unit at its location. */
708 alive = unit_is_alive(pass_id);
709 }
710 }
711 /* else at sea */
712 } else if (alive) {
713 /* Arrived all the way to the destination by boat. Deboard. */
714 if (can_unit_exist_at_tile(parameter->land.map, passenger, ptile)) {
716 }
717 }
718 /* else dead */
719 } else {
720 /* Not always an error; enemy units might block all paths. */
721 UNIT_LOG(LOG_DEBUG, passenger, "no path to destination");
722 }
723
724 pf_path_destroy(path);
725 pf_map_destroy(pfm);
726
727 return alive;
728}
729
730/**********************************************************************/
734bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry,
735 struct unit *passenger, struct tile *ptile)
736{
737 struct pft_amphibious parameter;
738 struct adv_risk_cost land_risk_cost;
739 struct adv_risk_cost sea_risk_cost;
740
741 dai_fill_unit_param(ait, &parameter.land, &land_risk_cost, passenger, ptile);
742 if (parameter.land.get_TB != no_fights) {
743 /* Use the ferry to go around danger areas: */
744 parameter.land.get_TB = no_intermediate_fights;
745 }
746 dai_fill_unit_param(ait, &parameter.sea, &sea_risk_cost, ferry, ptile);
748
749 /* Move as far along the path to the destination as we can;
750 * that is, ignore the presence of enemy units when computing the
751 * path */
752 parameter.combined.get_zoc = NULL;
753
754 return dai_amphibious_goto_constrained(ait, ferry, passenger, ptile,
755 &parameter);
756}
757
758/**********************************************************************/
768bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer,
769 struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
770{
771 struct civ_map *nmap = &(wld.map);
772
773 if (!unit_transported(punit)) {
774 /* We are not on a boat and we cannot walk */
775 int boatid;
776 struct unit *ferryboat = NULL;
777 int cap = with_bodyguard ? 2 : 1;
778 bool board_success = FALSE;
779
780 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "will have to go to (%d,%d) by boat",
781 TILE_XY(dest_tile));
782
783 if (!is_terrain_class_near_tile(nmap, unit_tile(punit), TC_OCEAN)) {
784 struct pf_path *path_to_ferry = NULL;
785
786 boatid = aiferry_find_boat(ait, punit, cap, &path_to_ferry);
787 if (boatid <= 0) {
789 "in ai_gothere cannot find any boats.");
790 def_ai_unit_data(punit, ait)->done = TRUE; /* Nothing to do */
791 return FALSE;
792 }
793
794 ferryboat = game_unit_by_number(boatid);
795 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "found boat[%d](%d,%d), going there",
796 boatid, TILE_XY(unit_tile(ferryboat)));
797 /* The path can be amphibious so we will stop at the coast.
798 * It might not lead _onto_ the boat. */
799 if (!adv_unit_execute_path(punit, path_to_ferry)) {
800 /* Died. */
801 pf_path_destroy(path_to_ferry);
802 return FALSE;
803 }
804 pf_path_destroy(path_to_ferry);
805 }
806
807 if (!is_terrain_class_near_tile(nmap, unit_tile(punit), TC_OCEAN)) {
808 /* Still haven't reached the coast */
809 return FALSE;
810 }
811
812 /* We are on the coast, look around for a boat */
813 boatid = aiferry_find_boat_nearby(ait, punit, cap);
814 if (boatid <= 0) {
815 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "requesting a boat.");
817 return FALSE;
818 }
819
820 /* Ok, a boat found, try boarding it */
821 ferryboat = game_unit_by_number(boatid);
822 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "found a nearby boat[%d](%d,%d)",
823 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
824 /* Setting ferry now in hope it won't run away even
825 * if we can't board it right now */
826 aiferry_psngr_meet_boat(ait, punit, ferryboat);
827
828 if (is_tiles_adjacent(unit_tile(punit), unit_tile(ferryboat))) {
829 (void) dai_unit_move(ait, punit, unit_tile(ferryboat));
830 }
831
832 /* FIXME: check if action is enabled. */
833 if (!can_unit_load(punit, ferryboat)) {
834 /* Something prevented us from boarding */
835 /* FIXME: this is probably a serious bug, but we just skip past
836 * it and continue. */
837 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "couldn't board boat[%d](%d,%d)",
838 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
839 return FALSE;
840 }
841
842 action_by_result_iterate(paction, ACTRES_TRANSPORT_BOARD) {
844 ferryboat))) {
845 if (unit_perform_action(pplayer,
846 punit->id, ferryboat->id, 0, "",
847 paction->id, ACT_REQ_PLAYER)) {
848 board_success = TRUE;
849 break;
850 }
851 }
853
854 if (!board_success) {
855 /* No action enabler active.
856 * TODO: Try to predict this failure so that the units wouldn't
857 * waste turns to travel to the rendezvous point. */
858 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "boarding boat[%d](%d,%d) not enabled",
859 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
860
861 return FALSE;
862 }
863
865 }
866
867 if (unit_transported(punit)) {
868 /* We are on a boat, ride it! */
869 struct unit *ferryboat = unit_transport_get(punit);
870
871 /* Check if we are the passenger-in-charge */
872 if (is_boat_free(ait, ferryboat, punit, 0)) {
873 struct unit *bodyguard = aiguard_guard_of(ait, punit);
874
876 "got boat[%d](moves left: %d), going (%d,%d)",
877 ferryboat->id, ferryboat->moves_left, TILE_XY(dest_tile));
878 aiferry_psngr_meet_boat(ait, punit, ferryboat);
879
880 punit->goto_tile = dest_tile;
881 /* Grab bodyguard */
882 if (bodyguard
883 && !same_pos(unit_tile(punit), unit_tile(bodyguard))) {
884 if (!goto_is_sane(bodyguard, unit_tile(punit))
885 || !dai_unit_goto(ait, bodyguard, unit_tile(punit))) {
886 /* Bodyguard can't get there or died en route */
888 bodyguard = NULL;
889 } else if (bodyguard->moves_left <= 0) {
890 /* Wait for me, I'm cooooming!! */
891 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "waiting for bodyguard");
893 return FALSE;
894 } else {
895 /* Crap bodyguard. Got stuck somewhere. Ditch it! */
896 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "ditching useless bodyguard");
898 dai_unit_new_task(ait, bodyguard, AIUNIT_NONE, NULL);
899 bodyguard = NULL;
900 }
901 }
902 if (bodyguard) {
904
905 /* Bodyguard either uses the same boat or none at all. */
906 action_by_result_iterate(paction, ACTRES_TRANSPORT_BOARD) {
907 if (action_prob_possible(action_prob_vs_unit(nmap, bodyguard,
908 paction->id,
909 ferryboat))) {
910 if (unit_perform_action(pplayer,
911 bodyguard->id, ferryboat->id, 0, "",
912 paction->id, ACT_REQ_PLAYER)) {
913 break;
914 }
915 }
917 }
918
919 if (!aiferry_goto_amphibious(ait, ferryboat, punit, dest_tile)) {
920 /* Died */
921 return FALSE;
922 }
923 if (same_pos(unit_tile(punit), dest_tile)) {
924 /* Arrived */
925 unit_activity_handling(punit, ACTIVITY_IDLE);
926 } else {
927 /* We are in still transit */
929 return FALSE;
930 }
931 } else {
932 /* Waiting for the boss to load and move us */
933 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "Cannot command boat [%d],"
934 " its boss is [%d]",
935 ferryboat->id, def_ai_unit_data(ferryboat, ait)->passenger);
936 return FALSE;
937 }
938 }
939
940 return TRUE;
941}
942
943
944/* ===================== Boat management ================================= */
945
946/**********************************************************************/
953static bool aiferry_findcargo(struct ai_type *ait, struct unit *pferry)
954{
955 /* Path-finding stuff */
956 struct pf_map *pfm;
957 struct pf_parameter parameter;
958 int passengers = dai_plr_data_get(ait, unit_owner(pferry),
959 NULL)->stats.passengers;
960 struct player *pplayer;
961 const struct civ_map *nmap = &(wld.map);
962
963 if (passengers <= 0) {
964 /* No passengers anywhere */
965 return FALSE;
966 }
967
968 UNIT_LOG(LOGLEVEL_FERRY, pferry, "Ferryboat is looking for cargo.");
969
970 pplayer = unit_owner(pferry);
971 pft_fill_unit_overlap_param(&parameter, nmap, pferry);
972 parameter.omniscience = !has_handicap(pplayer, H_MAP);
973 /* If we have omniscience, we use it, since paths to some places
974 * might be "blocked" by unknown. We don't want to fight though */
975 parameter.get_TB = no_fights;
976
977 pfm = pf_map_new(&parameter);
978 pf_map_tiles_iterate(pfm, ptile, TRUE) {
979 unit_list_iterate(ptile->units, aunit) {
980 struct unit_ai *unit_data = def_ai_unit_data(aunit, ait);
981
982 if (unit_owner(pferry) == unit_owner(aunit)
983 && (unit_data->ferryboat == FERRY_WANTED
984 || unit_data->ferryboat == pferry->id)) {
985 UNIT_LOG(LOGLEVEL_FERRY, pferry,
986 "Found a potential cargo %s[%d](%d,%d), going there",
987 unit_rule_name(aunit),
988 aunit->id,
989 TILE_XY(unit_tile(aunit)));
990 pferry->goto_tile = unit_tile(aunit);
991 /* Exchange phone numbers */
992 aiferry_psngr_meet_boat(ait, aunit, pferry);
993 pf_map_destroy(pfm);
994 return TRUE;
995 }
998
999 /* False positive can happen if we cannot find a route to the passenger
1000 * because of an internal sea or enemy blocking the route */
1001 UNIT_LOG(LOGLEVEL_FERRY, pferry,
1002 "AI Passengers counting reported false positive %d", passengers);
1003 pf_map_destroy(pfm);
1004 return FALSE;
1005}
1006
1007/**********************************************************************/
1019static bool aiferry_find_interested_city(struct ai_type *ait,
1020 struct unit *pferry)
1021{
1022 /* Path-finding stuff */
1023 struct pf_map *pfm;
1024 struct pf_parameter parameter;
1025 /* Early termination condition */
1026 int turns_horizon = FC_INFINITY;
1027 /* Future return value */
1028 bool needed = FALSE;
1029 const struct civ_map *nmap = &(wld.map);
1030
1031 UNIT_LOG(LOGLEVEL_FERRY, pferry, "Ferry looking for a city that needs it");
1032
1033 pft_fill_unit_parameter(&parameter, nmap, pferry);
1034 /* We are looking for our own cities, no need to look into the unknown */
1035 parameter.get_TB = no_fights_or_unknown;
1036 parameter.omniscience = FALSE;
1037 pfm = pf_map_new(&parameter);
1038
1040 struct city *pcity;
1041
1042 if (pos.turn >= turns_horizon) {
1043 /* Won't be able to find anything better than what we have */
1044 break;
1045 }
1046
1047 pcity = tile_city(pos.tile);
1048
1049 if (pcity && city_owner(pcity) == unit_owner(pferry)
1050 && (def_ai_city_data(pcity, ait)->choice.need_boat
1051 || (VUT_UTYPE == pcity->production.kind
1053 L_FERRYBOAT)))) {
1054 bool really_needed = TRUE;
1055 int turns = city_production_turns_to_build(pcity, TRUE);
1056
1057 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s (%d, %d) looks promising...",
1058 city_name_get(pcity), TILE_XY(pcity->tile));
1059
1060 if (pos.turn > turns
1061 && VUT_UTYPE == pcity->production.kind
1062 && utype_has_role(pcity->production.value.utype, L_FERRYBOAT)) {
1063 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1064 "will finish building its own ferry too soon",
1065 city_name_get(pcity));
1066 continue;
1067 }
1068
1069 if (turns >= turns_horizon) {
1070 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1071 "has just started building",
1072 city_name_get(pcity));
1073 continue;
1074 }
1075
1076 unit_list_iterate(pos.tile->units, aunit) {
1077 if (aunit != pferry && unit_owner(aunit) == unit_owner(pferry)
1078 && unit_has_type_role(aunit, L_FERRYBOAT)) {
1079
1080 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1081 "has another ferry",
1082 city_name_get(pcity));
1083 really_needed = FALSE;
1084 break;
1085 }
1087
1088 if (really_needed) {
1089 UNIT_LOG(LOGLEVEL_FERRY, pferry, "will go to %s unless we "
1090 "find something better",
1091 city_name_get(pcity));
1092 pferry->goto_tile = pos.tile;
1093 turns_horizon = turns;
1094 needed = TRUE;
1095 }
1096 }
1098
1099 pf_map_destroy(pfm);
1100 return needed;
1101}
1102
1103/**********************************************************************/
1113void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer,
1114 struct unit *punit)
1115{
1116 struct city *pcity;
1117 int sanity = punit->id;
1118 struct unit_ai *unit_data;
1119 int bossid;
1120 const struct unit_type *ptype;
1121 const struct civ_map *nmap = &(wld.map);
1122
1124
1125 /* Try to recover hitpoints if we are in a city, before we do anything */
1126 if (punit->hp < unit_type_get(punit)->hp
1127 && (pcity = tile_city(unit_tile(punit)))) {
1128 UNIT_LOG(LOGLEVEL_FERRY, punit, "waiting in %s to recover hitpoints",
1129 city_name_get(pcity));
1131 return;
1132 }
1133
1134 /* Check if we are an empty barbarian boat and so not needed */
1135 if (is_barbarian(pplayer) && get_transporter_occupancy(punit) == 0) {
1136 wipe_unit(punit, ULR_RETIRED, NULL);
1137 return;
1138 }
1139
1140 unit_data = def_ai_unit_data(punit, ait);
1141
1142 bossid = unit_data->passenger; /* Old boss */
1143
1144 do {
1145 /* Do we have the passenger-in-charge on board? */
1146 if (unit_data->passenger > 0) {
1147 struct unit *psngr = game_unit_by_number(unit_data->passenger);
1148
1149 /* If the passenger-in-charge is adjacent, we should wait for it to
1150 * board. We will pass control to it later. */
1151 if (!psngr
1152 || real_map_distance(unit_tile(punit), unit_tile(psngr)) > 1) {
1154 "recorded passenger[%d] is not on board, checking for "
1155 "others", unit_data->passenger);
1156 unit_data->passenger = FERRY_ABANDON_BOSS;
1157 }
1158 }
1159
1160 if (unit_data->passenger == FERRY_AVAILABLE
1161 || unit_data->passenger == FERRY_ABANDON_BOSS) {
1162 struct unit *candidate = NULL;
1163
1164 /* Try to select passenger-in-charge from among our passengers */
1166 if (unit_owner(aunit) != pplayer) {
1167 /* We used to check if ferryboat was set to us or to
1168 * FERRY_WANTED too, but this was a bit strict. Especially
1169 * when we don't save these values in a savegame. */
1170 continue;
1171 }
1172
1173 if (def_ai_unit_data(aunit, ait)->task != AIUNIT_ESCORT) {
1174 candidate = aunit;
1175 break;
1176 } else {
1177 /* Bodyguards shouldn't be in charge of boats so continue looking */
1178 candidate = aunit;
1179 }
1181
1182 if (candidate) {
1184 "appointed %s[%d] our passenger-in-charge",
1185 unit_rule_name(candidate),
1186 candidate->id);
1187 bossid = candidate->id;
1188 aiferry_psngr_meet_boat(ait, candidate, punit);
1189 }
1190 }
1191
1192 if (unit_data->passenger > 0) {
1193 struct unit *boss = game_unit_by_number(bossid);
1194
1195 fc_assert_ret(NULL != boss);
1196
1197 if (unit_has_type_flag(boss, UTYF_SETTLERS)
1198 || unit_is_cityfounder(boss)) {
1199 /* Temporary hack: settlers all go in the end, forcing them
1200 * earlier might mean uninitialised cache, so just wait for them */
1201 return;
1202 }
1203
1204 UNIT_LOG(LOGLEVEL_FERRY, punit, "passing control to %s[%d]",
1205 unit_rule_name(boss),
1206 boss->id);
1207 dai_manage_unit(ait, pplayer, boss);
1208
1209 if (!game_unit_by_number(sanity) || punit->moves_left <= 0) {
1210 return;
1211 }
1212 if (game_unit_by_number(bossid)) {
1213 if (same_pos(unit_tile(punit), unit_tile(boss))) {
1214 /* The boss decided to stay put on the ferry. We aren't moving. */
1215 UNIT_LOG(LOG_DEBUG, boss, "drove ferry - done for now");
1216 def_ai_unit_data(boss, ait)->done = TRUE;
1217 return;
1218 } else if (unit_data->passenger == bossid
1220 /* The boss isn't on the ferry, has not passed control away,
1221 * and we have other passengers?
1222 * Forget about the boss. */
1223 unit_data->passenger = FERRY_ABANDON_BOSS;
1224 }
1225 }
1226 if (unit_data->passenger != bossid
1227 && unit_data->passenger != FERRY_ABANDON_BOSS) {
1228 /* Boss handling resulted in boss change. Run next round with new boss. */
1229 bossid = unit_data->passenger;
1230 }
1231 } else {
1232 /* Cannot select a passenger-in-charge */
1233 break;
1234 }
1235 } while (get_transporter_occupancy(punit) != 0);
1236
1237 if (unit_data->passenger == FERRY_ABANDON_BOSS) {
1238 /* As nobody else wanted the control, restore it to old boss. */
1239 unit_data->passenger = bossid;
1240 }
1241
1242 /* Not carrying anyone, even the ferryman */
1243
1244 ptype = unit_type_get(punit);
1245
1246 if (IS_ATTACKER(ptype) && punit->moves_left > 0) {
1247 /* AI used to build frigates to attack and then use them as ferries
1248 * -- Syela */
1249 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
1250 UNIT_LOG(LOGLEVEL_FERRY, punit, "passing ferry over to attack code");
1251 dai_manage_military(ait, nmap, pplayer, punit);
1252 return;
1253 }
1254
1255 UNIT_LOG(LOGLEVEL_FERRY, punit, "Ferryboat is not carrying anyone "
1256 "(moves left: %d).", punit->moves_left);
1258 unit_activity_handling(punit, ACTIVITY_IDLE);
1259 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
1261
1262 /* Try to find passengers */
1263 if (aiferry_findcargo(ait, punit)) {
1264 UNIT_LOG(LOGLEVEL_FERRY, punit, "picking up cargo (moves left: %d)",
1265 punit->moves_left);
1266 if (dai_unit_goto(ait, punit, punit->goto_tile)) {
1269 struct unit *cargo = game_unit_by_number(unit_data->passenger);
1270
1271 /* See if passenger can jump on board! */
1272 fc_assert_ret(cargo != punit);
1273 dai_manage_unit(ait, pplayer, cargo);
1274 }
1275 }
1276 return;
1277 }
1278
1279 /* Try to find a city that needs a ferry */
1282 UNIT_LOG(LOGLEVEL_FERRY, punit, "staying in city that needs us");
1283 unit_data->done = TRUE;
1284 return;
1285 } else {
1286 UNIT_LOG(LOGLEVEL_FERRY, punit, "going to city that needs us");
1289 unit_data->done = TRUE; /* save some CPU */
1290 }
1291 return;
1292 }
1293 }
1294
1295 UNIT_LOG(LOGLEVEL_FERRY, punit, "Passing control of ferry to explorer code");
1296 switch (manage_auto_explorer(punit)) {
1297 case MR_DEATH:
1298 /* don't use punit! */
1299 return;
1300 case MR_OK:
1301 /* FIXME: continue moving? */
1302 break;
1303 default:
1304 unit_data->done = TRUE;
1305 break;
1306 };
1307
1308 if (punit->moves_left > 0) {
1309 struct city *safe_city = find_nearest_safe_city(punit);
1310
1311 if (safe_city != NULL) {
1312 punit->goto_tile = safe_city->tile;
1313 UNIT_LOG(LOGLEVEL_FERRY, punit, "No work, going home");
1314 unit_data->done = TRUE;
1315 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
1316 (void) dai_unit_goto(ait, punit, safe_city->tile);
1317 }
1318 }
1319
1320 return;
1321}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6703
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:5953
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:488
#define action_by_result_iterate_end
Definition actions.h:492
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:82
bool is_ai_data_phase_open(struct ai_type *ait, struct player *pplayer)
Definition aidata.c:132
struct ai_plr * dai_plr_data_get(struct ai_type *ait, struct player *pplayer, bool *caller_closes)
Definition aidata.c:308
void dai_data_phase_finished(struct ai_type *ait, struct player *pplayer)
Definition aidata.c:285
static bool aiferry_findcargo(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:951
static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
Definition aiferry.c:612
#define FERRY_WANTED
Definition aiferry.c:71
bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
Definition aiferry.c:766
int aiferry_find_boat(struct ai_type *ait, struct unit *punit, int cap, struct pf_path **path)
Definition aiferry.c:497
#define FERRY_NONE
Definition aiferry.c:72
void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiferry.c:1111
bool is_boat_free(struct ai_type *ait, struct unit *boat, struct unit *punit, int cap)
Definition aiferry.c:440
bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
Definition aiferry.c:151
void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:94
static bool aiferry_find_interested_city(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:1017
#define LOGLEVEL_FINDFERRY
Definition aiferry.c:82
void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:223
void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry, const struct unit_type *old)
Definition aiferry.c:191
bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile)
Definition aiferry.c:732
bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:473
static void aiferry_psngr_meet_boat(struct ai_type *ait, struct unit *punit, struct unit *pferry)
Definition aiferry.c:316
static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:341
static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit, int cap)
Definition aiferry.c:588
static unsigned sea_move(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition aiferry.c:423
int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:355
#define LOGLEVEL_GOBYBOAT
Definition aiferry.c:80
bool dai_amphibious_goto_constrained(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile, struct pft_amphibious *parameter)
Definition aiferry.c:636
bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
Definition aiferry.c:161
#define FERRY_ABANDON_BOSS
Definition aiferry.c:66
void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
Definition aiferry.c:169
void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:253
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 aiferry.c:396
#define FERRY_AVAILABLE
Definition aiferry.c:65
static void aiferry_request_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:290
#define LOGLEVEL_FERRY
Definition aiferry.c:78
void aiguard_request_guard(struct ai_type *ait, struct unit *punit)
Definition aiguard.c:228
struct unit * aiguard_guard_of(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:270
static struct ai_plr * def_ai_player_data(const struct player *pplayer, struct ai_type *deftype)
Definition aiplayer.h:54
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition aiplayer.h:42
static struct unit_ai * def_ai_unit_data(const struct unit *punit, struct ai_type *deftype)
Definition aiplayer.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 aitools.c:470
bool goto_is_sane(struct unit *punit, struct tile *ptile)
Definition aitools.c:430
struct tile * immediate_destination(struct unit *punit, struct tile *dest_tile)
Definition aitools.c:303
bool dai_unit_goto(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:606
void dai_log_path(struct unit *punit, struct pf_path *path, struct pf_parameter *parameter)
Definition aitools.c:357
void dai_unit_new_task(struct ai_type *ait, struct unit *punit, enum ai_unit_task task, struct tile *ptile)
Definition aitools.c:644
bool dai_unit_move(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:1073
void dai_manage_military(struct ai_type *ait, const struct civ_map *nmap, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2496
void dai_manage_unit(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2651
struct city * find_nearest_safe_city(struct unit *punit)
Definition aiunit.c:1629
@ AIUNIT_NONE
Definition aiunit.h:27
@ AIUNIT_ESCORT
Definition aiunit.h:28
#define IS_ATTACKER(ptype)
Definition aiunit.h:70
#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:1115
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:805
#define city_owner(_pcity_)
Definition city.h:543
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
struct civ_game game
Definition game.c:57
struct world wld
Definition game.c:58
struct unit * game_unit_by_number(int id)
Definition game.c:111
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:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_base(level, message,...)
Definition log.h:94
@ LOG_DEBUG
Definition log.h:34
#define log_error(message,...)
Definition log.h:103
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:929
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:628
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
#define square_iterate_end
Definition map.h:388
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:299
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
bool can_unit_transport(const struct unit *transporter, const struct unit *transported)
Definition movement.c:813
#define SINGLE_MOVE
Definition movement.h:24
@ MR_OK
Definition movement.h:33
@ MR_DEATH
Definition movement.h:34
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:840
void pft_fill_unit_overlap_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:891
enum tile_behavior no_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:509
enum tile_behavior no_intermediate_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:524
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:994
int player_number(const struct player *pplayer)
Definition player.c:828
const char * player_name(const struct player *pplayer)
Definition player.c:886
static bool is_barbarian(const struct player *pplayer)
Definition player.h:488
#define is_ai(plr)
Definition player.h:234
#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 aidata.h:78
struct ai_plr::@267 stats
int boats
Definition aidata.h:79
int available_boats
Definition aidata.h:80
Definition ai.h:50
Definition city.h:309
struct universal production
Definition city.h:382
struct tile * tile
Definition city.h:311
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:49
struct unit_list * units
Definition tile.h:57
bool done
Definition aiunit.h:44
int ferryboat
Definition aiunit.h:34
int passenger
Definition aiunit.h:35
enum move_level sea_move
Definition unittype.h:150
struct unit_class::@84 adv
bool ferry
Definition aiunit.h:52
int move_rate
Definition unittype.h:497
Definition unit.h:138
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
struct unit_list * transporting
Definition unit.h:184
int hp
Definition unit.h:151
struct tile * goto_tile
Definition unit.h:155
enum universals_n kind
Definition fc_types.h:758
universals_u value
Definition fc_types.h:757
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:600
#define is_ocean_tile(ptile)
Definition terrain.h:289
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
known_type
Definition tile.h:34
#define TILE_XY(ptile)
Definition tile.h:42
const struct unit_type * utype
Definition fc_types.h:604
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1767
bool unit_is_alive(int id)
Definition unit.c:2237
bool is_losing_hp(const struct unit *punit)
Definition unit.c:2212
bool can_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:744
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2425
bool unit_is_cityfounder(const struct unit *punit)
Definition unit.c:2623
int get_transporter_capacity(const struct unit *punit)
Definition unit.c:299
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2409
bool unit_has_orders(const struct unit *punit)
Definition unit.c:204
#define unit_tile(_pu)
Definition unit.h:395
#define CHECK_UNIT(punit)
Definition unit.h:268
#define unit_owner(_pu)
Definition unit.h:394
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6179
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:3175
#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:2794
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2247
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3328
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1639
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:193
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2547
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:202
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
void * utype_ai_data(const struct unit_type *ptype, const struct ai_type *ai)
Definition unittype.c:2755
@ MOVE_NONE
Definition unittype.h:131
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604