public void UpdateSettlementCenter() { SettlementCenter = new Point((int)Roads.Average(g => g.Center.X), (int)Roads.Average(g => g.Center.Y)); }
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); } }