From ac98b83746ae39003ec950e5bf592aabf8e44937 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 16 Jan 2022 13:06:48 +0200 Subject: [PATCH 15/15] AI: Avoid infinite recursion with AI settlers When ruleset has city founding restrictions that AI code is not yet prepared for, AI was retrying it in infinite recursion. After this change AI just aborts handling of that settler when city founding fails because of such reason it does not understand. This is far from ideal as the settler then does nothing, but at least this prevents server from crashing. Reported by lexxie9952 See osdn #43638 Signed-off-by: Marko Lindqvist --- ai/default/aisettler.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/ai/default/aisettler.c b/ai/default/aisettler.c index decc7a1f9b..a79a5e9a04 100644 --- a/ai/default/aisettler.c +++ b/ai/default/aisettler.c @@ -183,6 +183,8 @@ struct cityresult { int city_radius_sq; /* current squared radius of the city */ }; +enum cb_error_level { CBE_OK, CBE_RECOVERABLE, CBE_FATAL }; + static const struct tile_data_cache *tdc_plr_get(struct ai_type *ait, struct player *plr, int tindex); @@ -213,8 +215,9 @@ static struct cityresult *find_best_city_placement(struct ai_type *ait, struct unit *punit, bool look_for_boat, bool use_virt_boat); -static bool dai_do_build_city(struct ai_type *ait, struct player *pplayer, - struct unit *punit); +static enum cb_error_level dai_do_build_city(struct ai_type *ait, + struct player *pplayer, + struct unit *punit); /***************************************************************************** Allocated a city result. @@ -1047,14 +1050,19 @@ BUILD_CITY: return; } if (same_pos(unit_tile(punit), ptile)) { - if (!dai_do_build_city(ait, pplayer, punit)) { + enum cb_error_level elevel = dai_do_build_city(ait, pplayer, punit); + + if (elevel != CBE_OK) { UNIT_LOG(LOG_DEBUG, punit, "could not make city on %s", tile_get_info_text(unit_tile(punit), TRUE, 0)); dai_unit_new_task(ait, punit, AIUNIT_NONE, NULL); - /* Only known way to end in here is that hut turned in to a city - * when settler entered tile. So this is not going to lead in any - * serious recursion. */ - dai_auto_settler_run(ait, pplayer, punit, state); + + if (elevel == CBE_RECOVERABLE) { + /* Only known way to end in here is that hut turned in to a city + * when settler entered tile. So this is not going to lead in any + * serious recursion. */ + dai_auto_settler_run(ait, pplayer, punit, state); + } return; } else { @@ -1232,8 +1240,9 @@ void dai_auto_settler_free(struct ai_plr *ai) /************************************************************************** Build a city and initialize AI infrastructure cache. **************************************************************************/ -static bool dai_do_build_city(struct ai_type *ait, struct player *pplayer, - struct unit *punit) +static enum cb_error_level dai_do_build_city(struct ai_type *ait, + struct player *pplayer, + struct unit *punit) { struct tile *ptile = unit_tile(punit); struct city *pcity; @@ -1250,7 +1259,7 @@ static bool dai_do_build_city(struct ai_type *ait, struct player *pplayer, * and it turned in to a city when settler entered tile. */ log_debug("%s: There is already a city at (%d, %d)!", player_name(pplayer), TILE_XY(ptile)); - return FALSE; + return CBE_RECOVERABLE; } handle_unit_do_action(pplayer, punit->id, ptile->index, 0, city_name_suggestion(pplayer, ptile), @@ -1270,8 +1279,9 @@ static bool dai_do_build_city(struct ai_type *ait, struct player *pplayer, /* The request was illegal to begin with. */ log_error("%s: Failed to build city at (%d, %d). Reason id: %d", player_name(pplayer), TILE_XY(ptile), reason); + return CBE_FATAL; } - return FALSE; + return CBE_RECOVERABLE; } /* We have to rebuild at least the cache for this city. This event is @@ -1283,7 +1293,7 @@ static bool dai_do_build_city(struct ai_type *ait, struct player *pplayer, /* Init ai.choice. Handling ferryboats might use it. */ adv_init_choice(&def_ai_city_data(pcity, ait)->choice); - return TRUE; + return CBE_OK; } /************************************************************************** -- 2.34.1