/// <inheritdoc/>
        public Task <ISectorMap> CreateAsync(ISectorMapFactoryOptions generationOptions)
        {
            if (generationOptions is null)
            {
                throw new ArgumentNullException(nameof(generationOptions));
            }

            var transitions = generationOptions.Transitions;

            var cellularAutomatonOptions = (ISectorCellularAutomataMapFactoryOptionsSubScheme)generationOptions.OptionsSubScheme;

            if (cellularAutomatonOptions == null)
            {
                throw new ArgumentException($"Для {nameof(generationOptions)} не задано {nameof(ISectorSubScheme.MapGeneratorOptions)} равно null.");
            }

            var matrixWidth  = cellularAutomatonOptions.MapWidth;
            var matrixHeight = cellularAutomatonOptions.MapHeight;

            var chanceToStartAlive = cellularAutomatonOptions.ChanceToStartAlive;

            var targetRegionDraftCount = transitions.Count() + 1;
            var createResult           = CreateInner(
                targetRegionDraftCount,
                chanceToStartAlive,
                matrixWidth,
                matrixHeight);

            var matrix       = createResult.Matrix;
            var draftRegions = createResult.Regions;

            var map = CreateSectorMap(matrix, draftRegions, transitions);

            return(Task.FromResult(map));
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public Task <ISectorMap> CreateAsync(ISectorMapFactoryOptions generationOptions)
        {
            if (generationOptions is null)
            {
                throw new ArgumentNullException(nameof(generationOptions));
            }

            var factoryOptions = (ISectorSquareMapFactoryOptionsSubScheme)generationOptions.OptionsSubScheme;

            if (factoryOptions == null)
            {
                throw new ArgumentException($"Для {nameof(generationOptions)} не задано {nameof(ISectorSubScheme.MapGeneratorOptions)} равно null.");
            }

            var mapSize = factoryOptions.Size;

            ISectorMap map = new SectorGraphMap();

            MapFiller.FillSquareMap(map, mapSize);

            var mapRegion = new MapRegion(1, map.Nodes.ToArray())
            {
                IsStart   = true,
                IsOut     = true,
                ExitNodes = new[] { map.Nodes.Last() }
            };

            map.Regions.Add(mapRegion);

            return(Task.FromResult(map));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Создание карты.
        /// </summary>
        /// <returns>
        /// Возвращает экземпляр карты.
        /// </returns>
        public Task <ISectorMap> CreateAsync(ISectorMapFactoryOptions generationOptions)
        {
            if (generationOptions is null)
            {
                throw new System.ArgumentNullException(nameof(generationOptions));
            }

            var roomFactoryOptions = generationOptions.OptionsSubScheme as ISectorRoomMapFactoryOptionsSubScheme;

            if (roomFactoryOptions is null)
            {
                throw new System.ArgumentException("Не задана схема генерации в настройках", nameof(generationOptions));
            }

            var map = CreateMapInstance();

            var edgeHash = new HashSet <string>();

            // Генерируем случайные координаты комнат
            var transitions = generationOptions.Transitions;

            var rooms = _roomGenerator.GenerateRoomsInGrid(roomFactoryOptions.RegionCount,
                                                           RoomMinSize,
                                                           roomFactoryOptions.RegionSize,
                                                           transitions);

            // Создаём узлы и рёбра комнат
            _roomGenerator.CreateRoomNodes(map, rooms, edgeHash);

            // Соединяем комнаты
            _roomGenerator.BuildRoomCorridors(map, rooms, edgeHash);

            // Указание регионов карты
            var regionIdCounter = 1;

            foreach (var room in rooms)
            {
                var passableRoomNodes = room.Nodes;
                var region            = new MapRegion(regionIdCounter, passableRoomNodes.Cast <IGraphNode>().ToArray());
                regionIdCounter++;
                map.Regions.Add(region);

                if (room.IsStart)
                {
                    region.IsStart = true;
                    continue;
                }

                if (room.Transitions?.Any() == true)
                {
                    region.ExitNodes = (from regionNode in region.Nodes
                                        where map.Transitions.Keys.Contains(regionNode)
                                        select regionNode).ToArray();

                    continue;
                }
            }

            return(Task.FromResult(map));
        }
Ejemplo n.º 4
0
        public async Task <ISectorMap> CreateAsync(ISectorMapFactoryOptions generationOptions)
        {
            if (_factoryFuncAsync == null)
            {
                throw new InvalidOperationException("Не задана фабричная функция.");
            }

            //TODO Объяснить, почему тут нужно использовать ConfigureAwait(false)
            // Это рекомендация Codacy.
            // Но есть статья https://habr.com/ru/company/clrium/blog/463587/,
            // в которой объясняется, что не всё так просто.
            // Нужно чёткое понимание, зачем здесь ConfigureAwait(false) и
            // к какому результату это приводит по сравнению с простым await.
            var map = await _factoryFuncAsync(generationOptions).ConfigureAwait(false);

            return(map);
        }
Ejemplo n.º 5
0
        public Task <ISectorMap> CreateAsync(ISectorMapFactoryOptions generationOptions)
        {
            if (generationOptions is null)
            {
                throw new ArgumentNullException(nameof(generationOptions));
            }

            var factoryOptions = (ISectorOpenMapFactoryOptionsSubScheme)generationOptions.OptionsSubScheme;

            if (factoryOptions == null)
            {
                throw new ArgumentException(
                          $"Map generation options {nameof(ISectorSubScheme.MapGeneratorOptions)} are not defined in {nameof(generationOptions)}.");
            }

            var mapSize = factoryOptions.Size;

            return(CreateInternalAsync(mapSize, generationOptions.Transitions));
        }
        /// <inheritdoc />
        public Task <ISectorMap> CreateAsync(ISectorMapFactoryOptions generationOptions)
        {
            if (generationOptions is null)
            {
                throw new ArgumentNullException(nameof(generationOptions));
            }

            var transitions = generationOptions.Transitions;

            var cellularAutomatonOptions =
                (ISectorCellularAutomataMapFactoryOptionsSubScheme)generationOptions.OptionsSubScheme;

            if (cellularAutomatonOptions == null)
            {
                throw new ArgumentException(
                          $"Для {nameof(generationOptions)} не задано {nameof(ISectorSubScheme.MapGeneratorOptions)} равно null.");
            }

            var matrixWidth  = cellularAutomatonOptions.MapWidth;
            var matrixHeight = cellularAutomatonOptions.MapHeight;

            var fillProbability = cellularAutomatonOptions.ChanceToStartAlive;

            var cellularAutomatonGenerator = new CellularAutomatonGenerator(_dice);

            var mapRuleManager = new MapRuleManager();
            var rule           = new RegionCountRule {
                Count = transitions.Count() + 1
            };

            mapRuleManager.AddRule(rule);

            var regionPostProcessors = new IRegionPostProcessor[]
            {
                new SplitToTargetCountRegionPostProcessor(mapRuleManager, _dice)
            };

            for (var retryIndex = 0; retryIndex < RETRY_MAX_COUNT; retryIndex++)
            {
                var matrix = new Matrix <bool>(matrixWidth, matrixHeight);

                var regions = cellularAutomatonGenerator.Generate(ref matrix, fillProbability, 7);

                try
                {
                    regions = PostProcess(regionPostProcessors, regions);

                    ClosestRegionConnector.Connect(matrix, regions);

                    var map = CreateSectorMap(matrix, regions.ToArray(), transitions);

                    return(Task.FromResult(map));
                }
                catch (CellularAutomatonException)
                {
                    // This means that with the current starting data it is not possible to create a suitable map.
                    // Start the next iteration.
                }
            }

            // If the cycle has ended, then no attempt has ended with a successful map building
            throw new InvalidOperationException("Failed to create a map within the maximum number of attempts.");
        }