From 60c0d35c7aa617e5a81563f7a0606ba66dad00a6 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 17 Dec 2022 14:12:36 +0200 Subject: [PATCH 3/3] AI: Don't consider negative EFT_GROWTH_FOOD effective Several places were checking if the EFT_GROWTH_VALUE is exactly 0. Turned those to consider negative values similar way (actual effect is clipped between 0 ... 100) See osdn #46290 Signed-off-by: Marko Lindqvist --- ai/default/aicity.c | 6 +++--- ai/default/daieffects.c | 2 ++ server/cityturn.c | 22 ++++++++++++---------- server/cityturn.h | 4 +++- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/ai/default/aicity.c b/ai/default/aicity.c index 05b38b185b..8f83054a74 100644 --- a/ai/default/aicity.c +++ b/ai/default/aicity.c @@ -518,7 +518,7 @@ static void dai_spend_gold(struct ai_type *ait, struct player *pplayer) if (is_unit_choice_type(bestchoice.type) && utype_is_cityfounder(bestchoice.value.utype)) { - if (get_city_bonus(pcity, EFT_GROWTH_FOOD) == 0 + if (get_city_bonus(pcity, EFT_GROWTH_FOOD) <= 0 && bestchoice.value.utype->pop_cost > 0 && city_size_get(pcity) <= bestchoice.value.utype->pop_cost) { /* Don't buy settlers in cities that cannot afford the population cost. */ @@ -635,8 +635,8 @@ static int unit_foodbox_cost(struct unit *punit) int cost = 0; int i; - /* The default is to lose 100%. The growth bonus reduces this. */ - int foodloss_pct = 100 - get_city_bonus(pcity, EFT_GROWTH_FOOD); + /* The default is to lose 100%. The growth bonus reduces this. */ + int foodloss_pct = 100 - city_granary_savings(pcity); foodloss_pct = CLIP(0, foodloss_pct, 100); fc_assert_ret_val(pcity != NULL, -1); diff --git a/ai/default/daieffects.c b/ai/default/daieffects.c index 53d0228c57..436c8f9b3c 100644 --- a/ai/default/daieffects.c +++ b/ai/default/daieffects.c @@ -277,6 +277,8 @@ adv_want dai_effect_value(struct player *pplayer, struct government *gov, break; } case EFT_GROWTH_FOOD: + /* FIXME: As total value is clipped 0 ... 100, single + * effect should have no value at all in some cases. */ v += c * 4 + (amount / 7) * pcity->surplus[O_FOOD]; break; case EFT_HEALTH_PCT: diff --git a/server/cityturn.c b/server/cityturn.c index a02aa0e6df..5c51965fcd 100644 --- a/server/cityturn.c +++ b/server/cityturn.c @@ -465,7 +465,7 @@ static void city_turn_notify(const struct city *pcity, turns_growth = (city_granary_size(city_size_get(pcity)) - pcity->food_stock - 1) / pcity->surplus[O_FOOD]; - if (0 == get_city_bonus(pcity, EFT_GROWTH_FOOD) + if (get_city_bonus(pcity, EFT_GROWTH_FOOD) <= 0 && 0 < get_current_construction_bonus(pcity, EFT_GROWTH_FOOD, RPT_CERTAIN) && 0 < pcity->surplus[O_SHIELD]) { @@ -796,7 +796,7 @@ void city_repair_size(struct city *pcity, int change) Normally this value is 0% but this can be increased by EFT_GROWTH_FOOD effects. **************************************************************************/ -static int granary_savings(const struct city *pcity) +int city_granary_savings(const struct city *pcity) { int savings = get_city_bonus(pcity, EFT_GROWTH_FOOD); @@ -812,8 +812,9 @@ static int granary_savings(const struct city *pcity) static void city_reset_foodbox(struct city *pcity, int new_size) { fc_assert_ret(pcity != NULL); + pcity->food_stock = (city_granary_size(new_size) - * granary_savings(pcity)) / 100; + * city_granary_savings(pcity)) / 100; } /************************************************************************** @@ -824,16 +825,16 @@ static void city_reset_foodbox(struct city *pcity, int new_size) static bool city_increase_size(struct city *pcity, struct player *nationality) { int new_food; - int savings_pct = granary_savings(pcity); + int savings_pct = city_granary_savings(pcity); bool have_square = FALSE; - bool rapture_grow = city_rapture_grow(pcity); /* check before size increase! */ + bool rapture_grow = city_rapture_grow(pcity); /* Check before size increase! */ struct tile *pcenter = city_tile(pcity); struct player *powner = city_owner(pcity); struct impr_type *pimprove = pcity->production.value.building; int saved_id = pcity->id; if (!city_can_grow_to(pcity, city_size_get(pcity) + 1)) { - /* need improvement */ + /* Need improvement */ if (get_current_construction_bonus(pcity, EFT_SIZE_ADJ, RPT_CERTAIN) > 0 || get_current_construction_bonus(pcity, EFT_SIZE_UNLIMIT, RPT_CERTAIN) > 0) { notify_player(powner, city_tile(pcity), E_CITY_AQ_BUILDING, ftc_server, @@ -880,7 +881,7 @@ static bool city_increase_size(struct city *pcity, struct player *nationality) && is_city_option_set(pcity, CITYO_NEW_EINSTEIN)) { pcity->specialists[best_specialist(O_SCIENCE, pcity)]++; } else if ((pcity->surplus[O_FOOD] >= 2 || !have_square) - && is_city_option_set(pcity, CITYO_NEW_TAXMAN)) { + && is_city_option_set(pcity, CITYO_NEW_TAXMAN)) { pcity->specialists[best_specialist(O_GOLD, pcity)]++; } else { pcity->specialists[DEFAULT_SPECIALIST]++; /* or else city is !sane */ @@ -1018,7 +1019,8 @@ static void city_populate(struct city *pcity, struct player *nationality) if (city_exist(saved_id)) { city_reset_foodbox(pcity, city_size_get(pcity)); } - return; + + return; } } unit_list_iterate_safe_end; if (city_size_get(pcity) > 1) { @@ -1029,8 +1031,8 @@ static void city_populate(struct city *pcity, struct player *nationality) } else { notify_player(city_owner(pcity), city_tile(pcity), E_CITY_FAMINE, ftc_server, - _("Famine destroys %s entirely."), - city_link(pcity)); + _("Famine destroys %s entirely."), + city_link(pcity)); } city_reset_foodbox(pcity, city_size_get(pcity) - 1); city_reduce_size(pcity, 1, NULL, "famine"); diff --git a/server/cityturn.h b/server/cityturn.h index 92b2da91eb..ac6e12dd8c 100644 --- a/server/cityturn.h +++ b/server/cityturn.h @@ -1,4 +1,4 @@ -/********************************************************************** +/*********************************************************************** Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,6 +36,8 @@ bool city_reduce_size(struct city *pcity, citizens pop_loss, struct player *destroyer, const char *reason); void city_repair_size(struct city *pcity, int change); +int city_granary_savings(const struct city *pcity); + void send_city_turn_notifications(struct connection *pconn); void update_city_activities(struct player *pplayer); int city_incite_cost(struct player *pplayer, struct city *pcity); -- 2.35.1