public NewMicrobeActionData(OrganelleLayout <OrganelleTemplate> oldEditedMicrobeOrganelles, int previousMP, MembraneType oldMembrane) { OldEditedMicrobeOrganelles = oldEditedMicrobeOrganelles; PreviousMP = previousMP; OldMembrane = oldMembrane; }
/// <summary> /// Adds a new organelle to a mutation result /// </summary> private void AddNewOrganelle(OrganelleLayout <OrganelleTemplate> organelles, OrganelleDefinition organelle) { try { organelles.Add(GetRealisticPosition(organelle, organelles)); } catch (ArgumentException) { // Failing to add a mutation is not serious } }
private OrganelleTemplate GetRealisticPosition(OrganelleDefinition organelle, OrganelleLayout <OrganelleTemplate> existingOrganelles) { var result = new OrganelleTemplate(organelle, new Hex(0, 0), 0); // Loop through all the organelles and find an open spot to // place our new organelle attached to existing organelles // This almost always is over at the first iteration, so its // not a huge performance hog foreach (var otherOrganelle in existingOrganelles.OrderBy(_ => random.Next())) { // The otherOrganelle is the organelle we wish to be next to // Loop its hexes and check positions next to them foreach (var hex in otherOrganelle.RotatedHexes) { // Offset by hexes in organelle we are looking at var pos = otherOrganelle.Position + hex; for (int side = 1; side <= 6; ++side) { for (int radius = 1; radius <= 3; ++radius) { // Offset by hex offset multiplied by a factor to check for greater range var hexOffset = Hex.HexNeighbourOffset[(Hex.HexSide)side]; hexOffset *= radius; result.Position = pos + hexOffset; // Check every possible rotation value. for (int rotation = 0; rotation <= 5; ++rotation) { result.Orientation = rotation; if (existingOrganelles.CanPlace(result)) { return(result); } } } } } } // We didnt find an open spot, this doesn't make much sense throw new ArgumentException("Mutation code could not find a good position " + "for a new organelle"); }
/// <summary> /// Wipes clean the current cell. /// </summary> public void CreateNewMicrobe() { if (!FreeBuilding) { throw new InvalidOperationException("can't reset cell when not freebuilding"); } var previousMP = MutationPoints; var oldEditedMicrobeOrganelles = new OrganelleLayout <OrganelleTemplate>(); var oldMembrane = Membrane; foreach (var organelle in editedMicrobeOrganelles) { oldEditedMicrobeOrganelles.Add(organelle); } var action = new EditorAction(this, 0, redo => { MutationPoints = Constants.BASE_MUTATION_POINTS; Membrane = SimulationParameters.Instance.GetMembrane("single"); editedMicrobeOrganelles.RemoveAll(); editedMicrobeOrganelles.Add(new OrganelleTemplate(GetOrganelleDefinition("cytoplasm"), new Hex(0, 0), 0)); gui.UpdateMembraneButtons(Membrane.InternalName); gui.UpdateSpeed(CalculateSpeed()); }, undo => { editedMicrobeOrganelles.RemoveAll(); MutationPoints = previousMP; Membrane = oldMembrane; gui.UpdateMembraneButtons(Membrane.InternalName); gui.UpdateSpeed(CalculateSpeed()); foreach (var organelle in oldEditedMicrobeOrganelles) { editedMicrobeOrganelles.Add(organelle); } }); EnqueueAction(action); }
/// <summary> /// Resets the organelles in this microbe to match the species definition /// </summary> public void ResetOrganelleLayout() { // TODO: It would be much better if only organelles that need // to be removed where removed, instead of everything. // When doing that all organelles will need to be re-added anyway if this turned from a prokaryote to eukaryote if (organelles == null) { organelles = new OrganelleLayout <PlacedOrganelle>(OnOrganelleAdded, OnOrganelleRemoved); } else { // Just clear the existing ones organelles.Clear(); } foreach (var entry in Species.Organelles.Organelles) { var placed = new PlacedOrganelle { Definition = entry.Definition, Position = entry.Position, Orientation = entry.Orientation, }; organelles.Add(placed); } // Reproduction progress is lost allOrganellesDivided = false; // Unbind if a colony's master cell removed its binding agent. if (Colony != null && Colony.Master == this && !organelles.Any(p => p.IsBindingAgent)) { Colony.RemoveFromColony(this); } }
/// <summary> /// Wipes clean the current cell. /// </summary> public void CreateNewMicrobe() { if (!FreeBuilding) { throw new InvalidOperationException("can't reset cell when not freebuilding"); } var previousMP = MutationPoints; var oldEditedMicrobeOrganelles = new OrganelleLayout <OrganelleTemplate>(); foreach (var organelle in editedMicrobeOrganelles) { oldEditedMicrobeOrganelles.Add(organelle); } var action = new EditorAction(this, 0, redo => { MutationPoints = Constants.BASE_MUTATION_POINTS; editedMicrobeOrganelles.RemoveAll(); editedMicrobeOrganelles.Add(new OrganelleTemplate(GetOrganelleDefinition("cytoplasm"), new Hex(0, 0), 0)); }, undo => { editedMicrobeOrganelles.RemoveAll(); MutationPoints = previousMP; foreach (var organelle in oldEditedMicrobeOrganelles) { editedMicrobeOrganelles.Add(organelle); } }); EnqueueAction(action); }
public MicrobeSpecies(uint id) : base(id) { Organelles = new OrganelleLayout <OrganelleTemplate>(); }
/// <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"); 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()); } } }
/// <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."); }
public MicrobeSpecies(uint id, string genus, string epithet) : base(id, genus, epithet) { Organelles = new OrganelleLayout <OrganelleTemplate>(); }
/// <summary> /// Combined old editor init and activate method /// </summary> private void InitEditor() { // For now we only show a loading screen if auto-evo is not ready yet if (!CurrentGame.GameWorld.IsAutoEvoFinished()) { ready = false; gui.SetLoadingStatus(true); gui.SetLoadingText("Loading Microbe Editor", CurrentGame.GameWorld.GetAutoEvoRun().Status); } else { OnEditorReady(); } MutationPoints = Constants.BASE_MUTATION_POINTS; editedMicrobeOrganelles = new OrganelleLayout <OrganelleTemplate>( OnOrganelleAdded, OnOrganelleRemoved); organelleRot = 0; Symmetry = 0; gui.ResetSymmetryButton(); UpdateUndoRedoButtons(); // The world is reset each time so these are gone placedHexes = new List <MeshInstance>(); placedModels = new List <SceneDisplayer>(); // Check generation and set it here. CurrentGame.SetBool("edited_microbe", true); if (CurrentGame.FreeBuild) { GD.Print("Editor going to freebuild mode because player has activated freebuild"); FreeBuilding = true; } else { // Make sure freebuilding doesn't get stuck on FreeBuilding = false; } // Sent freebuild value to GUI gui.NotifyFreebuild(FreeBuilding); playerPatchOnEntry = CurrentGame.GameWorld.Map.CurrentPatch; // Send info to the GUI about the organelle effectiveness in the current patch CalculateOrganelleEffectivenessInPatch(); // Reset this, GUI will tell us to enable it again ShowHover = false; targetPatch = null; canStillMove = true; UpdatePatchBackgroundImage(); gui.SetMap(CurrentGame.GameWorld.Map); var playerSpecies = CurrentGame.GameWorld.PlayerSpecies; SetupEditedSpecies(playerSpecies as MicrobeSpecies); gui.UpdateGlucoseReduction(Constants.GLUCOSE_REDUCTION_RATE); }