Ejemplo n.º 1
0
        /// <summary>
        ///   The heart of the simulation that handles the processed parameters and calculates future populations.
        /// </summary>
        private static void SimulatePatchStep(RunResults populations, Patch patch, List <Species> species, Random random)
        {
            // Skip if there aren't any species in this patch
            if (species.Count < 1)
            {
                return;
            }

            var biome = patch.Biome;

            // TODO: this is where the proper auto-evo algorithm goes

            // Here's a temporary boost when there are few species and penalty
            // when there are many species
            bool lowSpecies  = species.Count <= Constants.AUTO_EVO_LOW_SPECIES_THRESHOLD;
            bool highSpecies = species.Count >= Constants.AUTO_EVO_HIGH_SPECIES_THRESHOLD;

            foreach (var currentSpecies in species)
            {
                int currentPopulation = populations.GetPopulationInPatch(currentSpecies, patch);
                int populationChange  = random.Next(
                    -Constants.AUTO_EVO_RANDOM_POPULATION_CHANGE, Constants.AUTO_EVO_RANDOM_POPULATION_CHANGE + 1);

                if (lowSpecies)
                {
                    populationChange += Constants.AUTO_EVO_LOW_SPECIES_BOOST;
                }
                else if (highSpecies)
                {
                    populationChange -= Constants.AUTO_EVO_HIGH_SPECIES_PENALTY;
                }

                populations.AddPopulationResultForSpecies(currentSpecies, patch, currentPopulation + populationChange);
            }
        }
        /// <summary>
        ///   The heart of the simulation that handles the processed parameters and calculates future populations.
        /// </summary>
        private static void SimulatePatchStep(RunResults populations, Patch patch, List <Species> genericSpecies,
                                              Random random)
        {
            _ = random;

            // Skip if there aren't any species in this patch
            if (genericSpecies.Count < 1)
            {
                return;
            }

            // This algorithm version is for microbe species
            var species = genericSpecies.Select(s => (MicrobeSpecies)s).ToList();

            var biome = patch.Biome;

            var sunlightInPatch = biome.Compounds[Sunlight].Dissolved * Constants.AUTO_EVO_SUNLIGHT_ENERGY_AMOUNT;

            var hydrogenSulfideInPatch = biome.Compounds[HydrogenSulfide].Density
                                         * biome.Compounds[HydrogenSulfide].Amount * Constants.AUTO_EVO_COMPOUND_ENERGY_AMOUNT;

            var glucoseInPatch = (biome.Compounds[Glucose].Density
                                  * biome.Compounds[Glucose].Amount
                                  + patch.GetTotalChunkCompoundAmount(Glucose)) * Constants.AUTO_EVO_COMPOUND_ENERGY_AMOUNT;

            var ironInPatch = patch.GetTotalChunkCompoundAmount(Iron) * Constants.AUTO_EVO_COMPOUND_ENERGY_AMOUNT;

            // Begin of new auto-evo prototype algorithm

            var speciesEnergies = new Dictionary <MicrobeSpecies, float>(species.Count);

            var totalPhotosynthesisScore       = 0.0f;
            var totalChemosynthesisScore       = 0.0f;
            var totalChemolithoautotrophyScore = 0.0f;
            var totalGlucoseScore = 0.0f;

            var totalPredationScore = 0.0f;

            // Calculate the total scores of each type in the current patch
            foreach (var currentSpecies in species)
            {
                totalPhotosynthesisScore       += GetCompoundUseScore(currentSpecies, Sunlight);
                totalChemosynthesisScore       += GetCompoundUseScore(currentSpecies, HydrogenSulfide);
                totalChemolithoautotrophyScore += GetCompoundUseScore(currentSpecies, Iron);
                totalGlucoseScore   += GetCompoundUseScore(currentSpecies, Glucose);
                totalPredationScore += GetPredationScore(currentSpecies);
            }

            // Avoid division by 0
            totalPhotosynthesisScore       = Math.Max(MathUtils.EPSILON, totalPhotosynthesisScore);
            totalChemosynthesisScore       = Math.Max(MathUtils.EPSILON, totalChemosynthesisScore);
            totalChemolithoautotrophyScore = Math.Max(MathUtils.EPSILON, totalChemolithoautotrophyScore);
            totalGlucoseScore   = Math.Max(MathUtils.EPSILON, totalGlucoseScore);
            totalPredationScore = Math.Max(MathUtils.EPSILON, totalPredationScore);

            // Calculate the share of environmental energy captured by each species
            var energyAvailableForPredation = 0.0f;

            foreach (var currentSpecies in species)
            {
                var currentSpeciesEnergy = 0.0f;

                currentSpeciesEnergy += sunlightInPatch
                                        * GetCompoundUseScore(currentSpecies, Sunlight) / totalPhotosynthesisScore;

                currentSpeciesEnergy += hydrogenSulfideInPatch
                                        * GetCompoundUseScore(currentSpecies, HydrogenSulfide) / totalChemosynthesisScore;

                currentSpeciesEnergy += ironInPatch
                                        * GetCompoundUseScore(currentSpecies, Iron) / totalChemolithoautotrophyScore;

                currentSpeciesEnergy += glucoseInPatch
                                        * GetCompoundUseScore(currentSpecies, Glucose) / totalGlucoseScore;

                energyAvailableForPredation += currentSpeciesEnergy * Constants.AUTO_EVO_PREDATION_ENERGY_MULTIPLIER;
                speciesEnergies.Add(currentSpecies, currentSpeciesEnergy);
            }

            // Calculate the share of predation done by each species
            // Then update populations
            foreach (var currentSpecies in species)
            {
                speciesEnergies[currentSpecies] += energyAvailableForPredation
                                                   * GetPredationScore(currentSpecies) / totalPredationScore;
                speciesEnergies[currentSpecies] -= energyAvailableForPredation / species.Count;

                var newPopulation = (long)(speciesEnergies[currentSpecies]
                                           / Math.Pow(currentSpecies.Organelles.Count, 1.3f));

                // Can't survive without enough population
                if (newPopulation < Constants.AUTO_EVO_MINIMUM_VIABLE_POPULATION)
                {
                    newPopulation = 0;
                }

                populations.AddPopulationResultForSpecies(currentSpecies, patch, newPopulation);
            }
        }