private UpdateType GetUpdateType() { var config = ConfigurationManager.SettlementConfiguration[CurrentEpoch]; double probNewRoad = config.ProbNewRoad; double probNewBuildings = config.ProbNewBuildings; if (EpochSpecific.IncreaseProbabilityOfAddingBuildings(Settlement, CurrentEpoch)) { probNewRoad = 0.2; probNewBuildings = 0.5; } UpdateType updateType; switch (RandomProvider.NextDouble()) { case double d when d < probNewRoad: { updateType = UpdateType.NewRoads; break; } case double d when d < probNewRoad + probNewBuildings: { updateType = UpdateType.NewBuildings; break; } default: updateType = UpdateType.NewTypes; break; } return(updateType); }
public SettlementUpdate CreateNewSettlementUpdate( UpdateType updateType, Epoch epoch, int iteration, int maxIterations) { var roadTypeSetUp = new RoadTypeSetUp() { Epoch = epoch, SettlementCenter = SettlementCenter, AvgDistanceToSettlementCenter = (int)Roads.Average(r => r.Center.DistanceTo(SettlementCenter)) }; SettlementUpdate settlementUpdate = new SettlementUpdate(updateType); switch (updateType) { case UpdateType.NewRoads: { var genes = this.Roads.ToList(); if (RandomProvider.NextDouble() < 0.5) //in order to make it more probable for roads closer to center to be selected { var numberOfGenesToInclude = (int)(0.2 * genes.Count) <= 1 ? 1 : (int)(0.2 * genes.Count); genes = genes.OrderBy(g => g.Center.DistanceTo(this.SettlementCenter)) .Take(2 * numberOfGenesToInclude) .ToList(); } var roadToAttach = genes[RandomProvider.Next(genes.Count)]; var road = this.CreateNewRoad(roadToAttach); if (!CanAddRoad(road)) { return(settlementUpdate); } var possiblePlaces = road.GetPossibleBuildingPositions(new PossibleBuildingPositions(this.Roads, Fields)); var buildingsToAdd = RandomProvider.Next(1, possiblePlaces.Count > MaxBuildingsToAddPerIteration / 2 ? MaxBuildingsToAddPerIteration / 2 : possiblePlaces.Count); for (int i = 0; i < buildingsToAdd; i++) { var building = Building.GetRandom(epoch); building.Position = possiblePlaces[RandomProvider.Next(possiblePlaces.Count)]; building.Road = road; building.Material = EpochSpecific.GetMaterialForBuilding(epoch); road.AddBuilding(building); } road.SetUpRoadType(roadTypeSetUp); settlementUpdate.NewRoads.Add(road); return(settlementUpdate); } case UpdateType.NewBuildings: { var roadWithoutBuildings = this.Roads.FirstOrDefault(g => !g.Buildings.Any()); var roadsToAttachCount = this.Roads.Count * 0.3 < 10 ? 10 : (int)(this.Roads.Count * 0.3); var roadsToAttach = this.Roads .OrderByDescending(g => 2 * g.Length - g.Buildings.Count) .Take(roadsToAttachCount) .ToArray(); var roadToAttach = roadWithoutBuildings ?? roadsToAttach[RandomProvider.Next(roadsToAttach.Count())]; var copy = roadToAttach.Copy(); var possiblePlaces = copy.GetPossibleBuildingPositions(new PossibleBuildingPositions(this.Roads, Fields)); if (!possiblePlaces.Any()) { return(settlementUpdate); } var buildingsToAdd = RandomProvider.Next(1, possiblePlaces.Count > MaxBuildingsToAddPerIteration ? MaxBuildingsToAddPerIteration : possiblePlaces.Count); double coef = (3 * iteration / (maxIterations * 0.1)); buildingsToAdd = (int)(coef * buildingsToAdd); for (int i = 0; i < buildingsToAdd; i++) { var building = Building.GetRandom(epoch); building.Position = possiblePlaces[RandomProvider.Next(possiblePlaces.Count)]; building.Road = roadToAttach; building.Material = EpochSpecific.GetMaterialForBuilding(epoch); copy.AddBuilding(building); settlementUpdate.NewBuildings.Add(building); } return(settlementUpdate); } default: for (int i = 0; i < BuildingsPerUpdate; i++) { var roadsWithBuildings = this.Roads.Where(g => g.Buildings.Any()).ToList(); var road = roadsWithBuildings[RandomProvider.Next(roadsWithBuildings.Count)]; var building = road.Buildings[RandomProvider.Next(road.Buildings.Count)]; if (!(building is Residence) && Math.Abs(building.Fitness.Value) > 0.1) { continue; //don't update rare buildings with positive fitness } var newBuilding = Building.GetRandom(epoch); newBuilding.Position = building.Position; newBuilding.Direction = building.Direction; newBuilding.Road = building.Road; newBuilding.Material = EpochSpecific.GetMaterialForBuilding(epoch); if (building.GetType() != newBuilding.GetType() || building.Material != newBuilding.Material) { settlementUpdate.UpdatedBuildings.Add((building, newBuilding)); } } for (int i = 0; i < RoadsPerUpdate; i++) { var unpavedRoads = this.Roads.Where(g => g.Type == RoadType.Unpaved).ToList(); if (!unpavedRoads.Any()) { break; } var oldRoad = unpavedRoads[RandomProvider.Next(unpavedRoads.Count)]; var newRoad = oldRoad.Copy(); newRoad.SetUpRoadType(roadTypeSetUp); if (!oldRoad.Type.Equals(newRoad.Type)) { settlementUpdate.UpdatedRoads.Add((oldRoad, newRoad)); } } return(settlementUpdate); } }
public void NewIteration() { var updateType = GetUpdateType(); var structures = Enumerable.Range(1, 100).ToList() .Select(s => Settlement.CreateNewSettlementUpdate( updateType, CurrentEpoch, Iteration, 1000)) .ToList(); var settlementUpdate = GetBestStructures(structures); var roadTypeSetUp = new RoadTypeSetUp() { Epoch = CurrentEpoch, SettlementCenter = Settlement.SettlementCenter, AvgDistanceToSettlementCenter = (int)Settlement.Roads.Average(r => r.Center.DistanceTo(Settlement.SettlementCenter)) }; LastSettlementUpdate = settlementUpdate; switch (updateType) { case UpdateType.NewRoads: { settlementUpdate.NewRoads .ForEach(r => { r.SetUpRoadType(roadTypeSetUp); Settlement.AddRoad(r); }); break; } case UpdateType.NewBuildings: settlementUpdate.NewBuildings .ForEach(b => { Settlement.AddBuildingToRoad(b.Road, b); }); break; case UpdateType.NewTypes: settlementUpdate.UpdatedBuildings.ForEach(update => { Settlement.RemoveBuildingFromRoad(update.oldBuilding.Road, update.oldBuilding); Settlement.AddBuildingToRoad(update.newBuilding.Road, update.newBuilding); }); settlementUpdate.UpdatedRoads.ForEach(update => { update.oldRoad.SetRoadType(update.newRoad.Type); //for only types }); break; } this.Settlement.Buildings.ForEach(b => { b.Age++; if (b.Age % 100 == 0) { var old = (b as ICopyable <IBuilding>).Copy(); b.Material = EpochSpecific.GetMaterialForBuilding(CurrentEpoch); if (old.Material != b.Material) { settlementUpdate.UpdatedBuildings.Add((old, b)); } } }); this.Settlement.Roads.ForEach(r => { r.Age++; if (r.Age % 100 == 0) { var old = (r as ICopyable <IRoad>).Copy(); r.SetUpRoadType(roadTypeSetUp); if (old.Type != r.Type) { settlementUpdate.UpdatedRoads.Add((old, r)); } } }); if (RandomProvider.NextDouble() < FloodMutationProbability) { settlementUpdate.FloodMutationResult = Settlement.InvokeFloodMutation(); } if (RandomProvider.NextDouble() < EarthquakeMutationProbability) { settlementUpdate.EarthquakeMutationResult = Settlement.InvokeEarthquakeMutation(); } if (RandomProvider.NextDouble() < FireMutationProbability) { settlementUpdate.FireMutationResult = Settlement.InvokeFireMutation(); } if (EpochSpecific.CanEnterNextEpoch(Settlement, CurrentEpoch)) { switch (CurrentEpoch) { case Epoch.First: CurrentEpoch = Epoch.Second; break; case Epoch.Second: CurrentEpoch = Epoch.Third; break; case Epoch.Third: //TODO break; default: throw new ArgumentOutOfRangeException(); } } if (Iteration % 100 == 0) { Settlement.UpdateSettlementCenter(); } Iteration++; }