Project

General

Profile

Bug #1564 » 3_4-airlift_possible_corr1.patch

Alexandr Ignatiev, 07/07/2025 11:34 PM

View differences:

common/movement.c
return is_native_tile(utype, ptile);
}
/************************************************************************//**
Return if a unit of utype could possibly "exist" at the city tile of pcity
given the information known to pov_player. pcity is presumed to exist.
nmap is supposed to be client map.
This means it can physically be present on the tile (without the use of a
transporter). See can_exist_at_tile() for the omniscient check.
****************************************************************************/
bool could_exist_in_city(const struct civ_map *nmap,
const struct player *pov_player,
const struct unit_type *utype,
const struct city *pcity)
{
struct unit_class *uclass;
struct tile *ctile;
fc_assert_ret_val(nullptr != pcity && nullptr != utype, FALSE);
ctile = city_tile(pcity);
uclass = utype_class(utype);
if (uclass_has_flag(uclass, UCF_BUILD_ANYWHERE)) {
/* If the city stands, it can exist there */
return TRUE;
}
adjc_iterate(nmap, ctile, ptile) {
if (!tile_is_seen(ptile, pov_player)
|| is_native_tile_to_class(uclass, ptile)) {
/* Could be native. This ignores a rare case when we don't see
* only the city center and any native terrain is NoCities */
return TRUE;
}
} adjc_iterate_end;
if (1 == game.info.citymindist
&& is_city_channel_tile(nmap, uclass, ctile, nullptr)) {
/* FIXME: false negative results for city channels might appear */
/* Channeled. */
return TRUE;
}
/* It definitely can't exist there */
return FALSE;
}
/************************************************************************//**
Return TRUE iff the unit can "exist" at this location. This means it can
physically be present on the tile (without the use of a transporter). See
common/movement.h
bool can_exist_at_tile(const struct civ_map *nmap,
const struct unit_type *utype,
const struct tile *ptile);
bool could_exist_in_city(const struct civ_map *nmap,
const struct player *pov_player,
const struct unit_type *utype,
const struct city *pcity);
bool can_unit_exist_at_tile(const struct civ_map *nmap,
const struct unit *punit, const struct tile *ptile);
bool can_unit_survive_at_tile(const struct civ_map *nmap,
common/unit.c
{
const struct city *psrc_city = tile_city(unit_tile(punit));
const struct player *punit_owner;
const struct tile *dst_tile = nullptr;
const struct unit_type *putype = unit_type_get(punit);
bool flagless = utype_has_flag(putype, UTYF_FLAGLESS);
enum unit_airlift_result ok_result = AR_OK;
if (0 == punit->moves_left
&& !utype_may_act_move_frags(unit_type_get(punit),
ACTION_AIRLIFT, 0)) {
&& !utype_may_act_move_frags(putype, ACTION_AIRLIFT, 0)) {
/* No moves left. */
return AR_NO_MOVES;
}
......
return AR_OCCUPIED;
}
if (NULL == psrc_city) {
if (nullptr == psrc_city) {
/* No city there. */
return AR_NOT_IN_CITY;
}
......
return AR_BAD_DST_CITY;
}
if (pdest_city
&& (NULL == restriction
|| (tile_get_known(city_tile(pdest_city), restriction)
== TILE_KNOWN_SEEN))
&& !can_unit_exist_at_tile(nmap, punit, city_tile(pdest_city))) {
/* Can't exist at the destination tile. */
return AR_BAD_DST_CITY;
if (nullptr != pdest_city) {
dst_tile = city_tile(pdest_city);
if (nullptr != restriction
? !can_exist_at_tile(nmap, putype, dst_tile)
: !could_exist_in_city(nmap, restriction, putype, pdest_city)) {
/* Can't exist at the destination tile. */
return AR_BAD_DST_CITY;
}
}
punit_owner = unit_owner(punit);
......
return AR_BAD_SRC_CITY;
}
if (pdest_city
&& punit_owner != city_owner(pdest_city)
&& !(game.info.airlifting_style & AIRLIFTING_ALLIED_DEST
&& pplayers_allied(punit_owner, city_owner(pdest_city)))) {
/* Not allowed to airlift to this destination. */
return AR_BAD_DST_CITY;
/* Check diplomatic possibility of the destination */
if (nullptr != pdest_city) {
if (punit_owner != city_owner(pdest_city)) {
if (!(game.info.airlifting_style & AIRLIFTING_ALLIED_DEST
&& pplayers_allied(punit_owner, city_owner(pdest_city)))
|| flagless || is_non_allied_unit_tile(dst_tile, punit_owner, FALSE)) {
/* Not allowed to airlift to this destination. */
return AR_BAD_DST_CITY;
}
} else if (flagless
&& is_non_allied_unit_tile(dst_tile, punit_owner, TRUE)) {
/* Foreign units block airlifting to this destination */
return AR_BAD_DST_CITY;
}
}
if (NULL == restriction || city_owner(psrc_city) == restriction) {
/* We know for sure whether or not src can airlift this turn. */
if (0 >= psrc_city->airlift
&& (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)
|| !game.info.airlift_from_always_enabled)) {
/* The source cannot airlift for this turn (maybe already airlifted
* or no airport).
* See also do_airline() in server/unittools.h. */
return AR_SRC_NO_FLIGHTS;
} /* else, there is capacity; continue to other checks */
} else {
/* We don't have access to the 'airlift' field. Assume it's OK; can
* only find out for sure by trying it. */
ok_result = AR_OK_SRC_UNKNOWN;
/* Check airlift capacities */
if (!game.info.airlift_from_always_enabled) {
if (nullptr == restriction || city_owner(psrc_city) == restriction) {
/* We know for sure whether or not src can airlift this turn. */
if (0 >= psrc_city->airlift
&& !(game.info.airlifting_style & AIRLIFTING_UNLIMITED_SRC)) {
/* The source cannot airlift for this turn (maybe already airlifted
* or no airport).
* See also do_airline() in server/unittools.h. */
return AR_SRC_NO_FLIGHTS;
} /* else, there is capacity; continue to other checks */
} else {
/* We don't have access to the 'airlift' field. Assume it's OK; can
* only find out for sure by trying it. */
ok_result = AR_OK_SRC_UNKNOWN;
}
}
if (pdest_city) {
if (NULL == restriction || city_owner(pdest_city) == restriction) {
if (nullptr != pdest_city && !game.info.airlift_to_always_enabled) {
if (nullptr == restriction || city_owner(pdest_city) == restriction) {
if (0 >= pdest_city->airlift
&& (!(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)
|| !game.info.airlift_to_always_enabled)) {
&& !(game.info.airlifting_style & AIRLIFTING_UNLIMITED_DEST)) {
/* The destination cannot support airlifted units for this turn
* (maybe already airlifted or no airport).
* See also do_airline() in server/unittools.h. */
server/unittools.c
/**********************************************************************//**
Moves a unit. No checks whatsoever! This is meant as a practical
function for other functions, like do_airline(), which do the checking
themselves.
either by themselves or by their callers
If you move a unit you should always use this function, as it also sets
the transport status of the unit correctly. Note that the source tile (the
(2-2/8)