From 4e6a5c64f4b371cd2abb2bfff7dedcf0787c45d5 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Wed, 14 Jun 2023 11:16:30 +0300 Subject: [PATCH 28/28] Make action_by_result_iterate() to go over cached list No point in iterating over all the actions, and then to pick just one or two that match the result. See osdn #47904 Signed-off-by: Marko Lindqvist --- ai/default/aiferry.c | 10 +++++----- ai/default/daicity.c | 4 ++-- ai/default/daimilitary.c | 35 +++++++++++++++++----------------- client/control.c | 5 ++--- client/helpdata.c | 4 ++-- client/packhand.c | 12 ++++++------ common/actions.c | 26 +++++++++++++++++++++++++ common/actions.h | 29 +++++++++++++++++----------- common/city.c | 4 ++-- common/fc_types.h | 2 ++ common/movement.c | 2 +- common/unit.c | 8 ++++---- common/unittype.c | 6 +++--- server/advisors/advdata.c | 8 ++++---- server/advisors/autosettlers.h | 14 +++++++------- server/rscompat.c | 11 +++++------ server/rssanity.c | 4 ++-- server/ruleset.c | 4 ++-- 18 files changed, 110 insertions(+), 78 deletions(-) diff --git a/ai/default/aiferry.c b/ai/default/aiferry.c index fb4faab4b4..6fe2508b96 100644 --- a/ai/default/aiferry.c +++ b/ai/default/aiferry.c @@ -836,9 +836,8 @@ bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, return FALSE; } - action_by_result_iterate(paction, act_id, ACTRES_TRANSPORT_BOARD) { - if (action_prob_possible(action_prob_vs_unit(punit, - paction->id, + action_by_result_iterate(paction, ACTRES_TRANSPORT_BOARD) { + if (action_prob_possible(action_prob_vs_unit(punit, paction->id, ferryboat))) { if (unit_perform_action(pplayer, punit->id, ferryboat->id, 0, "", @@ -901,7 +900,7 @@ bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, fc_assert(same_pos(unit_tile(punit), unit_tile(bodyguard))); /* Bodyguard either uses the same boat or none at all. */ - action_by_result_iterate(paction, act_id, ACTRES_TRANSPORT_BOARD) { + action_by_result_iterate(paction, ACTRES_TRANSPORT_BOARD) { if (action_prob_possible(action_prob_vs_unit(bodyguard, paction->id, ferryboat))) { @@ -913,8 +912,9 @@ bool aiferry_gobyboat(struct ai_type *ait, struct player *pplayer, } } action_by_result_iterate_end; } + if (!aiferry_goto_amphibious(ait, ferryboat, punit, dest_tile)) { - /* died */ + /* Died */ return FALSE; } if (same_pos(unit_tile(punit), dest_tile)) { diff --git a/ai/default/daicity.c b/ai/default/daicity.c index ef4f77501a..287d9f3a12 100644 --- a/ai/default/daicity.c +++ b/ai/default/daicity.c @@ -412,7 +412,7 @@ static void dai_upgrade_units(struct city *pcity, int limit, bool military) continue; } - action_list_iterate(upgrade_actions, act_id) { + action_array_iterate(upgrade_actions, act_id) { if (action_ever_possible(act_id)) { const struct action *paction = action_by_number(act_id); int cost = unit_upgrade_price(pplayer, old_type, punittype); @@ -438,7 +438,7 @@ static void dai_upgrade_units(struct city *pcity, int limit, bool military) increase_maxbuycost(pplayer, cost); } } - } action_list_iterate_end; + } action_array_iterate_end; } } unit_list_iterate_end; } diff --git a/ai/default/daimilitary.c b/ai/default/daimilitary.c index 1ea9b65eaf..6cb422eb4b 100644 --- a/ai/default/daimilitary.c +++ b/ai/default/daimilitary.c @@ -561,35 +561,34 @@ static unsigned int assess_danger_unit(const struct city *pcity, } /* Find the worst attack action to expect */ - action_by_result_iterate(paction, id, ACTRES_ATTACK) { + action_by_result_iterate(paction, ACTRES_ATTACK) { /* Is it possible that punit will do action id to the city? */ - int b; - if (action_may_happen_unit_on_city(id, punit, pcity, *move_time)) { + if (action_may_happen_unit_on_city(paction->id, punit, pcity, *move_time)) { + int b; + attack_danger = TRUE; - } else { - continue; - } - b = get_unittype_bonus(uowner, ptile, punittype, paction, EFT_ATTACK_BONUS); - if (b > amod) { - amod = b; + + b = get_unittype_bonus(uowner, ptile, punittype, paction, EFT_ATTACK_BONUS); + if (b > amod) { + amod = b; + } } } action_by_result_iterate_end; /* FIXME: it's a dummy support for anti-bombard defense just to do something against * approaching bombarders. Some better logic is needed, see OSDN#41778 */ if (!attack_danger) { - action_by_result_iterate(paction, id, ACTRES_BOMBARD) { - int b; + action_by_result_iterate(paction, ACTRES_BOMBARD) { + if (action_may_happen_unit_on_city(paction->id, punit, pcity, *move_time)) { + int b; - if (action_may_happen_unit_on_city(id, punit, pcity, *move_time)) { attack_danger = TRUE; - } else { - continue; - } - b = get_unittype_bonus(uowner, ptile, punittype, paction, EFT_ATTACK_BONUS); - if (b > amod) { - amod = b; + + b = get_unittype_bonus(uowner, ptile, punittype, paction, EFT_ATTACK_BONUS); + if (b > amod) { + amod = b; + } } } action_by_result_iterate_end; /* Here something should be done cuz the modifier affects diff --git a/client/control.c b/client/control.c index d8d28d0a87..4ed4bc2d50 100644 --- a/client/control.c +++ b/client/control.c @@ -2051,7 +2051,7 @@ void request_unit_load(struct unit *pcargo, struct unit *ptrans, if (ptrans && can_client_issue_orders() && could_unit_load(pcargo, ptrans)) { - action_by_result_iterate(paction, act_id, + action_by_result_iterate(paction, same_pos(unit_tile(pcargo), ptile) ? ACTRES_TRANSPORT_BOARD : ACTRES_TRANSPORT_EMBARK) { @@ -2060,8 +2060,7 @@ void request_unit_load(struct unit *pcargo, struct unit *ptrans, /* Try the first action that may be legal. */ /* Implement something like do_disband_alternative() if a ruleset * appears where this isn't good enough. */ - request_do_action(paction->id, - pcargo->id, ptrans->id, 0, ""); + request_do_action(paction->id, pcargo->id, ptrans->id, 0, ""); break; } } action_by_result_iterate_end; diff --git a/client/helpdata.c b/client/helpdata.c index b7d850721a..0251051b25 100644 --- a/client/helpdata.c +++ b/client/helpdata.c @@ -1348,12 +1348,12 @@ char *helptext_building(char *buf, size_t bufsz, struct player *pplayer, action_list_end(nuke_actions, i); } - action_list_iterate(nuke_actions, act_id) { + action_array_iterate(nuke_actions, act_id) { if (num_role_units(action_id_get_role(act_id)) > 0) { u = get_role_unit(action_id_get_role(act_id), 0); break; } - } action_list_iterate_end; + } action_array_iterate_end; if (u) { if (advance_number(u->require_advance) != A_NONE) { diff --git a/client/packhand.c b/client/packhand.c index b4baa7709f..5770d0e364 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -1662,7 +1662,7 @@ void handle_unit_info(const struct packet_unit_info *packet) static void action_decision_handle(struct unit *punit) { if (!gui_options.popup_attack_actions) { - action_list_iterate(auto_attack_actions, act_id) { + action_array_iterate(auto_attack_actions, act_id) { if (utype_can_do_action(unit_type_get(punit), act_id)) { /* An auto action like auto attack could be legal. Check for those * at once so they won't have to wait for player focus. */ @@ -1674,7 +1674,7 @@ static void action_decision_handle(struct unit *punit) REQEST_BACKGROUND_FAST_AUTO_ATTACK); return; } - } action_list_iterate_end; + } action_array_iterate_end; } /* This should be done in the foreground */ @@ -5000,7 +5000,7 @@ static action_id auto_attack_act(const struct act_prob *act_probs) { action_id attack_action = ACTION_NONE; - action_list_iterate(auto_attack_actions, act_id) { + action_array_iterate(auto_attack_actions, act_id) { if (action_prob_possible(act_probs[act_id])) { /* An attack. */ if (attack_action == ACTION_NONE) { @@ -5011,13 +5011,13 @@ static action_id auto_attack_act(const struct act_prob *act_probs) return ACTION_NONE; } } - } action_list_iterate_end; - action_list_iterate(auto_attack_blockers, act_id) { + } action_array_iterate_end; + action_array_iterate(auto_attack_blockers, act_id) { if (action_prob_possible(act_probs[act_id])) { /* An interesting non attack action has been found. */ return ACTION_NONE; } - } action_list_iterate_end; + } action_array_iterate_end; return attack_action; } diff --git a/common/actions.c b/common/actions.c index 17971bf0ed..89372773bc 100644 --- a/common/actions.c +++ b/common/actions.c @@ -143,6 +143,8 @@ static struct act_prob ap_diplomat_battle(const struct unit *pattacker, FC_STATIC_ASSERT(MAP_DISTANCE_MAX <= ACTION_DISTANCE_LAST_NON_SIGNAL, action_range_can_not_cover_the_whole_map); +static struct action_list *actlist_by_result[ACTRES_LAST]; + /**********************************************************************//** Returns a new array of alternative action enabler contradictions. Only one has to not contradict the enabler for it to be seen as fulfilled. @@ -1458,6 +1460,10 @@ void actions_init(void) { int i, j; + for (i = 0; i < ACTRES_LAST; i++) { + actlist_by_result[i] = action_list_new(); + } + /* Hard code the actions */ hard_code_actions(); @@ -1554,6 +1560,11 @@ void actions_free(void) } astr_free(&ui_name_str); + + for (i = 0; i < ACTRES_LAST; i++) { + action_list_destroy(actlist_by_result[i]); + actlist_by_result[i] = NULL; + } } /**********************************************************************//** @@ -1598,6 +1609,11 @@ static struct action *action_new(action_id id, action->id = id; action->result = result; + + if (result != ACTRES_LAST) { + action_list_append(actlist_by_result[result], action); + } + /* Not set here */ BV_CLR_ALL(action->sub_results); @@ -9276,3 +9292,13 @@ const char *action_target_kind_help(enum action_target_kind kind) return _(atk_helpnames[kind]); } + +/************************************************************************//** + Returns action id list by result. +****************************************************************************/ +struct action_list *action_list_by_result(enum action_result result) +{ + fc_assert(result < ACTRES_LAST); + + return actlist_by_result[result]; +} diff --git a/common/actions.h b/common/actions.h index 5a357735b8..6c2a5b3f27 100644 --- a/common/actions.h +++ b/common/actions.h @@ -472,16 +472,23 @@ struct action_enabler } \ } -#define action_by_result_iterate(_paction_, _act_id_, _result_) \ +/* Get 'struct action_id_list' and related functions: */ +#define SPECLIST_TAG action +#define SPECLIST_TYPE struct action +#include "speclist.h" + +#define action_list_iterate(_list_, _act_) \ + TYPED_LIST_ITERATE(struct action, _list_, _act_) +#define action_list_iterate_end LIST_ITERATE_END + +struct action_list *action_list_by_result(enum action_result result); + +#define action_by_result_iterate(_paction_, _result_) \ { \ - action_iterate(_act_id_) { \ - struct action *_paction_ = action_by_number(_act_id_); \ - if (!action_has_result(_paction_, _result_)) { \ - continue; \ - } + action_list_iterate(action_list_by_result(_result_), _paction_) { \ #define action_by_result_iterate_end \ - } action_iterate_end; \ + } action_list_iterate_end; \ } #define action_by_activity_iterate(_paction_, _act_id_, _activity_) \ @@ -496,7 +503,7 @@ struct action_enabler } action_iterate_end; \ } -#define action_list_iterate(_act_list_, _act_id_) \ +#define action_array_iterate(_act_list_, _act_id_) \ { \ int _pos_; \ \ @@ -508,7 +515,7 @@ struct action_enabler break; \ } -#define action_list_iterate_end \ +#define action_array_iterate_end \ } \ } @@ -599,10 +606,10 @@ action_auto_perf_iterate(_act_perf_) { \ } action_auto_perf_iterate_end #define action_auto_perf_actions_iterate(_autoperf_, _act_id_) \ - action_list_iterate(_autoperf_->alternatives, _act_id_) + action_array_iterate(_autoperf_->alternatives, _act_id_) #define action_auto_perf_actions_iterate_end \ - action_list_iterate_end + action_array_iterate_end /* Hard coded location of action auto performers. Used for conversion while * action auto performers aren't directly exposed to the ruleset. */ diff --git a/common/city.c b/common/city.c index 63b53b2e42..d4e35b9619 100644 --- a/common/city.c +++ b/common/city.c @@ -1447,8 +1447,8 @@ bool city_can_be_built_here(const struct tile *ptile, return TRUE; } - action_by_result_iterate(paction, act_id, ACTRES_FOUND_CITY) { - if (!utype_can_do_action(unit_type_get(punit), act_id)) { + action_by_result_iterate(paction, ACTRES_FOUND_CITY) { + if (!utype_can_do_action(unit_type_get(punit), paction->id)) { /* This action can't be done by this unit type at all. */ continue; } diff --git a/common/fc_types.h b/common/fc_types.h index ffc829bf54..387e964eff 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -301,6 +301,8 @@ enum output_type_id { #define SPECENUM_COUNT ACTRES_NONE #include "specenum_gen.h" +#define ACTRES_LAST ACTRES_NONE + /* Used in the network protocol. */ #define SPECENUM_NAME action_sub_result /* Will enter each enterable hut at the target tile */ diff --git a/common/movement.c b/common/movement.c index ce1e4c3900..e95361b174 100644 --- a/common/movement.c +++ b/common/movement.c @@ -130,7 +130,7 @@ int utype_unknown_move_cost(const struct unit_type *utype) /* Move cost from effects. */ worst_effect_mc = 0; - action_by_result_iterate(paction, act_id, ACTRES_UNIT_MOVE) { + action_by_result_iterate(paction, ACTRES_UNIT_MOVE) { struct universal req_pattern[] = { { .kind = VUT_ACTION, .value.action = paction }, { .kind = VUT_UTYPE, .value.utype = utype }, diff --git a/common/unit.c b/common/unit.c index 0d5d2ca08d..119f28ef4c 100644 --- a/common/unit.c +++ b/common/unit.c @@ -816,13 +816,13 @@ bool can_unit_alight_or_be_unloaded(const struct unit *pcargo, **************************************************************************/ bool can_unit_paradrop(const struct unit *punit) { - action_by_result_iterate(paction, act_id, ACTRES_PARADROP) { - if (action_maybe_possible_actor_unit(act_id, punit)) { + action_by_result_iterate(paction, ACTRES_PARADROP) { + if (action_maybe_possible_actor_unit(paction->id, punit)) { return TRUE; } } action_by_result_iterate_end; - action_by_result_iterate(paction, act_id, ACTRES_PARADROP_CONQUER) { - if (action_maybe_possible_actor_unit(act_id, punit)) { + action_by_result_iterate(paction, ACTRES_PARADROP_CONQUER) { + if (action_maybe_possible_actor_unit(paction->id, punit)) { return TRUE; } } action_by_result_iterate_end; diff --git a/common/unittype.c b/common/unittype.c index d29be9b207..52b6bd1fba 100644 --- a/common/unittype.c +++ b/common/unittype.c @@ -461,7 +461,7 @@ bool utype_can_do_action_result(const struct unit_type *putype, { fc_assert_ret_val(putype, FALSE); - action_by_result_iterate(paction, act_id, result) { + action_by_result_iterate(paction, result) { if (utype_can_do_action(putype, paction->id)) { return TRUE; } @@ -1031,7 +1031,7 @@ bool utype_can_do_action_result_when_ustate(const struct unit_type *putype, { fc_assert_ret_val(putype, FALSE); - action_by_result_iterate(paction, act_id, result) { + action_by_result_iterate(paction, result) { if (utype_can_do_act_when_ustate(putype, paction->id, prop, is_there)) { return TRUE; } @@ -1281,7 +1281,7 @@ bool utype_is_consumed_by_action(const struct action *paction, bool utype_is_consumed_by_action_result(enum action_result result, const struct unit_type *utype) { - action_by_result_iterate(paction, act_id, result) { + action_by_result_iterate(paction, result) { if (!utype_can_do_action(utype, paction->id)) { continue; } diff --git a/server/advisors/advdata.c b/server/advisors/advdata.c index abb3ba92f2..ac98abfb4b 100644 --- a/server/advisors/advdata.c +++ b/server/advisors/advdata.c @@ -364,15 +364,15 @@ bool adv_data_phase_init(struct player *pplayer, bool is_new_phase) } /* If they build nukes, worry a lot. */ - action_list_iterate(nuke_actions, act_id) { + action_array_iterate(nuke_actions, act_id) { if (unit_can_do_action(punit, act_id)) { danger_of_nukes = TRUE; } - } action_list_iterate_end; + } action_array_iterate_end; } unit_list_iterate_end; /* Check for nuke capability */ - action_list_iterate(nuke_actions, act_id) { + action_array_iterate(nuke_actions, act_id) { int i; int nuke_units = num_role_units(action_id_get_role(act_id)); @@ -384,7 +384,7 @@ bool adv_data_phase_init(struct player *pplayer, bool is_new_phase) adv->threats.nuclear = 1; } } - } action_list_iterate_end; + } action_array_iterate_end; } players_iterate_end; /* Increase from fear to terror if opponent actually has nukes */ diff --git a/server/advisors/autosettlers.h b/server/advisors/autosettlers.h index 3933b8fa5d..01d7ee3fd4 100644 --- a/server/advisors/autosettlers.h +++ b/server/advisors/autosettlers.h @@ -69,30 +69,30 @@ extern action_id as_actions_transform[MAX_NUM_ACTIONS]; #define as_transform_action_iterate(_act_) \ { \ - action_list_iterate(as_actions_transform, _act_) + action_array_iterate(as_actions_transform, _act_) #define as_transform_action_iterate_end \ - action_list_iterate_end \ + action_array_iterate_end \ } extern action_id as_actions_extra[MAX_NUM_ACTIONS]; #define as_extra_action_iterate(_act_) \ { \ - action_list_iterate(as_actions_extra, _act_) + action_array_iterate(as_actions_extra, _act_) #define as_extra_action_iterate_end \ - action_list_iterate_end \ + action_array_iterate_end \ } extern action_id as_actions_rmextra[MAX_NUM_ACTIONS]; #define as_rmextra_action_iterate(_act_) \ { \ - action_list_iterate(as_actions_rmextra, _act_) + action_array_iterate(as_actions_rmextra, _act_) #define as_rmextra_action_iterate_end \ - action_list_iterate_end \ + action_array_iterate_end \ } -#endif /* FC__AUTOSETTLERS_H */ +#endif /* FC__AUTOSETTLERS_H */ diff --git a/server/rscompat.c b/server/rscompat.c index 91b279ca7f..38085ab763 100644 --- a/server/rscompat.c +++ b/server/rscompat.c @@ -945,7 +945,7 @@ void rscompat_postprocess(struct rscompat_info *info) effect_req_append(peffect, req_from_str("UnitFlag", "Local", FALSE, TRUE, TRUE, "OneAttack")); - action_by_result_iterate(paction, act_id, ACTRES_ATTACK) { + action_by_result_iterate(paction, ACTRES_ATTACK) { if (paction->actor_consuming_always) { /* Not relevant. */ continue; @@ -996,10 +996,10 @@ void rscompat_postprocess(struct rscompat_info *info) continue; } - action_by_result_iterate(paction, act_id, ACTRES_PARADROP) { + action_by_result_iterate(paction, ACTRES_PARADROP) { paratroopers_mr_sub_to_effect(putype, paction); } action_by_result_iterate_end; - action_by_result_iterate(paction, act_id, ACTRES_PARADROP_CONQUER) { + action_by_result_iterate(paction, ACTRES_PARADROP_CONQUER) { paratroopers_mr_sub_to_effect(putype, paction); } action_by_result_iterate_end; } unit_type_iterate_end; @@ -1608,8 +1608,7 @@ void rscompat_postprocess(struct rscompat_info *info) action_enablers_for_action(ACTION_PARADROP), ae) { struct action_enabler *edit; - action_by_result_iterate(para_action, para_id, - ACTRES_PARADROP_CONQUER) { + action_by_result_iterate(para_action, ACTRES_PARADROP_CONQUER) { /* Conquer City and/or owned Extra during war if one is there */ edit = action_enabler_copy(ae); edit->action = para_action->id; @@ -1671,7 +1670,7 @@ void rscompat_postprocess(struct rscompat_info *info) } extra_type_by_cause_iterate_end; } action_by_result_iterate_end; - action_by_result_iterate(para_action, para_id, ACTRES_PARADROP) { + action_by_result_iterate(para_action, ACTRES_PARADROP) { if (para_action->id == ACTION_PARADROP) { /* Use when not at war and against unclaimed tiles. */ e_req = req_from_values(VUT_CITYTILE, REQ_RANGE_LOCAL, diff --git a/server/rssanity.c b/server/rssanity.c index eba8da046b..b867a98a20 100644 --- a/server/rssanity.c +++ b/server/rssanity.c @@ -1594,8 +1594,8 @@ bool autoadjust_ruleset_data(void) enum action_result blocked_result = must_block[i].blocked; enum action_result blocker_result = must_block[i].blocker; - action_by_result_iterate (blocked, blocker_id, blocked_result) { - action_by_result_iterate (blocker, blocked_id, blocker_result) { + action_by_result_iterate(blocked, blocked_result) { + action_by_result_iterate(blocker, blocker_result) { if (!action_would_be_blocked_by(blocked, blocker)) { log_verbose("Autoblocking %s with %s", action_rule_name(blocked), diff --git a/server/ruleset.c b/server/ruleset.c index 64f2dde924..99ac05ff98 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -7287,7 +7287,7 @@ static bool load_ruleset_game(struct section_file *file, bool act, /* Hard code action sub results for now. */ /* Unit Enter Hut */ - action_by_result_iterate(paction, act_id, ACTRES_HUT_ENTER) { + action_by_result_iterate(paction, ACTRES_HUT_ENTER) { BV_SET(paction->sub_results, ACT_SUB_RES_HUT_ENTER); } action_by_result_iterate_end; BV_SET(action_by_number(ACTION_PARADROP_ENTER)->sub_results, @@ -7296,7 +7296,7 @@ static bool load_ruleset_game(struct section_file *file, bool act, ACT_SUB_RES_HUT_ENTER); /* Unit Frighten Hut */ - action_by_result_iterate(paction, act_id, ACTRES_HUT_FRIGHTEN) { + action_by_result_iterate(paction, ACTRES_HUT_FRIGHTEN) { BV_SET(paction->sub_results, ACT_SUB_RES_HUT_FRIGHTEN); } action_by_result_iterate_end; BV_SET(action_by_number(ACTION_PARADROP_FRIGHTEN)->sub_results, -- 2.39.2