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); }
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)); }
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)); }