From 3f81f634b3036f745853772ab02cec85af09b914 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Tue, 4 Apr 2023 22:28:01 +0300 Subject: [PATCH 14/14] 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 | 45 ++++++++++++++++++++-------------------- ai/default/aiunit.h | 8 ++++--- ai/default/daimilitary.c | 33 ++++++++++++++++------------- 4 files changed, 49 insertions(+), 41 deletions(-) diff --git a/ai/default/aidiplomat.c b/ai/default/aidiplomat.c index 7d5b25b74e..5a0f8187fa 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 f72f3de7e7..018a7797cb 100644 --- a/ai/default/aiunit.c +++ b/ai/default/aiunit.c @@ -312,43 +312,44 @@ int unittype_def_rating_squared(const struct unit_type *att_type, } /************************************************************************** -Compute how much we want to kill certain victim we've chosen, counted in -SHIELDs. + Compute how much we want to kill certain victim we've chosen, counted in + SHIELDs. -FIXME?: The equation is not accurate as the other values can vary for other -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 + FIXME?: The equation is not accurate as the other values can vary for other + 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. + 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) + 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) **************************************************************************/ -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 @@ -1144,7 +1145,7 @@ int 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 4c61e630c4..ef53abe486 100644 --- a/ai/default/aiunit.h +++ b/ai/default/aiunit.h @@ -108,7 +108,8 @@ bool find_beachhead(const struct player *pplayer, struct pf_map *ferry_map, struct tile **ferry_dest, struct tile **beachhead_tile); int 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, struct unit_type **pboattype, @@ -119,7 +120,8 @@ int unittype_def_rating_squared(const struct unit_type *att_type, const struct unit_type *def_type, const 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); +adv_want kill_desire(adv_want benefit, int attack, int loss, int vuln, + int attack_count); bool is_on_unit_upgrade_path(const struct unit_type *test, const struct unit_type *base); @@ -161,4 +163,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 caf267ceb7..535aae97e5 100644 --- a/ai/default/daimilitary.c +++ b/ai/default/daimilitary.c @@ -828,7 +828,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(punittype) + tech_cost)); + (desire * total_want + / (utype_build_shield_cost(punittype) + tech_cost)); } } } simple_ai_unit_type_iterate_end; @@ -903,7 +904,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, struct unit_type *victim_unit_type, struct player *victim_player, int veteran, struct tile *ptile, @@ -1114,7 +1115,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), @@ -1150,23 +1152,26 @@ static void process_attacker_want(struct ai_type *ait, } /************************************************************************** -This function -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) -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. + This function + 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() ) + 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. **************************************************************************/ -static struct adv_choice *kill_something_with(struct ai_type *ait, struct player *pplayer, - struct city *pcity, struct unit *myunit, +static struct adv_choice *kill_something_with(struct ai_type *ait, + struct player *pplayer, + struct city *pcity, + struct unit *myunit, struct adv_choice *choice) { /* 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; struct unit_type *def_type; -- 2.39.2