示例#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);
            }
        }
示例#2
0
        private void CheckCurrentPatchSpecies(RunResults results)
        {
            foreach (var candidateSpecies in patch.SpeciesInPatch)
            {
                if (candidateSpecies.Value < configuration.NewBiodiversityIncreasingSpeciesPopulation)
                {
                    continue;
                }

                var found = TryBiodiversitySplit(candidateSpecies.Key, true);

                if (found == null)
                {
                    continue;
                }

                OnSpeciesCreated(found, candidateSpecies.Key, results);

                if (configuration.UseBiodiversityForceSplit)
                {
                    // TODO: implement this
                    throw new NotImplementedException(
                              "Marking biodiversity increase as split is not implemented");
                }

                break;
            }
        }
示例#3
0
        public bool RunStep(RunResults results)
        {
            // ReSharper disable RedundantArgumentDefaultValue
            var config = new SimulationConfiguration(configuration, map, 1)
            {
                Results = results,
                CollectEnergyInformation = collectEnergyInfo,
            };

            // ReSharper restore RedundantArgumentDefaultValue

            if (extraSpecies != null)
            {
                config.ExtraSpecies = extraSpecies;
            }

            if (excludedSpecies != null)
            {
                config.ExcludedSpecies = excludedSpecies;
            }

            // Directly feed the population results to the main results object

            PopulationSimulation.Simulate(config);

            return(true);
        }
示例#4
0
        public bool RunStep(RunResults results)
        {
            // We gather populations that may be targeted in the patch, depending on the parameters,
            // this may exclude migrated or newly created species.
            // Excluded species are only protected for one generation. The player is a target as well,
            // although they will be rescued before extinction can apply to them.
            var targetSpeciesPopulationsByPatch = results.GetPopulationsByPatch(
                !configuration.ProtectMigrationsFromSpeciesCap, true);

            var newSpecies = results.GetNewSpecies();

            foreach (var patch in patches)
            {
                // If no species exist in a patch, we need to skip handling the current patch
                if (!targetSpeciesPopulationsByPatch.TryGetValue(patch, out var tmpTarget))
                {
                    continue;
                }

                IEnumerable <KeyValuePair <Species, long> > targetEnumerator = tmpTarget;

                if (configuration.ProtectNewCellsFromSpeciesCap)
                {
                    targetEnumerator = targetEnumerator.Where(s => !newSpecies.Contains(s.Key));
                }

                var targetSpecies = targetEnumerator.ToList();

                // Only bother if we're above the limit
                if (targetSpecies.Count <= configuration.MaximumSpeciesInPatch)
                {
                    continue;
                }

                GD.Print("Running extinction step in patch ", patch.Name, ". ",
                         "Total count:", targetSpecies.Count);

                var orderedTargetSpecies = targetSpecies.OrderBy(s => s.Value).Select(s => s.Key);

                var speciesToRemoveCount = targetSpecies.Count - Math.Max(configuration.MaximumSpeciesInPatch, 0);

                // Remove worst-faring species in targets (which again exclude *temporarily* protected ones).
                foreach (var speciesToRemove in orderedTargetSpecies.Take(speciesToRemoveCount))
                {
                    // We rescue the player if needed
                    if (speciesToRemove.PlayerSpecies)
                    {
                        continue;
                    }

                    GD.Print("Forced extinction of species ", speciesToRemove.FormattedName,
                             " in patch ", patch.Name, ".");
                    results.KillSpeciesInPatch(speciesToRemove, patch,
                                               configuration.RefundMigrationsInExtinctions);
                }
            }

            return(true);
        }
示例#5
0
        public bool RunStep(RunResults results)
        {
            foreach (var species in speciesToCheck)
            {
                results.RemoveMigrationsForSplitPatches(species);
            }

            return(true);
        }
示例#6
0
        protected override void OnBestResultFound(RunResults results, IAttemptResult bestVariant)
        {
            var variant = (AttemptResult)bestVariant;

            if (variant.Migration == null)
            {
                return;
            }

            results.AddMigrationResultForSpecies(species, variant.Migration);
        }
示例#7
0
        private void OnSpeciesCreated(Species species, Species fromSpecies, RunResults results)
        {
            results.AddNewSpecies(species,
                                  new[]
            {
                new KeyValuePair <Patch, long>(patch, configuration.NewBiodiversityIncreasingSpeciesPopulation),
            },
                                  RunResults.NewSpeciesType.FillNiche, fromSpecies);

            createdASpecies = true;
        }
示例#8
0
        public bool RunStep(RunResults results)
        {
            if (tryCurrentPatch)
            {
                CheckCurrentPatchSpecies(results);

                tryCurrentPatch = false;
                return(false);
            }

            if (createdASpecies)
            {
                return(true);
            }

            CheckNeighbourPatchSpecies(results);

            return(true);
        }
示例#9
0
        private void CheckNeighbourPatchSpecies(RunResults results)
        {
            var alreadyCheckedSpecies = new HashSet <Species>(patch.SpeciesInPatch.Select(p => p.Key));

            foreach (var neighbour in patch.Adjacent)
            {
                foreach (var candidateSpecies in neighbour.SpeciesInPatch)
                {
                    if (candidateSpecies.Value < configuration.NewBiodiversityIncreasingSpeciesPopulation ||
                        alreadyCheckedSpecies.Contains(candidateSpecies.Key))
                    {
                        continue;
                    }

                    if (random.NextDouble() > configuration.BiodiversityFromNeighbourPatchChance)
                    {
                        continue;
                    }

                    alreadyCheckedSpecies.Add(candidateSpecies.Key);

                    var found = TryBiodiversitySplit(candidateSpecies.Key, false);

                    if (found == null)
                    {
                        continue;
                    }

                    OnSpeciesCreated(found, candidateSpecies.Key, results);

                    if (!configuration.BiodiversityNearbyPatchIsFreePopulation)
                    {
                        // TODO: implement this
                        throw new NotImplementedException(
                                  "adding population penalty to neighbour patch is not implemented");
                    }

                    break;
                }
            }
        }
示例#10
0
        public bool Step(RunResults results)
        {
            bool ran = false;

            if (tryCurrentVariant)
            {
                var result = TryCurrentVariant();

                if (currentBest == null || result.Score > currentBest.Score)
                {
                    currentBest = result;
                }

                tryCurrentVariant = false;
                ran = true;
            }

            if (variantsToTry > 0 && !ran)
            {
                var result = TryVariant();

                if (currentBest == null || result.Score > currentBest.Score)
                {
                    currentBest = result;
                }

                --variantsToTry;
                ran = true;
            }

            if (!tryCurrentVariant && variantsToTry <= 0)
            {
                // Store the best result
                OnBestResultFound(results, currentBest);
                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#11
0
        public bool RunStep(RunResults results)
        {
            bool ran = false;

            if (tryCurrentVariant)
            {
                var result = TryCurrentVariant();

                CheckScore(result);

                tryCurrentVariant = false;
                ran = true;
            }

            if (variantsToTry > 0 && !ran)
            {
                var result = TryVariant();

                CheckScore(result);

                --variantsToTry;
            }

            if (!tryCurrentVariant && variantsToTry <= 0)
            {
                // Store the best result
                if (currentBest == null)
                {
                    throw new Exception($"Variant step didn't try anything ({nameof(currentBest)} is null)");
                }

                OnBestResultFound(results, currentBest);
                return(true);
            }

            return(false);
        }
示例#12
0
 public bool RunStep(RunResults results)
 {
     operation(results);
     return(true);
 }
示例#13
0
 /// <summary>
 ///   Called after the best attempted variant is determined
 /// </summary>
 /// <param name="results">Results to apply the found solution to.</param>
 /// <param name="bestVariant">Best variant found.</param>
 protected abstract void OnBestResultFound(RunResults results, IAttemptResult bestVariant);
        /// <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);
            }
        }
示例#15
0
 protected override void OnBestResultFound(RunResults results, IAttemptResult bestVariant)
 {
     results.AddMutationResultForSpecies(species, ((AttemptResult)bestVariant).Mutation);
 }