public void OnStartFor(OrganelleTemplate organelle) { storedOrganelle = organelle; shownChoices = SimulationParameters.Instance.GetCloudCompounds(); foreach (var choice in shownChoices) { compounds.AddItem(choice.Name); } // Select glucose by default var defaultCompoundIndex = shownChoices.FindIndex(c => c.InternalName == Constants.CHEMORECEPTOR_DEFAULT_COMPOUND_NAME); if (defaultCompoundIndex < 0) { defaultCompoundIndex = 0; } // Apply current upgrade values or defaults if (organelle.Upgrades?.CustomUpgradeData is ChemoreceptorUpgrades configuration) { compounds.Selected = shownChoices.FindIndex(c => c == configuration.TargetCompound); maximumDistance.Value = configuration.SearchRange; minimumAmount.Value = configuration.SearchAmount; colour.Color = configuration.LineColour; } else { compounds.Selected = defaultCompoundIndex; maximumDistance.Value = Constants.CHEMORECEPTOR_RANGE_DEFAULT; minimumAmount.Value = Constants.CHEMORECEPTOR_AMOUNT_DEFAULT; colour.Color = Colors.White; } }
public MoveActionData(OrganelleTemplate organelle, Hex oldLocation, Hex newLocation, int oldRotation, int newRotation) { Organelle = organelle; OldLocation = oldLocation; NewLocation = newLocation; OldRotation = oldRotation; NewRotation = newRotation; }
/// <summary> /// Helper for AddOrganelle /// </summary> private void PlaceIfPossible(string organelleType, int q, int r, int rotation) { var organelle = new OrganelleTemplate(GetOrganelleDefinition(organelleType), new Hex(q, r), rotation); if (!IsValidPlacement(organelle)) return; // Skip placing if the player can't afford the organelle if (organelle.Definition.MPCost > MutationPoints && !FreeBuilding) return; AddOrganelle(organelle); }
private void AddOrganelle(OrganelleTemplate organelle) { // 1 - you put nucleus but you already have it // 2 - you put organelle that need nucleus and you don't have it if ((organelle.Definition.Name == "nucleus" && HasNucleus) || (organelle.Definition.ProkaryoteChance == 0 && !HasNucleus && organelle.Definition.ChanceToCreate != 0)) return; var action = new EditorAction(this, organelle.Definition.MPCost, DoOrganellePlaceAction, UndoOrganellePlaceAction, new PlacementActionData(organelle)); EnqueueAction(action); }
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> /// Symmetric flagella are a corner case for speed calculations because the sum of all /// directions is kind of broken in their case, so we have to choose which one of the symmetric flagella /// we must discard from the direction calculation /// Here we only discard if the flagella we input is the "bad" one /// </summary> private static Vector3 ChooseFromSymmetricFlagella(IEnumerable <OrganelleTemplate> organelles, OrganelleTemplate testedOrganelle, Vector3 maximumMovementDirection) { foreach (var organelle in organelles) { if (organelle != testedOrganelle && organelle.Position + testedOrganelle.Position == new Hex(0, 0)) { var organelleLength = (maximumMovementDirection - GetOrganelleDirection(organelle)).Length(); var testedOrganelleLength = (maximumMovementDirection - GetOrganelleDirection(testedOrganelle)).Length(); if (organelleLength > testedOrganelleLength) { return(maximumMovementDirection); } return(maximumMovementDirection - GetOrganelleDirection(testedOrganelle)); } } return(maximumMovementDirection); }
public void OpenForOrganelle(OrganelleTemplate organelle, string upgraderScene, MicrobeEditor editor) { var scene = GD.Load <PackedScene>(upgraderScene); if (scene == null) { GD.PrintErr($"Failed to load upgrader scene for organelle of type {organelle.Definition.InternalName}"); return; } var instance = scene.Instance(); upgrader = (IOrganelleUpgrader)instance; organelleSpecificContent.FreeChildren(); organelleSpecificContent.AddChild(instance); popup.PopupCenteredShrink(); scrollContainer.ScrollVertical = 0; upgrader.OnStartFor(organelle); storedEditor = editor; }
public RemoveActionData(OrganelleTemplate organelle) { Organelle = organelle; }
public PlacementActionData(OrganelleTemplate organelle) { Organelle = organelle; }
/// <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 static Vector3 GetOrganelleDirection(OrganelleTemplate organelle) { return((Hex.AxialToCartesian(new Hex(0, 0)) - Hex.AxialToCartesian(organelle.Position)).Normalized()); }
private void OnOrganelleRemoved(OrganelleTemplate organelle) { OnOrganellesChanged(); }
private bool IsValidPlacement(OrganelleTemplate organelle) { bool notPlacingCytoplasm = organelle.Definition.InternalName != "cytoplasm"; return(editedMicrobeOrganelles.CanPlaceAndIsTouching(organelle, notPlacingCytoplasm)); }