/// <summary> /// Creates a mutated version of parentOrganelles in organelles /// </summary> private void MutateMicrobeOrganelles(OrganelleLayout <OrganelleTemplate> parentOrganelles, OrganelleLayout <OrganelleTemplate> organelles, bool isBacteria) { var nucleus = SimulationParameters.Instance.GetOrganelleType("nucleus"); for (var iteration = 0; iteration < 10; iteration++) { organelles.Clear(); // Delete or replace an organelle randomly for (int i = 0; i < parentOrganelles.Count; i++) { bool copy = true; var organelle = parentOrganelles[i]; if (parentOrganelles.Count < 2) { // Removing last organelle would be silly } else if (organelle.Definition != nucleus) { // Chance to replace or remove if not a nucleus if (random.Next(0.0f, 1.0f) < Constants.MUTATION_DELETION_RATE) { copy = false; } else if (random.Next(0.0f, 1.0f) < Constants.MUTATION_REPLACEMENT_RATE) { copy = false; var replacer = new OrganelleTemplate(GetRandomOrganelle(isBacteria), organelle.Position, organelle.Orientation); // The replacing organelle might not fit at the same position try { organelles.Add(replacer); } catch (ArgumentException) { // Couldn't replace it copy = true; } } } if (!copy) { continue; } // Copy the organelle try { organelles.Add((OrganelleTemplate)organelle.Clone()); } catch (ArgumentException) { // Add the organelle randomly back to the list to make // sure we don't throw it away AddNewOrganelle(organelles, organelle.Definition); } } // Can add up to 6 new organelles (Which should allow AI to catch up to player more // We can insert new organelles at the end of the list if (random.Next(0.0f, 1.0f) < Constants.MUTATION_CREATION_RATE) { AddNewOrganelle(organelles, GetRandomOrganelle(isBacteria)); } /* * Probability of mutation occuring 5 time(s) = 0.15 = 1.0E-5 * Probability of mutation NOT occuring = (1 - 0.1)5 = 0.59049 * Probability of mutation occuring = 1 - (1 - 0.1)5 = 0.40951 */ // We can insert new organelles at the end of the list for (int n = 0; n < 5; ++n) { if (random.Next(0.0f, 1.0f) < Constants.MUTATION_EXTRA_CREATION_RATE) { AddNewOrganelle(organelles, GetRandomOrganelle(isBacteria)); } } if (isBacteria) { if (random.Next(0.0f, 100.0f) <= Constants.MUTATION_BACTERIA_TO_EUKARYOTE) { AddNewOrganelle(organelles, nucleus); } } // Disallow creating empty species as that throws an exception when trying to spawn if (organelles.Count < 1) { // Add the first parent species organelle AddNewOrganelle(organelles, parentOrganelles[0].Definition); // If still empty, copy the first organelle of the parent if (organelles.Count < 1) { organelles.Add((OrganelleTemplate)parentOrganelles[0].Clone()); } } // Try again if the mutation has islands if (organelles.GetIslandHexes().Count == 0) { return; } } GD.PrintErr("Could not create a valid mutation after 10 retries."); }
/// <summary> /// Creates a mutated version of parentOrganelles in organelles /// </summary> private void MutateMicrobeOrganelles(OrganelleLayout <OrganelleTemplate> parentOrganelles, OrganelleLayout <OrganelleTemplate> mutatedOrganelles, bool isBacteria) { var nucleus = SimulationParameters.Instance.GetOrganelleType("nucleus"); for (var iteration = 0; iteration < 10; iteration++) { mutatedOrganelles.Clear(); // Chance to replace each organelle randomly foreach (var parentOrganelle in parentOrganelles) { var organelle = (OrganelleTemplate)parentOrganelle.Clone(); // Chance to replace or remove if not a nucleus if (organelle.Definition != nucleus) { if (random.Next(0.0f, 1.0f) < Constants.MUTATION_DELETION_RATE / Math.Sqrt(parentOrganelles.Count)) { // Don't copy over this organelle, removing this one from the new species continue; } if (random.Next(0.0f, 1.0f) < Constants.MUTATION_REPLACEMENT_RATE) { organelle = new OrganelleTemplate(GetRandomOrganelle(isBacteria), organelle.Position, organelle.Orientation); } } // Copy the organelle try { mutatedOrganelles.Add(organelle); } catch (ArgumentException) { // Add the organelle randomly back to the list to make // sure we don't throw it away AddNewOrganelle(mutatedOrganelles, organelle.Definition); } } // We can insert new organelles at the end of the list for (int i = 0; i < 6; ++i) { if (random.Next(0.0f, 1.0f) < Constants.MUTATION_CREATION_RATE) { AddNewOrganelle(mutatedOrganelles, GetRandomOrganelle(isBacteria)); } } if (isBacteria) { if (random.Next(0.0f, 1.0f) <= Constants.MUTATION_BACTERIA_TO_EUKARYOTE) { AddNewOrganelle(mutatedOrganelles, nucleus); } } // Disallow creating empty species as that throws an exception when trying to spawn if (mutatedOrganelles.Count < 1) { // Add the first parent species organelle AddNewOrganelle(mutatedOrganelles, parentOrganelles[0].Definition); // If still empty, copy the first organelle of the parent if (mutatedOrganelles.Count < 1) { mutatedOrganelles.Add((OrganelleTemplate)parentOrganelles[0].Clone()); } } // If the mutation has no islands, we can use this iteration if (mutatedOrganelles.GetIslandHexes().Count == 0) { return; } } GD.PrintErr("Could not create a valid mutation after 10 retries."); }