Beispiel #1
0
        protected override IAttemptResult TryVariant()
        {
            var migration = GetRandomMigration();

            // Move generation can randomly fail
            if (migration == null)
            {
                return(new AttemptResult(null, -1));
            }

            var config = new SimulationConfiguration(configuration, map, Constants.AUTO_EVO_VARIANT_SIMULATION_STEPS);

            config.SetPatchesToRunBySpeciesPresence(species);
            config.PatchesToRun.Add(migration.From);
            config.PatchesToRun.Add(migration.To);

            config.Migrations.Add(new Tuple <Species, SpeciesMigration>(species, migration));

            // TODO: this could be faster to just simulate the source and
            // destination patches (assuming in the future no global effects of
            // migrations are added, which would need a full patch map
            // simulation anyway)
            PopulationSimulation.Simulate(config);

            var population = config.Results.GetGlobalPopulation(species);

            return(new AttemptResult(migration, population));
        }
Beispiel #2
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);
        }
Beispiel #3
0
 private static void RunSimulationStep(SimulationConfiguration parameters, List <Species> species, Random random)
 {
     foreach (var entry in parameters.OriginalMap.Patches)
     {
         // Simulate the species in each patch taking into account the already computed populations
         SimulatePatchStep(parameters.Results, entry.Value,
                           species.Where((item) => parameters.Results.GetPopulationInPatch(item, entry.Value) > 0).ToList(),
                           random);
     }
 }
Beispiel #4
0
        protected override IAttemptResult TryCurrentVariant()
        {
            var config = new SimulationConfiguration(map, Constants.AUTOEVO_VARIANT_SIMULATION_STEPS);

            PopulationSimulation.Simulate(config);

            var population = config.Results.GetGlobalPopulation(species);

            return(new AttemptResult(null, population));
        }
Beispiel #5
0
        public static void Simulate(SimulationConfiguration parameters)
        {
            var random = new Random();

            var speciesToSimulate = CopyInitialPopulationsToResults(parameters);

            while (parameters.StepsLeft > 0)
            {
                RunSimulationStep(parameters, speciesToSimulate, random);
                --parameters.StepsLeft;
            }
        }
Beispiel #6
0
 private static void RunSimulationStep(SimulationConfiguration parameters, List <Species> species,
                                       IEnumerable <KeyValuePair <int, Patch> > patchesToSimulate, Random random, SimulationCache cache,
                                       AutoEvoConfiguration autoEvoConfiguration)
 {
     foreach (var entry in patchesToSimulate)
     {
         // Simulate the species in each patch taking into account the already computed populations
         SimulatePatchStep(parameters, entry.Value,
                           species.Where(item => parameters.Results.GetPopulationInPatch(item, entry.Value) > 0),
                           random, cache, autoEvoConfiguration);
     }
 }
Beispiel #7
0
        protected override IAttemptResult TryVariant()
        {
            var mutated = (MicrobeSpecies)species.Clone();

            mutations.CreateMutatedSpecies((MicrobeSpecies)species, mutated);

            var config = new SimulationConfiguration(map, Constants.AUTOEVO_VARIANT_SIMULATION_STEPS);

            config.ExcludedSpecies.Add(species);
            config.ExtraSpecies.Add(mutated);

            PopulationSimulation.Simulate(config);

            var population = config.Results.GetGlobalPopulation(mutated);

            return(new AttemptResult(mutated, population));
        }
Beispiel #8
0
        private MicrobeSpecies TryBiodiversitySplit(Species splitFrom, bool inCurrentPatch)
        {
            var config = new SimulationConfiguration(configuration, map, Constants.AUTO_EVO_VARIANT_SIMULATION_STEPS);

            var split = (MicrobeSpecies)splitFrom.Clone();

            if (configuration.BiodiversitySplitIsMutated)
            {
                mutations.CreateMutatedSpecies((MicrobeSpecies)splitFrom, split);
            }

            // Set the starting population in the patch
            split.Population = configuration.NewBiodiversityIncreasingSpeciesPopulation;

            config.ExtraSpecies.Add(split);
            config.PatchesToRun.Add(patch);

            if (inCurrentPatch)
            {
                // TODO: should we apply the population reduction to splitFrom?
            }

            PopulationSimulation.Simulate(config);

            var population = config.Results.GetPopulationInPatch(split, patch);

            if (population < configuration.NewBiodiversityIncreasingSpeciesPopulation)
            {
                return(null);
            }

            // TODO: could compare the original species population here to determine if this change is beneficial to
            // it as well (in which case a non-force species split could be done)

            // Successfully found a species to create in order to increase biodiversity
            return(split);
        }
Beispiel #9
0
        public static void Simulate(SimulationConfiguration parameters)
        {
            var random = new Random();
            var cache  = new SimulationCache();

            var speciesToSimulate = CopyInitialPopulationsToResults(parameters);

            IEnumerable <KeyValuePair <int, Patch> > patchesToSimulate = parameters.OriginalMap.Patches;

            // Skip patches not configured to be simulated in order to run faster
            if (parameters.PatchesToRun.Count > 0)
            {
                patchesToSimulate = patchesToSimulate.Where(p => parameters.PatchesToRun.Contains(p.Value));
            }

            var patchesList = patchesToSimulate.ToList();

            while (parameters.StepsLeft > 0)
            {
                RunSimulationStep(parameters, speciesToSimulate, patchesList, random, cache,
                                  parameters.AutoEvoConfiguration);
                --parameters.StepsLeft;
            }
        }
Beispiel #10
0
        /// <summary>
        ///   Populates the initial population numbers taking config into account
        /// </summary>
        private static List <Species> CopyInitialPopulationsToResults(SimulationConfiguration parameters)
        {
            var species = new List <Species>();

            // Copy non excluded species
            foreach (var candidateSpecies in parameters.OriginalMap.FindAllSpeciesWithPopulation())
            {
                if (parameters.ExcludedSpecies.Contains(candidateSpecies))
                {
                    continue;
                }

                species.Add(candidateSpecies);
            }

            // Copy extra species
            species.AddRange(parameters.ExtraSpecies);

            // Prepare population numbers for each patch for each of the included species
            foreach (var entry in parameters.OriginalMap.Patches)
            {
                var patch = entry.Value;

                foreach (var currentSpecies in species)
                {
                    int currentPopulation = patch.GetSpeciesPopulation(currentSpecies);

                    // If this is an extra species, this first takes the
                    // population from extra species that match its index, if that
                    // doesn't exist then the population number is used
                    if (currentPopulation == 0 && parameters.ExtraSpecies.Contains(currentSpecies))
                    {
                        bool useGlobal = true;

                        for (int i = 0; i < parameters.ExtraSpecies.Count; ++i)
                        {
                            if (parameters.ExtraSpecies[i] == currentSpecies)
                            {
                                if (parameters.ExcludedSpecies.Count > i)
                                {
                                    currentPopulation = patch.GetSpeciesPopulation(parameters.ExcludedSpecies[i]);
                                    useGlobal         = false;
                                }

                                break;
                            }
                        }

                        if (useGlobal)
                        {
                            currentPopulation = currentSpecies.Population;
                        }
                    }

                    // Apply migrations
                    foreach (var migration in parameters.Migrations)
                    {
                        if (migration.Item1 == currentSpecies)
                        {
                            if (migration.Item2.From == patch)
                            {
                                currentPopulation -= migration.Item2.Population;
                            }
                            else if (migration.Item2.To == patch)
                            {
                                currentPopulation += migration.Item2.Population;
                            }
                        }
                    }

                    // All species even ones not in a patch need to have their population numbers added
                    // as the simulation expects to be able to get the populations
                    parameters.Results.AddPopulationResultForSpecies(currentSpecies, patch, currentPopulation);
                }
            }

            return(species);
        }
Beispiel #11
0
        /// <summary>
        ///   The heart of the simulation that handles the processed parameters and calculates future populations.
        /// </summary>
        private static void SimulatePatchStep(SimulationConfiguration simulationConfiguration, Patch patch,
                                              IEnumerable <Species> genericSpecies, Random random, SimulationCache cache,
                                              AutoEvoConfiguration autoEvoConfiguration)
        {
            _ = random;

            var  populations = simulationConfiguration.Results;
            bool trackEnergy = simulationConfiguration.CollectEnergyInformation;

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

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

            var energyBySpecies = new Dictionary <MicrobeSpecies, float>();

            foreach (var currentSpecies in species)
            {
                energyBySpecies[currentSpecies] = 0.0f;
            }

            bool strictCompetition = autoEvoConfiguration.StrictNicheCompetition;

            var niches = new List <FoodSource>
            {
                new EnvironmentalFoodSource(patch, Sunlight, Constants.AUTO_EVO_SUNLIGHT_ENERGY_AMOUNT),
                new CompoundFoodSource(patch, Glucose),
                new CompoundFoodSource(patch, HydrogenSulfide),
                new CompoundFoodSource(patch, Iron),
                new ChunkFoodSource(patch, "marineSnow"),
                new ChunkFoodSource(patch, "ironSmallChunk"),
                new ChunkFoodSource(patch, "ironBigChunk"),
            };

            foreach (var currentSpecies in species)
            {
                niches.Add(new HeterotrophicFoodSource(patch, currentSpecies));
            }

            foreach (var niche in niches)
            {
                // If there isn't a source of energy here, no need for more calculations
                if (niche.TotalEnergyAvailable() <= MathUtils.EPSILON)
                {
                    continue;
                }

                var fitnessBySpecies  = new Dictionary <MicrobeSpecies, float>();
                var totalNicheFitness = 0.0f;
                foreach (var currentSpecies in species)
                {
                    float thisSpeciesFitness;

                    if (strictCompetition)
                    {
                        // Softly enforces https://en.wikipedia.org/wiki/Competitive_exclusion_principle
                        // by exaggerating fitness differences
                        thisSpeciesFitness =
                            Mathf.Max(Mathf.Pow(niche.FitnessScore(currentSpecies, cache), 2.5f), 0.0f);
                    }
                    else
                    {
                        thisSpeciesFitness = Mathf.Max(niche.FitnessScore(currentSpecies, cache), 0.0f);
                    }

                    fitnessBySpecies[currentSpecies] = thisSpeciesFitness;
                    totalNicheFitness += thisSpeciesFitness;
                }

                // If no species can get energy this way, no need for more calculations
                if (totalNicheFitness <= MathUtils.EPSILON)
                {
                    continue;
                }

                foreach (var currentSpecies in species)
                {
                    var energy = fitnessBySpecies[currentSpecies] * niche.TotalEnergyAvailable() / totalNicheFitness;

                    // If this species can't gain energy here, don't count it (this also prevents it from appearing
                    // in food sources (if that's not what we want), if the species doesn't use this food source
                    if (energy <= MathUtils.EPSILON)
                    {
                        continue;
                    }

                    energyBySpecies[currentSpecies] += energy;

                    if (trackEnergy)
                    {
                        populations.AddTrackedEnergyForSpecies(currentSpecies, patch, niche,
                                                               fitnessBySpecies[currentSpecies], energy, totalNicheFitness);
                    }
                }
            }

            foreach (var currentSpecies in species)
            {
                var energyBalanceInfo = cache.GetEnergyBalanceForSpecies(currentSpecies, patch);

                // Modify populations based on energy
                var newPopulation = (long)(energyBySpecies[currentSpecies]
                                           / energyBalanceInfo.FinalBalanceStationary);

                if (trackEnergy)
                {
                    populations.AddTrackedEnergyConsumptionForSpecies(currentSpecies, patch, newPopulation,
                                                                      energyBySpecies[currentSpecies], energyBalanceInfo.FinalBalanceStationary);
                }

                // TODO: this is a hack for now to make the player experience better, try to get the same rules working
                // for the player and AI species in the future.
                if (currentSpecies.PlayerSpecies)
                {
                    // Severely penalize a species that can't osmoregulate
                    if (energyBalanceInfo.FinalBalanceStationary < 0)
                    {
                        newPopulation /= 10;
                    }
                }
                else
                {
                    // Severely penalize a species that can't move indefinitely
                    if (energyBalanceInfo.FinalBalance < 0)
                    {
                        newPopulation /= 10;
                    }
                }

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

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