Freeciv-3.1: /fast/freeciv/nightly/S3_1/ai/default/aiferry.c Source File

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 ================= */
78
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) {
116 ai->stats.available_boats++;
117 }
118 }
119 if (unit_data->ferryboat == FERRY_WANTED) {
120 UNIT_LOG(LOG_DEBUG, punit, "wants a boat.");
121 ai->stats.passengers++;
122 }
123 } unit_list_iterate_end;
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",
138 ai->stats.available_boats, ai->stats.boats);
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,
142 unit_rule_name(punit), punit->id,
143 def_ai_unit_data(punit, ait)->passenger);
144 n++;
145 }
146 } unit_list_iterate_end;
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++;
182 ai->stats.available_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) {
206 ai->stats.available_boats--;
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++;
218 ai->stats.available_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) {
237 ai->stats.available_boats--;
238 }
239 } else {
240 /* Not a ferry */
241 if (unit_data->ferryboat > 0) {
242 aiferry_clear_boat(ait, punit);
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 * Substract virtual units or already counted */
299 if ((punit->id == 0) ||
300 ((ai->stats.passengers > 0) &&
301 (unit_data->ferryboat == FERRY_WANTED))) {
302 aiferry_clear_boat(ait, punit);
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 */
328 aiferry_clear_boat(ait, punit);
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 }
371 } unit_list_iterate_end;
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)
465 && (get_transporter_capacity(boat)
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
482 if (unit_transported(punit)
483 && def_ai_unit_data(unit_transport_get(punit), ait)->passenger
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);
534 param.get_TB = no_fights_or_unknown;
535 param.get_EC = sea_move;
536 param.get_MC = combined_land_sea_move;
537 param.ignore_none_scopes = FALSE;
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) {
565 UNIT_LOG(LOGLEVEL_FINDFERRY, punit,
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 }
579 } unit_list_iterate_end;
580 } square_iterate_end;
581 } pf_map_positions_iterate_end;
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 }
600 } unit_list_iterate_end;
601 } square_iterate_end;
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 }
628 } unit_list_iterate_safe_end;
629}
630
631/**********************************************************************/
638bool dai_amphibious_goto_constrained(struct ai_type *ait,
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
649 fc_assert_ret_val(is_ai(unit_owner(passenger)), TRUE);
650 fc_assert_ret_val(!unit_has_orders(passenger), TRUE);
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)) {
715 unit_transport_unload_send(passenger);
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);
747 pft_fill_amphibious_parameter(&parameter);
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) {
788 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit,
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.");
816 aiferry_request_boat(ait, punit);
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) {
843 if (action_prob_possible(action_prob_vs_unit(punit, paction->id,
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 }
852 } action_by_result_iterate_end;
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
864 fc_assert(unit_transported(punit));
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
875 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit,
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 */
887 aiguard_request_guard(ait, punit);
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");
892 def_ai_unit_data(punit, ait)->done = TRUE;
893 return FALSE;
894 } else {
895 /* Crap bodyguard. Got stuck somewhere. Ditch it! */
896 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "ditching useless bodyguard");
897 aiguard_request_guard(ait, punit);
898 dai_unit_new_task(ait, bodyguard, AIUNIT_NONE, NULL);
899 bodyguard = NULL;
900 }
901 }
902 if (bodyguard) {
903 fc_assert(same_pos(unit_tile(punit), unit_tile(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(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 }
916 } action_by_result_iterate_end;
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 */
928 def_ai_unit_data(punit, ait)->done = TRUE;
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 }
996 } unit_list_iterate_end;
997 } pf_map_tiles_iterate_end;
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
1039 pf_map_positions_iterate(pfm, pos, TRUE) {
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
1052 && utype_has_role(pcity->production.value.utype,
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 }
1086 } unit_list_iterate_end;
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 }
1097 } pf_map_positions_iterate_end;
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
1122 CHECK_UNIT(punit);
1123
1124 /* Try to recover hitpoints if we are in a city, before we do anything */
1125 if (punit->hp < unit_type_get(punit)->hp
1126 && (pcity = tile_city(unit_tile(punit)))) {
1127 UNIT_LOG(LOGLEVEL_FERRY, punit, "waiting in %s to recover hitpoints",
1128 city_name_get(pcity));
1129 def_ai_unit_data(punit, ait)->done = TRUE;
1130 return;
1131 }
1132
1133 /* Check if we are an empty barbarian boat and so not needed */
1134 if (is_barbarian(pplayer) && get_transporter_occupancy(punit) == 0) {
1135 wipe_unit(punit, ULR_RETIRED, NULL);
1136 return;
1137 }
1138
1139 unit_data = def_ai_unit_data(punit, ait);
1140
1141 bossid = unit_data->passenger; /* Old boss */
1142
1143 do {
1144 /* Do we have the passenger-in-charge on board? */
1145 if (unit_data->passenger > 0) {
1146 struct unit *psngr = game_unit_by_number(unit_data->passenger);
1147
1148 /* If the passenger-in-charge is adjacent, we should wait for it to
1149 * board. We will pass control to it later. */
1150 if (!psngr
1151 || real_map_distance(unit_tile(punit), unit_tile(psngr)) > 1) {
1152 UNIT_LOG(LOGLEVEL_FERRY, punit,
1153 "recorded passenger[%d] is not on board, checking for "
1154 "others", unit_data->passenger);
1155 unit_data->passenger = FERRY_ABANDON_BOSS;
1156 }
1157 }
1158
1159 if (unit_data->passenger == FERRY_AVAILABLE
1160 || unit_data->passenger == FERRY_ABANDON_BOSS) {
1161 struct unit *candidate = NULL;
1162
1163 /* Try to select passenger-in-charge from among our passengers */
1164 unit_list_iterate(punit->transporting, aunit) {
1165 if (unit_owner(aunit) != pplayer) {
1166 /* We used to check if ferryboat was set to us or to
1167 * FERRY_WANTED too, but this was a bit strict. Especially
1168 * when we don't save these values in a savegame. */
1169 continue;
1170 }
1171
1172 if (def_ai_unit_data(aunit, ait)->task != AIUNIT_ESCORT) {
1173 candidate = aunit;
1174 break;
1175 } else {
1176 /* Bodyguards shouldn't be in charge of boats so continue looking */
1177 candidate = aunit;
1178 }
1179 } unit_list_iterate_end;
1180
1181 if (candidate) {
1182 UNIT_LOG(LOGLEVEL_FERRY, punit,
1183 "appointed %s[%d] our passenger-in-charge",
1184 unit_rule_name(candidate),
1185 candidate->id);
1186 bossid = candidate->id;
1187 aiferry_psngr_meet_boat(ait, candidate, punit);
1188 }
1189 }
1190
1191 if (unit_data->passenger > 0) {
1192 struct unit *boss = game_unit_by_number(bossid);
1193
1194 fc_assert_ret(NULL != boss);
1195
1196 if (unit_has_type_flag(boss, UTYF_SETTLERS)
1197 || unit_is_cityfounder(boss)) {
1198 /* Temporary hack: settlers all go in the end, forcing them
1199 * earlier might mean uninitialised cache, so just wait for them */
1200 return;
1201 }
1202
1203 UNIT_LOG(LOGLEVEL_FERRY, punit, "passing control to %s[%d]",
1204 unit_rule_name(boss),
1205 boss->id);
1206 dai_manage_unit(ait, pplayer, boss);
1207
1208 if (!game_unit_by_number(sanity) || punit->moves_left <= 0) {
1209 return;
1210 }
1211 if (game_unit_by_number(bossid)) {
1212 if (same_pos(unit_tile(punit), unit_tile(boss))) {
1213 /* The boss decided to stay put on the ferry. We aren't moving. */
1214 UNIT_LOG(LOG_DEBUG, boss, "drove ferry - done for now");
1215 def_ai_unit_data(boss, ait)->done = TRUE;
1216 return;
1217 } else if (unit_data->passenger == bossid
1218 && get_transporter_occupancy(punit) != 0) {
1219 /* The boss isn't on the ferry, has not passed control away,
1220 * and we have other passengers?
1221 * Forget about the boss. */
1222 unit_data->passenger = FERRY_ABANDON_BOSS;
1223 }
1224 }
1225 if (unit_data->passenger != bossid
1226 && unit_data->passenger != FERRY_ABANDON_BOSS) {
1227 /* Boss handling resulted in boss change. Run next round with new boss. */
1228 bossid = unit_data->passenger;
1229 }
1230 } else {
1231 /* Cannot select a passenger-in-charge */
1232 break;
1233 }
1234 } while (get_transporter_occupancy(punit) != 0);
1235
1236 if (unit_data->passenger == FERRY_ABANDON_BOSS) {
1237 /* As nobody else wanted the control, restore it to old boss. */
1238 unit_data->passenger = bossid;
1239 }
1240
1241 /* Not carrying anyone, even the ferryman */
1242
1243 ptype = unit_type_get(punit);
1244
1245 if (IS_ATTACKER(ptype) && punit->moves_left > 0) {
1246 /* AI used to build frigates to attack and then use them as ferries
1247 * -- Syela */
1248 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
1249 UNIT_LOG(LOGLEVEL_FERRY, punit, "passing ferry over to attack code");
1250 dai_manage_military(ait, pplayer, punit);
1251 return;
1252 }
1253
1254 UNIT_LOG(LOGLEVEL_FERRY, punit, "Ferryboat is not carrying anyone "
1255 "(moves left: %d).", punit->moves_left);
1256 aiferry_make_available(ait, punit);
1257 unit_activity_handling(punit, ACTIVITY_IDLE);
1258 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
1259 CHECK_UNIT(punit);
1260
1261 /* Try to find passengers */
1262 if (aiferry_findcargo(ait, punit)) {
1263 UNIT_LOG(LOGLEVEL_FERRY, punit, "picking up cargo (moves left: %d)",
1264 punit->moves_left);
1265 if (dai_unit_goto(ait, punit, punit->goto_tile)) {
1266 if (is_tiles_adjacent(unit_tile(punit), punit->goto_tile)
1267 || same_pos(unit_tile(punit), punit->goto_tile)) {
1268 struct unit *cargo = game_unit_by_number(unit_data->passenger);
1269
1270 /* See if passenger can jump on board! */
1271 fc_assert_ret(cargo != punit);
1272 dai_manage_unit(ait, pplayer, cargo);
1273 }
1274 }
1275 return;
1276 }
1277
1278 /* Try to find a city that needs a ferry */
1279 if (aiferry_find_interested_city(ait, punit)) {
1280 if (same_pos(unit_tile(punit), punit->goto_tile)) {
1281 UNIT_LOG(LOGLEVEL_FERRY, punit, "staying in city that needs us");
1282 unit_data->done = TRUE;
1283 return;
1284 } else {
1285 UNIT_LOG(LOGLEVEL_FERRY, punit, "going to city that needs us");
1286 if (dai_unit_goto(ait, punit, punit->goto_tile)
1287 && same_pos(unit_tile(punit), punit->goto_tile)) {
1288 unit_data->done = TRUE; /* save some CPU */
1289 }
1290 return;
1291 }
1292 }
1293
1294 UNIT_LOG(LOGLEVEL_FERRY, punit, "Passing control of ferry to explorer code");
1295 switch (manage_auto_explorer(punit)) {
1296 case MR_DEATH:
1297 /* don't use punit! */
1298 return;
1299 case MR_OK:
1300 /* FIXME: continue moving? */
1301 break;
1302 default:
1303 unit_data->done = TRUE;
1304 break;
1305 };
1306
1307 if (punit->moves_left > 0) {
1308 struct city *safe_city = find_nearest_safe_city(punit);
1309
1310 if (safe_city != NULL) {
1311 punit->goto_tile = safe_city->tile;
1312 UNIT_LOG(LOGLEVEL_FERRY, punit, "No work, going home");
1313 unit_data->done = TRUE;
1314 dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL);
1315 (void) dai_unit_goto(ait, punit, safe_city->tile);
1316 }
1317 }
1318
1319 return;
1320}
action_prob_possible
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:6709
action_prob_vs_unit
struct act_prob action_prob_vs_unit(const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5955
action_by_result_iterate
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:488
action_by_result_iterate_end
#define action_by_result_iterate_end
Definition actions.h:492
advdata.h
adv_follow_path
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
adv_unit_execute_path
bool adv_unit_execute_path(struct unit *punit, struct pf_path *path)
Definition advgoto.c:82
advgoto.h
is_ai_data_phase_open
bool is_ai_data_phase_open(struct ai_type *ait, struct player *pplayer)
Definition aidata.c:132
dai_plr_data_get
struct ai_plr * dai_plr_data_get(struct ai_type *ait, struct player *pplayer, bool *caller_closes)
Definition aidata.c:308
dai_data_phase_finished
void dai_data_phase_finished(struct ai_type *ait, struct player *pplayer)
Definition aidata.c:285
aidata.h
aiferry_findcargo
static bool aiferry_findcargo(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:951
dai_activate_passengers
static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
Definition aiferry.c:612
FERRY_WANTED
#define FERRY_WANTED
Definition aiferry.c:71
aiferry_gobyboat
bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
Definition aiferry.c:766
aiferry_find_boat
int aiferry_find_boat(struct ai_type *ait, struct unit *punit, int cap, struct pf_path **path)
Definition aiferry.c:497
FERRY_NONE
#define FERRY_NONE
Definition aiferry.c:72
dai_manage_ferryboat
void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiferry.c:1111
is_boat_free
bool is_boat_free(struct ai_type *ait, struct unit *boat, struct unit *punit, int cap)
Definition aiferry.c:440
dai_is_ferry_type
bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
Definition aiferry.c:151
aiferry_init_stats
void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:94
aiferry_find_interested_city
static bool aiferry_find_interested_city(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:1017
LOGLEVEL_FINDFERRY
#define LOGLEVEL_FINDFERRY
Definition aiferry.c:82
dai_ferry_lost
void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:223
dai_ferry_transformed
void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry, const struct unit_type *old)
Definition aiferry.c:191
aiferry_goto_amphibious
bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile)
Definition aiferry.c:732
is_boss_of_boat
bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:473
aiferry_psngr_meet_boat
static void aiferry_psngr_meet_boat(struct ai_type *ait, struct unit *punit, struct unit *pferry)
Definition aiferry.c:316
aiferry_make_available
static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:341
aiferry_find_boat_nearby
static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit, int cap)
Definition aiferry.c:588
sea_move
static unsigned sea_move(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition aiferry.c:423
aiferry_avail_boats
int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:355
LOGLEVEL_GOBYBOAT
#define LOGLEVEL_GOBYBOAT
Definition aiferry.c:80
dai_amphibious_goto_constrained
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
dai_is_ferry
bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
Definition aiferry.c:161
FERRY_ABANDON_BOSS
#define FERRY_ABANDON_BOSS
Definition aiferry.c:66
dai_ferry_init_ferry
void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
Definition aiferry.c:169
aiferry_clear_boat
void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:253
combined_land_sea_move
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
FERRY_AVAILABLE
#define FERRY_AVAILABLE
Definition aiferry.c:65
aiferry_request_boat
static void aiferry_request_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:290
LOGLEVEL_FERRY
#define LOGLEVEL_FERRY
Definition aiferry.c:78
aiferry.h
aiguard_request_guard
void aiguard_request_guard(struct ai_type *ait, struct unit *punit)
Definition aiguard.c:228
aiguard_guard_of
struct unit * aiguard_guard_of(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:270
aiguard.h
ailog.h
aiplayer.h
def_ai_player_data
static struct ai_plr * def_ai_player_data(const struct player *pplayer, struct ai_type *deftype)
Definition aiplayer.h:54
def_ai_city_data
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition aiplayer.h:42
def_ai_unit_data
static struct unit_ai * def_ai_unit_data(const struct unit *punit, struct ai_type *deftype)
Definition aiplayer.h:48
dai_fill_unit_param
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:468
goto_is_sane
bool goto_is_sane(struct unit *punit, struct tile *ptile)
Definition aitools.c:428
immediate_destination
struct tile * immediate_destination(struct unit *punit, struct tile *dest_tile)
Definition aitools.c:301
dai_unit_goto
bool dai_unit_goto(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:604
dai_log_path
void dai_log_path(struct unit *punit, struct pf_path *path, struct pf_parameter *parameter)
Definition aitools.c:355
dai_unit_new_task
void dai_unit_new_task(struct ai_type *ait, struct unit *punit, enum ai_unit_task task, struct tile *ptile)
Definition aitools.c:642
dai_unit_move
bool dai_unit_move(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:1071
aitools.h
dai_manage_military
void dai_manage_military(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2497
dai_manage_unit
void dai_manage_unit(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiunit.c:2652
find_nearest_safe_city
struct city * find_nearest_safe_city(struct unit *punit)
Definition aiunit.c:1630
aiunit.h
AIUNIT_NONE
@ AIUNIT_NONE
Definition aiunit.h:27
AIUNIT_ESCORT
@ AIUNIT_ESCORT
Definition aiunit.h:28
IS_ATTACKER
#define IS_ATTACKER(ptype)
Definition aiunit.h:70
n
#define n
Definition astring.c:77
manage_auto_explorer
enum unit_move_result manage_auto_explorer(struct unit *punit)
Definition autoexplorer.c:273
autoexplorer.h
autosettlers.h
city_name_get
const char * city_name_get(const struct city *pcity)
Definition city.c:1106
city_production_turns_to_build
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:804
city_owner
#define city_owner(_pcity_)
Definition city.h:543
daicity.h
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
game
struct civ_game game
Definition game.c:57
wld
struct world wld
Definition game.c:58
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:111
game.h
pos
static struct tile * pos
Definition finddlg.c:53
hand_gen.h
has_handicap
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
handicaps.h
H_MAP
@ H_MAP
Definition handicaps.h:28
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert
#define fc_assert(condition)
Definition log.h:176
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_base
#define log_base(level, message,...)
Definition log.h:94
LOG_DEBUG
@ LOG_DEBUG
Definition log.h:34
log_error
#define log_error(message,...)
Definition log.h:103
is_tiles_adjacent
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:929
same_pos
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:938
real_map_distance
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:628
square_iterate
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:385
square_iterate_end
#define square_iterate_end
Definition map.h:388
map_move_cost
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
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
can_unit_transport
bool can_unit_transport(const struct unit *transporter, const struct unit *transported)
Definition movement.c:813
movement.h
SINGLE_MOVE
#define SINGLE_MOVE
Definition movement.h:24
MR_OK
@ MR_OK
Definition movement.h:33
MR_DEATH
@ MR_DEATH
Definition movement.h:34
pf_path_destroy
void pf_path_destroy(struct pf_path *path)
Definition path_finding.c:3411
pf_map_new
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
Definition path_finding.c:3182
pf_map_path
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
Definition path_finding.c:3235
pf_map_iter_path
struct pf_path * pf_map_iter_path(struct pf_map *pfm)
Definition path_finding.c:3337
pf_map_destroy
void pf_map_destroy(struct pf_map *pfm)
Definition path_finding.c:3206
pf_path_advance
bool pf_path_advance(struct pf_path *path, struct tile *ptile)
Definition path_finding.c:3475
path_finding.h
PF_IMPOSSIBLE_MC
#define PF_IMPOSSIBLE_MC
Definition path_finding.h:266
pf_move_scope
pf_move_scope
Definition path_finding.h:319
PF_MS_CITY
@ PF_MS_CITY
Definition path_finding.h:322
PF_MS_NATIVE
@ PF_MS_NATIVE
Definition path_finding.h:321
pf_map_positions_iterate_end
#define pf_map_positions_iterate_end
Definition path_finding.h:612
PF_TURN_FACTOR
#define PF_TURN_FACTOR
Definition path_finding.h:272
pf_map_tiles_iterate
#define pf_map_tiles_iterate(ARG_pfm, NAME_tile, COND_from_start)
Definition path_finding.h:561
pf_map_positions_iterate
#define pf_map_positions_iterate(ARG_pfm, NAME_pos, COND_from_start)
Definition path_finding.h:605
pf_map_tiles_iterate_end
#define pf_map_tiles_iterate_end
Definition path_finding.h:568
pft_fill_unit_parameter
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
pft_fill_unit_overlap_param
void pft_fill_unit_overlap_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:891
no_fights
enum tile_behavior no_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:509
no_intermediate_fights
enum tile_behavior no_intermediate_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:524
no_fights_or_unknown
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
pft_fill_amphibious_parameter
void pft_fill_amphibious_parameter(struct pft_amphibious *parameter)
Definition pf_tools.c:994
pf_tools.h
player_number
int player_number(const struct player *pplayer)
Definition player.c:828
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:886
is_barbarian
static bool is_barbarian(const struct player *pplayer)
Definition player.h:488
is_ai
#define is_ai(plr)
Definition player.h:234
FC_INFINITY
#define FC_INFINITY
Definition shared.h:36
MAX
#define MAX(x, y)
Definition shared.h:54
srv_log.h
UNIT_LOG
#define UNIT_LOG(loglevel, punit, msg,...)
Definition srv_log.h:98
adv_risk_cost
Definition advgoto.h:26
ai_plr
Definition aidata.h:71
ai_plr::passengers
int passengers
Definition aidata.h:78
ai_plr::stats
struct ai_plr::@267 stats
ai_plr::boats
int boats
Definition aidata.h:79
ai_plr::available_boats
int available_boats
Definition aidata.h:80
ai_type
Definition ai.h:50
city
Definition city.h:309
city::production
struct universal production
Definition city.h:382
city::tile
struct tile * tile
Definition city.h:311
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_map
Definition map_types.h:71
packet_game_info::turn
int turn
Definition packets_gen.h:241
pf_map
Definition path_finding.c:78
pf_parameter
Definition path_finding.h:357
pf_parameter::ignore_none_scopes
bool ignore_none_scopes
Definition path_finding.h:393
pf_parameter::get_TB
enum tile_behavior(* get_TB)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition path_finding.h:398
pf_parameter::owner
const struct player * owner
Definition path_finding.h:374
pf_parameter::get_zoc
bool(* get_zoc)(const struct player *pplayer, const struct tile *ptile, const struct civ_map *zmap)
Definition path_finding.h:430
pf_parameter::get_MC
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)
Definition path_finding.h:382
pf_parameter::get_EC
unsigned(* get_EC)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition path_finding.h:405
pf_parameter::utype
const struct unit_type * utype
Definition path_finding.h:373
pf_parameter::omniscience
bool omniscience
Definition path_finding.h:376
pf_path
Definition path_finding.h:344
pf_path::positions
struct pf_position * positions
Definition path_finding.h:346
pf_position::tile
struct tile * tile
Definition path_finding.h:328
pft_amphibious
Definition pf_tools.h:36
pft_amphibious::combined
struct pf_parameter combined
Definition pf_tools.h:42
pft_amphibious::sea
struct pf_parameter land sea
Definition pf_tools.h:38
player
Definition player.h:249
player::units
struct unit_list * units
Definition player.h:282
tile
Definition tile.h:49
tile::units
struct unit_list * units
Definition tile.h:57
unit_ai
Definition aiunit.h:32
unit_ai::done
bool done
Definition aiunit.h:44
unit_ai::ferryboat
int ferryboat
Definition aiunit.h:34
unit_ai::passenger
int passenger
Definition aiunit.h:35
unit_class
Definition unittype.h:136
unit_class::sea_move
enum move_level sea_move
Definition unittype.h:150
unit_class::adv
struct unit_class::@84 adv
unit_type_ai
Definition aiunit.h:50
unit_type_ai::ferry
bool ferry
Definition aiunit.h:52
unit_type
Definition unittype.h:481
unit_type::move_rate
int move_rate
Definition unittype.h:497
unit_type::hp
int hp
Definition unittype.h:505
unit_type::fuel
int fuel
Definition unittype.h:513
unit
Definition unit.h:138
unit::moves_left
int moves_left
Definition unit.h:150
unit::id
int id
Definition unit.h:145
unit::transporting
struct unit_list * transporting
Definition unit.h:184
unit::hp
int hp
Definition unit.h:151
unit::goto_tile
struct tile * goto_tile
Definition unit.h:155
universal::kind
enum universals_n kind
Definition fc_types.h:758
universal::value
universals_u value
Definition fc_types.h:757
world::map
struct civ_map map
Definition world_object.h:38
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
is_terrain_class_near_tile
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:600
is_ocean_tile
#define is_ocean_tile(ptile)
Definition terrain.h:289
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
known_type
known_type
Definition tile.h:34
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:42
universals_u::utype
const struct unit_type * utype
Definition fc_types.h:604
get_transporter_occupancy
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1763
unit_is_alive
bool unit_is_alive(int id)
Definition unit.c:2233
is_losing_hp
bool is_losing_hp(const struct unit *punit)
Definition unit.c:2208
can_unit_load
bool can_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:740
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2421
unit_is_cityfounder
bool unit_is_cityfounder(const struct unit *punit)
Definition unit.c:2619
get_transporter_capacity
int get_transporter_capacity(const struct unit *punit)
Definition unit.c:301
unit_transported
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2405
unit_has_orders
bool unit_has_orders(const struct unit *punit)
Definition unit.c:207
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
CHECK_UNIT
#define CHECK_UNIT(punit)
Definition unit.h:268
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
unit_activity_handling
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6176
unit_perform_action
bool unit_perform_action(struct player *pplayer, const int actor_id, const int target_id, const int sub_tgt_id_incoming, const char *name, const action_id action_type, const enum action_requester requester)
Definition unithand.c:3173
unithand.h
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_safe
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_list_iterate_safe_end
#define unit_list_iterate_safe_end
Definition unitlist.h:61
send_unit_info
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2797
wipe_unit
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2251
unit_transport_unload_send
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3327
unittools.h
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
unit_rule_name
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1639
utype_has_role
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:193
unit_class_get
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2546
unit_has_type_role
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:202
unit_has_type_flag
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:184
utype_ai_data
void * utype_ai_data(const struct unit_type *ptype, const struct ai_type *ai)
Definition unittype.c:2741
MOVE_NONE
@ MOVE_NONE
Definition unittype.h:131
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:604