From 83efb2f0a7b8e7192baf111a539eac66a1c89957 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Mon, 4 Sep 2023 12:19:18 +0300 Subject: [PATCH 22/22] Lua: Fix Unit:is_on_possible_city_tile() See osdn #48582 Signed-off-by: Marko Lindqvist --- ai/default/daisettler.c | 5 +++-- client/gui-gtk-3.22/editprop.c | 2 +- client/gui-gtk-4.0/editprop.c | 2 +- client/mapview_common.c | 10 +++++----- client/tilespec.c | 2 +- common/city.c | 26 ++++++++++++++++++++++++-- common/city.h | 11 ++++++----- common/scriptcore/api_game_methods.c | 6 +++++- server/citytools.c | 2 +- 9 files changed, 47 insertions(+), 19 deletions(-) diff --git a/ai/default/daisettler.c b/ai/default/daisettler.c index fcfa772345..efa6546fdf 100644 --- a/ai/default/daisettler.c +++ b/ai/default/daisettler.c @@ -707,7 +707,7 @@ struct cityresult *city_desirability(struct ai_type *ait, struct player *pplayer fc_assert_ret_val(punit, NULL); fc_assert_ret_val(pplayer, NULL); - if (!city_can_be_built_here(ptile, punit) + if (!city_can_be_built_here(ptile, punit, FALSE) || (has_handicap(pplayer, H_MAP) && !map_is_known(ptile, pplayer))) { return NULL; @@ -1037,10 +1037,11 @@ BUILD_CITY: /* Check that the mission is still possible. If the tile has become * unavailable, call it off. */ - if (!city_can_be_built_here(ptile, punit)) { + if (!city_can_be_built_here(ptile, punit, FALSE)) { dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL); set_unit_activity(punit, ACTIVITY_IDLE); send_unit_info(NULL, punit); + return; /* Avoid recursion at all cost */ } else { /* Go there */ diff --git a/client/gui-gtk-3.22/editprop.c b/client/gui-gtk-3.22/editprop.c index 75fd39639f..234a0dc695 100644 --- a/client/gui-gtk-3.22/editprop.c +++ b/client/gui-gtk-3.22/editprop.c @@ -5826,7 +5826,7 @@ static void property_page_create_objects(struct property_page *pp, if (pplayer && hint_tiles) { tile_list_iterate(hint_tiles, atile) { if (!is_enemy_unit_tile(atile, pplayer) - && city_can_be_built_here(atile, NULL)) { + && city_can_be_built_here(atile, NULL, FALSE)) { ptile = atile; break; } diff --git a/client/gui-gtk-4.0/editprop.c b/client/gui-gtk-4.0/editprop.c index 0ea24f350d..542ef91f57 100644 --- a/client/gui-gtk-4.0/editprop.c +++ b/client/gui-gtk-4.0/editprop.c @@ -5849,7 +5849,7 @@ static void property_page_create_objects(struct property_page *pp, if (pplayer && hint_tiles) { tile_list_iterate(hint_tiles, atile) { if (!is_enemy_unit_tile(atile, pplayer) - && city_can_be_built_here(atile, NULL)) { + && city_can_be_built_here(atile, NULL, FALSE)) { ptile = atile; break; } diff --git a/client/mapview_common.c b/client/mapview_common.c index f89772ec21..b84b563f80 100644 --- a/client/mapview_common.c +++ b/client/mapview_common.c @@ -2873,21 +2873,21 @@ struct city *find_city_or_settler_near_tile(const struct tile *ptile, if ((NULL == client.conn.playing || unit_owner(psettler) == client.conn.playing) && unit_can_do_action(psettler, ACTION_FOUND_CITY) - && city_can_be_built_here(unit_tile(psettler), psettler)) { - if (!closest_settler) { + && city_can_be_built_here(unit_tile(psettler), psettler, FALSE)) { + if (closest_settler == NULL) { closest_settler = psettler; } - if (!best_settler && psettler->client.colored) { + if (best_settler == NULL && psettler->client.colored) { best_settler = psettler; } } } unit_list_iterate_end; } city_tile_iterate_end; - if (best_settler) { + if (best_settler != NULL) { /* Rule e */ *punit = best_settler; - } else if (closest_settler) { + } else if (closest_settler != NULL) { /* Rule f */ *punit = closest_settler; } diff --git a/client/tilespec.c b/client/tilespec.c index 81a01dcc5e..6b8f79d461 100644 --- a/client/tilespec.c +++ b/client/tilespec.c @@ -5521,7 +5521,7 @@ bool unit_drawn_with_city_outline(const struct unit *punit, bool check_focus) && unit_is_cityfounder(punit) && !unit_has_orders(punit) && (client_tile_get_known(unit_tile(punit)) != TILE_UNKNOWN - && city_can_be_built_here(unit_tile(punit), punit)) + && city_can_be_built_here(unit_tile(punit), punit, FALSE)) && (!check_focus || unit_is_in_focus(punit)); } diff --git a/common/city.c b/common/city.c index 428a5bda9f..b850fea97f 100644 --- a/common/city.c +++ b/common/city.c @@ -1463,8 +1463,11 @@ bool citymindist_prevents_city_on_tile(const struct tile *ptile) blue (e.g., through editing). **************************************************************************/ bool city_can_be_built_here(const struct tile *ptile, - const struct unit *punit) + const struct unit *punit, + bool hut_test) { + struct civ_map *nmap = &(wld.map); + if (!city_can_be_built_tile_only(ptile)) { return FALSE; } @@ -1474,6 +1477,25 @@ bool city_can_be_built_here(const struct tile *ptile, return TRUE; } + if (hut_test) { + struct player *towner; + + /* Huts can be found only from native tiles, owned by the unit owner. + * Unlike actual city building, this behavior is not affected + * by the ruleset. */ + if (!can_unit_exist_at_tile(nmap, punit, ptile)) { + return FALSE; + } + + towner = tile_owner(ptile); + + if (towner == NULL || towner == unit_owner(punit)) { + return TRUE; + } + + return FALSE; + } + action_by_result_iterate(paction, ACTRES_FOUND_CITY) { if (!utype_can_do_action(unit_type_get(punit), action_id(paction))) { /* This action can't be done by this unit type at all. */ @@ -1481,7 +1503,7 @@ bool city_can_be_built_here(const struct tile *ptile, } /* Non native tile detection */ - if (!can_unit_exist_at_tile(&(wld.map), punit, ptile) + if (!can_unit_exist_at_tile(nmap, punit, ptile) /* The ruleset may allow founding cities on non native terrain. */ && !utype_can_do_act_when_ustate(unit_type_get(punit), paction->id, USP_LIVABLE_TILE, FALSE)) { diff --git a/common/city.h b/common/city.h index 0485dfb4bd..9c508c800e 100644 --- a/common/city.h +++ b/common/city.h @@ -683,11 +683,11 @@ void generate_city_map_indices(void); void free_city_map_index(void); void city_production_caravan_shields_init(void); -/* output on spot */ +/* Output on spot */ int city_tile_output(const struct city *pcity, const struct tile *ptile, - bool is_celebrating, Output_type_id otype); + bool is_celebrating, Output_type_id otype); int city_tile_output_now(const struct city *pcity, const struct tile *ptile, - Output_type_id otype); + Output_type_id otype); bool base_city_can_work_tile(const struct player *restriction, const struct city *pcity, @@ -697,10 +697,11 @@ bool city_can_work_tile(const struct city *pcity, const struct tile *ptile); bool citymindist_prevents_city_on_tile(const struct tile *ptile); bool city_can_be_built_here(const struct tile *ptile, - const struct unit *punit); + const struct unit *punit, + bool hut_test); bool city_can_be_built_tile_only(const struct tile *ptile); -/* list functions */ +/* List functions */ struct city *city_list_find_number(struct city_list *This, int id); struct city *city_list_find_name(struct city_list *This, const char *name); diff --git a/common/scriptcore/api_game_methods.c b/common/scriptcore/api_game_methods.c index 942ae2a599..183b43d3d9 100644 --- a/common/scriptcore/api_game_methods.c +++ b/common/scriptcore/api_game_methods.c @@ -1312,13 +1312,17 @@ int api_methods_tile_sq_distance(lua_State *L, Tile *ptile1, Tile *ptile2) /**********************************************************************//** Can punit found a city on its tile? + + FIXME: Unlike name suggests, this is currently used for finding + cities from huts and the like, and is not suitable for checking + if specified unit could act to build a city. **************************************************************************/ bool api_methods_unit_city_can_be_built_here(lua_State *L, Unit *punit) { LUASCRIPT_CHECK_STATE(L, FALSE); LUASCRIPT_CHECK_SELF(L, punit, FALSE); - return city_can_be_built_here(unit_tile(punit), punit); + return city_can_be_built_here(unit_tile(punit), punit, TRUE); } /**********************************************************************//** diff --git a/server/citytools.c b/server/citytools.c index 4ccdd8fced..0bfe43cb8a 100644 --- a/server/citytools.c +++ b/server/citytools.c @@ -1673,7 +1673,7 @@ bool create_city_for_player(struct player *pplayer, struct tile *ptile, const char *name) { if (is_enemy_unit_tile(ptile, pplayer) - || !city_can_be_built_here(ptile, nullptr)) { + || !city_can_be_built_here(ptile, nullptr, FALSE)) { return FALSE; } -- 2.40.1