diff options
Diffstat (limited to 'src/skills.cc')
-rw-r--r-- | src/skills.cc | 457 |
1 files changed, 290 insertions, 167 deletions
diff --git a/src/skills.cc b/src/skills.cc index dc543ed8..96d34e06 100644 --- a/src/skills.cc +++ b/src/skills.cc @@ -57,6 +57,8 @@ using boost::algorithm::iequals; */ static void increase_skill(int i, s16b *invest) { + auto &s_info = game->s_info; + s32b max_skill_overage; /* No skill points to be allocated */ @@ -99,6 +101,8 @@ static void increase_skill(int i, s16b *invest) */ static void decrease_skill(int i, s16b *invest) { + auto &s_info = game->s_info; + /* Cannot decrease more */ if (!invest[i]) return; @@ -121,14 +125,17 @@ static void decrease_skill(int i, s16b *invest) * Given the name of a skill, returns skill index or -1 if no * such skill is found */ -s16b find_skill(cptr name) +s16b find_skill(cptr needle) { + auto const &s_descriptors = game->edit_data.s_descriptors; + /* Scan skill list */ - for (int i = 1; i < max_s_idx; i++) + for (std::size_t i = 1; i < s_descriptors.size(); i++) { - if (s_descriptors[i].name && streq(s_descriptors[i].name, name)) + auto const &name = s_descriptors[i].name; + if (!name.empty() && (name == needle)) { - return (i); + return i; } } @@ -136,15 +143,15 @@ s16b find_skill(cptr name) return -1; } -s16b find_skill_i(cptr name) +s16b find_skill_i(cptr needle) { - u16b i; + auto const &s_descriptors = game->edit_data.s_descriptors; /* Scan skill list */ - for (i = 1; i < max_s_idx; i++) + for (std::size_t i = 1; i < s_descriptors.size(); i++) { - /* The name matches */ - if (s_descriptors[i].name && iequals(s_descriptors[i].name, name)) + auto const &name = s_descriptors[i].name; + if (!name.empty() && iequals(name, needle)) { return (i); } @@ -160,6 +167,8 @@ s16b find_skill_i(cptr name) */ s16b get_skill(int skill) { + auto const &s_info = game->s_info; + return (s_info[skill].value / SKILL_STEP); } @@ -170,7 +179,7 @@ s16b get_skill(int skill) */ s16b get_skill_scale(int skill, u32b scale) { - s32b temp; + auto const &s_info = game->s_info; /* * SKILL_STEP shouldn't matter here because the second parameter is @@ -182,29 +191,35 @@ s16b get_skill_scale(int skill, u32b scale) * formula given above, I verified this works the same by using a tiny * scheme program... -- pelpel */ - temp = scale * s_info[skill].value; + s32b temp = scale * s_info[skill].value; return (temp / SKILL_MAX); } -static int get_idx(int i) +static std::size_t get_idx(int i) { - for (int j = 1; j < max_s_idx; j++) + auto const &s_descriptors = game->edit_data.s_descriptors; + + for (std::size_t j = 1; j < s_descriptors.size(); j++) { if (s_descriptors[j].order == i) - return (j); + { + return j; + } } - return (0); + + return 0; } static bool_ is_known(int s_idx) { - int i; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; if (wizard) return TRUE; if (s_info[s_idx].value || s_info[s_idx].mod) return TRUE; - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { /* It is our child, if we don't know it we continue to search, if we know it it is enough*/ if (s_descriptors[i].father == s_idx) @@ -218,35 +233,51 @@ static bool_ is_known(int s_idx) return FALSE; } -static void init_table_aux(int table[MAX_SKILLS][2], int *idx, int father, int lev, bool_ full) +namespace { // anonymous + +struct skill_entry { + std::size_t skill_idx; + int indent_level; +}; + +} + +static void init_table_aux(std::vector<skill_entry> *table, int father, int lev, bool_ full) { - for (int j = 1; j < max_s_idx; j++) + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + + for (std::size_t j = 1; j < s_descriptors.size(); j++) { - int i = get_idx(j); + std::size_t i = get_idx(j); + if (s_descriptors[i].father != father) continue; if (s_info[i].hidden) continue; if (!is_known(i)) continue; - table[*idx][0] = i; - table[*idx][1] = lev; - (*idx)++; + skill_entry entry; + entry.skill_idx = i; + entry.indent_level = lev; + table->emplace_back(entry); if (s_info[i].dev || full) { - init_table_aux(table, idx, i, lev + 1, full); + init_table_aux(table, i, lev + 1, full); } } } -static void init_table(int table[MAX_SKILLS][2], int *max, bool_ full) +static void init_table(std::vector<skill_entry> *table, bool_ full) { - *max = 0; - init_table_aux(table, max, -1, 0, full); + table->clear(); + init_table_aux(table, -1, 0, full); } static bool has_child(int sel) { - for (int i = 1; i < max_s_idx; i++) + auto const &s_descriptors = game->edit_data.s_descriptors; + + for (std::size_t i = 1; i < s_descriptors.size(); i++) { if ((s_descriptors[i].father == sel) && is_known(i)) { @@ -263,42 +294,51 @@ static bool has_child(int sel) */ void dump_skills(FILE *fff) { - int i, j, max = 0; - int table[MAX_SKILLS][2]; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + char buf[80]; - init_table(table, &max, TRUE); + std::vector<skill_entry> table; + table.reserve(s_descriptors.size()); + init_table(&table, TRUE); fprintf(fff, "\nSkills (points left: %d)", p_ptr->skill_points); - for (j = 0; j < max; j++) + for (auto const &entry: table) { - int z; - - i = table[j][0]; + std::size_t i = entry.skill_idx; + auto const &skill = s_info[i]; + auto const &skill_name = s_descriptors[i].name; - if ((s_info[i].value == 0) && (i != SKILL_MISC)) + if ((skill.value == 0) && (i != SKILL_MISC)) { - if (s_info[i].mod == 0) continue; + if (skill.mod == 0) + { + continue; + } } sprintf(buf, "\n"); - for (z = 0; z < table[j][1]; z++) strcat(buf, " "); + for (int z = 0; z < entry.indent_level; z++) + { + strcat(buf, " "); + } if (!has_child(i)) { - strcat(buf, format(" . %s", s_descriptors[i].name)); + strcat(buf, format(" . %s", skill_name.c_str())); } else { - strcat(buf, format(" - %s", s_descriptors[i].name)); + strcat(buf, format(" - %s", skill_name.c_str())); } fprintf(fff, "%-49s%s%06.3f [%05.3f]", - buf, s_info[i].value < 0 ? "-" : " ", - static_cast<double>(ABS(s_info[i].value)) / SKILL_STEP, - static_cast<double>(s_info[i].mod) / 1000); + buf, skill.value < 0 ? "-" : " ", + static_cast<double>(ABS(skill.value)) / SKILL_STEP, + static_cast<double>(skill.mod) / 1000); } fprintf(fff, "\n"); @@ -308,9 +348,12 @@ void dump_skills(FILE *fff) /* * Draw the skill tree */ -void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start) +static void print_skills(std::vector<skill_entry> const &table, int sel, int start) { - int i, j; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; + + int j; int wid, hgt; cptr keys; @@ -322,52 +365,73 @@ void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start) display_message(0, 1, strlen(keys), TERM_WHITE, keys); c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED, format("Skill points left: %d", p_ptr->skill_points), 2, 0); - print_desc_aux(s_descriptors[table[sel][0]].desc, 3, 0); + print_desc_aux(s_descriptors[table[sel].skill_idx].desc.c_str(), 3, 0); for (j = start; j < start + (hgt - 7); j++) { byte color = TERM_WHITE; char deb = ' ', end = ' '; - if (j >= max) break; + if (j >= static_cast<int>(table.size())) + { + break; + } + + std::size_t i = table[j].skill_idx; + auto const &name = s_descriptors[i].name; + auto const &skill = s_info[i]; - i = table[j][0]; + if ((skill.value == 0) && (i != SKILL_MISC)) + { + if (skill.mod == 0) + { + color = TERM_L_DARK; + } + else + { + color = TERM_ORANGE; + } + } + else if (skill.value == SKILL_MAX) + { + color = TERM_L_BLUE; + } - if ((s_info[i].value == 0) && (i != SKILL_MISC)) + if (skill.hidden) { - if (s_info[i].mod == 0) color = TERM_L_DARK; - else color = TERM_ORANGE; + color = TERM_L_RED; } - else if (s_info[i].value == SKILL_MAX) color = TERM_L_BLUE; - if (s_info[i].hidden) color = TERM_L_RED; + if (j == sel) { color = TERM_L_GREEN; deb = '['; end = ']'; } + if (!has_child(i)) { - c_prt(color, format("%c.%c%s", deb, end, s_descriptors[i].name), - j + 7 - start, table[j][1] * 4); + c_prt(color, format("%c.%c%s", deb, end, name.c_str()), + j + 7 - start, table[j].indent_level * 4); } - else if (s_info[i].dev) + else if (skill.dev) { - c_prt(color, format("%c-%c%s", deb, end, s_descriptors[i].name), - j + 7 - start, table[j][1] * 4); + c_prt(color, format("%c-%c%s", deb, end, name.c_str()), + j + 7 - start, table[j].indent_level * 4); } else { - c_prt(color, format("%c+%c%s", deb, end, s_descriptors[i].name), - j + 7 - start, table[j][1] * 4); + c_prt(color, format("%c+%c%s", deb, end, name.c_str()), + j + 7 - start, table[j].indent_level * 4); } + c_prt(color, format("%s%02ld.%03ld [%01d.%03d]", - s_info[i].value < 0 ? "-" : " ", - ABS(s_info[i].value) / SKILL_STEP, - ABS(s_info[i].value) % SKILL_STEP, - ABS(s_info[i].mod) / 1000, - ABS(s_info[i].mod) % 1000), + skill.value < 0 ? "-" : " ", + ABS(skill.value) / SKILL_STEP, + ABS(skill.value) % SKILL_STEP, + ABS(skill.mod) / 1000, + ABS(skill.mod) % 1000), j + 7 - start, 60); } } @@ -377,6 +441,8 @@ void print_skills(int table[MAX_SKILLS][2], int max, int sel, int start) */ void recalc_skills(bool_ init) { + auto const &s_info = game->s_info; + static int thaum_level = 0; /* TODO: This should be a hook in ToME's lua */ @@ -429,49 +495,64 @@ void recalc_skills(bool_ init) /* * Recalc the skill value */ -static void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s32b *bonus) +static void recalc_skills_theory( + std::vector<s16b> &invest, + std::vector<s32b> const &base_val, + std::vector<s32b> const &base_mod, + std::vector<s32b> const &bonus) { - int i, j; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; /* First we assign the normal points */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { /* Calc the base */ s_info[i].value = base_val[i] + (base_mod[i] * invest[i]) + bonus[i]; /* It cannot exceed SKILL_MAX */ - if (s_info[i].value > SKILL_MAX) s_info[i].value = SKILL_MAX; + if (s_info[i].value > SKILL_MAX) + { + s_info[i].value = SKILL_MAX; + } } /* Then we modify related skills */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - for (j = 1; j < max_s_idx; j++) - { - /* Ignore self */ - if (j == i) continue; + auto const &s_descriptor = s_descriptors[i]; - /* Exclusive skills */ - if ((s_descriptors[i].action[j] == SKILL_EXCLUSIVE) && invest[i]) + // Process all exlusions + if (invest[i]) + { + for (auto exclude_si: s_descriptor.excludes) { - /* Turn it off */ - p_ptr->skill_points += invest[j]; - invest[j] = 0; - s_info[j].value = 0; + // Give back skill points invested during this "session" + p_ptr->skill_points += invest[exclude_si]; + invest[exclude_si] = 0; + + // Turn it off + s_info[exclude_si].value = 0; } + } - /* Non-exclusive skills */ - else if (s_descriptors[i].action[j]) - { - /* Increase / decrease with a % */ - s32b val = s_info[j].value + (invest[i] * s_info[j].mod * s_descriptors[i].action[j] / 100); + // Add any bonuses + for (auto const &increase: s_descriptor.increases) + { + auto increase_si = std::get<0>(increase); + auto increase_pct = std::get<1>(increase); - /* It cannot exceed SKILL_MAX */ - if (val > SKILL_MAX) val = SKILL_MAX; + /* Increase/decrease by percentage */ + s32b val = s_info[increase_si].value + (invest[i] * s_info[increase_si].mod * increase_pct / 100); - /* Save the modified value */ - s_info[j].value = val; + /* It cannot exceed SKILL_MAX */ + if (val > SKILL_MAX) + { + val = SKILL_MAX; } + + /* Save the modified value */ + s_info[increase_si].value = val; } } } @@ -481,10 +562,11 @@ static void recalc_skills_theory(s16b *invest, s32b *base_val, s32b *base_mod, s */ void do_cmd_skill() { - int sel = 0, start = 0, max; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; + + int sel = 0, start = 0; char c; - int table[MAX_SKILLS][2]; - int i; int wid, hgt; s16b skill_points_save; @@ -493,39 +575,38 @@ void do_cmd_skill() /* Save the screen */ screen_save(); - /* Allocate arrays to save skill values */ - std::unique_ptr<s32b[]> skill_values_save(new s32b[MAX_SKILLS]); - std::unique_ptr<s32b[]> skill_mods_save(new s32b[MAX_SKILLS]); - std::unique_ptr<s16b[]> skill_invest(new s16b[MAX_SKILLS]); - std::unique_ptr<s32b[]> skill_bonus(new s32b[MAX_SKILLS]); + /* Allocate arrays to save skill values and track assigned points */ + std::vector<s32b> skill_values_save; skill_values_save.resize(s_descriptors.size(), 0); + std::vector<s32b> skill_mods_save; skill_mods_save.resize(s_descriptors.size(), 0); + std::vector<s16b> skill_invest; skill_invest.resize(s_descriptors.size(), 0); + std::vector<s32b> skill_bonus; skill_bonus.resize(s_descriptors.size(), 0); /* Save skill points */ skill_points_save = p_ptr->skill_points; /* Save skill values */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - skill_type *s_ptr = &s_info[i]; - + auto s_ptr = &s_info[i]; skill_values_save[i] = s_ptr->value; skill_mods_save[i] = s_ptr->mod; - skill_invest[i] = 0; - skill_bonus[i] = 0; } /* Clear the screen */ Term_clear(); /* Initialise the skill list */ - init_table(table, &max, FALSE); + std::vector<skill_entry> table; + table.reserve(s_descriptors.size()); + init_table(&table, FALSE); while (TRUE) { Term_get_size(&wid, &hgt); /* Display list of skills */ - recalc_skills_theory(skill_invest.get(), skill_values_save.get(), skill_mods_save.get(), skill_bonus.get()); - print_skills(table, max, sel, start); + recalc_skills_theory(skill_invest, skill_values_save, skill_mods_save, skill_bonus); + print_skills(table, sel, start); /* Wait for user input */ c = inkey(); @@ -536,16 +617,21 @@ void do_cmd_skill() /* Expand / collapse list of skills */ else if (c == '\r') { - s_info[table[sel][0]].dev = !s_info[table[sel][0]].dev; - - init_table(table, &max, FALSE); + // Toggle the selected skill + s_info[table[sel].skill_idx].dev = !s_info[table[sel].skill_idx].dev; + // Re-populate table + init_table(&table, FALSE); } /* Next page */ else if (c == 'n') { sel += (hgt - 7); - if (sel >= max) sel = max - 1; + + if (sel >= static_cast<int>(table.size())) + { + sel = table.size() - 1; + } } /* Previous page */ @@ -570,31 +656,31 @@ void do_cmd_skill() if (dir == 8) sel--; /* Miscellaneous skills cannot be increased/decreased as a group */ - if ((sel >= 0) && (sel < max) && table[sel][0] == SKILL_MISC) continue; + if ((sel >= 0) && (sel < static_cast<int>(table.size())) && table[sel].skill_idx == SKILL_MISC) continue; /* Increase the current skill */ - if (dir == 6) increase_skill(table[sel][0], skill_invest.get()); + if (dir == 6) increase_skill(table[sel].skill_idx, skill_invest.data()); /* Decrease the current skill */ - if (dir == 4) decrease_skill(table[sel][0], skill_invest.get()); + if (dir == 4) decrease_skill(table[sel].skill_idx, skill_invest.data()); /* XXX XXX XXX Wizard mode commands outside of wizard2.c */ /* Increase the skill */ - if (wizard && (c == '+')) skill_bonus[table[sel][0]] += SKILL_STEP; + if (wizard && (c == '+')) skill_bonus[table[sel].skill_idx] += SKILL_STEP; /* Decrease the skill */ - if (wizard && (c == '-')) skill_bonus[table[sel][0]] -= SKILL_STEP; + if (wizard && (c == '-')) skill_bonus[table[sel].skill_idx] -= SKILL_STEP; /* Contextual help */ if (c == '?') { - help_skill(s_descriptors[table[sel][0]].name); + help_skill(s_descriptors[table[sel].skill_idx].name); } /* Handle boundaries and scrolling */ - if (sel < 0) sel = max - 1; - if (sel >= max) sel = 0; + if (sel < 0) sel = table.size() - 1; + if (sel >= static_cast<int>(table.size())) sel = 0; if (sel < start) start = sel; if (sel >= start + (hgt - 7)) start = sel - (hgt - 7) + 1; } @@ -616,10 +702,9 @@ void do_cmd_skill() p_ptr->skill_points = skill_points_save; /* Restore skill values */ - for (i = 0; i < max_s_idx; i++) + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - skill_type *s_ptr = &s_info[i]; - + auto s_ptr = &s_info[i]; s_ptr->value = skill_values_save[i]; s_ptr->mod = skill_mods_save[i]; } @@ -671,9 +756,11 @@ cptr get_melee_name() s16b get_melee_skills() { - int i, j = 0; + auto const &s_info = game->s_info; - for (i = 0; i < MAX_MELEE; i++) + int j = 0; + + for (std::size_t i = 0; i < MAX_MELEE; i++) { if ((s_info[melee_skills[i]].value > 0) && (!s_info[melee_skills[i]].hidden)) { @@ -784,7 +871,7 @@ void select_default_melee() /* * Print a batch of skills. */ -static void print_skill_batch(const std::vector<std::tuple<std::string const &, int>> &p, int start) +static void print_skill_batch(const std::vector<std::tuple<std::string, int>> &p, int start) { char buff[80]; int j = 0; @@ -812,12 +899,14 @@ static void print_skill_batch(const std::vector<std::tuple<std::string const &, static int do_cmd_activate_skill_aux() { auto const &ab_info = game->edit_data.ab_info; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; char which; int start = 0; int ret; - std::vector<std::tuple<std::string const &,int>> p; + std::vector<std::tuple<std::string,int>> p; /* More than 1 melee skill ? */ if (get_melee_skills() > 1) @@ -825,7 +914,7 @@ static int do_cmd_activate_skill_aux() p.push_back(std::make_tuple("Change melee mode", 0)); } - for (size_t i = 1; i < max_s_idx; i++) + for (size_t i = 1; i < s_descriptors.size(); i++) { if (s_descriptors[i].action_mkey && s_info[i].value && ((!s_info[i].hidden) || (i == SKILL_LEARN))) { @@ -960,6 +1049,8 @@ static int do_cmd_activate_skill_aux() void do_cmd_activate_skill() { auto const &ab_info = game->edit_data.ab_info; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto const &s_info = game->s_info; int x_idx; bool_ push = TRUE; @@ -978,8 +1069,8 @@ void do_cmd_activate_skill() x_idx = command_arg; /* Check validity */ - int i; - for (i = 1; i < max_s_idx; i++) + std::size_t i; + for (i = 1; i < s_descriptors.size(); i++) { if (s_info[i].value && (s_descriptors[i].action_mkey == x_idx)) { @@ -996,7 +1087,7 @@ void do_cmd_activate_skill() } } - if ((j == ab_info.size()) && (i == max_s_idx)) + if ((j == ab_info.size()) && (i == s_descriptors.size())) { msg_print("Uh?"); return; @@ -1201,32 +1292,39 @@ bool_ forbid_non_blessed() /* * Augment skill value/modifier with the given skill_modifiers */ -static void augment_skills(s32b *v, s32b *m, skill_modifier const &s) +static void augment_skills(s32b *v, s32b *m, std::vector<skill_modifier> const &modifiers, std::size_t i) { - *v = modify_aux(*v, s.base, s.basem); - *m = modify_aux(*m, s.mod, s.modm); + if (i < modifiers.size()) // Ignore if the skill has no modifiers. + { + auto const &s = modifiers[i]; + *v = modify_aux(*v, s.base, s.basem); + *m = modify_aux(*m, s.mod, s.modm); + } } /* * Gets the base value of a skill, given a race/class/... */ -void compute_skills(s32b *v, s32b *m, int i) +void compute_skills(s32b *v, s32b *m, std::size_t i) { auto const &gen_skill = game->edit_data.gen_skill; - augment_skills(v, m, gen_skill.modifiers[i]); - augment_skills(v, m, rp_ptr->skill_modifiers.modifiers[i]); - augment_skills(v, m, rmp_ptr->skill_modifiers.modifiers[i]); - augment_skills(v, m, cp_ptr->skill_modifiers.modifiers[i]); - augment_skills(v, m, spp_ptr->skill_modifiers.modifiers[i]); + augment_skills(v, m, gen_skill.modifiers, i); + augment_skills(v, m, rp_ptr->skill_modifiers.modifiers, i); + augment_skills(v, m, rmp_ptr->skill_modifiers.modifiers, i); + augment_skills(v, m, cp_ptr->skill_modifiers.modifiers, i); + augment_skills(v, m, spp_ptr->skill_modifiers.modifiers, i); } /* * Initialize a skill with given values */ -void init_skill(s32b value, s32b mod, int i) +void init_skill(s32b value, s32b mod, std::size_t i) { + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; + s_info[i].value = value; s_info[i].mod = mod; s_info[i].hidden = (s_descriptors[i].flags & SKF_HIDDEN) @@ -1294,29 +1392,27 @@ static std::vector<size_t> wrs(const std::vector<s32b> &unscaled_weights) void do_get_new_skill() { - std::vector<std::string> items; - int skl[LOST_SWORD_NSKILLS]; - s32b val[LOST_SWORD_NSKILLS], mod[LOST_SWORD_NSKILLS]; - int available_skills[MAX_SKILLS]; - int max_a = 0, res, i; + auto const &s_descriptors = game->edit_data.s_descriptors; + auto &s_info = game->s_info; /* Check if some skills didn't influence other stuff */ recalc_skills(TRUE); /* Grab the ones we can gain */ - max_a = 0; - for (i = 0; i < max_s_idx; i++) + std::vector<size_t> available_skills; + available_skills.reserve(s_descriptors.size()); + for (std::size_t i = 0; i < s_descriptors.size(); i++) { if (s_descriptors[i].flags & SKF_RANDOM_GAIN) { - available_skills[max_a] = i; - max_a++; + available_skills.push_back(i); } } /* Perform the selection */ std::vector<s32b> weights; - for (i = 0; i < max_a; i++) { + for (std::size_t i = 0; i < available_skills.size(); i++) + { weights.push_back(s_descriptors[available_skills[i]].random_gain_chance); } @@ -1324,10 +1420,14 @@ void do_get_new_skill() assert(indexes.size() >= LOST_SWORD_NSKILLS); /* Extract the information needed from the skills */ - for (i = 0; i < LOST_SWORD_NSKILLS; i++) + int skl[LOST_SWORD_NSKILLS]; + s32b val[LOST_SWORD_NSKILLS]; + s32b mod[LOST_SWORD_NSKILLS]; + std::vector<std::string> items; + for (std::size_t i = 0; i < LOST_SWORD_NSKILLS; i++) { s32b s_idx = available_skills[indexes[i]]; - skill_type *s_ptr = &s_info[s_idx]; + auto s_ptr = &s_info[s_idx]; if (s_ptr->mod) { @@ -1341,7 +1441,9 @@ void do_get_new_skill() val[i] = s_ptr->mod * 1; mod[i] = 100; if (mod[i] + s_ptr->mod > 500) + { mod[i] = 500 - s_ptr->mod; + } } else { @@ -1355,41 +1457,56 @@ void do_get_new_skill() val[i] = 1000; } - if (s_ptr->value + val[i] > SKILL_MAX) { + if (s_ptr->value + val[i] > SKILL_MAX) + { val[i] = SKILL_MAX - s_ptr->value; } skl[i] = s_idx; items.push_back(format("%-40s: +%02ld.%03ld value, +%01d.%03d modifier", - s_descriptors[s_idx].name, + s_descriptors[s_idx].name.c_str(), val[i] / SKILL_STEP, val[i] % SKILL_STEP, mod[i] / SKILL_STEP, mod[i] % SKILL_STEP)); } + // Ask for a skill while (TRUE) { char last = 'a' + (LOST_SWORD_NSKILLS-1); char buf[80]; sprintf(buf, "Choose a skill to learn (a-%c to choose, ESC to cancel)?", last); - res = ask_menu(buf, items); + int res = ask_menu(buf, items); /* Ok ? lets learn ! */ if (res > -1) { + std::size_t chosen_skill = skl[res]; + bool_ oppose = FALSE; int oppose_skill = -1; - /* Check we don't oppose an existing skill */ - for (i = 0; i < max_s_idx; i++) + /* Check we don't oppose a skill the player already has */ + for (std::size_t i = 0; i < s_descriptors.size(); i++) { - if ((s_descriptors[i].action[skl[res]] == SKILL_EXCLUSIVE) && - (s_info[i].value != 0)) + auto const &s_descriptor = s_descriptors[i]; + + // Only bother if player has skill + if (s_info[i].value) { - oppose = TRUE; - oppose_skill = i; - break; + // Check if i'th skill opposes the chosen one. + auto found = std::find( + s_descriptor.excludes.begin(), + s_descriptor.excludes.end(), + chosen_skill); + + if (found != s_descriptor.excludes.end()) + { + oppose = TRUE; + oppose_skill = i; + break; + } } } @@ -1407,26 +1524,32 @@ void do_get_new_skill() /* Prepare prompt */ msg = format("This skill is mutually exclusive with " "at least %s, continue?", - s_descriptors[oppose_skill].name); + s_descriptors[oppose_skill].name.c_str()); - /* The player rejected the choice */ - if (!get_check(msg)) continue; + /* The player rejected the choice; go back to prompt */ + if (!get_check(msg)) + { + continue; + } } - auto const s_desc = &s_descriptors[skl[res]]; - auto const s_ptr = &s_info[skl[res]]; + auto const s_desc = &s_descriptors[chosen_skill]; + auto const s_ptr = &s_info[chosen_skill]; + s_ptr->value += val[res]; s_ptr->mod += mod[res]; + if (mod[res]) { msg_format("You can now learn the %s skill.", - s_desc->name); + s_desc->name.c_str()); } else { msg_format("Your knowledge of the %s skill increases.", - s_desc->name); + s_desc->name.c_str()); } + break; } } |