From 05baa20cedc01d347a590960748cddfe7d1afb01 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Wed, 14 Jun 2023 10:50:02 +0300 Subject: [PATCH 34/34] 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 | 20 ++++++++++++-------- ai/default/daimilitary.c | 37 +++++++++++++++++++------------------ client/control.c | 9 +++++---- common/actions.c | 26 ++++++++++++++++++++++++++ common/actions.h | 21 ++++++++++++++------- common/city.c | 4 ++-- common/movement.c | 4 ++-- common/unit.c | 12 ++++++------ common/unittype.c | 12 ++++++------ server/rssanity.c | 6 +++--- server/ruleset.c | 4 ++-- 11 files changed, 97 insertions(+), 58 deletions(-) diff --git a/ai/default/aiferry.c b/ai/default/aiferry.c index 4b15086a5f..78ecdbce12 100644 --- a/ai/default/aiferry.c +++ b/ai/default/aiferry.c @@ -834,13 +834,14 @@ 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) { + enum gen_action act_id = action_id(paction); + + if (action_prob_possible(action_prob_vs_unit(punit, act_id, ferryboat))) { if (unit_perform_action(pplayer, punit->id, ferryboat->id, 0, "", - paction->id, ACT_REQ_PLAYER)) { + act_id, ACT_REQ_PLAYER)) { board_success = TRUE; break; } @@ -899,20 +900,23 @@ 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) { + enum gen_action act_id = action_id(paction); + if (action_prob_possible(action_prob_vs_unit(bodyguard, - paction->id, + act_id, ferryboat))) { if (unit_perform_action(pplayer, bodyguard->id, ferryboat->id, 0, "", - paction->id, ACT_REQ_PLAYER)) { + act_id, ACT_REQ_PLAYER)) { break; } } } 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/daimilitary.c b/ai/default/daimilitary.c index 18ee57ceb4..4aa168d7d5 100644 --- a/ai/default/daimilitary.c +++ b/ai/default/daimilitary.c @@ -570,37 +570,38 @@ 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? */ /* FIXME: some unit parameters (notably, veterancy) may meddle in */ - int b; - if (action_may_happen_unit_on_city(id, punit, pcity, *move_time)) { + if (action_may_happen_unit_on_city(action_id(paction), 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) { + action_by_result_iterate(paction, ACTRES_BOMBARD) { /* FIXME: some unit parameters (notably, veterancy) may meddle in */ - int b; - if (action_may_happen_unit_on_city(id, punit, pcity, *move_time)) { + if (action_may_happen_unit_on_city(action_id(paction), 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; /* Here something should be done cuz the modifier affects diff --git a/client/control.c b/client/control.c index dd00b20148..326cad26c3 100644 --- a/client/control.c +++ b/client/control.c @@ -2129,17 +2129,18 @@ 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) { - if (action_prob_possible(action_prob_vs_unit(pcargo, paction->id, + enum gen_action act_id = action_id(paction); + + if (action_prob_possible(action_prob_vs_unit(pcargo, act_id, 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(act_id, pcargo->id, ptrans->id, 0, ""); break; } } action_by_result_iterate_end; diff --git a/common/actions.c b/common/actions.c index c3bceba4ae..cfe4b4d1de 100644 --- a/common/actions.c +++ b/common/actions.c @@ -141,6 +141,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. @@ -1530,6 +1532,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(); @@ -1626,6 +1632,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; + } } /**********************************************************************//** @@ -1670,6 +1681,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); @@ -8649,3 +8665,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 f9666f1f6b..1b8699418c 100644 --- a/common/actions.h +++ b/common/actions.h @@ -447,6 +447,17 @@ struct action_enabler } \ } +/* 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); + /* TODO: Turn this to an iteration over precalculated list */ #define action_noninternal_iterate(_act_) \ { \ @@ -458,16 +469,12 @@ struct action_enabler } action_iterate_end; \ } -#define action_by_result_iterate(_paction_, _act_id_, _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_) \ diff --git a/common/city.c b/common/city.c index f5b7e7a196..5af8065a5b 100644 --- a/common/city.c +++ b/common/city.c @@ -1468,8 +1468,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), action_id(paction))) { /* This action can't be done by this unit type at all. */ continue; } diff --git a/common/movement.c b/common/movement.c index d37deac332..a952dbe2b9 100644 --- a/common/movement.c +++ b/common/movement.c @@ -130,14 +130,14 @@ 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 }, }; int max_effect_mc; - if (!utype_can_do_action(utype, paction->id)) { + if (!utype_can_do_action(utype, action_id(paction))) { /* Not relevant. */ continue; } diff --git a/common/unit.c b/common/unit.c index 5979d5e68b..8c0aacff66 100644 --- a/common/unit.c +++ b/common/unit.c @@ -802,8 +802,8 @@ bool can_unit_deboard_or_be_unloaded(const struct unit *pcargo, **************************************************************************/ bool can_unit_teleport(const struct unit *punit) { - action_by_result_iterate(paction, act_id, ACTRES_TELEPORT) { - if (action_maybe_possible_actor_unit(act_id, punit)) { + action_by_result_iterate(paction, ACTRES_TELEPORT) { + if (action_maybe_possible_actor_unit(action_id(paction), punit)) { return TRUE; } } action_by_result_iterate_end; @@ -818,13 +818,13 @@ bool can_unit_teleport(const struct unit *punit) **************************************************************************/ 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(action_id(paction), 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(action_id(paction), punit)) { return TRUE; } } action_by_result_iterate_end; diff --git a/common/unittype.c b/common/unittype.c index f95ea25fe7..4363779350 100644 --- a/common/unittype.c +++ b/common/unittype.c @@ -389,8 +389,8 @@ 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) { - if (utype_can_do_action(putype, paction->id)) { + action_by_result_iterate(paction, result) { + if (utype_can_do_action(putype, action_id(paction))) { return TRUE; } } action_by_result_iterate_end; @@ -979,8 +979,8 @@ 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) { - if (utype_can_do_act_when_ustate(putype, paction->id, prop, is_there)) { + action_by_result_iterate(paction, result) { + if (utype_can_do_act_when_ustate(putype, action_id(paction), prop, is_there)) { return TRUE; } } action_by_result_iterate_end; @@ -1229,8 +1229,8 @@ 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) { - if (!utype_can_do_action(utype, paction->id)) { + action_by_result_iterate(paction, result) { + if (!utype_can_do_action(utype, action_id(paction))) { continue; } diff --git a/server/rssanity.c b/server/rssanity.c index 239e46fe53..63c50c4a8a 100644 --- a/server/rssanity.c +++ b/server/rssanity.c @@ -1616,13 +1616,13 @@ 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), action_rule_name(blocker)); - BV_SET(blocked->blocked_by, blocker->id); + BV_SET(blocked->blocked_by, action_id(blocker)); } } action_by_result_iterate_end; } action_by_result_iterate_end; diff --git a/server/ruleset.c b/server/ruleset.c index 52c8738184..9e42001ba2 100644 --- a/server/ruleset.c +++ b/server/ruleset.c @@ -7690,7 +7690,7 @@ static bool load_ruleset_actions(struct section_file *file, /* 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, @@ -7699,7 +7699,7 @@ static bool load_ruleset_actions(struct section_file *file, 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