コード例 #1
0
    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;
        }
    }
コード例 #2
0
 public MoveActionData(OrganelleTemplate organelle, Hex oldLocation, Hex newLocation, int oldRotation,
                       int newRotation)
 {
     Organelle   = organelle;
     OldLocation = oldLocation;
     NewLocation = newLocation;
     OldRotation = oldRotation;
     NewRotation = newRotation;
 }
コード例 #3
0
ファイル: MicrobeEditor.cs プロジェクト: ichabodphage/Thrive
    /// <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);
    }
コード例 #4
0
ファイル: MicrobeEditor.cs プロジェクト: ichabodphage/Thrive
    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);
    }
コード例 #5
0
    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");
    }
コード例 #6
0
    /// <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);
    }
コード例 #7
0
    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;
    }
コード例 #8
0
 public RemoveActionData(OrganelleTemplate organelle)
 {
     Organelle = organelle;
 }
コード例 #9
0
 public PlacementActionData(OrganelleTemplate organelle)
 {
     Organelle = organelle;
 }
コード例 #10
0
    /// <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());
            }
        }
    }
コード例 #11
0
    /// <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.");
    }
コード例 #12
0
 public static Vector3 GetOrganelleDirection(OrganelleTemplate organelle)
 {
     return((Hex.AxialToCartesian(new Hex(0, 0)) - Hex.AxialToCartesian(organelle.Position)).Normalized());
 }
コード例 #13
0
 private void OnOrganelleRemoved(OrganelleTemplate organelle)
 {
     OnOrganellesChanged();
 }
コード例 #14
0
    private bool IsValidPlacement(OrganelleTemplate organelle)
    {
        bool notPlacingCytoplasm = organelle.Definition.InternalName != "cytoplasm";

        return(editedMicrobeOrganelles.CanPlaceAndIsTouching(organelle, notPlacingCytoplasm));
    }