Bug #1564 » 3_4-airlift_possible_corr1.patch
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
|