void iuse::purifier(game *g, player *p, item *it, bool t) { std::vector<int> valid; // Which flags the player has for (int i = 0; i < PF_MAX2; i++) { if (p->has_trait(pl_flag(i)) && traits[i].curable) valid.push_back(i); } if (valid.size() == 0) { int stat_raised = rng(1, 4); std::string adj; switch (stat_raised) { case 1: adj = "stronger"; p->str_max++; break; case 2: adj = "nimbler"; p->dex_max++; break; case 3: adj = "smarter"; p->int_max++; break; case 4: adj = "more perceptive"; p->per_max++; break; } if (!p->is_npc()) g->add_msg("You feel %s.", adj.c_str()); return; } int num_cured = rng(1, valid.size()); if (num_cured > 4) num_cured = 4; for (int i = 0; i < num_cured && valid.size() > 0; i++) { int index = rng(0, valid.size() - 1); if (!p->is_npc()) g->add_msg("You lose your %s.", traits[valid[index]].name.c_str()); p->toggle_trait(pl_flag(valid[index])); valid.erase(valid.begin() + index); } }
void player::mutate(game *g) { bool force_bad = one_in(3); // 33% chance! if (has_trait(PF_ROBUST) && force_bad && one_in(3)) force_bad = false; // 11% chance! // First, see if we should ugrade/extend an existing mutation std::vector<pl_flag> upgrades; for (int i = 1; i < PF_MAX2; i++) { if (has_trait(i)) { for (int j = 0; j < g->mutation_data[i].replacements.size(); j++) { pl_flag tmp = g->mutation_data[i].replacements[j]; if (!has_trait(tmp) && !has_child_flag(g, tmp) && (!force_bad || traits[tmp].points <= 0)) upgrades.push_back(tmp); } for (int j = 0; j < g->mutation_data[i].additions.size(); j++) { pl_flag tmp = g->mutation_data[i].additions[j]; if (!has_trait(tmp) && !has_child_flag(g, tmp) && (!force_bad || traits[tmp].points <= 0)) upgrades.push_back(tmp); } } } if (upgrades.size() > 0 && rng(0, upgrades.size() + 4) < upgrades.size()) { mutate_towards(g, upgrades[ rng(0, upgrades.size() - 1) ]); return; } // Next, see if we should mutate within a given category mutation_category cat = MUTCAT_NULL; int total = 0, highest = 0; for (int i = 0; i < NUM_MUTATION_CATEGORIES; i++) { total += mutation_category_level[i]; if (mutation_category_level[i] > highest) { cat = mutation_category(i); highest = mutation_category_level[i]; } } if (rng(0, total) > highest) cat = MUTCAT_NULL; // Not a strong enough pull, just mutate something random! std::vector<pl_flag> valid; // Valid mutations bool first_pass = (cat != MUTCAT_NULL); do { // If we tried once with a non-NULL category, and couldn't find anything valid // there, try again with MUTCAT_NULL if (cat != MUTCAT_NULL && !first_pass) cat = MUTCAT_NULL; if (cat == MUTCAT_NULL) { // Pull the full list for (int i = 1; i < PF_MAX2; i++) { if (g->mutation_data[i].valid) valid.push_back( pl_flag(i) ); } } else // Pull the category's list valid = mutations_from_category(cat); // Remove anything we already have, or that we have a child of, or that's // positive and we're forcing bad for (int i = 0; i < valid.size(); i++) { if (has_trait(valid[i]) || has_child_flag(g, valid[i]) || (force_bad && traits[ valid[i] ].points > 0)) { valid.erase(valid.begin() + i); i--; } } if (valid.empty()) first_pass = false; // So we won't repeat endlessly } while (valid.empty() && cat != MUTCAT_NULL); if (valid.empty()) return; // Couldn't find anything at all! pl_flag selection = valid[ rng(0, valid.size() - 1) ]; // Pick one! mutate_towards(g, selection); }
void game::mutation_wish() { WINDOW* w_list = newwin(25, 30, 0, 0); WINDOW* w_info = newwin(25, 50, 0, 30); int a = 0, shift = 0, result_selected = 0; int line; char ch = '.'; bool search = false, found = false; std::string pattern; std::string info; std::vector<int> search_results; do { werase(w_info); werase(w_list); mvwprintw(w_list, 0, 0, _("Mutate: ")); if (search) { found = false; if (ch == '\n') { search = false; found = true; ch = '.'; } else if (ch == KEY_BACKSPACE || ch == 127) { if (pattern.length() > 0) pattern.erase(pattern.end() - 1); } else if (ch == '>') { search = false; if (!search_results.empty()) { result_selected++; if (result_selected > search_results.size()) result_selected = 0; shift = search_results[result_selected]; a = 0; if (shift + 23 > PF_MAX2) { a = shift + 23 - PF_MAX2; shift = PF_MAX2 - 23; } } } else if (ch == '<') { search = false; if (!search_results.empty()) { result_selected--; if (result_selected < 0) result_selected = search_results.size() - 1; shift = search_results[result_selected]; a = 0; if (shift + 23 > PF_MAX2) { a = shift + 23 - PF_MAX2; shift = PF_MAX2 - 23; } } } else { pattern += ch; search_results.clear(); } if (search) { for (int i = 0; i < PF_MAX2; i++) { if (traits[i].name.find(pattern) != std::string::npos) { shift = i; a = 0; result_selected = 0; if (shift + 23 > PF_MAX2) { a = shift + 23 - PF_MAX2; shift = PF_MAX2 - 23; } found = true; search_results.push_back(i); } } if (search_results.size() > 0) { shift = search_results[0]; a = 0; } } } else { // Not searching; scroll by keys if (ch == 'j') a++; if (ch == 'k') a--; if (ch == '/') { search = true; pattern = ""; found = false; search_results.clear(); } if (ch == '>' && !search_results.empty()) { result_selected++; if (result_selected > search_results.size()) result_selected = 0; shift = search_results[result_selected]; a = 0; if (shift + 23 > PF_MAX2) { a = shift + 23 - PF_MAX2; shift = PF_MAX2 - 23; } } else if (ch == '<' && !search_results.empty()) { result_selected--; if (result_selected < 0) result_selected = search_results.size() - 1; shift = search_results[result_selected]; a = 0; if (shift + 23 > PF_MAX2) { a = shift + 23 - PF_MAX2; shift = PF_MAX2 - 23; } } } if (!search_results.empty()) mvwprintz(w_list, 0, 11, c_green, "%s ", pattern.c_str()); else if (pattern.length() > 0) mvwprintz(w_list, 0, 11, c_red, _("%s not found! "),pattern.c_str()); if (a < 0) { a = 0; shift--; if (shift < 0) shift = 0; } if (a > 22) { a = 22; shift++; if (shift + 23 > PF_MAX2) shift = PF_MAX2 - 23; } for (int i = 1; i < 24; i++) { nc_color col = c_white; if (i == a + 1) col = h_white; mvwprintz(w_list, i, 0, col, traits[i-1+shift].name.c_str()); } mvwprintw(w_info, 1, 0, mutation_data[a+shift].valid ? _("Valid") : _("Nonvalid")); int line2 = 2; mvwprintw(w_info, line2, 0, _("Prereqs:")); for (int j = 0; j < mutation_data[a+shift].prereqs.size(); j++) { mvwprintw(w_info, line2, 9, traits[ mutation_data[a+shift].prereqs[j] ].name.c_str()); line2++; } mvwprintw(w_info, line2, 0, _("Cancels:")); for (int j = 0; j < mutation_data[a+shift].cancels.size(); j++) { mvwprintw(w_info, line2, 9, traits[ mutation_data[a+shift].cancels[j] ].name.c_str()); line2++; } mvwprintw(w_info, line2, 0, _("Becomes:")); for (int j = 0; j < mutation_data[a+shift].replacements.size(); j++) { mvwprintw(w_info, line2, 9, traits[ mutation_data[a+shift].replacements[j] ].name.c_str()); line2++; } mvwprintw(w_info, line2, 0, _("Add-ons:")); for (int j = 0; j < mutation_data[a+shift].additions.size(); j++) { mvwprintw(w_info, line2, 9, traits[ mutation_data[a+shift].additions[j] ].name.c_str()); line2++; } wrefresh(w_info); wrefresh(w_list); if (search) ch = getch(); else ch = input(); } while (ch != '\n'); clear(); if (a+shift == 0) u.mutate(this); else u.mutate_towards(this, pl_flag(a + shift)); delwin(w_info); delwin(w_list); }
void player::mutate(game *g) { bool force_bad = one_in(3); bool force_good = false; if (has_trait(PF_ROBUST) && force_bad) { // Robust Genetics gives you a 33% chance for a good mutation, // instead of the 33% chance of a bad one. force_bad = false; force_good = true; } // Determine the mutation categorie mutation_category cat = MUTCAT_NULL; // Count up the players number of mutations in categories and find // the category with the highest single count. int total = 0, highest = 0; for (int i = 0; i < NUM_MUTATION_CATEGORIES; i++) { total += mutation_category_level[i]; if (mutation_category_level[i] > highest) { cat = mutation_category(i); highest = mutation_category_level[i]; } } // See if we should ugrade/extend an existing mutation... std::vector<pl_flag> upgrades; // ... or remove one that is not in our highest category std::vector<pl_flag> downgrades; // For each mutation... for (int base_mutation_index = 1; base_mutation_index < PF_MAX2; base_mutation_index++) { pl_flag base_mutation = (pl_flag) base_mutation_index; // ...that we have... if (has_trait(base_mutation)) { // ...consider the mutations that replace it. for (int i = 0; i < g->mutation_data[base_mutation].replacements.size(); i++) { pl_flag mutation = g->mutation_data[base_mutation].replacements[i]; if (mutation_ok(g, mutation, force_good, force_bad)) { upgrades.push_back(mutation); } } // ...consider the mutations that add to it. for (int i = 0; i < g->mutation_data[base_mutation].additions.size(); i++) { pl_flag mutation = g->mutation_data[base_mutation].additions[i]; if (mutation_ok(g, mutation, force_good, force_bad)) { upgrades.push_back(mutation); } } // ...consider whether its in our highest category if( has_trait(base_mutation) && !has_base_trait(base_mutation) ){ // Starting traits don't count toward categories std::vector<pl_flag> group = mutations_from_category(cat); bool in_cat = false; for (int j = 0; j < group.size(); j++) { if (group[j] == base_mutation) { in_cat = true; break; } } // mark for removal if(!in_cat) downgrades.push_back(base_mutation); } } } // Preliminary round to either upgrade or remove existing mutations if(one_in(2)){ if (upgrades.size() > 0) { // (upgrade count) chances to pick an upgrade, 4 chances to pick something else. int roll = rng(0, upgrades.size() + 4); if (roll < upgrades.size()) { // We got a valid upgrade index, so use it and return. mutate_towards(g, upgrades[roll]); return; } } } else { // Remove existing mutations that don't fit into our category if (downgrades.size() > 0 && cat != MUTCAT_NULL) { int roll = rng(0, downgrades.size() + 4); if (roll < downgrades.size()) { remove_mutation(g, downgrades[roll]); return; } } } std::vector<pl_flag> valid; // Valid mutations bool first_pass = true; do { // If we tried once with a non-NULL category, and couldn't find anything valid // there, try again with MUTCAT_NULL if (!first_pass) { cat = MUTCAT_NULL; } if (cat == MUTCAT_NULL) { // Pull the full list for (int i = 1; i < PF_MAX2; i++) { if (g->mutation_data[i].valid) { valid.push_back( pl_flag(i) ); } } } else { // Pull the category's list valid = mutations_from_category(cat); } // Remove anything we already have, that we have a child of, or that // goes against our intention of a good/bad mutation for (int i = 0; i < valid.size(); i++) { if (!mutation_ok(g, valid[i], force_good, force_bad)) { valid.erase(valid.begin() + i); i--; } } if (valid.empty()) { // So we won't repeat endlessly first_pass = false; } } while (valid.empty() && cat != MUTCAT_NULL); if (valid.empty()) { // Couldn't find anything at all! return; } pl_flag selection = valid[ rng(0, valid.size() - 1) ]; // Pick one! mutate_towards(g, selection); }