コード例 #1
0
ファイル: Microbe.Interior.cs プロジェクト: Shupsta/Thrive
    /// <summary>
    ///   Resets the compounds to be the ones this species spawns with. Called by spawn helpers
    /// </summary>
    public void SetInitialCompounds()
    {
        Compounds.ClearCompounds();

        foreach (var entry in Species.InitialCompounds)
        {
            Compounds.AddCompound(entry.Key, entry.Value);
        }
    }
コード例 #2
0
    /// <summary>
    ///   Absorbs compounds from this cloud
    /// </summary>
    public void AbsorbCompounds(int localX, int localY, CompoundBag storage,
                                Dictionary <Compound, float> totals, float delta, float rate)
    {
        var fractionToTake = 1.0f - (float)Math.Pow(0.5f, delta / Constants.CLOUD_ABSORPTION_HALF_LIFE);

        for (int i = 0; i < Constants.CLOUDS_IN_ONE; i++)
        {
            if (Compounds[i] == null)
            {
                break;
            }

            // Skip if compound is non-useful
            if (!storage.IsUseful(Compounds[i]))
            {
                continue;
            }

            // Overestimate of how much compounds we get
            float generousAmount = HackyAddress(Density[localX, localY], i) *
                                   Constants.SKIP_TRYING_TO_ABSORB_RATIO;

            // Skip if there isn't enough to absorb
            if (generousAmount < MathUtils.EPSILON)
            {
                continue;
            }

            float freeSpace = storage.Capacity - storage.GetCompoundAmount(Compounds[i]);

            float multiplier = 1.0f * rate;

            if (freeSpace < generousAmount)
            {
                // Allow partial absorption to allow cells to take from high density clouds
                multiplier = freeSpace / generousAmount;
            }

            float taken = TakeCompound(Compounds[i], localX, localY, fractionToTake * multiplier) *
                          Constants.ABSORPTION_RATIO;

            storage.AddCompound(Compounds[i], taken);

            // Keep track of total compounds absorbed for the cell
            if (!totals.ContainsKey(Compounds[i]))
            {
                totals.Add(Compounds[i], taken);
            }
            else
            {
                totals[Compounds[i]] += taken;
            }
        }
    }
コード例 #3
0
    /// <summary>
    ///   Absorbs compounds from this cloud
    /// </summary>
    public void AbsorbCompounds(int localX, int localY, CompoundBag storage,
                                Dictionary <string, float> totals, float delta)
    {
        var fractionToTake = 1.0f - (float)Math.Pow(0.5f, delta / Constants.CLOUD_ABSORPTION_HALF_LIFE);

        foreach (var slot in slots)
        {
            // Overestimate of how much compounds we get
            float generousAmount = slot.Density[localX, localY] *
                                   Constants.SKIP_TRYING_TO_ABSORB_RATIO;

            // Skip if there isn't enough to absorb
            if (generousAmount < MathUtils.EPSILON)
            {
                continue;
            }

            var compound = slot.Compound.InternalName;

            float freeSpace = storage.Capacity - storage.GetCompoundAmount(compound);

            float multiplier = 1.0f;

            if (freeSpace < generousAmount)
            {
                // Allow partial absorption to allow cells to take from high density clouds
                multiplier = freeSpace / generousAmount;
            }

            float taken = slot.TakeCompound(localX, localY, fractionToTake * multiplier) *
                          Constants.ABSORPTION_RATIO;

            storage.AddCompound(compound, taken);

            // Keep track of total compounds absorbed for the cell
            if (!totals.ContainsKey(compound))
            {
                totals.Add(compound, taken);
            }
            else
            {
                totals[compound] += taken;
            }
        }
    }
コード例 #4
0
    private void RunProcess(float delta, BioProcess processData, CompoundBag bag, TweakedProcess process,
                            SingleProcessStatistics currentProcessStatistics, float inverseDelta)
    {
        // Can your cell do the process
        bool canDoProcess = true;

        // Loop through to make sure you can follow through with your
        // whole process so nothing gets wasted as that would be
        // frustrating.
        float environmentModifier = 1.0f;

        // First check the environmental compounds so that we can build the right environment modifier for accurate
        // check of normal compound input amounts
        foreach (var entry in processData.Inputs)
        {
            // Set used compounds to be useful, we dont want to purge
            // those
            bag.SetUseful(entry.Key);

            if (!entry.Key.IsEnvironmental)
            {
                continue;
            }

            var dissolved = GetDissolved(entry.Key);

            // currentProcessStatistics?.AddInputAmount(entry.Key, entry.Value * inverseDelta);
            currentProcessStatistics?.AddInputAmount(entry.Key, dissolved);

            // do environmental modifier here, and save it for later
            environmentModifier *= dissolved / entry.Value;

            if (environmentModifier <= MathUtils.EPSILON)
            {
                currentProcessStatistics?.AddLimitingFactor(entry.Key);
            }
        }

        if (environmentModifier <= MathUtils.EPSILON)
        {
            canDoProcess = false;
        }

        foreach (var entry in processData.Inputs)
        {
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            var inputRemoved = entry.Value * process.Rate * delta;

            currentProcessStatistics?.AddInputAmount(entry.Key, inputRemoved * inverseDelta);

            // currentProcessStatistics?.AddInputAmount(entry.Key, 0);

            // If not enough compound we can't do the process
            if (bag.GetCompoundAmount(entry.Key) < inputRemoved)
            {
                canDoProcess = false;
                currentProcessStatistics?.AddLimitingFactor(entry.Key);
            }
        }

        // Output
        // This is now always looped (even when we can't do the process)
        // because the is useful part is needs to be always be done
        foreach (var entry in processData.Outputs)
        {
            // For now lets assume compounds we produce are also
            // useful
            bag.SetUseful(entry.Key);

            // Apply the general modifiers and
            // apply the environmental modifier
            var outputAdded = entry.Value * process.Rate * delta * environmentModifier;

            currentProcessStatistics?.AddOutputAmount(entry.Key, outputAdded * inverseDelta);

            // currentProcessStatistics?.AddOutputAmount(entry.Key, 0);

            // If no space we can't do the process, and if environmental
            // right now this isn't released anywhere
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            if (bag.GetCompoundAmount(entry.Key) + outputAdded > bag.Capacity)
            {
                canDoProcess = false;
                currentProcessStatistics?.AddCapacityProblem(entry.Key);
            }
        }

        // Only carry out this process if you have all the required
        // ingredients and enough space for the outputs
        if (!canDoProcess)
        {
            return;
        }

        if (currentProcessStatistics != null)
        {
            currentProcessStatistics.CurrentSpeed = process.Rate * environmentModifier;
        }

        // Consume inputs
        foreach (var entry in processData.Inputs)
        {
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            var inputRemoved = entry.Value * process.Rate * delta *
                               environmentModifier;

            currentProcessStatistics?.AddInputAmount(entry.Key, inputRemoved * inverseDelta);

            // This should always succeed (due to the earlier check) so
            // it is always assumed here that the process succeeded
            bag.TakeCompound(entry.Key, inputRemoved);
        }

        // Add outputs
        foreach (var entry in processData.Outputs)
        {
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            var outputGenerated = entry.Value * process.Rate * delta *
                                  environmentModifier;

            currentProcessStatistics?.AddOutputAmount(entry.Key, outputGenerated * inverseDelta);

            bag.AddCompound(entry.Key, outputGenerated);
        }
    }
コード例 #5
0
ファイル: ProcessSystem.cs プロジェクト: Shupsta/Thrive
    private void RunProcess(float delta, BioProcess processData, CompoundBag bag, TweakedProcess process,
                            SingleProcessStatistics currentProcessStatistics, float inverseDelta)
    {
        // Can your cell do the process
        bool canDoProcess = true;

        float environmentModifier = 1.0f;

        // This modifies the process overall speed to allow really fast processes to run, for example if there are
        // a ton of one organelle it might consume 100 glucose per go, which might be unlikely for the cell to have
        // so if there is *some* but not enough space for results (and also inputs) this can run the process as
        // fraction of the speed to allow the cell to still function well
        float spaceConstraintModifier = 1.0f;

        // First check the environmental compounds so that we can build the right environment modifier for accurate
        // check of normal compound input amounts
        foreach (var entry in processData.Inputs)
        {
            // Set used compounds to be useful, we dont want to purge those
            bag.SetUseful(entry.Key);

            if (!entry.Key.IsEnvironmental)
            {
                continue;
            }

            var dissolved = GetDissolved(entry.Key);

            // currentProcessStatistics?.AddInputAmount(entry.Key, entry.Value * inverseDelta);
            currentProcessStatistics?.AddInputAmount(entry.Key, dissolved);

            // do environmental modifier here, and save it for later
            environmentModifier *= dissolved / entry.Value;

            if (environmentModifier <= MathUtils.EPSILON)
            {
                currentProcessStatistics?.AddLimitingFactor(entry.Key);
            }
        }

        if (environmentModifier <= MathUtils.EPSILON)
        {
            canDoProcess = false;
        }

        // Compute spaceConstraintModifier before updating the final use and input amounts
        foreach (var entry in processData.Inputs)
        {
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            var inputRemoved = entry.Value * process.Rate * environmentModifier;

            // currentProcessStatistics?.AddInputAmount(entry.Key, 0);
            // We don't multiply by delta here because we report the per-second values anyway. In the actual process
            // output numbers (computed after testing the speed), we need to multiply by inverse delta
            currentProcessStatistics?.AddInputAmount(entry.Key, inputRemoved);

            inputRemoved = inputRemoved * delta * spaceConstraintModifier;

            // If not enough we can't run the process unless we can lower spaceConstraintModifier enough
            var availableAmount = bag.GetCompoundAmount(entry.Key);
            if (availableAmount < inputRemoved)
            {
                bool canRun = false;

                if (availableAmount > MathUtils.EPSILON)
                {
                    var neededModifier = availableAmount / inputRemoved;

                    if (neededModifier > Constants.MINIMUM_RUNNABLE_PROCESS_FRACTION)
                    {
                        spaceConstraintModifier = neededModifier;
                        canRun = true;

                        // Due to rounding errors there can be very small disparity here between the amount available
                        // and what we will take with the modifiers. See the comment in outputs for more details
                    }
                }

                if (!canRun)
                {
                    canDoProcess = false;
                    currentProcessStatistics?.AddLimitingFactor(entry.Key);
                }
            }
        }

        foreach (var entry in processData.Outputs)
        {
            // For now lets assume compounds we produce are also useful
            bag.SetUseful(entry.Key);

            var outputAdded = entry.Value * process.Rate * environmentModifier;

            // currentProcessStatistics?.AddOutputAmount(entry.Key, 0);
            currentProcessStatistics?.AddOutputAmount(entry.Key, outputAdded);

            outputAdded = outputAdded * delta * spaceConstraintModifier;

            // if environmental right now this isn't released anywhere
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            // If no space we can't do the process, if we can't adjust the space constraint modifier enough
            var remainingSpace = bag.Capacity - bag.GetCompoundAmount(entry.Key);
            if (outputAdded > remainingSpace)
            {
                bool canRun = false;

                if (remainingSpace > MathUtils.EPSILON)
                {
                    var neededModifier = remainingSpace / outputAdded;

                    if (neededModifier > Constants.MINIMUM_RUNNABLE_PROCESS_FRACTION)
                    {
                        spaceConstraintModifier = neededModifier;
                        canRun = true;
                    }

                    // With all of the modifiers we can lose a tiny bit of compound that won't fit due to rounding
                    // errors, but we ignore that here
                }

                if (!canRun)
                {
                    canDoProcess = false;
                    currentProcessStatistics?.AddCapacityProblem(entry.Key);
                }
            }
        }

        // Only carry out this process if you have all the required ingredients and enough space for the outputs
        if (!canDoProcess)
        {
            if (currentProcessStatistics != null)
            {
                currentProcessStatistics.CurrentSpeed = 0;
            }
            return;
        }

        float totalModifier = process.Rate * delta * environmentModifier * spaceConstraintModifier;

        if (currentProcessStatistics != null)
        {
            currentProcessStatistics.CurrentSpeed = process.Rate * environmentModifier * spaceConstraintModifier;
        }

        // Consume inputs
        foreach (var entry in processData.Inputs)
        {
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            var inputRemoved = entry.Value * totalModifier;

            currentProcessStatistics?.AddInputAmount(entry.Key, inputRemoved * inverseDelta);

            // This should always succeed (due to the earlier check) so it is always assumed here that this succeeded
            bag.TakeCompound(entry.Key, inputRemoved);
        }

        // Add outputs
        foreach (var entry in processData.Outputs)
        {
            if (entry.Key.IsEnvironmental)
            {
                continue;
            }

            var outputGenerated = entry.Value * totalModifier;

            currentProcessStatistics?.AddOutputAmount(entry.Key, outputGenerated * inverseDelta);

            bag.AddCompound(entry.Key, outputGenerated);
        }
    }