Freeciv-3.3: /fast/freeciv/nightly/main/ai/default/aiferry.c Source File

Freeciv-3.3

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