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)
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 ****************************************************************************/
15 #include <fc_config.h>
19 #include "bitvector.h"
40 /****************************************************************************
41 This function calculates the move rate of the unit, taking into
42 account the penalty for reduced hitpoints (affects sea and land
43 units only), the effects of wonders for sea units, and any veteran
45 ****************************************************************************/
46 int unit_move_rate(const struct unit
*punit
)
50 struct unit_class
*pclass
;
51 const struct veteran_level
*vlevel
;
53 fc_assert_ret_val(punit
!= NULL
, 0);
55 vlevel
= utype_veteran_level(unit_type(punit
), punit
->veteran
);
56 fc_assert_ret_val(vlevel
!= NULL
, 0);
58 base_move_rate
= unit_type(punit
)->move_rate
+ vlevel
->move_bonus
;
59 move_rate
= base_move_rate
;
61 pclass
= unit_class(punit
);
63 if (uclass_has_flag(pclass
, UCF_DAMAGE_SLOWS
)) {
64 /* Scale the MP based on how many HP the unit has. */
65 move_rate
= (move_rate
* punit
->hp
) / unit_type(punit
)->hp
;
68 /* Add on effects bonus (Magellan's Expedition, Lighthouse,
70 move_rate
+= (get_unit_bonus(punit
, EFT_MOVE_BONUS
) * SINGLE_MOVE
);
72 /* Don't let the move_rate be less than min_speed unless the base_move_rate is
73 * also less than min_speed. */
74 if (move_rate
< pclass
->min_speed
) {
75 move_rate
= MIN(pclass
->min_speed
, base_move_rate
);
82 /****************************************************************************
83 Return TRUE iff the unit can be a defender at its current location. This
84 should be checked when looking for a defender - not all units on the
85 tile are valid defenders.
86 ****************************************************************************/
87 bool unit_can_defend_here(const struct unit
*punit
)
89 struct unit
*ptrans
= unit_transport_get(punit
);
91 /* Do not just check if unit is transported.
92 * Even transported units may step out from transport to fight,
93 * if this is their native terrain. */
94 return (can_unit_exist_at_tile(punit
, unit_tile(punit
))
95 && (ptrans
== NULL
|| can_unit_unload(punit
, ptrans
)));
98 /****************************************************************************
99 This unit can attack non-native tiles (eg. Ships ability to
101 ****************************************************************************/
102 bool can_attack_non_native(const struct unit_type
*utype
)
104 return uclass_has_flag(utype_class(utype
), UCF_ATTACK_NON_NATIVE
)
105 && !utype_has_flag(utype
, UTYF_ONLY_NATIVE_ATTACK
);
108 /****************************************************************************
109 This unit can attack from non-native tiles (Marines can attack from
110 transport, ships from harbour cities)
111 ****************************************************************************/
112 bool can_attack_from_non_native(const struct unit_type
*utype
)
114 return uclass_has_flag(utype_class(utype
), UCF_ATT_FROM_NON_NATIVE
)
115 || utype_has_flag(utype
, UTYF_MARINES
);
118 /****************************************************************************
119 Return TRUE iff the unit is a sailing/naval/sea/water unit.
120 ****************************************************************************/
121 bool is_sailing_unit(const struct unit
*punit
)
123 return (uclass_move_type(unit_class(punit
)) == UMT_SEA
);
127 /****************************************************************************
128 Return TRUE iff this unit is a ground/land/normal unit.
129 ****************************************************************************/
130 bool is_ground_unit(const struct unit
*punit
)
132 return (uclass_move_type(unit_class(punit
)) == UMT_LAND
);
136 /****************************************************************************
137 Return TRUE iff this unit type is a sailing/naval/sea/water unit type.
138 ****************************************************************************/
139 bool is_sailing_unittype(const struct unit_type
*punittype
)
141 return (utype_move_type(punittype
) == UMT_SEA
);
145 /****************************************************************************
146 Return TRUE iff this unit type is a ground/land/normal unit type.
147 ****************************************************************************/
148 bool is_ground_unittype(const struct unit_type
*punittype
)
150 return (utype_move_type(punittype
) == UMT_LAND
);
153 /****************************************************************************
154 Check for a city channel.
155 ****************************************************************************/
156 bool is_city_channel_tile(const struct unit_class
*punitclass
,
157 const struct tile
*ptile
,
158 const struct tile
*pexclude
)
160 struct dbv tile_processed
;
161 struct tile_list
*process_queue
= tile_list_new();
164 dbv_init(&tile_processed
, map_num_tiles());
166 dbv_set(&tile_processed
, tile_index(ptile
));
167 adjc_iterate(ptile
, piter
) {
168 if (dbv_isset(&tile_processed
, tile_index(piter
))) {
170 } else if (piter
!= pexclude
171 && is_native_to_class(punitclass
, tile_terrain(piter
),
172 piter
->bases
, piter
->roads
)) {
175 } else if (piter
!= pexclude
176 && NULL
!= tile_city(piter
)) {
177 tile_list_append(process_queue
, piter
);
179 dbv_set(&tile_processed
, tile_index(piter
));
183 if (found
|| 0 == tile_list_size(process_queue
)) {
184 break; /* No more tile to process. */
186 ptile
= tile_list_front(process_queue
);
187 tile_list_pop_front(process_queue
);
191 dbv_free(&tile_processed
);
192 tile_list_destroy(process_queue
);
196 /****************************************************************************
197 Return TRUE iff a unit of the given unit type can "exist" at this location.
198 This means it can physically be present on the tile (without the use of a
199 transporter). See also can_unit_survive_at_tile.
200 ****************************************************************************/
201 bool can_exist_at_tile(const struct unit_type
*utype
,
202 const struct tile
*ptile
)
204 /* Cities are safe havens except for units in the middle of non-native
205 * terrain. This can happen if adjacent terrain is changed after unit
206 * arrived to city. */
207 if (NULL
!= tile_city(ptile
)
208 && (uclass_has_flag(utype_class(utype
), UCF_BUILD_ANYWHERE
)
209 || is_native_near_tile(utype_class(utype
), ptile
)
210 || (1 == game
.info
.citymindist
211 && is_city_channel_tile(utype_class(utype
), ptile
, NULL
)))) {
215 /* A trireme unit cannot exist in an ocean tile without access to land. */
216 if (utype_has_flag(utype
, UTYF_TRIREME
) && !is_safe_ocean(ptile
)) {
220 return is_native_tile(utype
, ptile
);
223 /****************************************************************************
224 Return TRUE iff the unit can "exist" at this location. This means it can
225 physically be present on the tile (without the use of a transporter). See
226 also can_unit_survive_at_tile.
227 ****************************************************************************/
228 bool can_unit_exist_at_tile(const struct unit
*punit
,
229 const struct tile
*ptile
)
231 return can_exist_at_tile(unit_type(punit
), ptile
);
234 /****************************************************************************
235 This tile is native to unit.
237 See is_native_to_class()
238 ****************************************************************************/
239 bool is_native_tile(const struct unit_type
*punittype
,
240 const struct tile
*ptile
)
242 return is_native_to_class(utype_class(punittype
), tile_terrain(ptile
),
243 tile_bases(ptile
), tile_roads(ptile
));
247 /****************************************************************************
248 This terrain is native to unit.
250 See is_native_to_class()
251 ****************************************************************************/
252 bool is_native_terrain(const struct unit_type
*punittype
,
253 const struct terrain
*pterrain
,
254 bv_bases bases
, bv_roads roads
)
256 return is_native_to_class(utype_class(punittype
), pterrain
, bases
, roads
);
259 /****************************************************************************
260 This tile is native to unit class.
262 See is_native_to_class()
263 ****************************************************************************/
264 bool is_native_tile_to_class(const struct unit_class
*punitclass
,
265 const struct tile
*ptile
)
267 return is_native_to_class(punitclass
, tile_terrain(ptile
),
268 tile_bases(ptile
), tile_roads(ptile
));
271 /****************************************************************************
272 This terrain is native to unit class. Units that require fuel dont survive
273 even on native terrain.
274 ****************************************************************************/
275 bool is_native_to_class(const struct unit_class
*punitclass
,
276 const struct terrain
*pterrain
,
277 bv_bases bases
, bv_roads roads
)
280 /* Unknown is considered native terrain */
284 if (BV_ISSET(pterrain
->native_to
, uclass_index(punitclass
))) {
288 road_type_list_iterate(punitclass
->cache
.native_tile_roads
, proad
) {
289 if (BV_ISSET(roads
, road_index(proad
))) {
292 } road_type_list_iterate_end
;
294 base_type_list_iterate(punitclass
->cache
.native_tile_bases
, pbase
) {
295 if (BV_ISSET(bases
, base_index(pbase
))) {
298 } base_type_list_iterate_end
;
303 /****************************************************************************
304 Is there native tile adjacent to given tile
305 ****************************************************************************/
306 bool is_native_near_tile(const struct unit_class
*uclass
, const struct tile
*ptile
)
308 if (is_native_tile_to_class(uclass
, ptile
)) {
312 adjc_iterate(ptile
, ptile2
) {
313 if (is_native_tile_to_class(uclass
, ptile2
)) {
321 /****************************************************************************
322 Return TRUE iff the unit can "survive" at this location. This means it can
323 not only be physically present at the tile but will be able to survive
324 indefinitely on its own (without a transporter). Units that require fuel
325 or have a danger of drowning are examples of non-survivable units. See
326 also can_unit_exist_at_tile.
328 (This function could be renamed as unit_wants_transporter.)
329 ****************************************************************************/
330 bool can_unit_survive_at_tile(const struct unit
*punit
,
331 const struct tile
*ptile
)
333 if (!can_unit_exist_at_tile(punit
, ptile
)) {
337 if (tile_city(ptile
)) {
341 if (tile_has_native_base(ptile
, unit_type(punit
))) {
342 /* Unit can always survive at native base */
346 if (utype_fuel(unit_type(punit
))) {
347 /* Unit requires fuel and this is not refueling tile */
351 if (is_losing_hp(punit
)) {
352 /* Unit is losing HP over time in this tile (no city or native base) */
360 /****************************************************************************
361 Returns whether the unit is allowed (by ZOC) to move from src_tile
362 to dest_tile (assumed adjacent).
365 1. You have units there already
366 2. Your unit isn't a ground unit
367 3. Your unit ignores ZOC (diplomat, freight, etc.)
368 4. You're moving from or to a city
369 5. You're moving from an ocean square (from a boat)
370 6. The spot you're moving from or to is in your ZOC
371 ****************************************************************************/
372 bool can_step_taken_wrt_to_zoc(const struct unit_type
*punittype
,
373 const struct player
*unit_owner
,
374 const struct tile
*src_tile
,
375 const struct tile
*dst_tile
)
377 if (unit_type_really_ignores_zoc(punittype
)) {
380 if (is_allied_unit_tile(dst_tile
, unit_owner
)) {
383 if (tile_city(src_tile
) || tile_city(dst_tile
)) {
386 if (is_ocean_tile(src_tile
)
387 || is_ocean_tile(dst_tile
)) {
390 return (is_my_zoc(unit_owner
, src_tile
)
391 || is_my_zoc(unit_owner
, dst_tile
));
395 /****************************************************************************
396 See can_step_take_wrt_to_zoc(). This function is exactly the same but
397 it takes a unit instead of a unittype and player.
398 ****************************************************************************/
399 static bool zoc_ok_move_gen(const struct unit
*punit
,
400 const struct tile
*src_tile
,
401 const struct tile
*dst_tile
)
403 return can_step_taken_wrt_to_zoc(unit_type(punit
), unit_owner(punit
),
408 /****************************************************************************
409 Returns whether the unit can safely move from its current position to
410 the adjacent dst_tile. This function checks only ZOC.
412 See can_step_taken_wrt_to_zoc().
413 ****************************************************************************/
414 bool zoc_ok_move(const struct unit
*punit
, const struct tile
*dst_tile
)
416 return zoc_ok_move_gen(punit
, unit_tile(punit
), dst_tile
);
420 /****************************************************************************
421 Returns whether the unit can move from its current tile to the destination
424 See unit_move_to_tile_test().
425 ****************************************************************************/
426 bool unit_can_move_to_tile(const struct unit
*punit
,
427 const struct tile
*dst_tile
,
430 return (MR_OK
== unit_move_to_tile_test(punit
,
431 punit
->activity
, unit_tile(punit
),
435 /**************************************************************************
436 Returns whether the unit can move from its current tile to the
437 destination tile. An enumerated value is returned indication the error
440 The unit can move if:
441 1) The unit is idle or on server goto.
442 2) The target location is next to the unit.
443 3) There are no non-allied units on the target tile.
444 4) Unit can move to a tile where it can't survive on its own if there
445 is free transport capacity.
446 5) Some units cannot take over a city.
447 6) Only units permitted to attack from non-native tiles may do so.
448 7) There are no peaceful but un-allied units on the target tile.
449 8) There is not a peaceful but un-allied city on the target tile.
450 9) There is no non-allied unit blocking (zoc) [or igzoc is true].
451 10) Triremes cannot move out of sight from land.
452 11) It is not the territory of a player we are at peace with.
453 12) The unit is unable to disembark from current transporter.
454 **************************************************************************/
455 enum unit_move_result
456 unit_move_to_tile_test(const struct unit
*punit
,
457 enum unit_activity activity
,
458 const struct tile
*src_tile
,
459 const struct tile
*dst_tile
, bool igzoc
)
463 const struct unit_type
*punittype
= unit_type(punit
);
464 const struct player
*puowner
= unit_owner(punit
);
467 if (activity
!= ACTIVITY_IDLE
468 && activity
!= ACTIVITY_GOTO
) {
469 /* For other activities the unit must be stationary. */
470 return MR_BAD_ACTIVITY
;
474 if (!is_tiles_adjacent(src_tile
, dst_tile
)) {
475 /* Of course you can only move to adjacent positions. */
476 return MR_BAD_DESTINATION
;
480 if (is_non_allied_unit_tile(dst_tile
, puowner
)) {
481 /* You can't move onto a tile with non-allied units on it (try
482 * attacking instead). */
483 return MR_DESTINATION_OCCUPIED_BY_NON_ALLIED_UNIT
;
487 if (!(can_exist_at_tile(punittype
, dst_tile
)
488 || NULL
!= transport_from_tile(punit
, dst_tile
))) {
489 return MR_NO_TRANSPORTER_CAPACITY
;
492 pcity
= is_enemy_city_tile(dst_tile
, puowner
);
495 if (!utype_can_take_over(punittype
)) {
496 return MR_BAD_TYPE_FOR_CITY_TAKE_OVER
;
498 /* No point checking for being able to take over from non-native
499 * for units that can't take over a city anyway. */
502 if (!can_exist_at_tile(punittype
, src_tile
)
503 && !can_attack_from_non_native(punittype
)) {
504 /* Don't use is_native_tile() because any unit in an
505 * adjacent city may conquer, regardless of flags. */
506 return MR_BAD_TYPE_FOR_CITY_TAKE_OVER_FROM_NON_NATIVE
;
512 if (is_non_attack_unit_tile(dst_tile
, puowner
)) {
513 /* You can't move into a non-allied tile.
515 * FIXME: this should never happen since it should be caught by check
521 pcity
= tile_city(dst_tile
);
522 if (pcity
&& pplayers_non_attack(city_owner(pcity
), puowner
)) {
523 /* You can't move into an empty city of a civilization you're at
524 * peace with - you must first either declare war or make alliance. */
530 || can_step_taken_wrt_to_zoc(punittype
, puowner
, src_tile
, dst_tile
);
532 /* The move is illegal because of zones of control. */
537 if (utype_has_flag(punittype
, UTYF_TRIREME
) && !is_safe_ocean(dst_tile
)) {
542 if (!utype_has_flag(punittype
, UTYF_CIVILIAN
)
543 && !player_can_invade_tile(puowner
, dst_tile
)) {
548 if (unit_transported(punit
)
549 && !can_unit_unload(punit
, unit_transport_get(punit
))) {
550 return MR_CANNOT_DISEMBARK
;
556 /**************************************************************************
557 Return true iff transporter has ability to transport transported.
558 **************************************************************************/
559 bool can_unit_transport(const struct unit
*transporter
,
560 const struct unit
*transported
)
562 fc_assert_ret_val(transporter
!= NULL
, FALSE
);
563 fc_assert_ret_val(transported
!= NULL
, FALSE
);
565 return can_unit_type_transport(unit_type(transporter
), unit_class(transported
));
568 /**************************************************************************
569 Return TRUE iff transporter type has ability to transport transported class.
570 **************************************************************************/
571 bool can_unit_type_transport(const struct unit_type
*transporter
,
572 const struct unit_class
*transported
)
574 if (transporter
->transport_capacity
<= 0) {
578 return BV_ISSET(transporter
->cargo
, uclass_index(transported
));
581 /****************************************************************************
582 Return the first transporter suitable for given unit from tile. It needs
583 to have free space. To find the best transporter, see
584 transporter_for_unit().
585 ****************************************************************************/
586 struct unit
*transport_from_tile(const struct unit
*punit
,
587 const struct tile
*ptile
)
589 unit_list_iterate(ptile
->units
, ptransport
) {
590 if (could_unit_load(punit
, ptransport
)) {
593 } unit_list_iterate_end
;
598 /**************************************************************************
599 Returns the number of free spaces for units of given class.
601 **************************************************************************/
602 int unit_class_transporter_capacity(const struct tile
*ptile
,
603 const struct player
*pplayer
,
604 const struct unit_class
*pclass
)
606 int availability
= 0;
608 unit_list_iterate(ptile
->units
, punit
) {
609 if (unit_owner(punit
) == pplayer
610 || pplayers_allied(unit_owner(punit
), pplayer
)) {
612 if (can_unit_type_transport(unit_type(punit
), pclass
)) {
613 availability
+= get_transporter_capacity(punit
);
614 availability
-= get_transporter_occupancy(punit
);
617 } unit_list_iterate_end
;
622 static int move_points_denomlen
= 0;
624 /****************************************************************************
625 Call whenever terrain_control.move_fragments / SINGLE_MOVE changes.
626 ****************************************************************************/
627 void init_move_fragments(void)
630 /* String length of maximum denominator for fractional representation of
631 * movement points, for padding of text representation */
632 fc_snprintf(denomstr
, sizeof(denomstr
), "%d", SINGLE_MOVE
);
633 move_points_denomlen
= strlen(denomstr
);
636 /****************************************************************************
637 Render positive movement points as text, including fractional movement
638 points, scaled by SINGLE_MOVE. Returns a pointer to a static buffer.
639 'reduce' is whether fractional movement points should be reduced to
640 lowest terms (this might be confusing in some cases).
641 'prefix' is a string put in front of all numeric output.
642 'none' is the string to display in place of the integer part if no
643 movement points (or NULL to just say 0).
644 'align' controls whether this is for a fixed-width table, in which case
645 padding spaces will be included to make all such strings line up when
647 ****************************************************************************/
648 const char *move_points_text_full(int mp
, bool reduce
, const char *prefix
,
649 const char *none
, bool align
)
651 static struct astring str
= ASTRING_INIT
;
654 if (align
&& SINGLE_MOVE
> 1) {
655 /* Align to worst-case denominator even if we might be reducing to
656 * lowest terms, as other entries in a table might not reduce */
657 pad1
= move_points_denomlen
; /* numerator or denominator */
658 pad2
= move_points_denomlen
*2+2; /* everything right of integer part */
660 /* If no possible fractional part, alignment unneeded even if requested */
667 if ((mp
== 0 && none
) || SINGLE_MOVE
== 0) {
668 /* No movement points, and we have a special representation to use */
669 /* (Also used when SINGLE_MOVE==0, to avoid dividing by zero, which is
670 * important for client before ruleset has been received. Doesn't much
671 * matter what we print in this case.) */
672 astr_add(&str
, "%s%*s", none
? none
: "", pad2
, "");
673 } else if ((mp
% SINGLE_MOVE
) == 0) {
674 /* Integer move points */
675 astr_add(&str
, "%s%d%*s", prefix
, mp
/ SINGLE_MOVE
, pad2
, "");
677 /* Fractional part */
680 fc_assert(SINGLE_MOVE
> 1);
682 /* Reduce to lowest terms */
684 /* Calculate greatest common divisor with Euclid's algorithm */
694 /* No cancellation */
697 if (mp
< SINGLE_MOVE
) {
698 /* Fractional move points */
699 astr_add(&str
, "%s%*d/%*d", prefix
,
700 pad1
, (mp
% SINGLE_MOVE
) / cancel
, pad1
, SINGLE_MOVE
/ cancel
);
702 /* Integer + fractional move points */
704 "%s%d %*d/%*d", prefix
, mp
/ SINGLE_MOVE
,
705 pad1
, (mp
% SINGLE_MOVE
) / cancel
, pad1
, SINGLE_MOVE
/ cancel
);
708 return astr_str(&str
);
711 /****************************************************************************
712 Simple version of move_points_text_full() -- render positive movement
713 points as text without any prefix or alignment.
714 ****************************************************************************/
715 const char *move_points_text(int mp
, bool reduce
)
717 return move_points_text_full(mp
, reduce
, NULL
, NULL
, FALSE
);