Freeciv-3.2
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 "aiguard.h"
50#include "aitools.h"
51#include "daicity.h"
52#include "daidata.h"
53#include "daiplayer.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 ================= */
77/* Logging in ferry management functions */
78#define LOGLEVEL_FERRY LOG_DEBUG
79/* Logging in go_by_boat functions */
80#define LOGLEVEL_GOBYBOAT LOG_DEBUG
81/* Logging in find_ferry functions */
82#define LOGLEVEL_FINDFERRY LOG_DEBUG
83/* Extra consistency checks */
84#ifdef FREECIV_DEBUG
85#define LOGLEVEL_FERRY_STATS LOG_NORMAL
86#endif
87
88
89/* ========= managing statistics and boat/passenger assignments ======== */
90
91/**********************************************************************/
94void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
95{
96 /* def_ai_player_data() instead of dai_plr_data_get() is deliberate.
97 We are only initializing player data structures and dai_plr_data_get()
98 would try to use it uninitialized. We are only setting values to
99 data structure, not reading them, so we have no need for extra
100 arrangements dai_plr_data_get() would do compared to def_ai_player_data()
101 */
102 struct ai_plr *ai = def_ai_player_data(pplayer, ait);
103
104 ai->stats.passengers = 0;
105 ai->stats.boats = 0;
106 ai->stats.available_boats = 0;
107
108 unit_list_iterate(pplayer->units, punit) {
109 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
110
111 if (dai_is_ferry(punit, ait)) {
112 ai->stats.boats++;
113 if (unit_data->passenger == FERRY_AVAILABLE) {
115 }
116 }
117 if (unit_data->ferryboat == FERRY_WANTED) {
118 UNIT_LOG(LOG_DEBUG, punit, "wants a boat.");
119 ai->stats.passengers++;
120 }
122}
123
124/**********************************************************************/
127#ifdef LOGLEVEL_FERRY_STATS
128static void aiferry_print_stats(struct ai_type *ait, struct player *pplayer)
129{
130 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, 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",
137 unit_list_iterate(pplayer->units, punit) {
138 if (dai_is_ferry(punit, ait)) {
139 log_base(LOGLEVEL_FERRY_STATS, "#%d. %s[%d], psngr=%d", n,
141 def_ai_unit_data(punit, ait)->passenger);
142 n++;
143 }
145}
146#endif /* LOGLEVEL_FERRY_STATS */
147
148/**********************************************************************/
151bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
152{
153 struct unit_type_ai *utai = utype_ai_data(pferry, ait);
154
155 return utai->ferry;
156}
157
158/**********************************************************************/
161bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
162{
164}
165
166/**********************************************************************/
169void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
170{
171 if (dai_is_ferry(ferry, ait)) {
172 bool caller_closes;
173 struct player *pplayer = unit_owner(ferry);
174 struct unit_ai *unit_data = def_ai_unit_data(ferry, ait);
175 struct ai_plr *ai = dai_plr_data_get(ait, pplayer,
177
178 unit_data->passenger = FERRY_AVAILABLE;
179 ai->stats.boats++;
181
182 if (caller_closes) {
183 dai_data_phase_finished(ait, pplayer);
184 }
185 }
186}
187
188/**********************************************************************/
191void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry,
192 const struct unit_type *old)
193{
194 bool old_f = dai_is_ferry_type(old, ait);
195 bool new_f = dai_is_ferry(ferry, ait);
196
197 if (old_f && !new_f) {
198 struct ai_plr *ai = dai_plr_data_get(ait, unit_owner(ferry), 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) {
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++;
217 }
218}
219
220/**********************************************************************/
223void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
224{
225 /* Ignore virtual units. */
226 if (punit->id != 0 && is_ai_data_phase_open(ait, unit_owner(punit))) {
227 bool close_here;
228 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
229 struct player *pplayer = unit_owner(punit);
230 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, &close_here);
231
232 if (dai_is_ferry(punit, ait)) {
233 ai->stats.boats--;
234 if (unit_data->passenger == FERRY_AVAILABLE) {
236 }
237 } else {
238 /* Not a ferry */
239 if (unit_data->ferryboat > 0) {
241 }
242 }
243
244 if (close_here) {
245 dai_data_phase_finished(ait, pplayer);
246 }
247 }
248}
249
250/**********************************************************************/
253void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
254{
255 struct unit_ai *unit_data = def_ai_unit_data(punit, ait);
256
257 if (unit_data->ferryboat == FERRY_WANTED) {
258 struct player *pplayer = unit_owner(punit);
259
260 if (is_ai_data_phase_open(ait, pplayer)) {
261 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, 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 * Subtract virtual units or already counted */
297 if ((punit->id == 0) ||
298 ((ai->stats.passengers > 0) &&
299 (unit_data->ferryboat == FERRY_WANTED))) {
301 }
302
303 /* Now add ourselves to the list of potential passengers */
304 ai->stats.passengers++;
305 UNIT_LOG(LOG_DEBUG, punit, "requests a boat (total passengers=%d).",
306 ai->stats.passengers);
307 unit_data->ferryboat = FERRY_WANTED;
308
309 /* Lastly, wait for ferry. */
310 unit_data->done = TRUE;
311}
312
313/**********************************************************************/
316static void aiferry_psngr_meet_boat(struct ai_type *ait,
317 struct unit *punit, struct unit *pferry)
318{
321
323
324 /* First delete the unit from the list of passengers and
325 * release its previous ferry */
327
328 /* If ferry was available, update the stats */
329 if (ferry_data->passenger == FERRY_AVAILABLE) {
331 }
332
333 /* Exchange the phone numbers */
335 ferry_data->passenger = punit->id;
336}
337
338/**********************************************************************/
341static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
342{
344
345 if (ferry_data->passenger != FERRY_AVAILABLE) {
347 ferry_data->passenger = FERRY_AVAILABLE;
348 }
349}
350
351/**********************************************************************/
355int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
356{
357 struct ai_plr *ai = dai_plr_data_get(ait, pplayer, 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 }
370
371 if (boats != ai->stats.available_boats) {
372 log_error("Player[%d] in turn %d: boats miscounted.",
373 player_number(pplayer), game.info.turn);
374 aiferry_print_stats(ait, pplayer);
375 }
376#endif /* LOGLEVEL_FERRY_STATS */
377
378 return ai->stats.available_boats;
379}
380
381/* ================== functions to find a boat ========================= */
382
383/**********************************************************************/
396static unsigned combined_land_sea_move(const struct tile *src_tile,
398 const struct tile *tgt_tile,
400 const struct pf_parameter *param)
401{
402 unsigned move_cost;
403
404 if (!((PF_MS_NATIVE | PF_MS_CITY) & dst_scope)) {
405 /* Any-to-Sea */
406 move_cost = 0;
407 } else if (!((PF_MS_NATIVE | PF_MS_CITY) & src_scope)) {
408 /* Sea-to-Land */
409 move_cost = PF_IMPOSSIBLE_MC;
410 } else {
411 /* Land-to-Land */
412 move_cost = map_move_cost(&(wld.map), param->owner, param->utype,
413 src_tile, tgt_tile);
414 }
415
416 return move_cost;
417}
418
419/**********************************************************************/
423static unsigned sea_move(const struct tile *ptile, enum known_type known,
424 const struct pf_parameter *param)
425{
426 if (is_ocean_tile(ptile)) {
427 /* Approximately TURN_FACTOR / average ferry move rate
428 * we can pass a better guess of the move rate through param->data
429 * but we don't know which boat we will find out there */
430 return SINGLE_MOVE * PF_TURN_FACTOR / 12;
431 } else {
432 return 0;
433 }
434}
435
436/**********************************************************************/
440bool is_boat_free(struct ai_type *ait, struct unit *boat,
441 struct unit *punit, int cap)
442{
443 /* - Only transporters capable of transporting this unit are eligible.
444 * - Units with orders are skipped (the AI doesn't control units with
445 * orders).
446 * - Only boats that we own are eligible.
447 * - Only available boats or boats that are already dedicated to this unit
448 * are eligible.
449 * - Only boats with enough remaining capacity are eligible.
450 * - Only units that can travel at sea are eligible.
451 * - Units that require fuel, except "Coast" ones, or lose hitpoints are
452 * not eligible.
453 */
455 const struct unit_type *ferry_type = unit_type_get(boat);
456 struct unit_ai *boat_data = def_ai_unit_data(boat, ait);
457
461 && (boat_data->passenger == FERRY_AVAILABLE
462 || boat_data->passenger == punit->id)
465 && ferry_class->adv.sea_move != MOVE_NONE
466 && !is_losing_hp(boat)
467 && (ferry_type->fuel == 0 || utype_has_flag(ferry_type, UTYF_COAST)));
468}
469
470/**********************************************************************/
473bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
474{
475 if (!unit_transported(punit)) {
476 /* Not even in boat */
477 return FALSE;
478 }
479
482 == punit->id) {
483 return TRUE;
484 }
485
486 return FALSE;
487}
488
489/**********************************************************************/
497int aiferry_find_boat(struct ai_type *ait, struct unit *punit,
498 int cap, struct pf_path **path)
499{
501 int best_id = 0;
502 struct pf_parameter param;
503 struct pf_map *search_map;
504 struct player *pplayer = unit_owner(punit);
505 const struct civ_map *nmap = &(wld.map);
506
507 /* currently assigned ferry */
508 int ferryboat = def_ai_unit_data(punit, ait)->ferryboat;
509
510 /* We may end calling pf_destroy_path for *path if it's not 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
531 param.omniscience = !has_handicap(pplayer, H_MAP);
533 param.get_EC = sea_move;
536
537 search_map = pf_map_new(&param);
538
540 /* Should this be !can_unit_exist_at_tile() instead of is_ocean() some day?
541 * That would allow special units to wade in shallow coast waters to meet
542 * ferry where deep sea starts. */
543 int radius = (is_ocean_tile(pos.tile) ? 1 : 0);
544
545 if (pos.turn + pos.total_EC/PF_TURN_FACTOR > best_turns) {
546 /* Won't find anything better */
547 /* FIXME: This condition is somewhat dodgy */
548 break;
549 }
550
551 square_iterate(&(wld.map), pos.tile, radius, ptile) {
552 unit_list_iterate(ptile->units, aunit) {
553 if (is_boat_free(ait, aunit, punit, cap)) {
554 /* Turns for the unit to get to rendezvous pnt */
555 int u_turns = pos.turn;
556 /* Turns for the boat to get to the rendezvous pnt */
557 int f_turns = ((pos.total_EC / PF_TURN_FACTOR * 16
558 - aunit->moves_left)
560 int turns = MAX(u_turns, f_turns);
561
562 if (turns < best_turns) {
564 "Found a potential boat %s[%d](%d,%d)(moves left: %d)",
566 TILE_XY(unit_tile(aunit)), aunit->moves_left);
567 if (path) {
568 if (*path) {
569 pf_path_destroy(*path);
570 }
572 }
573 best_turns = turns;
574 best_id = aunit->id;
575 }
576 }
581
582 return best_id;
583}
584
585/**********************************************************************/
588static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit,
589 int cap)
590{
591 UNIT_LOG(LOGLEVEL_FINDFERRY, punit, "asked find_ferry_nearby for a boat");
592
593 square_iterate(&(wld.map), unit_tile(punit), 1, ptile) {
594 unit_list_iterate(ptile->units, aunit) {
595 if (is_boat_free(ait, aunit, punit, cap)) {
596 return aunit->id;
597 }
600
601 return 0;
602}
603
604
605/* ============================= go by boat ============================== */
606
607/**********************************************************************/
612static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
613{
614 struct player *ferry_owner = unit_owner(ferry);
615
617 if (unit_transport_get(aunit) == ferry) {
620
621 if (unit_owner(aunit) == ferry_owner) {
622 /* Move it only if it's our own. */
624 }
625 }
627}
628
629/**********************************************************************/
637 struct unit *ferry,
638 struct unit *passenger,
639 struct tile *ptile,
640 struct pft_amphibious *parameter)
641{
642 bool alive = TRUE;
643 struct pf_map *pfm;
644 struct pf_path *path;
645 int pass_id = passenger->id;
646
649 fc_assert_ret_val(unit_tile(ferry) == unit_tile(passenger), TRUE);
650
651 ptile = immediate_destination(passenger, ptile);
652
653 if (same_pos(unit_tile(passenger), ptile)) {
654 /* Not an error; sometimes immediate_destination instructs the unit
655 * to stay here. For example, to refuel.*/
656 send_unit_info(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)",
688 /* Land leg */
689 alive = adv_follow_path(passenger, path, ptile);
690 /* Movement of the passenger outside the ferry can cause also
691 * ferry to die. That has happened at least when passenger
692 * destroyed city cutting the civ1-style channel (cities in
693 * a chain) ferry was in. */
694 if (unit_is_alive(ferry_id) && 0 < ferry->moves_left
695 && (!alive || unit_tile(ferry) != unit_tile(passenger))) {
696 /* The passenger is no longer on the ferry,
697 * and the ferry can still act.
698 * Give a chance for another passenger to take command
699 * of the ferry.
700 */
701 UNIT_LOG(LOG_DEBUG, ferry, "Activating passengers");
702 dai_activate_passengers(ait, ferry);
703
704 /* It is theoretically possible passenger died here due to
705 * autoattack against another passing unit at its location. */
707 }
708 }
709 /* else at sea */
710 } else if (alive) {
711 /* Arrived all the way to the destination by boat. Deboard. */
712 if (can_unit_exist_at_tile(parameter->land.map, passenger, ptile)) {
714 }
715 }
716 /* else dead */
717 } else {
718 /* Not always an error; enemy units might block all paths. */
719 UNIT_LOG(LOG_DEBUG, passenger, "no path to destination");
720 }
721
722 pf_path_destroy(path);
724
725 return alive;
726}
727
728/**********************************************************************/
732bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry,
733 struct unit *passenger, struct tile *ptile)
734{
735 struct pft_amphibious parameter;
738
739 dai_fill_unit_param(ait, &parameter.land, &land_risk_cost, passenger, ptile);
740 if (parameter.land.get_TB != no_fights) {
741 /* Use the ferry to go around danger areas: */
742 parameter.land.get_TB = no_intermediate_fights;
743 }
744 dai_fill_unit_param(ait, &parameter.sea, &sea_risk_cost, ferry, ptile);
746
747 /* Move as far along the path to the destination as we can;
748 * that is, ignore the presence of enemy units when computing the
749 * path */
750 parameter.combined.get_zoc = 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
782 struct pf_path *path_to_ferry = NULL;
783
785 if (boatid <= 0) {
787 "in ai_gothere cannot find any boats.");
788 def_ai_unit_data(punit, ait)->done = TRUE; /* Nothing to do */
789 return FALSE;
790 }
791
792 ferryboat = game_unit_by_number(boatid);
793 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "found boat[%d](%d,%d), going there",
794 boatid, TILE_XY(unit_tile(ferryboat)));
795 /* The path can be amphibious so we will stop at the coast.
796 * It might not lead _onto_ the boat. */
798 /* Died. */
800 return FALSE;
801 }
803 }
804
806 /* Still haven't reached the coast */
807 return FALSE;
808 }
809
810 /* We are on the coast, look around for a boat */
812 if (boatid <= 0) {
813 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "requesting a boat.");
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
841 enum gen_action act_id = action_id(paction);
842
844 ferryboat))) {
845 if (unit_perform_action(pplayer,
846 punit->id, ferryboat->id, 0, "",
847 act_id, ACT_REQ_PLAYER)) {
849 break;
850 }
851 }
853
854 if (!board_success) {
855 /* No action enabler active.
856 * TODO: Try to predict this failure so that the units wouldn't
857 * waste turns to travel to the rendezvous point. */
858 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "boarding boat[%d](%d,%d) not enabled",
859 ferryboat->id, TILE_XY(unit_tile(ferryboat)));
860
861 return FALSE;
862 }
863
865 }
866
867 if (unit_transported(punit)) {
868 /* We are on a boat, ride it! */
869 struct unit *ferryboat = unit_transport_get(punit);
870
871 /* Check if we are the passenger-in-charge */
872 if (is_boat_free(ait, ferryboat, punit, 0)) {
873 struct unit *bodyguard = aiguard_guard_of(ait, punit);
874
876 "got boat[%d](moves left: %d), going (%d,%d)",
877 ferryboat->id, ferryboat->moves_left, TILE_XY(dest_tile));
878 aiferry_psngr_meet_boat(ait, punit, ferryboat);
879
880 punit->goto_tile = dest_tile;
881 /* Grab bodyguard */
882 if (bodyguard
883 && !same_pos(unit_tile(punit), unit_tile(bodyguard))) {
884 if (!goto_is_sane(bodyguard, unit_tile(punit))
885 || !dai_unit_goto(ait, bodyguard, unit_tile(punit))) {
886 /* Bodyguard can't get there or died en route */
888 bodyguard = NULL;
889 } else if (bodyguard->moves_left <= 0) {
890 /* Wait for me, I'm cooooming!! */
891 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "waiting for bodyguard");
893 return FALSE;
894 } else {
895 /* Crap bodyguard. Got stuck somewhere. Ditch it! */
896 UNIT_LOG(LOGLEVEL_GOBYBOAT, punit, "ditching useless bodyguard");
898 dai_unit_new_task(ait, bodyguard, AIUNIT_NONE, NULL);
899 bodyguard = NULL;
900 }
901 }
902 if (bodyguard) {
904
905 /* Bodyguard either uses the same boat or none at all. */
907 enum gen_action act_id = action_id(paction);
908
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 }
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 */
928 } else {
929 /* We are in still transit */
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),
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);
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
985 && (unit_data->ferryboat == FERRY_WANTED
986 || unit_data->ferryboat == pferry->id)) {
988 "Found a potential cargo %s[%d](%d,%d), going there",
990 aunit->id,
992 pferry->goto_tile = unit_tile(aunit);
993 /* Exchange phone numbers */
996 return TRUE;
997 }
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 */
1004 "AI Passengers counting reported false positive %d", passengers);
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 */
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
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
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
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
1081
1082 UNIT_LOG(LOGLEVEL_FERRY, pferry, "%s is NOT suitable: "
1083 "has another ferry",
1084 city_name_get(pcity));
1086 break;
1087 }
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 }
1100
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
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));
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) {
1138 return;
1139 }
1140
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
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 */
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 }
1182
1183 if (candidate) {
1185 "appointed %s[%d] our passenger-in-charge",
1187 candidate->id);
1188 bossid = candidate->id;
1190 }
1191 }
1192
1193 if (unit_data->passenger > 0) {
1195
1197
1200 /* Temporary hack: settlers 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]",
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 }
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
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
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 */
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);
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)) {
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 */
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");
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) {
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;
1318 }
1319 }
1320
1321 return;
1322}
bool action_prob_possible(const struct act_prob probability)
Definition actions.c:5821
struct act_prob action_prob_vs_unit(const struct civ_map *nmap, const struct unit *actor_unit, const action_id act_id, const struct unit *target_unit)
Definition actions.c:5067
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:481
#define action_by_result_iterate_end
Definition actions.h:485
#define action_id(_act_)
Definition actions.h:661
bool adv_follow_path(struct unit *punit, struct pf_path *path, struct tile *ptile)
Definition advgoto.c:47
bool adv_unit_execute_path(struct unit *punit, struct pf_path *path)
Definition advgoto.c:82
static bool aiferry_findcargo(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:953
static void dai_activate_passengers(struct ai_type *ait, struct unit *ferry)
Definition aiferry.c:610
#define FERRY_WANTED
Definition aiferry.c:69
bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, struct unit *punit, struct tile *dest_tile, bool with_bodyguard)
Definition aiferry.c:764
int aiferry_find_boat(struct ai_type *ait, struct unit *punit, int cap, struct pf_path **path)
Definition aiferry.c:495
#define FERRY_NONE
Definition aiferry.c:70
void dai_manage_ferryboat(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition aiferry.c:1113
bool is_boat_free(struct ai_type *ait, struct unit *boat, struct unit *punit, int cap)
Definition aiferry.c:438
bool dai_is_ferry_type(const struct unit_type *pferry, struct ai_type *ait)
Definition aiferry.c:149
void aiferry_init_stats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:92
static bool aiferry_find_interested_city(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:1019
#define LOGLEVEL_FINDFERRY
Definition aiferry.c:80
void dai_ferry_lost(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:221
void dai_ferry_transformed(struct ai_type *ait, struct unit *ferry, const struct unit_type *old)
Definition aiferry.c:189
bool aiferry_goto_amphibious(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile)
Definition aiferry.c:730
bool is_boss_of_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:471
static void aiferry_psngr_meet_boat(struct ai_type *ait, struct unit *punit, struct unit *pferry)
Definition aiferry.c:314
static void aiferry_make_available(struct ai_type *ait, struct unit *pferry)
Definition aiferry.c:339
static int aiferry_find_boat_nearby(struct ai_type *ait, struct unit *punit, int cap)
Definition aiferry.c:586
static unsigned sea_move(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition aiferry.c:421
int aiferry_avail_boats(struct ai_type *ait, struct player *pplayer)
Definition aiferry.c:353
#define LOGLEVEL_GOBYBOAT
Definition aiferry.c:78
bool dai_amphibious_goto_constrained(struct ai_type *ait, struct unit *ferry, struct unit *passenger, struct tile *ptile, struct pft_amphibious *parameter)
Definition aiferry.c:634
bool dai_is_ferry(struct unit *pferry, struct ai_type *ait)
Definition aiferry.c:159
#define FERRY_ABANDON_BOSS
Definition aiferry.c:64
void dai_ferry_init_ferry(struct ai_type *ait, struct unit *ferry)
Definition aiferry.c:167
void aiferry_clear_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:251
static unsigned combined_land_sea_move(const struct tile *src_tile, enum pf_move_scope src_scope, const struct tile *tgt_tile, enum pf_move_scope dst_scope, const struct pf_parameter *param)
Definition aiferry.c:394
#define FERRY_AVAILABLE
Definition aiferry.c:63
static void aiferry_request_boat(struct ai_type *ait, struct unit *punit)
Definition aiferry.c:288
#define LOGLEVEL_FERRY
Definition aiferry.c:76
void aiguard_request_guard(struct ai_type *ait, struct unit *punit)
Definition aiguard.c:227
struct unit * aiguard_guard_of(struct ai_type *ait, struct unit *charge)
Definition aiguard.c:269
void dai_fill_unit_param(struct ai_type *ait, struct pf_parameter *parameter, struct adv_risk_cost *risk_cost, struct unit *punit, struct tile *ptile)
Definition aitools.c:470
bool goto_is_sane(struct unit *punit, struct tile *ptile)
Definition aitools.c:430
struct tile * immediate_destination(struct unit *punit, struct tile *dest_tile)
Definition aitools.c:303
bool dai_unit_goto(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:606
void dai_log_path(struct unit *punit, struct pf_path *path, struct pf_parameter *parameter)
Definition aitools.c:357
void dai_unit_new_task(struct ai_type *ait, struct unit *punit, enum ai_unit_task task, struct tile *ptile)
Definition aitools.c:644
bool dai_unit_move(struct ai_type *ait, struct unit *punit, struct tile *ptile)
Definition aitools.c:1085
#define n
Definition astring.c:77
enum unit_move_result manage_auto_explorer(struct unit *punit)
const char * city_name_get(const struct city *pcity)
Definition city.c:1137
int city_production_turns_to_build(const struct city *pcity, bool include_shield_stock)
Definition city.c:820
#define city_owner(_pcity_)
Definition city.h:563
char * incite_cost
Definition comments.c:75
bool is_ai_data_phase_open(struct ai_type *ait, struct player *pplayer)
Definition daidata.c:132
struct ai_plr * dai_plr_data_get(struct ai_type *ait, struct player *pplayer, bool *caller_closes)
Definition daidata.c:308
void dai_data_phase_finished(struct ai_type *ait, struct player *pplayer)
Definition daidata.c:285
static struct ai_plr * def_ai_player_data(const struct player *pplayer, struct ai_type *deftype)
Definition daiplayer.h:54
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition daiplayer.h:42
static struct unit_ai * def_ai_unit_data(const struct unit *punit, struct ai_type *deftype)
Definition daiplayer.h:48
void dai_manage_military(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition daiunit.c:2499
void dai_manage_unit(struct ai_type *ait, struct player *pplayer, struct unit *punit)
Definition daiunit.c:2654
struct city * find_nearest_safe_city(struct unit *punit)
Definition daiunit.c:1632
@ AIUNIT_NONE
Definition daiunit.h:27
@ AIUNIT_ESCORT
Definition daiunit.h:28
#define IS_ATTACKER(ptype)
Definition daiunit.h:70
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
static struct tile * pos
Definition finddlg.c:53
bool has_handicap(const struct player *pplayer, enum handicap_type htype)
Definition handicaps.c:66
@ H_MAP
Definition handicaps.h:28
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define log_base(level, message,...)
Definition log.h:94
@ LOG_DEBUG
Definition log.h:34
#define log_error(message,...)
Definition log.h:103
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:931
bool same_pos(const struct tile *tile1, const struct tile *tile2)
Definition map.c:940
int real_map_distance(const struct tile *tile0, const struct tile *tile1)
Definition map.c:630
#define square_iterate(nmap, center_tile, radius, tile_itr)
Definition map.h:391
#define square_iterate_end
Definition map.h:394
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:305
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:319
bool can_unit_transport(const struct unit *transporter, const struct unit *transported)
Definition movement.c:855
#define SINGLE_MOVE
Definition movement.h:26
@ MR_OK
Definition movement.h:35
@ MR_DEATH
Definition movement.h:36
void pf_path_destroy(struct pf_path *path)
struct pf_map * pf_map_new(const struct pf_parameter *parameter)
struct pf_path * pf_map_path(struct pf_map *pfm, struct tile *ptile)
struct pf_path * pf_map_iter_path(struct pf_map *pfm)
void pf_map_destroy(struct pf_map *pfm)
bool pf_path_advance(struct pf_path *path, struct tile *ptile)
#define PF_IMPOSSIBLE_MC
pf_move_scope
@ PF_MS_CITY
@ PF_MS_NATIVE
#define pf_map_positions_iterate_end
#define PF_TURN_FACTOR
#define pf_map_tiles_iterate(ARG_pfm, NAME_tile, COND_from_start)
#define pf_map_positions_iterate(ARG_pfm, NAME_pos, COND_from_start)
#define pf_map_tiles_iterate_end
void pft_fill_unit_parameter(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:840
void pft_fill_unit_overlap_param(struct pf_parameter *parameter, const struct civ_map *nmap, const struct unit *punit)
Definition pf_tools.c:891
enum tile_behavior no_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:509
enum tile_behavior no_intermediate_fights(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:524
enum tile_behavior no_fights_or_unknown(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
Definition pf_tools.c:493
void pft_fill_amphibious_parameter(struct pft_amphibious *parameter)
Definition pf_tools.c:994
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
static bool is_barbarian(const struct player *pplayer)
Definition player.h:489
#define is_ai(plr)
Definition player.h:230
#define FC_INFINITY
Definition shared.h:36
#define MAX(x, y)
Definition shared.h:54
#define UNIT_LOG(loglevel, punit, msg,...)
Definition srv_log.h:98
int passengers
Definition daidata.h:78
struct ai_plr::@253 stats
int boats
Definition daidata.h:79
int available_boats
Definition daidata.h:80
Definition ai.h:50
Definition city.h:320
struct universal production
Definition city.h:396
struct tile * tile
Definition city.h:322
struct packet_game_info info
Definition game.h:89
bool ignore_none_scopes
enum tile_behavior(* get_TB)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
const struct player * owner
bool(* get_zoc)(const struct player *pplayer, const struct tile *ptile, const struct civ_map *zmap)
unsigned(* get_MC)(const struct tile *from_tile, enum pf_move_scope src_move_scope, const struct tile *to_tile, enum pf_move_scope dst_move_scope, const struct pf_parameter *param)
unsigned(* get_EC)(const struct tile *ptile, enum known_type known, const struct pf_parameter *param)
const struct unit_type * utype
struct pf_position * positions
struct tile * tile
struct pf_parameter combined
Definition pf_tools.h:42
struct pf_parameter land sea
Definition pf_tools.h:38
struct unit_list * units
Definition player.h:280
Definition tile.h:50
struct unit_list * units
Definition tile.h:58
bool done
Definition daiunit.h:44
int ferryboat
Definition daiunit.h:34
int passenger
Definition daiunit.h:35
bool ferry
Definition daiunit.h:52
int move_rate
Definition unittype.h:517
Definition unit.h:138
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
struct unit_list * transporting
Definition unit.h:184
int hp
Definition unit.h:151
struct tile * tile
Definition unit.h:140
struct tile * goto_tile
Definition unit.h:155
enum universals_n kind
Definition fc_types.h:902
universals_u value
Definition fc_types.h:901
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
bool is_terrain_class_near_tile(const struct civ_map *nmap, const struct tile *ptile, enum terrain_class tclass)
Definition terrain.c:612
#define is_ocean_tile(ptile)
Definition terrain.h:303
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
known_type
Definition tile.h:35
#define TILE_XY(ptile)
Definition tile.h:43
const struct unit_type * utype
Definition fc_types.h:721
int get_transporter_occupancy(const struct unit *ptrans)
Definition unit.c:1783
bool unit_is_alive(int id)
Definition unit.c:2253
bool is_losing_hp(const struct unit *punit)
Definition unit.c:2228
bool can_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:725
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2441
bool unit_is_cityfounder(const struct unit *punit)
Definition unit.c:2641
int get_transporter_capacity(const struct unit *punit)
Definition unit.c:297
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2425
bool unit_has_orders(const struct unit *punit)
Definition unit.c:202
#define unit_tile(_pu)
Definition unit.h:397
#define CHECK_UNIT(punit)
Definition unit.h:270
#define unit_owner(_pu)
Definition unit.h:396
bool unit_activity_handling(struct unit *punit, enum unit_activity new_activity)
Definition unithand.c:6471
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:3313
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_safe(unitlist, _unit)
Definition unitlist.h:39
#define unit_list_iterate_end
Definition unitlist.h:33
#define unit_list_iterate_safe_end
Definition unitlist.h:61
void send_unit_info(struct conn_list *dest, struct unit *punit)
Definition unittools.c:2722
void wipe_unit(struct unit *punit, enum unit_loss_reason reason, struct player *killer)
Definition unittools.c:2131
void unit_transport_unload_send(struct unit *punit)
Definition unittools.c:3281
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
const char * unit_rule_name(const struct unit *punit)
Definition unittype.c:1587
bool utype_has_role(const struct unit_type *punittype, int role)
Definition unittype.c:199
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2499
bool unit_has_type_role(const struct unit *punit, enum unit_role_id role)
Definition unittype.c:208
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:190
void * utype_ai_data(const struct unit_type *ptype, const struct ai_type *ai)
Definition unittype.c:2739
@ MOVE_NONE
Definition unittype.h:144
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617