From 28ec78528c9bcf6d5bf34f8a12b9c95d60c491b9 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 26 Mar 2023 12:24:12 +0300 Subject: [PATCH 02/17] AI: Make kill_desire() to handle want as adv_want That's what callers are expecting, and it both - Adds sub-integer accuracy with low values - Avoids overflows with high values Overflows reported by mortmann Debugging and testing by alain_bkr See osdn #46286 Signed-off-by: Marko Lindqvist --- ai/default/aidiplomat.c | 4 ++-- ai/default/aiunit.c | 29 +++++++++++++++-------------- ai/default/aiunit.h | 11 +++++++---- ai/default/daimilitary.c | 13 ++++++++----- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/ai/default/aidiplomat.c b/ai/default/aidiplomat.c index de491fc147..3fb37f23d4 100644 --- a/ai/default/aidiplomat.c +++ b/ai/default/aidiplomat.c @@ -263,8 +263,8 @@ void dai_choose_diplomat_offensive(struct ai_type *ait, /* Discourage long treks */ time_to_dest *= ((time_to_dest + 1) / 2); - /* Almost kill_desire */ - want = (p_success * gain - p_failure * loss) / 100 + /* Almost kill_desire() */ + want = (adv_want)(p_success * gain - p_failure * loss) / 100 - SHIELD_WEIGHTING * time_to_dest; if (want <= 0) { return; diff --git a/ai/default/aiunit.c b/ai/default/aiunit.c index 5571cd31b4..0af0be36fb 100644 --- a/ai/default/aiunit.c +++ b/ai/default/aiunit.c @@ -320,36 +320,37 @@ int unittype_def_rating_squared(const struct unit_type *att_type, victims on same tile (we take values from best defender) - however I believe it's accurate just enough now and lost speed isn't worth that. --pasky - Benefit is something like 'attractiveness' of the victim, how nice it would be - to destroy it. Larger value, worse loss for enemy. + Benefit is something like 'attractiveness' of the victim, how nice it + would be to destroy it. Larger value, worse loss for enemy. - Attack is the total possible attack power we can throw on the victim. Note that - it usually comes squared. + Attack is the total possible attack power we can throw on the victim. + Note that it usually comes squared. - Loss is the possible loss when we would lose the unit we are attacking with (in - SHIELDs). + Loss is the possible loss when we would lose the unit we are attacking with + (in SHIELDs). Vuln is vulnerability of our unit when attacking the enemy. Note that it usually comes squared as well. Victim count is number of victims stacked in the target tile. Note that we - shouldn't treat cities as a stack (despite the code using this function) - the - scaling is probably different. (extremely dodgy usage of it -- GB) + shouldn't treat cities as a stack (despite the code using this function) - + the scaling is probably different. (extremely dodgy usage of it -- GB) **************************************************************************/ -int kill_desire(int benefit, int attack, int loss, int vuln, int victim_count) +adv_want kill_desire(adv_want benefit, int attack, int loss, int vuln, + int victim_count) { - int desire; + adv_want desire; /* attractiveness danger */ - desire = (unsigned int) (benefit * attack - loss * vuln) * victim_count * - SHIELD_WEIGHTING / (attack + vuln * victim_count); + desire = (benefit * attack - loss * vuln) * victim_count + * SHIELD_WEIGHTING / (attack + vuln * victim_count); return desire; } /**********************************************************************//** Compute how much we want to kill certain victim we've chosen, counted in - SHIELDs. See comment to kill_desire. + SHIELDs. See comment to kill_desire(). chance -- the probability the action will succeed, benefit -- the benefit (in shields) that we are getting in the case of @@ -1145,7 +1146,7 @@ adv_want find_something_to_kill(struct ai_type *ait, struct player *pplayer, bool harbor = FALSE; /* Do we have access to sea? */ bool go_by_boat; /* Whether we need a boat or not. */ int vulnerability; /* Enemy defense rating. */ - int benefit; /* Benefit from killing the target. */ + adv_want benefit; /* Benefit from killing the target. */ struct unit *pdefender; /* Enemy city defender. */ int move_time; /* Turns needed to target. */ int reserves; diff --git a/ai/default/aiunit.h b/ai/default/aiunit.h index 502381e0ad..3cb46c10f2 100644 --- a/ai/default/aiunit.h +++ b/ai/default/aiunit.h @@ -109,7 +109,8 @@ bool find_beachhead(const struct player *pplayer, struct pf_map *ferry_map, struct tile **ferry_dest, struct tile **beachhead_tile); adv_want find_something_to_kill(struct ai_type *ait, struct player *pplayer, struct unit *punit, - struct tile **pdest_tile, struct pf_path **ppath, + struct tile **pdest_tile, + struct pf_path **ppath, struct pf_map **pferrymap, struct unit **pferryboat, const struct unit_type **pboattype, @@ -119,8 +120,10 @@ int build_cost_balanced(const struct unit_type *punittype); int unittype_def_rating_squared(const struct unit_type *att_type, const struct unit_type *def_type, struct player *def_player, - struct tile *ptile, bool fortified, int veteran); -int kill_desire(int benefit, int attack, int loss, int vuln, int attack_count); + struct tile *ptile, bool fortified, + int veteran); +adv_want kill_desire(adv_want benefit, int attack, int loss, int vuln, + int attack_count); const struct impr_type *utype_needs_improvement(const struct unit_type *putype, const struct city *pcity); @@ -165,4 +168,4 @@ bool dai_unit_can_strike_my_unit(const struct unit *attacker, void dai_switch_to_explore(struct ai_type *ait, struct unit *punit, struct tile *target, enum override_bool *allow); -#endif /* FC__AIUNIT_H */ +#endif /* FC__AIUNIT_H */ diff --git a/ai/default/daimilitary.c b/ai/default/daimilitary.c index 2f70508aea..22a3ef8c88 100644 --- a/ai/default/daimilitary.c +++ b/ai/default/daimilitary.c @@ -1118,7 +1118,8 @@ bool dai_process_defender_want(struct ai_type *ait, struct player *pplayer, /* Yes, there's some similarity with kill_desire(). */ /* TODO: Explain what shield cost has to do with tech want. */ tech_desire[utype_index(punittype)] = - (desire * total_want / (utype_build_shield_cost(pcity, NULL, punittype) + tech_cost)); + (desire * total_want + / (utype_build_shield_cost(pcity, NULL, punittype) + tech_cost)); } } } simple_ai_unit_type_iterate_end; @@ -1193,7 +1194,7 @@ bool dai_process_defender_want(struct ai_type *ait, struct player *pplayer, **************************************************************************/ static void process_attacker_want(struct ai_type *ait, struct city *pcity, - int value, + adv_want value, const struct unit_type *victim_unit_type, struct player *victim_player, int veteran, struct tile *ptile, @@ -1408,7 +1409,8 @@ static void process_attacker_want(struct ai_type *ait, CITY_LOG(LOG_DEBUG, pcity, "overriding %s(" ADV_WANT_PRINTF ") with %s(" ADV_WANT_PRINTF ")" - " [attack=%d,value=%d,move_time=%d,vuln=%d,bcost=%d]", + " [attack=%d,value=" ADV_WANT_PRINTF + ",move_time=%d,vuln=%d,bcost=%d]", utype_rule_name(best_choice->value.utype), best_choice->want, utype_rule_name(punittype), @@ -1449,7 +1451,8 @@ static void process_attacker_want(struct ai_type *ait, 1. receives (in myunit) a first estimate of what we would like to build. 2. finds a potential victim for it. 3. calculates the relevant stats of the victim. - 4. finds the best attacker for this type of victim (in process_attacker_want) + 4. finds the best attacker for this type of victim + (in process_attacker_want() ) 5. if we still want to attack, records the best attacker in choice. If the target is overseas, the function might suggest building a ferry to carry a land attack unit, instead of the land attack unit itself. @@ -1462,7 +1465,7 @@ static struct adv_choice *kill_something_with(struct ai_type *ait, /* Our attack rating (with reinforcements) */ int attack; /* Benefit from fighting the target */ - int benefit; + adv_want benefit; /* Defender of the target city/tile */ struct unit *pdef; const struct unit_type *def_type; -- 2.39.2