Example #1
0
        /// <summary>
        /// Delegates the generation to the underlying view models.
        /// Displays the generated content using the unity objects
        /// </summary>
        /// <param name="finishAction">The action to invoke when the generation is completed.</param>
        /// <param name="generationStartAction">The action to invoke when a generation starts.</param>
        /// <param name="generationEndAction">The action to invoke when a generation ends.</param>
        /// <param name="cancellationToken">The cancellation token, used to cancel the generation.</param>
        internal async void GenerateAsync(
            Action finishAction,
            OnGenerationStart generationStartAction,
            OnGenerationEnd generationEndAction,
            CancellationToken cancellationToken)
        {
            Reset();
            _finishedGenerations = 0;

            _onGenerationStart = generationStartAction;
            _onGenerationEnd   = generationEndAction;

            // Invokes the finish action
            void OnGenerationFinish() => finishAction?.Invoke();

            // Update the cancellation token of the view models
            terrainViewModel.CancelToken = cancellationToken;
            cityViewModel.CancelToken    = cancellationToken;

            try
            {
                // Generate the terrain
                var(terrainMesh, terrainTexture) = await Task.Run(() => terrainViewModel.Generate(), cancellationToken);

                if (cancellationToken.IsCancellationRequested || terrainMesh == null || terrainTexture == null)
                {
                    // Either the task was cancelled or a terrain value is null, abort.
                    OnGenerationFinish();
                    return;
                }

                // Update component data
                _meshFilter.sharedMesh   = terrainMesh;
                _meshCollider.sharedMesh = terrainMesh;
                _meshRenderer.sharedMaterial.mainTexture = terrainTexture;

                // Update the model's terrain data
                _model.TerrainTexture   = terrainTexture;
                _model.TerrainHeightMap = _meshFilter.sharedMesh.HeightMap();
                _model.TerrainOffset    = _meshFilter.transform.position;

                // Generate a city
                _model.City = await Task.Run(() => cityViewModel.Generate(), cancellationToken);
            }
            catch (TaskCanceledException)
            {
                // A task was canceled, abort
                OnGenerationFinish();
                return;
            }

            if (cancellationToken.IsCancellationRequested || _model.City == null)
            {
                // Either the task was canceled or the city is not valid, abort.
                OnGenerationFinish();
                return;
            }

            // Create game objects based on the world data (terrain and city elements)
            CreateGameObjects(cancellationToken);

            // Invoke the finish action
            OnGenerationFinish();
        }
Example #2
0
        public Ann Train(int maxGenerations, int generationSize, double?errorThreshold, int mutationRate, int mutationRolls, bool waitForFlag, double[][] inputs, double[][] expectedOutputs, Crossover.CrossoverOperation crossoverOperation, ActivationFunction.ActivationMethod activationMethod)
        {
            Ann[] generation  = new Ann[generationSize];
            int   inputCount  = inputs[0].Length;
            int   outputCount = expectedOutputs[0].Length;

            for (int generationId = 0; generationId < maxGenerations; generationId++)
            {
                if (generationId == 0)
                {
                    for (int startingIndividual = 0; startingIndividual < generationSize; startingIndividual++)
                    {
                        Ann    ann   = new Ann(inputCount, outputCount, activationMethod);
                        double error = CalculateError(ann, inputs, expectedOutputs);
                        ann.Error = error;
                        generation[startingIndividual] = ann;
                    }
                }
                else
                {
                    Ann parentA = generation[0];
                    Ann parentB = generation[1];

                    for (int newIndividual = 0; newIndividual < generationSize; newIndividual++)
                    {
                        generation = generation.OrderByDescending(x => x.Error).ToArray();

                        Ann child = crossoverOperation.Invoke(parentA, parentB);
                        Mutations.RollToCauseRandomMutation(child, mutationRate, mutationRolls);
                        double error = CalculateError(child, inputs, expectedOutputs);
                        child.Error = error;

                        if (child.Error < generation[0].Error)
                        {
                            generation[0] = child;
                        }
                    }
                }

                generation.ToList().ForEach(x =>
                {
                    x.Error      = CalculateError(x, inputs, expectedOutputs);
                    x.Generation = generationId;
                });

                generation = generation.OrderBy(x => x.Error).ToArray();

                if (waitForFlag)
                {
                    waitFlag = true;
                    OnGenerationEnd?.Invoke(generation[0]);
                    while (waitFlag)
                    {
                    }
                }
                else
                {
                    OnGenerationEnd?.Invoke(generation[0]);
                }

                if (errorThreshold != null && generation[0].Error < errorThreshold)
                {
                    return(generation[0]);
                }
            }
            return(generation[0]);
        }