private TerrainCell GetStartProvinceCoords(Globe globe)
        {
            // Выбираем основной город, являющийся стартовым.
            // По городу определяем провинцию.

            var availableStartLocalities = globe.Localities;

            Locality startLocality;

            if (availableStartLocalities.Any())
            {
                var startLocalityIndex = _dice.Roll(0, availableStartLocalities.Count() - 1);
                startLocality = availableStartLocalities[startLocalityIndex];
            }
            else
            {
                startLocality = globe.Localities.FirstOrDefault();
            }

            if (startLocality == null)
            {
                //TODO Создать отдельный класс исключений GlobeGenerationException.
                throw new InvalidOperationException("Не удалось выбрать стартовую локацию.");
            }

            return(startLocality.Cell);
        }
        /// <summary>
        /// Создание игрового мира с историей и граф провинций.
        /// </summary>
        /// <returns>
        /// Возвращает объект игрового мира.
        /// </returns>
        public Task <GlobeGenerationResult> GenerateGlobeAsync()
        {
            return(Task.Run(() =>
            {
                var globe = new Globe
                {
                    Terrain = new TerrainCell[WORLD_SIZE][],
                    agentNameGenerator = new RandomName(_dice),
                    cityNameGenerator = new CityNameGenerator(_dice)
                };

                var realmTask = CreateRealmsAsync(globe, _realmNames);
                var terrainTask = CreateTerrainAsync(globe);

                Task.WaitAll(realmTask, terrainTask);

                CreateStartLocalities(globe);
                CreateStartAgents(globe);

                var cardQueue = CreateAgentCardQueue();

                // обработка итераций
                ProcessIterations(globe, cardQueue);

                globe.StartProvince = GetStartProvinceCoords(globe);
                globe.HomeProvince = GetHomeProvinceCoords(globe, globe.StartProvince);

                // Сейчас история пустая. Пока не разработаны требования, как лучше сделать.
                var globeHistory = new GlobeGenerationHistory();
                var result = new GlobeGenerationResult(globe, globeHistory);
                return result;
            }));
        }
        private void CreateStartLocalities(Globe globe)
        {
            for (var i = 0; i < StartRealmCount; i++)
            {
                var randomX = _dice.Roll(0, Size - 1);
                var randomY = _dice.Roll(0, Size - 1);

                var locality = new Locality()
                {
                    Name       = $"L{i}",
                    Cell       = globe.Terrain[randomX][randomY],
                    Owner      = globe.Realms[i],
                    Population = 3
                };

                var rolledBranchIndex = _dice.Roll(0, 7);
                locality.Branches = new Dictionary <BranchType, int>
                {
                    { (BranchType)rolledBranchIndex, 1 }
                };

                globe.Localities.Add(locality);

                globe.LocalitiesCells[locality.Cell] = locality;

                globe.scanResult.Free.Remove(locality.Cell);
            }
        }
        private void CreateStartLocalities(Globe globe)
        {
            for (var i = 0; i < START_ITERATION_REALMS; i++)
            {
                var randomX = _dice.Roll(0, WORLD_SIZE - 1);
                var randomY = _dice.Roll(0, WORLD_SIZE - 1);

                var localityName = globe.GetLocalityName(_dice);

                var locality = new Locality()
                {
                    Name       = localityName,
                    Cell       = globe.Terrain[randomX][randomY],
                    Owner      = globe.Realms[i],
                    Population = 3
                };

                var rolledBranchIndex = _dice.Roll(0, 7);
                locality.Branches = new Dictionary <BranchType, int>
                {
                    { (BranchType)rolledBranchIndex, 1 }
                };

                globe.Localities.Add(locality);

                globe.LocalitiesCells[locality.Cell] = locality;

                globe.ScanResult.Free.Remove(locality.Cell);
            }
        }
        /// <summary>
        /// Создание игрового мира с историей и граф провинций.
        /// </summary>
        /// <returns>
        /// Возвращает объект игрового мира.
        /// </returns>
        public Task <Globe> GenerateGlobeAsync()
        {
            var globe = new Globe
            {
                Terrain = new TerrainCell[Size][]
            };

            var realmTask   = CreateRealms(globe);
            var terrainTask = CreateTerrain(globe);

            Task.WaitAll(realmTask, terrainTask);

            CreateStartLocalities(globe);
            CreateStartAgents(globe);

            var agentsClock = new Stopwatch();

            agentsClock.Start();

            var cardQueue = CreateAgentCardQueue();

            // обработка итераций
            ProcessIterations(globe, cardQueue);

            agentsClock.Stop();
            Console.WriteLine(agentsClock.ElapsedMilliseconds / 1f + "s");

            return(Task.FromResult(globe));
        }
        //TODO Постараться объединить GetStartProvinceCoords и GetHomeProvinceCoords
        private TerrainCell GetHomeProvinceCoords(Globe globe, TerrainCell startProvince)
        {
            // Выбираем основной город, являющийся стартовым.
            // По городу определяем провинцию.

            var currentCubeCoords   = HexHelper.ConvertToCube(startProvince.Coords);
            var availableLocalities = globe.Localities
                                      .Where(x => x.Cell != startProvince)
                                      .Where(x => HexHelper.ConvertToCube(x.Cell.Coords).DistanceTo(currentCubeCoords) > 2)
                                      .Where(x => HexHelper.ConvertToCube(x.Cell.Coords).DistanceTo(currentCubeCoords) <= 5)
                                      .ToArray();

            Locality selectedLocality;

            if (availableLocalities.Any())
            {
                var localityIndex = _dice.Roll(0, availableLocalities.Count() - 1);
                selectedLocality = availableLocalities[localityIndex];
            }
            else
            {
                selectedLocality = globe.Localities.LastOrDefault();
            }

            if (selectedLocality == null)
            {
                //TODO Создать отдельный класс исключений GlobeGenerationException.
                throw new InvalidOperationException("Не удалось выбрать локацию для дома.");
            }

            return(selectedLocality.Cell);
        }
Beispiel #7
0
        public Globe Restore()
        {
            var globe = new Globe();

            globe.Terrain = Terrain;

            var realmDict = Realms.ToDictionary(storedRealm => storedRealm.Id, storedRealm => new Realm
            {
                Name   = storedRealm.Name,
                Banner = new RealmBanner {
                    MainColor = storedRealm.MainColor
                }
            });

            globe.Realms = realmDict.Select(x => x.Value).ToList();

            RestoreLocalities(out globe.Localities, out globe.LocalitiesCells, Localities, globe.Terrain, realmDict);

            RestoreAgents(out globe.Agents, Agents, globe.Terrain, realmDict);

            globe.AgentCrisys   = AgentCrisys;
            globe.HomeProvince  = globe.Terrain[HomeProvince.Coords.X][HomeProvince.Coords.Y];
            globe.StartProvince = globe.Terrain[StartProvince.Coords.X][StartProvince.Coords.Y];

            return(globe);
        }
        private static Task CreateRealmsAsync(Globe globe, string[] realmNames)
        {
            return(Task.Run(() =>
            {
                var realmColors = new[]
                {
                    Color.Red,
                    Color.Green,
                    Color.Blue,
                    Color.Yellow,
                    Color.Beige,
                    Color.LightGray,
                    Color.Magenta,
                    Color.Cyan
                };

                for (var i = 0; i < START_ITERATION_REALMS; i++)
                {
                    var realm = new Realm
                    {
                        Name = realmNames[i],
                        Banner = new RealmBanner {
                            MainColor = realmColors[i]
                        }
                    };

                    globe.Realms.Add(realm);
                }
            }));
        }
        private void CreateStartAgents(Globe globe)
        {
            for (var i = 0; i < StartAgentCount; i++)
            {
                var rolledLocalityIndex = _dice.Roll(0, globe.Localities.Count - 1);
                var locality            = globe.Localities[rolledLocalityIndex];

                var agentName = globe.agentNameGenerator.Generate(Sex.Male, 1);

                var agent = new Agent
                {
                    Name     = agentName,
                    Location = locality.Cell,
                    Realm    = locality.Owner
                };

                globe.Agents.Add(agent);

                CacheHelper.AddAgentToCell(globe.AgentCells, locality.Cell, agent);

                var rolledBranchIndex = _dice.Roll(0, 7);
                agent.Skills = new Dictionary <BranchType, int>
                {
                    { (BranchType)rolledBranchIndex, 1 }
                };
            }
        }
        /// <summary>
        /// Создание
        /// </summary>
        /// <param name="globe">Объект игрового мира, для которого создаётся локация.</param>
        /// <param name="cell">Провинция игрового мира из указанного выше <see cref="Globe" />,
        /// для которого создаётся локация.</param>
        /// <returns>
        /// Возвращает граф локация для провинции.
        /// </returns>
        public Task <GlobeRegion> GenerateRegionAsync(Globe globe, TerrainCell cell)
        {
            var locationSchemeSids = new[] {
                "rat-hole",
                "rat-kingdom",
                "demon-dungeon",
                "demon-lair",
                "crypt",
                "elder-place",
                "genomass-cave"
            };
            var region = new GlobeRegion(LocationBaseSize);

            for (var x = 0; x < LocationBaseSize; x++)
            {
                for (var y = 0; y < LocationBaseSize; y++)
                {
                    //var hasNodeRoll = _dice.Roll(6);
                    //if (hasNodeRoll <= 2)
                    //{
                    //    continue;
                    //}

                    var hasDundeonRoll = _dice.Roll(100);
                    if (hasDundeonRoll > 90)
                    {
                        var locationSidIndex = _dice.Roll(0, locationSchemeSids.Length - 1);
                        var locationSid      = locationSchemeSids[locationSidIndex];
                        var locationScheme   = _schemeService.GetScheme <ILocationScheme>(locationSid);
                        var node             = new GlobeRegionNode(x, y, locationScheme);
                        region.AddNode(node);
                    }
                    else
                    {
                        var hasCityRoll = _dice.Roll(100);

                        if (hasCityRoll > 90)
                        {
                            var locationScheme = _schemeService.GetScheme <ILocationScheme>("city");
                            var node           = new GlobeRegionNode(x, y, locationScheme)
                            {
                                IsTown = true
                            };
                            region.AddNode(node);
                        }
                        else
                        {
                            var locationScheme = _schemeService.GetScheme <ILocationScheme>("forest");
                            var node           = new GlobeRegionNode(x, y, locationScheme);
                            region.AddNode(node);
                        }
                    }
                }
            }

            return(Task.FromResult(region));
        }
Beispiel #11
0
        public static GlobeStorageData Create(Globe globe)
        {
            var storageData = new GlobeStorageData();

            storageData.Terrain = globe.Terrain;

            var realmDict = globe.Realms.ToDictionary(realm => realm, realm => new RealmStorageData
            {
                Id        = Guid.NewGuid().ToString(),
                MainColor = realm.Banner.MainColor,
                Name      = realm.Name
            });

            storageData.Realms = realmDict.Select(x => x.Value).ToArray();

            var localityDict = globe.Localities.ToDictionary(locality => locality,
                                                             locality => new LocalityStorageData
            {
                Id         = Guid.NewGuid().ToString(),
                Name       = locality.Name,
                Coords     = locality.Cell.Coords,
                RealmId    = realmDict[locality.Owner].Id,
                Population = locality.Population,
                Branches   = locality.Branches.Select(x => new LocalityBranchStorageData {
                    Type = x.Key, Value = x.Value
                }).ToArray()
            });

            storageData.Localities = localityDict.Select(x => x.Value).ToArray();

            var agentDict = globe.Agents.ToDictionary(agent => agent,
                                                      agent => new AgentStorageData
            {
                Id       = Guid.NewGuid().ToString(),
                Name     = agent.Name,
                Hp       = agent.Hp,
                RealmId  = realmDict[agent.Realm].Id,
                Location = agent.Location.Coords,
                Skills   = agent.Skills.Select(x => new AgentSkillStorageData
                {
                    Type  = x.Key,
                    Value = x.Value
                }).ToArray()
            });

            storageData.Agents = agentDict.Select(x => x.Value).ToArray();

            storageData.AgentCrisys = globe.AgentCrisys;

            storageData.HomeProvince = globe.HomeProvince;

            storageData.StartProvince = globe.StartProvince;

            return(storageData);
        }
        public static bool LimitIsReached(Agent agent, Globe globe)
        {
            var globeSize            = globe.Terrain.Count() * globe.Terrain[0].Count();
            var realmLocalitiesLimit = globeSize / globe.Realms.Count;

            // Можем выполнять захват, если не превышен лимит городов текущего государства.
            var realmLocalities = globe.Localities.Where(x => x.Owner == agent.Realm);

            if (realmLocalities.Count() >= realmLocalitiesLimit)
            {
                return(true);
            }

            return(false);
        }
        private Task CreateRealms(Globe globe)
        {
            var realmColors = new[] { Color.Red, Color.Green, Color.Blue, Color.Yellow };

            for (var i = 0; i < StartRealmCount; i++)
            {
                var realm = new Realm
                {
                    Name  = $"realm {i}",
                    Color = realmColors[i]
                };

                globe.Realms.Add(realm);
            }

            return(Task.CompletedTask);
        }
        private void ProcessIterations(Globe globe, Queue <IAgentCard> cardQueue)
        {
            for (var year = 0; year < HistoryIterationCount; year++)
            {
                foreach (var agent in globe.Agents.ToArray())
                {
                    var card = cardQueue.Dequeue();

                    if (card.CanUse(agent, globe))
                    {
                        card.Use(agent, globe, _dice);
                    }

                    cardQueue.Enqueue(card);
                }
            }
        }
        /// <summary>
        /// Создание
        /// </summary>
        /// <param name="globe">Объект игрового мира, для которого создаётся локация.</param>
        /// <param name="cell">Провинция игрового мира из указанного выше <see cref="Globe" />,
        /// для которого создаётся локация.</param>
        /// <returns>
        /// Возвращает граф локация для провинции.
        /// </returns>
        public Task <GlobeRegion> GenerateRegionAsync(Globe globe, TerrainCell cell)
        {
            var region = new GlobeRegion(LocationBaseSize);

            // Сейчас допускаем, что паттерны квадратные, меньше размера провинции.
            // Пока не вращаем и не искажаем.
            // Там, где может быть объект, гарантированно создаём один город и два подземелья.
            var regionDraft  = new GlobeRegionDraftValue[LocationBaseSize, LocationBaseSize];
            var startPattern = GlobeRegionPatterns.Start;
            var homePattern  = GlobeRegionPatterns.Home;
            // Расчитываем размер паттернов.
            // Исходим из того, что пока все паттерны квадратные и одинаковые по размеру.
            // Поэтому размер произвольного паттерна будет справедлив для всех остальных.
            // Паттерн старта выбран произвольно.
            var patternSize = startPattern.Values.GetUpperBound(0) - startPattern.Values.GetLowerBound(0) + 1;

            // Вставляем паттерны в указанные области
            ApplyRegionPattern(ref regionDraft, GetDefaultPattrn(), 1, 1);
            ApplyRegionPattern(ref regionDraft, GetDefaultPattrn(), LocationBaseSize - patternSize - 1, 1);
            ApplyRegionPattern(ref regionDraft, GetDefaultPattrn(), 1, LocationBaseSize - patternSize - 1);
            ApplyRegionPattern(ref regionDraft, GetDefaultPattrn(), LocationBaseSize - patternSize - 1, LocationBaseSize - patternSize - 1);
            if (globe.StartProvince == cell)
            {
                ApplyRegionPattern(ref regionDraft, startPattern, (LocationBaseSize - patternSize) / 2, (LocationBaseSize - patternSize) / 2);
            }
            else if (globe.HomeProvince == cell)
            {
                ApplyRegionPattern(ref regionDraft, homePattern, (LocationBaseSize - patternSize) / 2, (LocationBaseSize - patternSize) / 2);
            }
            else
            {
                ApplyRegionPattern(ref regionDraft, GetDefaultPattrn(), (LocationBaseSize - patternSize) / 2, (LocationBaseSize - patternSize) / 2);
            }

            for (var x = regionDraft.GetLowerBound(0); x <= regionDraft.GetUpperBound(0); x++)
            {
                for (var y = regionDraft.GetLowerBound(1); y <= regionDraft.GetUpperBound(1); y++)
                {
                    ValidateRegion(region, regionDraft, x, y);
                }
            }

            return(Task.FromResult(region));
        }
        private Task CreateTerrain(Globe globe)
        {
            for (var i = 0; i < Size; i++)
            {
                globe.Terrain[i] = new TerrainCell[Size];

                for (var j = 0; j < Size; j++)
                {
                    globe.Terrain[i][j] = new TerrainCell
                    {
                        Coords = new OffsetCoords(i, j)
                    };

                    globe.scanResult.Free.Add(globe.Terrain[i][j]);
                }
            }

            return(Task.CompletedTask);
        }
        private static Task CreateTerrainAsync(Globe globe)
        {
            return(Task.Run(() =>
            {
                for (var i = 0; i < WORLD_SIZE; i++)
                {
                    globe.Terrain[i] = new TerrainCell[WORLD_SIZE];

                    for (var j = 0; j < WORLD_SIZE; j++)
                    {
                        globe.Terrain[i][j] = new TerrainCell
                        {
                            Coords = new OffsetCoords(i, j)
                        };

                        var terrain = globe.Terrain[i][j];
                        globe.ScanResult.Free.Add(terrain);
                    }
                }
            }));
        }
        private void ProcessIterations(Globe globe, Queue <IAgentCard> cardQueue)
        {
            for (var iteration = 0; iteration < HISTORY_ITERATION_COUNT; iteration++)
            {
                foreach (var agent in globe.Agents.ToArray())
                {
                    var useCardRoll = _dice.Roll2D6();
                    if (useCardRoll > 7)
                    {
                        continue;
                    }

                    var card = cardQueue.Dequeue();

                    if (card.CanUse(agent, globe))
                    {
                        card.Use(agent, globe, _dice);
                    }

                    cardQueue.Enqueue(card);
                }
            }
        }
 public GlobeGenerationResult(Globe globe, GlobeGenerationHistory history)
 {
     Globe   = globe ?? throw new ArgumentNullException(nameof(globe));
     History = history ?? throw new ArgumentNullException(nameof(history));
 }