Example #1
0
        private void CreateChest(List <IGraphNode> openNodes, ISector sector, IDropTableScheme[] trashDropTables,
                                 IDropTableScheme[] treasuresDropTable)
        {
            // Выбрать из коллекции доступных узлов
            var rollIndex     = _chestGeneratorRandomSource.RollNodeIndex(openNodes.Count);
            var map           = sector.Map;
            var containerNode = MapRegionHelper.FindNonBlockedNode(openNodes[rollIndex], map, openNodes);

            if (containerNode == null)
            {
                // в этом случае будет сгенерировано на один сундук меньше.
                // узел, с которого не удаётся найти подходящий узел, удаляем,
                // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                openNodes.Remove(openNodes[rollIndex]);
                return;
            }

            // Проверка, что сундук не перегораживает проход.
            var isValid = CheckMap(sector, (HexNode)containerNode);

            if (!isValid)
            {
                // в этом случае будет сгенерировано на один сундук меньше.
                // узел, с которого не удаётся найти подходящий узел, удаляем,
                // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                openNodes.Remove(openNodes[rollIndex]);
                return;
            }

            openNodes.Remove(containerNode);

            var staticObject = CreateChestStaticObject(trashDropTables, treasuresDropTable, containerNode);

            sector.StaticObjectManager.Add(staticObject);
        }
Example #2
0
        public void CreateCitizens(ISector sector, IBotPlayer botPlayer, IEnumerable <MapRegion> citizenRegions)
        {
            var map = sector.Map;

            foreach (var region in citizenRegions)
            {
                // 1 к 9, потому что это наиболее удобное соотношение
                // для размещения неподвижных блокирующих объектов
                // без преграждения выходов.
                var citizenCount = region.Nodes.Count() / 9f;

                var availableNodes = from node in region.Nodes
                                     where !map.Transitions.Keys.Contains(node)
                                     select node;

                var openNodes = new List <IMapNode>(availableNodes);
                for (var i = 0; i < citizenCount; i++)
                {
                    //TODO Объединить этот блок с генератором сундуков, как дубликат
                    // Выбрать из коллекции доступных узлов
                    var rollIndex  = _citizenGeneratorRandomSource.RollNodeIndex(openNodes.Count);
                    var objectNode = MapRegionHelper.FindNonBlockedNode(openNodes[rollIndex], map, openNodes);
                    if (objectNode == null)
                    {
                        // В этом случае будет сгенерировано на одного жителя меньше.
                        // Узел, с которого не удаётся найти подходящий узел, удаляем,
                        // Чтобы больше его не анализировать, т.к. всё равно будет такой же неудачный исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    openNodes.Remove(objectNode);
                    var traderDropTable = _schemeService.GetScheme <IDropTableScheme>("trader");

                    var rollCitizenType = _citizenGeneratorRandomSource.RollCitizenType();

                    switch (rollCitizenType)
                    {
                    case CitizenType.Unintresting:
                        CreateCitizen(objectNode, botPlayer);
                        break;

                    case CitizenType.Trader:
                        CreateCitizen(traderDropTable, objectNode, botPlayer);
                        break;

                    case CitizenType.QuestGiver:
                        CreateCitizen(DialogFactory.Create(), objectNode, botPlayer);
                        break;

                    default:
                        //TODO Завести тип исключения на генерацию персонажей мирных жителей.
                        throw new System.Exception();
                    }
                }
            }
        }
        /// <summary>
        /// Создать сундуки в секторе.
        /// </summary>
        /// <param name="map">Карта сектора. Нужна для определения доступного места для сундука.</param>
        /// <param name="sectorSubScheme">Схема сектора. По сути - настройки для размещения сундуков.</param>
        /// <param name="regions">Регионы, в которых возможно размещение сундуков.</param>
        public void CreateChests(ISectorMap map, ISectorSubScheme sectorSubScheme, IEnumerable <MapRegion> regions)
        {
            var dropTables   = GetDropTables(sectorSubScheme);
            var chestCounter = sectorSubScheme.TotalChestCount;

            //TODO В схемах хранить уже приведённое значение пропорции.
            var countChestRatioNormal = 1f / sectorSubScheme.RegionChestCountRatio;

            foreach (var region in regions)
            {
                var maxChestCountRaw = region.Nodes.Count() * countChestRatioNormal;
                var maxChestCount    = (int)Math.Max(maxChestCountRaw, 1);
                var rolledCount      = _chestGeneratorRandomSource.RollChestCount(maxChestCount);

                var availableNodes = from node in region.Nodes
                                     where !map.Transitions.Keys.Contains(node)
                                     select node;
                var openNodes = new List <IMapNode>(availableNodes);
                for (var i = 0; i < rolledCount; i++)
                {
                    // Выбрать из коллекции доступных узлов
                    var rollIndex     = _chestGeneratorRandomSource.RollNodeIndex(openNodes.Count);
                    var containerNode = MapRegionHelper.FindNonBlockedNode(openNodes[rollIndex], map, openNodes);
                    if (containerNode == null)
                    {
                        // в этом случае будет сгенерировано на один сундук меньше.
                        // узел, с которого не удаётся найти подходящий узел, удаляем,
                        // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    openNodes.Remove(containerNode);
                    var container = new DropTablePropChest(containerNode,
                                                           dropTables,
                                                           _dropResolver);
                    _propContainerManager.Add(container);

                    chestCounter--;

                    if (chestCounter <= 0)
                    {
                        // лимит сундуков в секторе исчерпан.
                        break;
                    }
                }
            }
        }
Example #4
0
        /// <summary>
        /// Создать сундуки в секторе.
        /// </summary>
        /// <param name="map">Карта сектора. Нужна для определения доступного места для сундука.</param>
        /// <param name="sectorSubScheme">Схема сектора. По сути - настройки для размещения сундуков.</param>
        /// <param name="regions">Регионы, в которых возможно размещение сундуков.</param>
        public void CreateChests(ISectorMap map, ISectorSubScheme sectorSubScheme, IEnumerable <MapRegion> regions)
        {
            var trashDropTables    = GetTrashDropTables(sectorSubScheme);
            var treasuresDropTable = GetTreasuresDropTable();
            var chestCounter       = sectorSubScheme.TotalChestCount;

            //TODO В схемах хранить уже приведённое значение пропорции.
            var countChestRatioNormal = 1f / sectorSubScheme.RegionChestCountRatio;

            foreach (var region in regions)
            {
                var maxChestCountRaw = region.Nodes.Count() * countChestRatioNormal;
                var maxChestCount    = (int)Math.Max(maxChestCountRaw, 1);

                if (region.Nodes.Count() <= 1)
                {
                    // Для регионов, где только один узел,
                    // не создаём сундуки, иначе проход может быть загорожен.
                    // Актуально для фабрики карт на основе клеточного автомата,
                    // потому что он может генерить регионы из одного узла.

                    //TODO Попробовать проверять соседей узла.
                    // Возможно, одноклеточный регион находится в конце тупика.
                    // Тогда в нём можно разместить сундук.
                    // Критерий доступности такого региона - у узла только одни сосед.
                    continue;
                }

                var rolledCount = _chestGeneratorRandomSource.RollChestCount(maxChestCount);

                var availableNodes = from node in region.Nodes
                                     where !map.Transitions.Keys.Contains(node)
                                     where map.IsPositionAvailableForContainer(node)
                                     select node;

                var openNodes = new List <IMapNode>(availableNodes);
                for (var i = 0; i < rolledCount; i++)
                {
                    var containerPurpose = _chestGeneratorRandomSource.RollPurpose();

                    // Выбрать из коллекции доступных узлов
                    var rollIndex     = _chestGeneratorRandomSource.RollNodeIndex(openNodes.Count);
                    var containerNode = MapRegionHelper.FindNonBlockedNode(openNodes[rollIndex], map, openNodes);
                    if (containerNode == null)
                    {
                        // в этом случае будет сгенерировано на один сундук меньше.
                        // узел, с которого не удаётся найти подходящий узел, удаляем,
                        // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    // Проверка, что сундук не перегораживает проход.
                    var isValid = CheckMap(map, (HexNode)containerNode);
                    if (!isValid)
                    {
                        // в этом случае будет сгенерировано на один сундук меньше.
                        // узел, с которого не удаётся найти подходящий узел, удаляем,
                        // чтобы больше его не анализировать, т.к. всё равно будет такой же исход.
                        openNodes.Remove(openNodes[rollIndex]);
                        continue;
                    }

                    openNodes.Remove(containerNode);

                    IPropContainer container;
                    switch (containerPurpose)
                    {
                    case PropContainerPurpose.Trash:
                        container = new DropTablePropChest(containerNode, trashDropTables, _dropResolver)
                        {
                            Purpose = PropContainerPurpose.Trash
                        };
                        break;

                    case PropContainerPurpose.Treasures:
                        container = new DropTablePropChest(containerNode, treasuresDropTable, _dropResolver)
                        {
                            Purpose = PropContainerPurpose.Treasures
                        };
                        break;

                    default:
                        throw new InvalidOperationException($"Не корректное назначение {containerPurpose}.");
                    }
                    _propContainerManager.Add(container);

                    chestCounter--;

                    if (chestCounter <= 0)
                    {
                        // лимит сундуков в секторе исчерпан.
                        break;
                    }
                }
            }
        }