Esempio n. 1
0
void player::mutate_category(game *g, mutation_category cat)
{
    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;
    }

    // Pull the category's list for valid mutations
    std::vector<pl_flag> valid;
    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 we can't mutate in the category do nothing
    if (valid.empty()) return;

    pl_flag selection = valid[ rng(0, valid.size() - 1) ]; // Pick one!
    mutate_towards(g, selection);

    return;
}
Esempio n. 2
0
void player::mutate_towards(game *g, pl_flag mut)
{
 if (has_child_flag(g, mut)) {
  remove_child_flag(g, mut);
  return;
 }
 bool has_prereqs = false;
 std::vector<pl_flag> prereq = g->mutation_data[mut].prereqs;
 std::vector<pl_flag> cancel = g->mutation_data[mut].cancels;

 for (int i = 0; i < cancel.size(); i++) {
  if (!has_trait( cancel[i] )) {
   cancel.erase(cancel.begin() + i);
   i--;
  }
 }

 if (!cancel.empty()) {
  pl_flag removed = cancel[ rng(0, cancel.size() - 1) ];
  remove_mutation(g, removed);
  return;
 }

 for (int i = 0; !has_prereqs && i < prereq.size(); i++) {
  if (has_trait(prereq[i]))
   has_prereqs = true;
 }
 if (!has_prereqs && !prereq.empty()) {
  pl_flag devel = prereq[ rng(0, prereq.size() - 1) ];
  mutate_towards(g, devel);
  return;
 }

// Check if one of the prereqs that we have TURNS INTO this one
 pl_flag replacing = PF_NULL;
 prereq = g->mutation_data[mut].prereqs; // Reset it
 for (int i = 0; i < prereq.size(); i++) {
  if (has_trait(prereq[i])) {
   pl_flag pre = prereq[i];
   for (int j = 0; replacing == PF_NULL &&
                   j < g->mutation_data[pre].replacements.size(); j++) {
    if (g->mutation_data[pre].replacements[j] == mut)
     replacing = pre;
   }
  }
 }

 toggle_trait(mut);
 if (replacing != PF_NULL) {
  g->add_msg("Your %s turns into %s!", traits[replacing].name.c_str(),
             traits[mut].name.c_str());
  toggle_trait(replacing);
 } else
  g->add_msg("You gain %s!", traits[mut].name.c_str());
 mutation_effect(g, *this, mut);

// Weight us towards any categories that include this mutation
 for (int i = 0; i < NUM_MUTATION_CATEGORIES; i++) {
  std::vector<pl_flag> group = mutations_from_category(mutation_category(i));
  bool found = false;
  for (int j = 0; !found && j < group.size(); j++) {
   if (group[j] == mut)
    found = true;
  }
  if (found)
   mutation_category_level[i] += 8;
  else if (mutation_category_level[i] > 0 &&
           !one_in(mutation_category_level[i]))
   mutation_category_level[i]--;
 }

}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
void player::remove_mutation(game *g, pl_flag mut)
{
    // Check for dependant mutations first
    std::vector<pl_flag> dependant;
    for (int i = 0; i < PF_MAX2; i++)
    {
        for (std::vector<pl_flag>::iterator it = g->mutation_data[i].prereqs.begin();
             it != g->mutation_data[i].prereqs.end(); it++)
        {
            if (*it == i)
            {
                dependant.push_back((pl_flag)i);
                break;
            }
        }
    }
    if (dependant.size() != 0)
    {
        remove_mutation(g,dependant[rng(0,dependant.size())]);
        return;
    }

// Check if there's a prereq we should shrink back into
 pl_flag replacing = PF_NULL;
 std::vector<pl_flag> originals = g->mutation_data[mut].prereqs;
 for (int i = 0; replacing == PF_NULL && i < originals.size(); i++) {
  pl_flag pre = originals[i];
  for (int j = 0; replacing == PF_NULL &&
                  j < g->mutation_data[pre].replacements.size(); j++) {
   if (g->mutation_data[pre].replacements[j] == mut)
    replacing = pre;
  }
 }
 
// See if this mutation is cancelled by a base trait
//Only if there's no prereq to shrink to, thus we're at the bottom of the trait line
 if (replacing == PF_NULL) { 
 
 //Check each mutation until we reach the end or find a trait to revert to
 for (int i = 1; replacing == PF_NULL && i < PF_MAX2; i++) { 
 
   //See if it's in our list of base traits but not active
   if (has_base_trait(i) && !has_trait(i)) {
    //See if that base trait cancels the mutation we are using
    std::vector<pl_flag> traitcheck = g->mutation_data[i].cancels;
	if (!traitcheck.empty()) {
	 for (int j = 0; replacing == PF_NULL && j < traitcheck.size(); j++) {
	  if (g->mutation_data[i].cancels[j] == mut)
	   replacing = ((pl_flag)i);
	 }
	}
   }
  }
 }
// This should revert back to a removed base trait rather than simply removing the mutation
	toggle_mutation(mut);
 if (replacing != PF_NULL) {
  g->add_msg(_("Your %1$s mutation turns into %2$s."), traits[mut].name.c_str(),
             traits[replacing].name.c_str());
  toggle_mutation(replacing);
  mutation_loss_effect(g, *this, mut);
  mutation_effect(g, *this, replacing);
 } else {
  g->add_msg(_("You lose your %s mutation."), traits[mut].name.c_str());
  mutation_loss_effect(g, *this, mut);
 }
// Reduce the strength of the categories the removed mutation is a part of
 for (int i = 0; i < NUM_MUTATION_CATEGORIES; i++) {
  std::vector<pl_flag> group = mutations_from_category(mutation_category(i));
  bool found = false;
  for (int j = 0; !found && j < group.size(); j++) {
   if (group[j] == mut)
    found = true;
   }
  if (found) {
   mutation_category_level[i] -= 8;
   // If the category strength is below 0, set it to 0. We don't want negative category strength.
   if (mutation_category_level[i] < 0) {
    mutation_category_level[i] = 0;
   }
  }
 } 
}