From 02af577abadf8b11457aad9c9e40e090117d6404 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 18 Sep 2022 07:11:18 +0300 Subject: [PATCH 35/35] Reduce number or redundant advance_count() calls See osdn #45542 Signed-off-by: Marko Lindqvist --- ai/default/aitech.c | 44 +++++++++++++++------------- ai/default/daidiplomacy.c | 51 +++++++++++++++++---------------- client/gui-gtk-3.22/repodlgs.c | 9 +++--- client/gui-gtk-4.0/repodlgs.c | 9 +++--- client/gui-qt/repodlgs.cpp | 10 ++++--- client/gui-sdl2/action_dialog.c | 11 +++---- client/gui-sdl2/diplodlg.c | 9 +++--- client/gui-sdl2/repodlgs.c | 19 ++++++------ client/reqtree.c | 13 +++++---- common/research.c | 17 +++++------ common/tech.h | 20 +++++++++---- server/techtools.c | 45 +++++++++++++++++------------ 12 files changed, 144 insertions(+), 113 deletions(-) diff --git a/ai/default/aitech.c b/ai/default/aitech.c index 305b464604..485ad66971 100644 --- a/ai/default/aitech.c +++ b/ai/default/aitech.c @@ -76,6 +76,7 @@ static void dai_select_tech(struct ai_type *ait, int values[MAX(A_LAST, A_UNSET + 1)]; int goal_values[MAX(A_LAST, A_UNSET + 1)]; struct ai_plr *plr_data = def_ai_player_data(pplayer, ait); + Tech_type_id ac; memset(values, 0, sizeof(values)); values[A_UNSET] = -1; @@ -112,39 +113,40 @@ static void dai_select_tech(struct ai_type *ait, /* Fill in values for the techs: want of the tech * + average want of those we will discover en route */ - advance_index_iterate(A_FIRST, i) { + ac = advance_count(); + advance_index_iterate_max(A_FIRST, i, ac) { if (valid_advance_by_number(i)) { int steps = research_goal_unknown_techs(presearch, i); /* We only want it if we haven't got it (so AI is human after all) */ - if (steps > 0) { + if (steps > 0) { values[i] += plr_data->tech_want[i]; - advance_index_iterate(A_FIRST, k) { + advance_index_iterate_max(A_FIRST, k, ac) { if (research_goal_tech_req(presearch, i, k)) { values[k] += plr_data->tech_want[i] / steps; - } - } advance_index_iterate_end; + } + } advance_index_iterate_max_end; } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Fill in the values for the tech goals */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (valid_advance_by_number(i)) { int steps = research_goal_unknown_techs(presearch, i); if (steps == 0) { /* Can't be set as a goal any more */ goal_values[i] = -1; - continue; + continue; } - goal_values[i] = values[i]; - advance_index_iterate(A_FIRST, k) { + goal_values[i] = values[i]; + advance_index_iterate_max(A_FIRST, k, ac) { if (research_goal_tech_req(presearch, i, k)) { - goal_values[i] += values[k]; - } - } advance_index_iterate_end; + goal_values[i] += values[k]; + } + } advance_index_iterate_max_end; /* This is the best I could do. It still sometimes does freaky stuff * like setting goal to Republic and learning Monarchy, but that's what @@ -157,11 +159,11 @@ static void dai_select_tech(struct ai_type *ait, values[i], goal_values[i]); } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; newtech = A_UNSET; newgoal = A_UNSET; - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (valid_advance_by_number(i)) { if (values[i] > values[newtech] && research_invention_gettable(presearch, i, TRUE)) { @@ -169,19 +171,21 @@ static void dai_select_tech(struct ai_type *ait, } if (goal_values[i] > goal_values[newgoal] && research_invention_reachable(presearch, i)) { - newgoal = i; + newgoal = i; } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; + #ifdef REALLY_DEBUG_THIS - advance_index_iterate(A_FIRST, id) { + advance_index_iterate_max(A_FIRST, id, ac) { if (values[id] > 0 && research_invention_state(presearch, id) == TECH_PREREQS_KNOWN) { TECH_LOG(ait, LOG_DEBUG, pplayer, advance_by_number(id), - "turn end want: %d", values[id]); + "turn end want: %d", values[id]); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; #endif /* REALLY_DEBUG_THIS */ + if (choice) { choice->choice = newtech; choice->want = values[newtech] / num_cities_nonzero; diff --git a/ai/default/daidiplomacy.c b/ai/default/daidiplomacy.c index 0375a65725..125998c362 100644 --- a/ai/default/daidiplomacy.c +++ b/ai/default/daidiplomacy.c @@ -1161,20 +1161,21 @@ static void suggest_tech_exchange(struct ai_type *ait, struct research *presearch2 = research_get(player2); int worth[advance_count()]; bool is_dangerous; - + Tech_type_id ac = advance_count(); + worth[A_NONE] = 0; - advance_index_iterate(A_FIRST, tech) { + advance_index_iterate_max(A_FIRST, tech, ac) { if (research_invention_state(presearch1, tech) == TECH_KNOWN) { if (research_invention_state(presearch2, tech) != TECH_KNOWN && research_invention_gettable(presearch2, tech, game.info.tech_trade_allow_holes)) { worth[tech] = -compute_tech_sell_price(ait, player1, player2, tech, - &is_dangerous); - if (is_dangerous) { - /* don't try to exchange */ - worth[tech] = 0; - } + &is_dangerous); + if (is_dangerous) { + /* Don't try to exchange */ + worth[tech] = 0; + } } else { worth[tech] = 0; } @@ -1183,43 +1184,43 @@ static void suggest_tech_exchange(struct ai_type *ait, && research_invention_gettable(presearch1, tech, game.info.tech_trade_allow_holes)) { worth[tech] = compute_tech_sell_price(ait, player2, player1, tech, - &is_dangerous); - if (is_dangerous) { - /* don't try to exchange */ - worth[tech] = 0; - } + &is_dangerous); + if (is_dangerous) { + /* Don't try to exchange */ + worth[tech] = 0; + } } else { worth[tech] = 0; } } - } advance_index_iterate_end; - - advance_index_iterate(A_FIRST, tech) { + } advance_index_iterate_max_end; + + advance_index_iterate_max(A_FIRST, tech, ac) { if (worth[tech] <= 0) { continue; } - advance_index_iterate(A_FIRST, tech2) { + advance_index_iterate_max(A_FIRST, tech2, ac) { int diff; if (worth[tech2] >= 0) { continue; } - /* tech2 is given by player1, tech is given by player2 */ + /* Tech2 is given by player1, tech is given by player2 */ diff = worth[tech] + worth[tech2]; if ((diff > 0 && player1->economic.gold >= diff) || (diff < 0 && player2->economic.gold >= -diff) - || diff == 0) { + || diff == 0) { dai_diplomacy_suggest(player1, player2, CLAUSE_ADVANCE, FALSE, tech2); - dai_diplomacy_suggest(player1, player2, CLAUSE_ADVANCE, TRUE, tech); - if (diff > 0) { + dai_diplomacy_suggest(player1, player2, CLAUSE_ADVANCE, TRUE, tech); + if (diff > 0) { dai_diplomacy_suggest(player1, player2, CLAUSE_GOLD, FALSE, diff); - } else if (diff < 0) { + } else if (diff < 0) { dai_diplomacy_suggest(player1, player2, CLAUSE_GOLD, TRUE, -diff); - } - return; + } + return; } - } advance_index_iterate_end; - } advance_index_iterate_end; + } advance_index_iterate_max_end; + } advance_index_iterate_max_end; } /******************************************************************//** diff --git a/client/gui-gtk-3.22/repodlgs.c b/client/gui-gtk-3.22/repodlgs.c index c82847a679..de3256a036 100644 --- a/client/gui-gtk-3.22/repodlgs.c +++ b/client/gui-gtk-3.22/repodlgs.c @@ -389,6 +389,7 @@ static void science_report_update(struct science_report *preport) const char *text; double pct; Tech_type_id tech; + Tech_type_id ac = advance_count(); fc_assert_ret(NULL != preport); fc_assert_ret(NULL != presearch); @@ -419,11 +420,11 @@ static void science_report_update(struct science_report *preport) } /* Collect all techs which are reachable in the next step. */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (TECH_PREREQS_KNOWN == presearch->inventions[i].state) { sorting_list = g_list_prepend(sorting_list, GINT_TO_POINTER(i)); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Sort the list, append it to the store. */ sorting_list = g_list_sort(sorting_list, cmp_func); @@ -453,14 +454,14 @@ static void science_report_update(struct science_report *preport) } /* Collect all techs which are reachable in next 10 steps. */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_reachable(presearch, i) && TECH_KNOWN != presearch->inventions[i].state && (i == presearch->tech_goal || 10 >= presearch->inventions[i].num_required_techs)) { sorting_list = g_list_prepend(sorting_list, GINT_TO_POINTER(i)); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Sort the list, append it to the store. */ sorting_list = g_list_sort(sorting_list, cmp_func); diff --git a/client/gui-gtk-4.0/repodlgs.c b/client/gui-gtk-4.0/repodlgs.c index 994f101b73..e8bcf38d7a 100644 --- a/client/gui-gtk-4.0/repodlgs.c +++ b/client/gui-gtk-4.0/repodlgs.c @@ -428,6 +428,7 @@ static void science_report_update(struct science_report *preport) const char *text; double pct; Tech_type_id tech; + Tech_type_id ac = advance_count(); fc_assert_ret(NULL != preport); fc_assert_ret(NULL != presearch); @@ -458,11 +459,11 @@ static void science_report_update(struct science_report *preport) } /* Collect all techs which are reachable in the next step. */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (TECH_PREREQS_KNOWN == presearch->inventions[i].state) { sorting_list = g_list_prepend(sorting_list, GINT_TO_POINTER(i)); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Sort the list, append it to the store. */ sorting_list = g_list_sort(sorting_list, cmp_func); @@ -492,14 +493,14 @@ static void science_report_update(struct science_report *preport) } /* Collect all techs which are reachable in next 10 steps. */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_reachable(presearch, i) && TECH_KNOWN != presearch->inventions[i].state && (i == presearch->tech_goal || 10 >= presearch->inventions[i].num_required_techs)) { sorting_list = g_list_prepend(sorting_list, GINT_TO_POINTER(i)); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Sort the list, append it to the store. */ sorting_list = g_list_sort(sorting_list, cmp_func); diff --git a/client/gui-qt/repodlgs.cpp b/client/gui-qt/repodlgs.cpp index 337e80f35a..3499519a2b 100644 --- a/client/gui-qt/repodlgs.cpp +++ b/client/gui-qt/repodlgs.cpp @@ -970,6 +970,7 @@ void science_report::update_report() QString str; qlist_item item; struct sprite *sp; + Tech_type_id ac; fc_assert_ret(NULL != research); @@ -1008,7 +1009,8 @@ void science_report::update_report() } // Collect all techs which are reachable in the next step. - advance_index_iterate(A_FIRST, i) { + ac = advance_count(); + advance_index_iterate_max(A_FIRST, i, ac) { if (TECH_PREREQS_KNOWN == research->inventions[i].state) { item.tech_str = @@ -1016,11 +1018,11 @@ void science_report::update_report() item.id = i; curr_list->append(item); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; // Collect all techs which are reachable in next 10 steps. - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_reachable(research, i) && TECH_KNOWN != research->inventions[i].state && (i == research->tech_goal @@ -1030,7 +1032,7 @@ void science_report::update_report() item.id = i; goal_list->append(item); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; // Sort both lists std::sort(goal_list->begin(), goal_list->end(), comp_less_than); diff --git a/client/gui-sdl2/action_dialog.c b/client/gui-sdl2/action_dialog.c index 4c7b962e07..3459244843 100644 --- a/client/gui-sdl2/action_dialog.c +++ b/client/gui-sdl2/action_dialog.c @@ -340,9 +340,9 @@ static int spy_steal_popup_shared(struct widget *pwidget) int max_col, max_row, col, count = 0; int tech, idx; SDL_Rect area; - struct unit *actor_unit = game_unit_by_number(id); action_id act_id = diplomat_dlg->act_id; + Tech_type_id ac; is_more_user_input_needed = TRUE; popdown_diplomat_dialog(); @@ -361,14 +361,15 @@ static int spy_steal_popup_shared(struct widget *pwidget) count = 0; presearch = research_get(client_player()); vresearch = research_get(victim); - advance_index_iterate(A_FIRST, i) { + ac = advance_count(); + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_gettable(presearch, i, game.info.tech_steal_allow_holes) && TECH_KNOWN == research_invention_state(vresearch, i) && TECH_KNOWN != research_invention_state(presearch, i)) { count++; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (!count) { /* if there is no known tech to steal then @@ -455,7 +456,7 @@ static int spy_steal_popup_shared(struct widget *pwidget) pstr->style |= (TTF_STYLE_BOLD | SF_CENTER); count = 0; - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_gettable(presearch, i, game.info.tech_steal_allow_holes) && TECH_KNOWN == research_invention_state(vresearch, i) @@ -477,7 +478,7 @@ static int spy_steal_popup_shared(struct widget *pwidget) set_wflag(buf, WF_HIDDEN); } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Get Spy tech to use for "At Spy's Discretion" -- this will have the * side effect of displaying the unit's icon */ diff --git a/client/gui-sdl2/diplodlg.c b/client/gui-sdl2/diplodlg.c index 43987d10e5..03b8e15529 100644 --- a/client/gui-sdl2/diplodlg.c +++ b/client/gui-sdl2/diplodlg.c @@ -652,8 +652,9 @@ static struct advanced_dialog *popup_diplomatic_objects(struct player *pplayer0, const struct research *presearch0 = research_get(pplayer0); const struct research *presearch1 = research_get(pplayer1); int flag = A_NONE; + Tech_type_id ac = advance_count(); - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_state(presearch0, i) == TECH_KNOWN && research_invention_gettable(presearch1, i, game.info.tech_trade_allow_holes) @@ -686,10 +687,10 @@ static struct advanced_dialog *popup_diplomatic_objects(struct player *pplayer0, flag = ++i; break; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (flag > A_NONE) { - advance_index_iterate(flag, i) { + advance_index_iterate_max(flag, i, ac) { if (research_invention_state(presearch0, i) == TECH_KNOWN && research_invention_gettable(presearch1, i, game.info.tech_trade_allow_holes) @@ -712,7 +713,7 @@ static struct advanced_dialog *popup_diplomatic_objects(struct player *pplayer0, count++; } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; } /* Advances */ /* Trading: cities */ diff --git a/client/gui-sdl2/repodlgs.c b/client/gui-sdl2/repodlgs.c index 98651a8c01..66cffdbde7 100644 --- a/client/gui-sdl2/repodlgs.c +++ b/client/gui-sdl2/repodlgs.c @@ -2930,17 +2930,19 @@ static void popup_change_research_dialog(void) SDL_Surface *surf; int max_col, max_row, col, i, count = 0, h; SDL_Rect area; + Tech_type_id ac; if (is_future_tech(presearch->researching)) { return; } - advance_index_iterate(A_FIRST, aidx) { + ac = advance_count(); + advance_index_iterate_max(A_FIRST, aidx, ac) { if (!research_invention_gettable(presearch, aidx, FALSE)) { continue; } count++; - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (count < 2) { return; @@ -3003,7 +3005,7 @@ static void popup_change_research_dialog(void) count = 0; h = col * max_row; - advance_index_iterate(A_FIRST, aidx) { + advance_index_iterate_max(A_FIRST, aidx, ac) { if (!research_invention_gettable(presearch, aidx, FALSE)) { continue; } @@ -3023,7 +3025,7 @@ static void popup_change_research_dialog(void) if (count > h) { set_wflag(buf, WF_HIDDEN); } - } advance_index_iterate_end; + } advance_index_iterate_max_end; FREEUTF8STR(pstr); @@ -3117,18 +3119,19 @@ static void popup_change_research_goal_dialog(void) char cbuf[128]; int max_col, max_row, col, i, count = 0, h , num; SDL_Rect area; + Tech_type_id ac = advance_count(); /* Collect all techs which are reachable in under 11 steps * hist will hold afterwards the techid of the current choice */ - advance_index_iterate(A_FIRST, aidx) { + advance_index_iterate_max(A_FIRST, aidx, ac) { if (research_invention_reachable(presearch, aidx) && TECH_KNOWN != research_invention_state(presearch, aidx) && (11 > research_goal_unknown_techs(presearch, aidx) || aidx == presearch->tech_goal)) { count++; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (count < 1) { return; @@ -3195,7 +3198,7 @@ static void popup_change_research_goal_dialog(void) */ count = 0; h = col * max_row; - advance_index_iterate(A_FIRST, aidx) { + advance_index_iterate_max(A_FIRST, aidx, ac) { if (research_invention_reachable(presearch, aidx) && TECH_KNOWN != research_invention_state(presearch, aidx) && (11 > (num = research_goal_unknown_techs(presearch, aidx)) @@ -3220,7 +3223,7 @@ static void popup_change_research_goal_dialog(void) set_wflag(buf, WF_HIDDEN); } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; FREEUTF8STR(pstr); diff --git a/client/reqtree.c b/client/reqtree.c index 0ad467c17e..c68766c825 100644 --- a/client/reqtree.c +++ b/client/reqtree.c @@ -396,9 +396,10 @@ static struct reqtree *create_dummy_reqtree(struct player *pplayer, struct reqtree *tree = fc_malloc(sizeof(*tree)); int j; struct tree_node *nodes[advance_count()]; + Tech_type_id ac = advance_count(); nodes[A_NONE] = NULL; - advance_index_iterate(A_FIRST, tech) { + advance_index_iterate_max(A_FIRST, tech, ac) { if (!valid_advance_by_number(tech)) { nodes[tech] = NULL; continue; @@ -413,9 +414,9 @@ static struct reqtree *create_dummy_reqtree(struct player *pplayer, nodes[tech] = new_tree_node(); nodes[tech]->is_dummy = FALSE; nodes[tech]->tech = tech; - } advance_index_iterate_end; + } advance_index_iterate_max_end; - advance_index_iterate(A_FIRST, tech) { + advance_index_iterate_max(A_FIRST, tech, ac) { struct advance *padvance = valid_advance_by_number(tech); Tech_type_id tech_one, tech_two; @@ -447,18 +448,18 @@ static struct reqtree *create_dummy_reqtree(struct player *pplayer, add_requirement(nodes[tech], nodes[tech_two]); } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Copy nodes from local array to dynamically allocated one. * Skip non-existing entries */ tree->nodes = fc_calloc(advance_count(), sizeof(*tree->nodes)); j = 0; - advance_index_iterate(A_FIRST, tech) { + advance_index_iterate_max(A_FIRST, tech, ac) { if (nodes[tech]) { fc_assert_action(valid_advance_by_number(nodes[tech]->tech), continue); tree->nodes[j++] = nodes[tech]; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; tree->num_nodes = j; tree->layers = NULL; diff --git a/common/research.c b/common/research.c index 7605df3e90..efa203a196 100644 --- a/common/research.c +++ b/common/research.c @@ -501,8 +501,9 @@ void research_update(struct research *presearch) { enum tech_flag_id flag; int techs_researched; + Tech_type_id ac = advance_count(); - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { enum tech_state state = presearch->inventions[i].state; bool root_reqs_known = TRUE; bool reachable = research_get_reachable(presearch, i); @@ -566,19 +567,19 @@ void research_update(struct research *presearch) presearch->techs_researched++; } advance_req_iterate_end; presearch->techs_researched = techs_researched; - } advance_index_iterate_end; + } advance_index_iterate_max_end; #ifdef FREECIV_DEBUG - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { char buf[advance_count() + 1]; - advance_index_iterate(A_NONE, j) { + advance_index_iterate_max(A_NONE, j, ac) { if (BV_ISSET(presearch->inventions[i].required_techs, j)) { buf[j] = '1'; } else { buf[j] = '0'; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; buf[advance_count()] = '\0'; log_debug("%s: [%3d] %-25s => %s%s%s", @@ -590,19 +591,19 @@ void research_update(struct research *presearch) presearch->inventions[i].root_reqs_known ? "" : " [root reqs aren't known]"); log_debug("%s: [%3d] %s", research_rule_name(presearch), i, buf); - } advance_index_iterate_end; + } advance_index_iterate_max_end; #endif /* FREECIV_DEBUG */ for (flag = 0; flag <= tech_flag_id_max(); flag++) { /* Iterate over all possible tech flags (0..max). */ presearch->num_known_tech_with_flag[flag] = 0; - advance_index_iterate(A_NONE, i) { + advance_index_iterate_max(A_NONE, i, ac) { if (TECH_KNOWN == research_invention_state(presearch, i) && advance_has_flag(i, flag)) { presearch->num_known_tech_with_flag[flag]++; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; } } diff --git a/common/tech.h b/common/tech.h index 2e59475fcf..c80edf3663 100644 --- a/common/tech.h +++ b/common/tech.h @@ -238,16 +238,24 @@ void techs_precalc_data(void); /* Iteration */ -/* This iterates over almost all technologies. It includes non-existent +/* This iterates over almost all technologies. It includes non-existent * technologies, but not A_FUTURE. */ #define advance_index_iterate(_start, _index) \ -{ \ - Tech_type_id _index = (_start); \ - Tech_type_id _aco_##_index = advance_count(); \ +{ \ + advance_index_iterate_max(_start, _index, advance_count()) + +#define advance_index_iterate_end \ + advance_index_iterate_max_end \ +} + +#define advance_index_iterate_max(_start, _index, _max) \ +{ \ + Tech_type_id _index = (_start); \ + Tech_type_id _aco_##_index = (_max); \ for (; _index < _aco_##_index; _index++) { -#define advance_index_iterate_end \ - } \ +#define advance_index_iterate_max_end \ + } \ } const struct advance *advance_array_last(void); diff --git a/server/techtools.c b/server/techtools.c index 3a145b2b42..4e2d18a5f8 100644 --- a/server/techtools.c +++ b/server/techtools.c @@ -689,13 +689,14 @@ static Tech_type_id pick_random_tech_to_lose(const struct research *presearch) { bv_techs eligible_techs; + Tech_type_id full_count = advance_count(); /* A_NONE included in advance_count(). */ - int eligible = advance_count() - 1; + int eligible = full_count - 1; int chosen; BV_SET_ALL(eligible_techs); - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, full_count) { if (research_invention_state(presearch, i) != TECH_KNOWN) { if (BV_ISSET(eligible_techs, i)) { eligible--; @@ -704,6 +705,7 @@ pick_random_tech_to_lose(const struct research *presearch) } else { /* Knowing this tech may make others ineligible */ Tech_type_id root = advance_required(i, AR_ROOT); + /* Never lose techs that are root_req for a currently known tech * (including self root_req) */ if (root != A_NONE && BV_ISSET(eligible_techs, root)) { @@ -714,6 +716,7 @@ pick_random_tech_to_lose(const struct research *presearch) /* Ruleset can prevent this kind of tech loss from opening up * holes in the tech tree */ Tech_type_id prereq; + prereq = advance_required(i, AR_ONE); if (prereq != A_NONE && BV_ISSET(eligible_techs, prereq)) { eligible--; @@ -726,7 +729,7 @@ pick_random_tech_to_lose(const struct research *presearch) } } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (eligible == 0) { /* no researched technology at all */ @@ -735,14 +738,14 @@ pick_random_tech_to_lose(const struct research *presearch) chosen = fc_rand(eligible) + 1; - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, full_count) { if (BV_ISSET(eligible_techs, i)) { chosen--; if (chosen == 0) { return i; } } - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* should never be reached */ fc_assert_msg(chosen == 0, "internal error (eligible=%d, chosen=%d)", @@ -900,6 +903,7 @@ static Tech_type_id pick_random_tech(const struct research *presearch) } } } advance_index_iterate_end; + return tech; } @@ -1042,11 +1046,13 @@ void choose_tech_goal(struct research *presearch, Tech_type_id tech) ****************************************************************************/ void init_tech(struct research *research, bool update) { + Tech_type_id ac = advance_count(); + research_invention_set(research, A_NONE, TECH_KNOWN); - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { research_invention_set(research, i, TECH_UNKNOWN); - } advance_index_iterate_end; + } advance_index_iterate_max_end; #ifdef TECH_UPKEEP_DEBUGGING /* Print a list of the needed upkeep if 'i' techs are researched. @@ -1056,15 +1062,15 @@ void init_tech(struct research *research, bool update) Tech_type_id tech = A_LAST; /* Save the game research state. */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { global_state[i] = game.info.global_advances[i]; - } advance_index_iterate_end; + } advance_index_iterate_max_end; research->techs_researched = 1; research_update(presearch); /* Show research costs. */ - advance_index_iterate(A_NONE, i) { + advance_index_iterate_max(A_NONE, i, ac) { log_debug("[research %d] %-25s (ID: %3d) cost: %6d - reachable: %-3s " "(now) / %-3s (ever)", research_number(research), advance_rule_name(advance_by_number(i)), i, @@ -1072,18 +1078,18 @@ void init_tech(struct research *research, bool update) research_invention_gettable(research, i, FALSE) ? "yes" : "no", research_invention_reachable(research, i) ? "yes" : "no"); - } advance_index_iterate_end; + } advance_index_iterate_max_end; /* Update step for step each tech as known and print the upkeep. */ while (tech != A_NONE) { tech = A_NONE; - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_state(research, i) == TECH_PREREQS_KNOWN) { /* Found a tech which can be researched. */ tech = i; break; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (tech != A_NONE) { research->inventions[tech].state = TECH_KNOWN; @@ -1102,10 +1108,10 @@ void init_tech(struct research *research, bool update) } /* Reset the changes done. */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { research_invention_set(research, i, TECH_UNKNOWN); game.info.global_advances[i] = global_state[i]; - } advance_index_iterate_end; + } advance_index_iterate_max_end; } #endif /* TECH_UPKEEP_DEBUGGING */ @@ -1194,15 +1200,16 @@ Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, if (preferred == A_UNSET) { int j = 0; + Tech_type_id ac = advance_count(); - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_gettable(presearch, i, game.info.tech_steal_allow_holes) && research_invention_state(presearch, i) != TECH_KNOWN && research_invention_state(vresearch, i) == TECH_KNOWN) { j++; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; if (j == 0) { /* we've moved on to future tech */ @@ -1215,7 +1222,7 @@ Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, /* pick random tech */ j = fc_rand(j) + 1; stolen_tech = A_NONE; /* avoid compiler warning */ - advance_index_iterate(A_FIRST, i) { + advance_index_iterate_max(A_FIRST, i, ac) { if (research_invention_gettable(presearch, i, game.info.tech_steal_allow_holes) && research_invention_state(presearch, i) != TECH_KNOWN @@ -1226,7 +1233,7 @@ Tech_type_id steal_a_tech(struct player *pplayer, struct player *victim, stolen_tech = i; break; } - } advance_index_iterate_end; + } advance_index_iterate_max_end; fc_assert(stolen_tech != A_NONE); } } else { /* preferred != A_UNSET */ -- 2.35.1