From b9ba01269019a005841d4e32745c80471b63f894 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sat, 3 Dec 2022 21:58:10 +0200 Subject: [PATCH 50/50] AI: Check that hunt target is targetable Fixes segfault when there's nobody to attack at target's tile Reported by Lexxie See osdn #46176 Signed-off-by: Marko Lindqvist --- ai/default/aihunt.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/ai/default/aihunt.c b/ai/default/aihunt.c index 2f6755efb2..26068c4d8c 100644 --- a/ai/default/aihunt.c +++ b/ai/default/aihunt.c @@ -473,6 +473,8 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, int sanity_target = target->id; struct pf_path *path; struct unit_ai *target_data; + struct tile *target_tile; + struct unit *defender; /* Note that we need not (yet) be at war with aplayer */ if (!adv_is_player_dangerous(pplayer, aplayer)) { @@ -492,6 +494,12 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, continue; } + target_tile = unit_tile(target); + if (!unit_attack_unit_at_tile_result(punit, NULL, target, target_tile)) { + /* We can't attack the target */ + continue; + } + /* Figure out whether unit is coming closer */ if (target_data->cur_pos && target_data->prev_pos) { dist1 = real_map_distance(unit_tile(punit), *target_data->cur_pos); @@ -501,7 +509,7 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, } UNIT_LOG(LOGLEVEL_HUNT, punit, "considering chasing %s[%d](%d, %d) " "dist1 %d dist2 %d", - unit_rule_name(target), target->id, TILE_XY(unit_tile(target)), + unit_rule_name(target), target->id, TILE_XY(target_tile), dist1, dist2); /* We can't chase if we aren't faster or on intercept vector */ @@ -516,17 +524,17 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, target_data->prev_pos ? index_to_map_pos_y(tile_index(*target_data->prev_pos)) : -1, - TILE_XY(unit_tile(target))); + TILE_XY(target_tile)); continue; } /* Calculate juiciness of target, compare with existing target, * if any. */ dai_hunter_juiciness(pplayer, punit, target, &stackthreat, &stackcost); - stackcost *= unit_win_chance(punit, get_defender(punit, - unit_tile(target), - NULL), - NULL); + defender = get_defender(punit, target_tile, NULL); + if (defender != NULL) { + stackcost *= unit_win_chance(punit, defender, NULL); + } if (stackcost < unit_build_shield_cost_base(punit)) { UNIT_LOG(LOGLEVEL_HUNT, punit, "%d is too expensive (it %d vs us %d)", target->id, stackcost, @@ -551,7 +559,7 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, nation_rule_name(nation_of_unit(target)), unit_rule_name(target), target->id, - TILE_XY(unit_tile(target)), + TILE_XY(target_tile), stackthreat, dist1, dist2); @@ -563,7 +571,7 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, } /* This assigns missiles to us */ - dai_unit_new_task(ait, punit, AIUNIT_HUNTER, unit_tile(target)); + dai_unit_new_task(ait, punit, AIUNIT_HUNTER, target_tile); /* Check if we can nuke it */ dai_hunter_try_launch(ait, pplayer, punit, target); @@ -577,7 +585,7 @@ int dai_hunter_manage(struct ai_type *ait, struct player *pplayer, } /* Go towards it. */ - path = pf_map_path(pfm, unit_tile(target)); + path = pf_map_path(pfm, target_tile); if (!adv_unit_execute_path(punit, path)) { pf_path_destroy(path); pf_map_destroy(pfm); -- 2.35.1