Freeciv-3.2: /fast/freeciv/nightly/S3_2/common/movement.c Source File

Freeciv-3.2

Loading...
Searching...
No Matches
movement.c
Go to the documentation of this file.
1/****************************************************************************
2 Freeciv - Copyright (C) 2004 - The Freeciv Team
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 "bitvector.h"
20#include "fcintl.h"
21#include "log.h"
22#include "shared.h"
23#include "support.h"
24
25/* common */
26#include "astring.h"
27#include "base.h"
28#include "effects.h"
29#include "fc_types.h"
30#include "game.h"
31#include "map.h"
32#include "road.h"
33#include "unit.h"
34#include "unitlist.h"
35#include "unittype.h"
36#include "terrain.h"
37
38#include "movement.h"
39
40/************************************************************************/
47 int utype_move_rate(const struct unit_type *utype, const struct tile *ptile,
48 const struct player *pplayer, int veteran_level,
49 int hitpoints)
50{
51 const struct unit_class *uclass;
52 const struct veteran_level *vlevel;
53 int base_move_rate, move_rate;
54 int min_speed;
55
56 fc_assert_ret_val(NULL != utype, 0);
57 fc_assert_ret_val(NULL != pplayer, 0);
58 vlevel = utype_veteran_level(utype, veteran_level);
59 fc_assert_ret_val(NULL != vlevel, 0);
60 uclass = utype_class(utype);
61
62 base_move_rate = utype->move_rate + vlevel->move_bonus;
63 move_rate = base_move_rate;
64
65 if (uclass_has_flag(uclass, UCF_DAMAGE_SLOWS)) {
66 /* Scale the MP based on how many HP the unit has. */
67 move_rate = (move_rate * hitpoints) / utype->hp;
68 }
69
70 /* Add on effects bonus (Magellan's Expedition, Lighthouse,
71 * Nuclear Power). */
72 move_rate += (get_unittype_bonus(pplayer, ptile, utype, NULL,
73 EFT_MOVE_BONUS)
74 * SINGLE_MOVE);
75
76 /* Don't let the move_rate be less than min_speed unless the base_move_rate is
77 * also less than min_speed. */
78 min_speed = MIN(uclass->min_speed, base_move_rate);
79 if (move_rate < min_speed) {
80 move_rate = min_speed;
81 }
82
83 return move_rate;
84}
85
86/************************************************************************/
90 int unit_move_rate(const struct unit *punit)
91{
92 fc_assert_ret_val(NULL != punit, 0);
93
94 return utype_move_rate(unit_type_get(punit), unit_tile(punit),
95 unit_owner(punit), punit->veteran, punit->hp);
96}
97
98/************************************************************************/
105 int utype_unknown_move_cost(const struct unit_type *utype)
106{
107 const struct unit_class *uclass = utype_class(utype);
108 int move_cost;
109 int worst_effect_mc;
110
111 if (!uclass_has_flag(uclass, UCF_TERRAIN_SPEED)) {
112 /* Unit is not subject to terrain movement costs. */
113 move_cost = SINGLE_MOVE;
114 } else if (utype_has_flag(utype, UTYF_IGTER)) {
115 /* All terrain movement costs are equal! */
116 move_cost = MOVE_COST_IGTER;
117 } else {
118 /* Unit is subject to terrain movement costs. */
119 move_cost = 1; /* Arbitrary minimum. */
120 terrain_type_iterate(pterrain) {
121 if (is_native_to_class(uclass, pterrain, NULL)
122 && pterrain->movement_cost > move_cost) {
123 /* Exact movement cost matters only if we can enter
124 * the tile. */
125 move_cost = pterrain->movement_cost;
126 }
127 } terrain_type_iterate_end;
128 move_cost *= SINGLE_MOVE; /* Real value. */
129 }
130
131 /* Move cost from effects. */
132 worst_effect_mc = 0;
133 action_by_result_iterate(paction, ACTRES_UNIT_MOVE) {
134 struct universal req_pattern[] = {
135 { .kind = VUT_ACTION, .value.action = paction },
136 { .kind = VUT_UTYPE, .value.utype = utype },
137 };
138 int max_effect_mc;
139
140 if (!utype_can_do_action(utype, action_id(paction))) {
141 /* Not relevant. */
142 continue;
143 }
144
145 max_effect_mc = effect_cumulative_max(EFT_ACTION_SUCCESS_MOVE_COST,
146 req_pattern, ARRAY_SIZE(req_pattern));
147
148 if (max_effect_mc > worst_effect_mc) {
149 worst_effect_mc = max_effect_mc;
150 }
151 } action_by_result_iterate_end;
152 move_cost += worst_effect_mc;
153
154 /* Let's see if we can cross over all terrain types, else apply a malus.
155 * We want units that may encounter unsuitable terrain explore less.
156 * N.B.: We don't take in account terrain no unit can enter here. */
157 terrain_type_iterate(pterrain) {
158 if (BV_ISSET_ANY(pterrain->native_to)
159 && !is_native_to_class(uclass, pterrain, NULL)) {
160 /* Units that may encounter unsuitable terrain explore less. */
161 move_cost *= 2;
162 break;
163 }
164 } terrain_type_iterate_end;
165
166 return move_cost;
167}
168
169/************************************************************************/
174 bool unit_can_defend_here(const struct civ_map *nmap, const struct unit *punit)
175{
176 struct unit *ptrans = unit_transport_get(punit);
177
178 if (ptrans == NULL) {
179 /* FIXME: Redundant check; if unit is in the tile without transport
180 * it's known to be able to exist there. */
181 return can_unit_exist_at_tile(nmap, punit, unit_tile(punit));
182 }
183
184 switch (unit_type_get(punit)->tp_defense) {
185 case TDT_BLOCKED:
186 return FALSE;
187 case TDT_ALIGHT:
188 return can_unit_exist_at_tile(nmap, punit, unit_tile(punit))
189 && can_unit_deboard_or_be_unloaded(punit, ptrans);
190 case TDT_ALWAYS:
191 return TRUE;
192 }
193
194 fc_assert(FALSE);
195
196 return FALSE;
197}
198
199/************************************************************************/
204 bool can_attack_non_native_hard_reqs(const struct unit_type *utype)
205{
206 return uclass_has_flag(utype_class(utype), UCF_ATTACK_NON_NATIVE)
207 && !utype_has_flag(utype, UTYF_ONLY_NATIVE_ATTACK);
208}
209
210/************************************************************************/
214 bool can_attack_non_native(const struct unit_type *utype)
215{
216 return can_attack_non_native_hard_reqs(utype)
217 && (utype_can_do_action_result(utype, ACTRES_ATTACK)
218 || utype_can_do_action_result(utype, ACTRES_BOMBARD)
219 || utype_can_do_action_result(utype, ACTRES_WIPE_UNITS)
220 || utype_can_do_action_result(utype, ACTRES_NUKE_UNITS));
221}
222
223/************************************************************************/
227 bool can_attack_from_non_native(const struct unit_type *utype)
228{
229 return (utype_can_do_action_result_when_ustate(utype, ACTRES_ATTACK,
230 USP_NATIVE_TILE, FALSE)
231 || utype_can_do_action_result_when_ustate(utype,
232 ACTRES_WIPE_UNITS,
233 USP_LIVABLE_TILE, FALSE)
234 || utype_can_do_action_result_when_ustate(utype,
235 ACTRES_CONQUER_CITY,
236 USP_LIVABLE_TILE,
237 FALSE));
238}
239
240/************************************************************************/
243 bool is_city_channel_tile(const struct civ_map *nmap,
244 const struct unit_class *punitclass,
245 const struct tile *ptile,
246 const struct tile *pexclude)
247{
248 struct dbv tile_processed;
249 struct tile_list *process_queue = tile_list_new();
250 bool found = FALSE;
251
252 dbv_init(&tile_processed, map_num_tiles());
253 for (;;) {
254 dbv_set(&tile_processed, tile_index(ptile));
255 adjc_iterate(nmap, ptile, piter) {
256 if (dbv_isset(&tile_processed, tile_index(piter))) {
257 continue;
258 } else if (piter != pexclude
259 && is_native_to_class(punitclass, tile_terrain(piter),
260 tile_extras(piter))) {
261 found = TRUE;
262 break;
263 } else if (piter != pexclude
264 && NULL != tile_city(piter)) {
265 tile_list_append(process_queue, piter);
266 } else {
267 dbv_set(&tile_processed, tile_index(piter));
268 }
269 } adjc_iterate_end;
270
271 if (found || 0 == tile_list_size(process_queue)) {
272 break; /* No more tile to process. */
273 } else {
274 ptile = tile_list_front(process_queue);
275 tile_list_pop_front(process_queue);
276 }
277 }
278
279 dbv_free(&tile_processed);
280 tile_list_destroy(process_queue);
281
282 return found;
283}
284
285/************************************************************************/
290 bool can_exist_at_tile(const struct civ_map *nmap,
291 const struct unit_type *utype,
292 const struct tile *ptile)
293{
294 /* Cities are safe havens except for units in the middle of non-native
295 * terrain. This can happen if adjacent terrain is changed after unit
296 * arrived to city. */
297 if (NULL != tile_city(ptile)
298 && (uclass_has_flag(utype_class(utype), UCF_BUILD_ANYWHERE)
299 || is_native_near_tile(nmap, utype_class(utype), ptile)
300 || (1 == game.info.citymindist
301 && is_city_channel_tile(nmap, utype_class(utype), ptile, NULL)))) {
302 return TRUE;
303 }
304
305 /* UTYF_COAST_STRICT unit cannot exist in an ocean tile without access to land. */
306 if (utype_has_flag(utype, UTYF_COAST_STRICT)
307 && !is_safe_ocean(nmap, ptile)) {
308 return FALSE;
309 }
310
311 return is_native_tile(utype, ptile);
312}
313
314/************************************************************************/
319 bool can_unit_exist_at_tile(const struct civ_map *nmap,
320 const struct unit *punit,
321 const struct tile *ptile)
322{
323 return can_exist_at_tile(nmap, unit_type_get(punit), ptile);
324}
325
326/************************************************************************/
331 bool is_native_tile(const struct unit_type *punittype,
332 const struct tile *ptile)
333{
334 return is_native_to_class(utype_class(punittype), tile_terrain(ptile),
335 tile_extras(ptile));
336}
337
338/************************************************************************/
342 bool is_native_to_class(const struct unit_class *punitclass,
343 const struct terrain *pterrain,
344 const bv_extras *extras)
345{
346 if (!pterrain) {
347 /* Unknown is considered native terrain */
348 return TRUE;
349 }
350
351 if (BV_ISSET(pterrain->native_to, uclass_index(punitclass))) {
352 return TRUE;
353 }
354
355 if (extras != NULL) {
356 extra_type_list_iterate(punitclass->cache.native_tile_extras, pextra) {
357 if (BV_ISSET(*extras, extra_index(pextra))) {
358 return TRUE;
359 }
360 } extra_type_list_iterate_end;
361 }
362
363 return FALSE;
364}
365
366
367/************************************************************************/
373 bool is_native_move(const struct civ_map *nmap,
374 const struct unit_class *punitclass,
375 const struct tile *src_tile,
376 const struct tile *dst_tile)
377{
378 const struct road_type *proad;
379
380 if (is_native_to_class(punitclass, tile_terrain(dst_tile), NULL)) {
381 /* We aren't using extras to make the destination native. */
382 return TRUE;
383 } else if (!is_native_tile_to_class(punitclass, src_tile)) {
384 /* Disembarking or leaving port, so ignore road connectivity. */
385 return TRUE;
386 } else if (is_native_to_class(punitclass, tile_terrain(src_tile), NULL)) {
387 /* Native source terrain depends entirely on destination tile nativity. */
388 return is_native_tile_to_class(punitclass, dst_tile);
389 }
390
391 /* Check for non-road native extras on the source tile. */
392 extra_type_list_iterate(punitclass->cache.native_tile_extras, pextra) {
393 if (tile_has_extra(src_tile, pextra)
394 && !is_extra_caused_by(pextra, EC_ROAD)
395 && is_native_tile_to_class(punitclass, dst_tile)) {
396 /* If there is one, and the destination is native, the move is native. */
397 return TRUE;
398 }
399 } extra_type_list_iterate_end;
400
401 extra_type_list_iterate(punitclass->cache.native_tile_extras, pextra) {
402 if (!tile_has_extra(dst_tile, pextra)) {
403 continue;
404 } else if (!is_extra_caused_by(pextra, EC_ROAD)) {
405 /* The destination is native because of a non-road extra. */
406 return TRUE;
407 }
408
409 proad = extra_road_get(pextra);
410
411 if (road_has_flag(proad, RF_JUMP_TO)) {
412 extra_type_list_iterate(punitclass->cache.native_tile_extras, jextra) {
413 if (pextra != jextra
414 && is_extra_caused_by(jextra, EC_ROAD)
415 && tile_has_extra(src_tile, jextra)
416 && road_has_flag(jextra->data.road, RF_JUMP_FROM)) {
417 return TRUE;
418 }
419 } extra_type_list_iterate_end;
420 }
421
422 extra_type_list_iterate(proad->integrators, iextra) {
423 if (!tile_has_extra(src_tile, iextra)) {
424 continue;
425 }
426 if (ALL_DIRECTIONS_CARDINAL()) {
427 /* move_mode does not matter as all of them accept cardinal move */
428 return TRUE;
429 }
430 switch (extra_road_get(iextra)->move_mode) {
431 case RMM_FAST_ALWAYS:
432 /* Road connects source and destination, so we're fine. */
433 return TRUE;
434 case RMM_CARDINAL:
435 /* Road connects source and destination if cardinal move. */
436 if (is_move_cardinal(nmap, src_tile, dst_tile)) {
437 return TRUE;
438 }
439 break;
440 case RMM_RELAXED:
441 if (is_move_cardinal(nmap, src_tile, dst_tile)) {
442 /* Cardinal moves have no between tiles, so connected. */
443 return TRUE;
444 }
445 cardinal_between_iterate(nmap, src_tile, dst_tile, between) {
446 if (tile_has_extra(between, iextra)
447 || (pextra != iextra && tile_has_extra(between, pextra))) {
448 /* We have a link for the connection.
449 * 'pextra != iextra' is there just to avoid tile_has_extra()
450 * in by far more common case that 'pextra == iextra' */
451 return TRUE;
452 }
453 } cardinal_between_iterate_end;
454 break;
455 }
456 } extra_type_list_iterate_end;
457 } extra_type_list_iterate_end;
458
459 return FALSE;
460}
461
462/************************************************************************/
465 bool is_native_near_tile(const struct civ_map *nmap,
466 const struct unit_class *uclass,
467 const struct tile *ptile)
468{
469 if (is_native_tile_to_class(uclass, ptile)) {
470 return TRUE;
471 }
472
473 adjc_iterate(nmap, ptile, ptile2) {
474 if (is_native_tile_to_class(uclass, ptile2)) {
475 return TRUE;
476 }
477 } adjc_iterate_end;
478
479 return FALSE;
480}
481
482/************************************************************************/
491 bool can_unit_survive_at_tile(const struct civ_map *nmap,
492 const struct unit *punit,
493 const struct tile *ptile)
494{
495 const struct unit_type *utype;
496
497 if (!can_unit_exist_at_tile(nmap, punit, ptile)) {
498 return FALSE;
499 }
500
501 if (tile_city(ptile)) {
502 return TRUE;
503 }
504
505 utype = unit_type_get(punit);
506 if (tile_has_refuel_extra(ptile, utype_class(utype))) {
507 /* Unit can always survive at refueling base */
508 return TRUE;
509 }
510
511 if (utype_has_flag(utype, UTYF_COAST) && is_safe_ocean(nmap, ptile)) {
512 /* Refueling coast */
513 return TRUE;
514 }
515
516 if (utype_fuel(utype)) {
517 /* Unit requires fuel and this is not refueling tile */
518 return FALSE;
519 }
520
521 if (is_losing_hp(punit)) {
522 /* Unit is losing HP over time in this tile (no city or native base) */
523 return FALSE;
524 }
525
526 return TRUE;
527}
528
529
530/************************************************************************/
542 bool can_step_taken_wrt_to_zoc(const struct unit_type *punittype,
543 const struct player *unit_owner,
544 const struct tile *src_tile,
545 const struct tile *dst_tile,
546 const struct civ_map *zmap)
547{
548 if (unit_type_really_ignores_zoc(punittype)) {
549 return TRUE;
550 }
551 if (is_allied_unit_tile(dst_tile, unit_owner)) {
552 return TRUE;
553 }
554 if (tile_city(src_tile) || tile_city(dst_tile)) {
555 return TRUE;
556 }
557 if (terrain_has_flag(tile_terrain(src_tile), TER_NO_ZOC)
558 || terrain_has_flag(tile_terrain(dst_tile), TER_NO_ZOC)) {
559 return TRUE;
560 }
561
562 return (is_my_zoc(unit_owner, src_tile, zmap)
563 || is_my_zoc(unit_owner, dst_tile, zmap));
564}
565
566/************************************************************************/
572 bool unit_can_move_to_tile(const struct civ_map *nmap,
573 const struct unit *punit,
574 const struct tile *dst_tile,
575 bool igzoc,
576 bool enter_transport,
577 bool enter_enemy_city)
578{
579 return (MR_OK == unit_move_to_tile_test(nmap, punit,
580 punit->activity, unit_tile(punit),
581 dst_tile, igzoc,
582 enter_transport, NULL,
583 enter_enemy_city));
584}
585
586/************************************************************************/
592 bool unit_can_teleport_to_tile(const struct civ_map *nmap,
593 const struct unit *punit,
594 const struct tile *dst_tile,
595 bool enter_transport,
596 bool enter_enemy_city)
597{
598 return (MR_OK == unit_teleport_to_tile_test(nmap, punit, punit->activity,
599 unit_tile(punit), dst_tile,
600 enter_transport, NULL,
601 enter_enemy_city));
602}
603
604/************************************************************************/
629enum unit_move_result
630unit_move_to_tile_test(const struct civ_map *nmap,
631 const struct unit *punit,
632 enum unit_activity activity,
633 const struct tile *src_tile,
634 const struct tile *dst_tile, bool igzoc,
635 bool enter_transport, struct unit *embark_to,
636 bool enter_enemy_city)
637{
638 bool zoc;
639 struct city *pcity;
640 const struct unit_type *punittype = unit_type_get(punit);
641 const struct player *puowner = unit_owner(punit);
642
643 /* 1) */
644 if (activity != ACTIVITY_IDLE
645 && activity != ACTIVITY_GOTO) {
646 /* For other activities the unit must be stationary. */
647 return MR_BAD_ACTIVITY;
648 }
649
650 /* 2) */
651 if (punit->stay) {
652 return MR_UNIT_STAY;
653 }
654
655 /* 3) */
656 if ((!is_server() || game.server.random_move_time != puowner)
657 && utype_has_flag(punittype, UTYF_RANDOM_MOVEMENT)) {
658 return MR_RANDOM_ONLY;
659 }
660
661 /* 4) */
662 if (!is_tiles_adjacent(src_tile, dst_tile)) {
663 /* Of course you can only move to adjacent positions. */
664 return MR_BAD_DESTINATION;
665 }
666
667 /* 5) */
668 if (is_non_allied_unit_tile(dst_tile, puowner)) {
669 /* You can't move onto a tile with non-allied units on it (try
670 * attacking instead). */
671 return MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT;
672 }
673
674 /* 6) */
675 if (puowner->ai_common.barbarian_type == ANIMAL_BARBARIAN
676 && dst_tile->terrain->animal != punittype) {
677 return MR_ANIMAL_DISALLOWED;
678 }
679
680 /* 7) */
681 if (embark_to != NULL) {
682 if (!could_unit_load(punit, embark_to)) {
683 return MR_NO_TRANSPORTER_CAPACITY;
684 }
685 } else if (!(can_exist_at_tile(nmap, punittype, dst_tile)
686 || (enter_transport
687 && unit_could_load_at(punit, dst_tile)))) {
688 return MR_NO_TRANSPORTER_CAPACITY;
689 }
690
691 /* 8) */
692 if (is_non_attack_unit_tile(dst_tile, puowner)) {
693 /* You can't move into a non-allied tile.
694 *
695 * FIXME: this should never happen since it should be caught by check
696 * #4. */
697 return MR_NO_WAR;
698 }
699
700 /* 9) */
701 if ((pcity = tile_city(dst_tile))) {
702 if (enter_enemy_city) {
703 if (pplayers_non_attack(city_owner(pcity), puowner)) {
704 /* You can't move into an empty city of a civilization you're at
705 * peace with - you must first either declare war or make an
706 * alliance. */
707 return MR_NO_WAR;
708 }
709 } else {
710 if (!pplayers_allied(city_owner(pcity), puowner)) {
711 /* You can't move into an empty city of a civilization you're not
712 * allied to. Assume that the player tried to attack. */
713 return MR_NO_WAR;
714 }
715 }
716 }
717
718 /* 10) */
719 zoc = igzoc
720 || can_step_taken_wrt_to_zoc(punittype, puowner, src_tile, dst_tile, nmap);
721 if (!zoc) {
722 /* The move is illegal because of zones of control. */
723 return MR_ZOC;
724 }
725
726 /* 11) */
727 if (utype_has_flag(punittype, UTYF_COAST_STRICT)
728 && !pcity && !is_safe_ocean(nmap, dst_tile)) {
729 return MR_TRIREME;
730 }
731
732 /* 12) */
733 if (!utype_has_flag(punittype, UTYF_CIVILIAN)
734 && !player_can_invade_tile(puowner, dst_tile)) {
735 return MR_PEACE;
736 }
737
738 /* 13) */
739 if (unit_transported(punit)
740 && !can_unit_unload(punit, unit_transport_get(punit))) {
741 return MR_CANNOT_DISEMBARK;
742 }
743
744 /* 14) */
745 if (!(is_native_move(nmap, utype_class(punittype), src_tile, dst_tile)
746 /* Allow non-native moves into cities or boarding transport. */
747 || pcity
748 || unit_could_load_at(punit, dst_tile))) {
749 return MR_NON_NATIVE_MOVE;
750 }
751
752 return MR_OK;
753}
754
755/************************************************************************/
773enum unit_move_result
774unit_teleport_to_tile_test(const struct civ_map *nmap,
775 const struct unit *punit,
776 enum unit_activity activity,
777 const struct tile *src_tile,
778 const struct tile *dst_tile,
779 bool enter_transport, struct unit *embark_to,
780 bool enter_enemy_city)
781{
782 struct city *pcity;
783 const struct unit_type *punittype = unit_type_get(punit);
784 const struct player *puowner = unit_owner(punit);
785
786 /* 1) */
787 if (is_non_allied_unit_tile(dst_tile, puowner)) {
788 /* You can't move onto a tile with non-allied units on it (try
789 * attacking instead). */
790 return MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT;
791 }
792
793 /* 2) */
794 if (puowner->ai_common.barbarian_type == ANIMAL_BARBARIAN
795 && dst_tile->terrain->animal != punittype) {
796 return MR_ANIMAL_DISALLOWED;
797 }
798
799 /* 3) */
800 if (embark_to != NULL) {
801 if (!could_unit_load(punit, embark_to)) {
802 return MR_NO_TRANSPORTER_CAPACITY;
803 }
804 } else if (!(can_exist_at_tile(nmap, punittype, dst_tile)
805 || (enter_transport
806 && unit_could_load_at(punit, dst_tile)))) {
807 return MR_NO_TRANSPORTER_CAPACITY;
808 }
809
810 /* 4) */
811 if (is_non_attack_unit_tile(dst_tile, puowner)) {
812 /* You can't move into a non-allied tile.
813 *
814 * FIXME: this should never happen since it should be caught by check
815 * #1. */
816 return MR_NO_WAR;
817 }
818
819 /* 5) */
820 if ((pcity = tile_city(dst_tile))) {
821 if (enter_enemy_city) {
822 if (pplayers_non_attack(city_owner(pcity), puowner)) {
823 /* You can't move into an empty city of a civilization you're at
824 * peace with - you must first either declare war or make an
825 * alliance. */
826 return MR_NO_WAR;
827 }
828 } else {
829 if (!pplayers_allied(city_owner(pcity), puowner)) {
830 /* You can't move into an empty city of a civilization you're not
831 * allied to. Assume that the player tried to attack. */
832 return MR_NO_WAR;
833 }
834 }
835 }
836
837 /* 6) */
838 if (utype_has_flag(punittype, UTYF_COAST_STRICT)
839 && !pcity && !is_safe_ocean(nmap, dst_tile)) {
840 return MR_TRIREME;
841 }
842
843 /* 7) */
844 if (!utype_has_flag(punittype, UTYF_CIVILIAN)
845 && !player_can_invade_tile(puowner, dst_tile)) {
846 return MR_PEACE;
847 }
848
849 return MR_OK;
850}
851
852/************************************************************************/
855 bool can_unit_transport(const struct unit *transporter,
856 const struct unit *transported)
857{
858 fc_assert_ret_val(transporter != NULL, FALSE);
859 fc_assert_ret_val(transported != NULL, FALSE);
860
861 return can_unit_type_transport(unit_type_get(transporter),
862 unit_class_get(transported));
863}
864
865/************************************************************************/
868 bool can_unit_type_transport(const struct unit_type *transporter,
869 const struct unit_class *transported)
870{
871 if (transporter->transport_capacity <= 0) {
872 return FALSE;
873 }
874
875 return BV_ISSET(transporter->cargo, uclass_index(transported));
876}
877
878/************************************************************************/
883 bool unit_can_load(const struct unit *punit)
884{
885 if (unit_transported(punit)) {
886 /* In another transport already. Can it unload first? */
887 if (!can_unit_unload(punit, punit->transporter)) {
888 return FALSE;
889 }
890 }
891
892 unit_list_iterate(unit_tile(punit)->units, ptransport) {
893 /* could_unit_load() instead of can_unit_load() since latter
894 * would check against unit already being transported, and we need
895 * to support unload+load to a new transport. */
896 if (ptransport != punit->transporter) {
897 if (could_unit_load(punit, ptransport)) {
898 return TRUE;
899 }
900 }
901 } unit_list_iterate_end;
902
903 return FALSE;
904}
905
906/************************************************************************/
911 bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
912{
913 unit_list_iterate(ptile->units, ptransport) {
914 if (could_unit_load(punit, ptransport)) {
915 return TRUE;
916 }
917 } unit_list_iterate_end;
918
919 return FALSE;
920}
921
922 static int move_points_denomlen = 0;
923
924/************************************************************************/
927 void init_move_fragments(void)
928{
929 char denomstr[10];
930 /* String length of maximum denominator for fractional representation of
931 * movement points, for padding of text representation */
932 fc_snprintf(denomstr, sizeof(denomstr), "%d", SINGLE_MOVE);
933 move_points_denomlen = strlen(denomstr);
934}
935
936/************************************************************************/
948 const char *move_points_text_full(int mp, bool reduce, const char *prefix,
949 const char *none, bool align)
950{
951 static struct astring str = ASTRING_INIT;
952 int pad1, pad2;
953
954 if (align && SINGLE_MOVE > 1) {
955 /* Align to worst-case denominator even if we might be reducing to
956 * lowest terms, as other entries in a table might not reduce */
957 pad1 = move_points_denomlen; /* numerator or denominator */
958 pad2 = move_points_denomlen*2+2; /* everything right of integer part */
959 } else {
960 /* If no possible fractional part, alignment unneeded even if requested */
961 pad1 = pad2 = 0;
962 }
963 if (!prefix) {
964 prefix = "";
965 }
966 astr_clear(&str);
967 if ((mp == 0 && none) || SINGLE_MOVE == 0) {
968 /* No movement points, and we have a special representation to use */
969 /* (Also used when SINGLE_MOVE == 0, to avoid dividing by zero, which is
970 * important for client before ruleset has been received. Doesn't much
971 * matter what we print in this case.) */
972 astr_add(&str, "%s%*s", none ? none : "", pad2, "");
973 } else if ((mp % SINGLE_MOVE) == 0) {
974 /* Integer move points */
975 astr_add(&str, "%s%d%*s", prefix, mp / SINGLE_MOVE, pad2, "");
976 } else {
977 /* Fractional part */
978 int cancel;
979
980 fc_assert(SINGLE_MOVE > 1);
981 if (reduce) {
982 /* Reduce to lowest terms */
983 int gcd = mp;
984 /* Calculate greatest common divisor with Euclid's algorithm */
985 int b = SINGLE_MOVE;
986
987 while (b != 0) {
988 int t = b;
989 b = gcd % b;
990 gcd = t;
991 }
992 cancel = gcd;
993 } else {
994 /* No cancellation */
995 cancel = 1;
996 }
997 if (mp < SINGLE_MOVE) {
998 /* Fractional move points */
999 astr_add(&str, "%s%*d/%*d", prefix,
1000 pad1, (mp % SINGLE_MOVE) / cancel, pad1, SINGLE_MOVE / cancel);
1001 } else {
1002 /* Integer + fractional move points */
1003 astr_add(&str,
1004 "%s%d %*d/%*d", prefix, mp / SINGLE_MOVE,
1005 pad1, (mp % SINGLE_MOVE) / cancel, pad1, SINGLE_MOVE / cancel);
1006 }
1007 }
1008 return astr_str(&str);
1009}
1010
1011/************************************************************************/
1015 const char *move_points_text(int mp, bool reduce)
1016{
1017 return move_points_text_full(mp, reduce, NULL, NULL, FALSE);
1018}
action_by_result_iterate
#define action_by_result_iterate(_paction_, _result_)
Definition actions.h:479
action_by_result_iterate_end
#define action_by_result_iterate_end
Definition actions.h:483
action_id
#define action_id(_act_)
Definition actions.h:659
astr_clear
void astr_clear(struct astring *astr)
Definition astring.c:205
astr_add
void astr_add(struct astring *astr, const char *format,...)
Definition astring.c:287
str
#define str
Definition astring.c:76
astring.h
astr_str
static const char * astr_str(const struct astring *astr) fc__attribute((nonnull(1)))
Definition astring.h:93
ASTRING_INIT
#define ASTRING_INIT
Definition astring.h:44
base.h
dbv_init
void dbv_init(struct dbv *pdbv, int bits)
Definition bitvector.c:50
dbv_set
void dbv_set(struct dbv *pdbv, int bit)
Definition bitvector.c:144
dbv_isset
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
dbv_free
void dbv_free(struct dbv *pdbv)
Definition bitvector.c:95
bitvector.h
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
BV_ISSET_ANY
#define BV_ISSET_ANY(vec)
Definition bitvector.h:109
city_owner
#define city_owner(_pcity_)
Definition city.h:563
incite_cost
char * incite_cost
Definition comments.c:74
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
effect_cumulative_max
int effect_cumulative_max(enum effect_type type, struct universal *unis, size_t n_unis)
Definition effects.c:388
get_unittype_bonus
int get_unittype_bonus(const struct player *pplayer, const struct tile *ptile, const struct unit_type *punittype, const struct action *paction, enum effect_type effect_type)
Definition effects.c:1035
effects.h
extras
static struct extra_type extras[MAX_EXTRA_TYPES]
Definition extras.c:31
extra_type_list_iterate
#define extra_type_list_iterate(extralist, pextra)
Definition extras.h:165
is_extra_caused_by
#define is_extra_caused_by(e, c)
Definition extras.h:203
extra_index
#define extra_index(_e_)
Definition extras.h:183
extra_type_list_iterate_end
#define extra_type_list_iterate_end
Definition extras.h:167
extra_road_get
#define extra_road_get(_e_)
Definition extras.h:191
is_server
static bool is_server(void)
Definition fc_interface.h:69
fc_types.h
fcintl.h
game
struct civ_game game
Definition game.c:62
game.h
log.h
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
is_move_cardinal
bool is_move_cardinal(const struct civ_map *nmap, const struct tile *start_tile, const struct tile *end_tile)
Definition map.c:1365
map_num_tiles
int map_num_tiles(void)
Definition map.c:1014
is_tiles_adjacent
bool is_tiles_adjacent(const struct tile *tile0, const struct tile *tile1)
Definition map.c:931
is_safe_ocean
bool is_safe_ocean(const struct civ_map *nmap, const struct tile *ptile)
Definition map.c:667
map.h
adjc_iterate_end
#define adjc_iterate_end
Definition map.h:433
cardinal_between_iterate
#define cardinal_between_iterate(nmap, tile1, tile2, between)
Definition map.h:477
adjc_iterate
#define adjc_iterate(nmap, center_tile, itr_tile)
Definition map.h:428
ALL_DIRECTIONS_CARDINAL
#define ALL_DIRECTIONS_CARDINAL()
Definition map.h:53
cardinal_between_iterate_end
#define cardinal_between_iterate_end
Definition map.h:482
move_points_text
const char * move_points_text(int mp, bool reduce)
Definition movement.c:1015
move_points_text_full
const char * move_points_text_full(int mp, bool reduce, const char *prefix, const char *none, bool align)
Definition movement.c:948
can_exist_at_tile
bool can_exist_at_tile(const struct civ_map *nmap, const struct unit_type *utype, const struct tile *ptile)
Definition movement.c:290
unit_move_to_tile_test
enum unit_move_result unit_move_to_tile_test(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, const struct tile *src_tile, const struct tile *dst_tile, bool igzoc, bool enter_transport, struct unit *embark_to, bool enter_enemy_city)
Definition movement.c:630
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:319
is_native_tile
bool is_native_tile(const struct unit_type *punittype, const struct tile *ptile)
Definition movement.c:331
can_step_taken_wrt_to_zoc
bool can_step_taken_wrt_to_zoc(const struct unit_type *punittype, const struct player *unit_owner, const struct tile *src_tile, const struct tile *dst_tile, const struct civ_map *zmap)
Definition movement.c:542
utype_unknown_move_cost
int utype_unknown_move_cost(const struct unit_type *utype)
Definition movement.c:105
unit_can_load
bool unit_can_load(const struct unit *punit)
Definition movement.c:883
can_unit_transport
bool can_unit_transport(const struct unit *transporter, const struct unit *transported)
Definition movement.c:855
unit_move_rate
int unit_move_rate(const struct unit *punit)
Definition movement.c:90
unit_could_load_at
bool unit_could_load_at(const struct unit *punit, const struct tile *ptile)
Definition movement.c:911
move_points_denomlen
static int move_points_denomlen
Definition movement.c:922
can_attack_non_native_hard_reqs
bool can_attack_non_native_hard_reqs(const struct unit_type *utype)
Definition movement.c:204
can_attack_from_non_native
bool can_attack_from_non_native(const struct unit_type *utype)
Definition movement.c:227
unit_teleport_to_tile_test
enum unit_move_result unit_teleport_to_tile_test(const struct civ_map *nmap, const struct unit *punit, enum unit_activity activity, const struct tile *src_tile, const struct tile *dst_tile, bool enter_transport, struct unit *embark_to, bool enter_enemy_city)
Definition movement.c:774
unit_can_defend_here
bool unit_can_defend_here(const struct civ_map *nmap, const struct unit *punit)
Definition movement.c:174
unit_can_teleport_to_tile
bool unit_can_teleport_to_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *dst_tile, bool enter_transport, bool enter_enemy_city)
Definition movement.c:592
is_native_move
bool is_native_move(const struct civ_map *nmap, const struct unit_class *punitclass, const struct tile *src_tile, const struct tile *dst_tile)
Definition movement.c:373
is_native_to_class
bool is_native_to_class(const struct unit_class *punitclass, const struct terrain *pterrain, const bv_extras *extras)
Definition movement.c:342
utype_move_rate
int utype_move_rate(const struct unit_type *utype, const struct tile *ptile, const struct player *pplayer, int veteran_level, int hitpoints)
Definition movement.c:47
is_city_channel_tile
bool is_city_channel_tile(const struct civ_map *nmap, const struct unit_class *punitclass, const struct tile *ptile, const struct tile *pexclude)
Definition movement.c:243
can_unit_survive_at_tile
bool can_unit_survive_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:491
is_native_near_tile
bool is_native_near_tile(const struct civ_map *nmap, const struct unit_class *uclass, const struct tile *ptile)
Definition movement.c:465
unit_can_move_to_tile
bool unit_can_move_to_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *dst_tile, bool igzoc, bool enter_transport, bool enter_enemy_city)
Definition movement.c:572
can_unit_type_transport
bool can_unit_type_transport(const struct unit_type *transporter, const struct unit_class *transported)
Definition movement.c:868
init_move_fragments
void init_move_fragments(void)
Definition movement.c:927
can_attack_non_native
bool can_attack_non_native(const struct unit_type *utype)
Definition movement.c:214
movement.h
SINGLE_MOVE
#define SINGLE_MOVE
Definition movement.h:26
is_native_tile_to_class
static bool is_native_tile_to_class(const struct unit_class *punitclass, const struct tile *ptile)
Definition movement.h:84
unit_move_result
unit_move_result
Definition movement.h:34
MR_CANNOT_DISEMBARK
@ MR_CANNOT_DISEMBARK
Definition movement.h:48
MR_OK
@ MR_OK
Definition movement.h:35
MR_RANDOM_ONLY
@ MR_RANDOM_ONLY
Definition movement.h:52
MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT
@ MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT
Definition movement.h:45
MR_TRIREME
@ MR_TRIREME
Definition movement.h:47
MR_NON_NATIVE_MOVE
@ MR_NON_NATIVE_MOVE
Definition movement.h:49
MR_BAD_ACTIVITY
@ MR_BAD_ACTIVITY
Definition movement.h:41
MR_ANIMAL_DISALLOWED
@ MR_ANIMAL_DISALLOWED
Definition movement.h:50
MR_PEACE
@ MR_PEACE
Definition movement.h:39
MR_ZOC
@ MR_ZOC
Definition movement.h:40
MR_NO_WAR
@ MR_NO_WAR
Definition movement.h:38
MR_BAD_DESTINATION
@ MR_BAD_DESTINATION
Definition movement.h:42
MR_NO_TRANSPORTER_CAPACITY
@ MR_NO_TRANSPORTER_CAPACITY
Definition movement.h:46
MR_UNIT_STAY
@ MR_UNIT_STAY
Definition movement.h:51
MOVE_COST_IGTER
#define MOVE_COST_IGTER
Definition movement.h:27
player_can_invade_tile
bool player_can_invade_tile(const struct player *pplayer, const struct tile *ptile)
Definition player.c:270
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
pplayers_non_attack
bool pplayers_non_attack(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1459
road_has_flag
bool road_has_flag(const struct road_type *proad, enum road_flag_id flag)
Definition road.c:410
road.h
shared.h
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MIN
#define MIN(x, y)
Definition shared.h:55
astring
Definition astring.h:36
city
Definition city.h:320
civ_game::random_move_time
struct player * random_move_time
Definition game.h:275
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::server
struct civ_game::@31::@35 server
civ_map
Definition map_types.h:71
dbv
Definition bitvector.h:32
packet_game_info::citymindist
int citymindist
Definition packets_gen.h:145
player
Definition player.h:247
player::units
struct unit_list * units
Definition player.h:280
road_type
Definition road.h:71
road_type::move_mode
enum road_move_mode move_mode
Definition road.h:75
terrain
Definition terrain.h:182
terrain::native_to
bv_unit_classes native_to
Definition terrain.h:257
tile
Definition tile.h:50
tile::units
struct unit_list * units
Definition tile.h:58
unit_class
Definition unittype.h:149
unit_class::min_speed
int min_speed
Definition unittype.h:154
unit_type
Definition unittype.h:500
unit_type::transport_capacity
int transport_capacity
Definition unittype.h:523
unit_type::cargo
bv_unit_classes cargo
Definition unittype.h:558
unit_type::move_rate
int move_rate
Definition unittype.h:517
unit_type::hp
int hp
Definition unittype.h:524
unit
Definition unit.h:138
unit::activity
enum unit_activity activity
Definition unit.h:157
unit::hp
int hp
Definition unit.h:151
unit::stay
bool stay
Definition unit.h:205
unit::transporter
struct unit * transporter
Definition unit.h:183
unit::utype
const struct unit_type * utype
Definition unit.h:139
unit::veteran
int veteran
Definition unit.h:152
universal
Definition fc_types.h:901
universal::kind
enum universals_n kind
Definition fc_types.h:903
veteran_level
Definition unittype.h:486
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
terrain.h
terrain_type_iterate
#define terrain_type_iterate(_p)
Definition terrain.h:373
terrain_type_iterate_end
#define terrain_type_iterate_end
Definition terrain.h:379
terrain_has_flag
#define terrain_has_flag(terr, flag)
Definition terrain.h:283
tile_has_refuel_extra
bool tile_has_refuel_extra(const struct tile *ptile, const struct unit_class *uclass)
Definition tile.c:309
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile_index
#define tile_index(_pt_)
Definition tile.h:88
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:110
tile_extras
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:120
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
unit_type_really_ignores_zoc
bool unit_type_really_ignores_zoc(const struct unit_type *punittype)
Definition unit.c:1501
is_losing_hp
bool is_losing_hp(const struct unit *punit)
Definition unit.c:2224
can_unit_deboard_or_be_unloaded
bool can_unit_deboard_or_be_unloaded(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:773
unit_transport_get
struct unit * unit_transport_get(const struct unit *pcargo)
Definition unit.c:2437
could_unit_load
bool could_unit_load(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:696
unit_transported
bool unit_transported(const struct unit *pcargo)
Definition unit.c:2421
can_unit_unload
bool can_unit_unload(const struct unit *pcargo, const struct unit *ptrans)
Definition unit.c:748
unit.h
unit_tile
#define unit_tile(_pu)
Definition unit.h:390
is_non_attack_unit_tile
static bool is_non_attack_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:450
is_allied_unit_tile
static bool is_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:401
unit_owner
#define unit_owner(_pu)
Definition unit.h:389
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:425
is_my_zoc
static bool is_my_zoc(const struct player *unit_owner, const struct tile *ptile, const struct civ_map *zmap)
Definition unit.h:471
unitlist.h
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
unit_class_get
struct unit_class * unit_class_get(const struct unit *punit)
Definition unittype.c:2498
utype_can_do_action_result_when_ustate
bool utype_can_do_action_result_when_ustate(const struct unit_type *putype, enum action_result result, const enum ustate_prop prop, const bool is_there)
Definition unittype.c:975
utype_can_do_action_result
bool utype_can_do_action_result(const struct unit_type *putype, enum action_result result)
Definition unittype.c:387
utype_veteran_level
const struct veteran_level * utype_veteran_level(const struct unit_type *punittype, int level)
Definition unittype.c:2583
utype_can_do_action
bool utype_can_do_action(const struct unit_type *putype, const action_id act_id)
Definition unittype.c:371
unittype.h
uclass_has_flag
static bool uclass_has_flag(const struct unit_class *punitclass, enum unit_class_flag_id flag)
Definition unittype.h:766
utype_class
#define utype_class(_t_)
Definition unittype.h:749
utype_fuel
#define utype_fuel(ptype)
Definition unittype.h:836
utype_has_flag
static bool utype_has_flag(const struct unit_type *punittype, int flag)
Definition unittype.h:617
uclass_index
#define uclass_index(_c_)
Definition unittype.h:742