public HousingSlots AvailableHousing() { HousingSlots availableHousing = new HousingSlots(); availableHousing.low = resources.totalHousingSlots.low - resources.occuppiedHousingSlots.low; availableHousing.middle = resources.totalHousingSlots.middle - resources.occuppiedHousingSlots.middle; availableHousing.high = resources.totalHousingSlots.high - resources.occuppiedHousingSlots.high; return(availableHousing); }
static public HousingSlots operator+(HousingSlots slots1, HousingSlots slots2) { HousingSlots sum = new HousingSlots(); sum.low = slots1.low + slots2.low; sum.middle = slots1.middle + slots2.middle; sum.high = slots1.high + slots2.high; return(sum); }
static public HousingSlots operator/(HousingSlots slots, float denominator) { HousingSlots sum = new HousingSlots(); sum.low = System.Convert.ToUInt32(System.Convert.ToDouble(slots.low) / denominator); sum.middle = System.Convert.ToUInt32(System.Convert.ToDouble(slots.middle) / denominator); sum.high = System.Convert.ToUInt32(System.Convert.ToDouble(slots.high) / denominator); return(sum); }
void ProcessMigration() //called once per day. { //compute immigration rate based on happiness and empty housing. HousingSlots availableHousing = GameManager.resourceMan.AvailableHousing(); ulong totalAvailableHousing = availableHousing.Sum(); int minHappinessForImmigration = 35; int maxHappinessForImmigration = 75; //int _immigration = Mathf.RoundToInt(((float)populationHappiness.overall / 100.0f) * (0.8f * maxImmigrationRate)); float happinesContirbution = Mathf.Clamp((float)(populationHappiness.overall - minHappinessForImmigration) / (float)(maxHappinessForImmigration - minHappinessForImmigration), 0.0f, 1.0f); int _immigration = Mathf.RoundToInt(happinesContirbution * (float)maxImmigrationRate); _immigration = Mathf.Max(Random.Range(Mathf.RoundToInt(_immigration - 0.2f * maxImmigrationRate), Mathf.RoundToInt(_immigration + 0.2f * maxImmigrationRate)), growthStats.minImmigrationRate); _immigration = (int)Mathf.Min(_immigration, maxImmigrationRate, totalAvailableHousing); int actualImmigration = 0; //pointless? if (_immigration > 0 && totalAvailableHousing > 0) { //Spawn new citizens here. //This is a test implementation float lowRatio = availableHousing.low / totalAvailableHousing; float middleRatio = availableHousing.middle / totalAvailableHousing; float highRatio = availableHousing.high / totalAvailableHousing; for (int i = 0; i < Mathf.FloorToInt(_immigration * lowRatio); i++) { GenerateImmigrationCase(CitizenClass.low); actualImmigration++; } for (int i = 0; i < Mathf.FloorToInt(_immigration * middleRatio); i++) { GenerateImmigrationCase(CitizenClass.middle); actualImmigration++; } for (int i = 0; i < Mathf.FloorToInt(_immigration * highRatio); i++) { GenerateImmigrationCase(CitizenClass.high); actualImmigration++; } } growthStats.immigrationRate = actualImmigration; GameManager.resourceMan.Population() = PopulationCount(); GameManager.uiMan.UpdatePopulation(PopulationCount()); }
//Simulation runs coroutines. IEnumerator BuildingsSimRun() //the current logic assigns available resources prioritizing older buildings (those coming first in buildingsMan.constructedBuildings list) { //Current issue with this logic: It's expensive! Most buildings won't have their operational status and parameters changed each sim update cycle, yet we would still compute //productions and consumptions for all buildings at every sim update. A better approach would be to let each building process changes on its own by updating global values //or registering itself for processing by a central manager. Downside of this approach would be checking against race conditions, and a more complicated code. while (true) { if (isRunning) { //General Buildings float totalWaterDemand = 0.0f; float totalPowerDemand = 0.0f; HousingSlots totalHousingSlots = new HousingSlots(); HousingSlots occuppiedHousingSlots = new HousingSlots(); //To avoid having multiple loops, the loop bellow will cover several, building-specific calls depending on building types. Some exceptions will have their //own loops bellow, but in theory could also be merged with this loop. //TODO consider merging into a single loop with if-statements. foreach (Building building in GameManager.buildingsMan.constructedBuildings) { //Fill requirement resources //TODO consider moving this to a function that only updates when its state changes (e.g. new building constructed, stats changed, etc). Would complicate //the code elsewhere though. totalWaterDemand += building.GetStats().requiredResources.water; totalPowerDemand += building.GetStats().requiredResources.power; //update building effect on natural resources and environment building.UpdateEffectOnNature(dateUpdateRateHours); building.CheckAndShowResourceShortages(); //for residential buildings, if (building.GetStats().type == BuildingType.residential) { ResidentialBuilding residentialBuilding = building.gameObject.GetComponent <ResidentialBuilding>(); //update housing slots totalHousingSlots.IncrementSlotValue(residentialBuilding.HousingCapacity(), residentialBuilding.ResidentClass()); occuppiedHousingSlots.IncrementSlotValue(residentialBuilding.ResidentsCount(), residentialBuilding.ResidentClass()); residentialBuilding.UpdateHousingQuality(); } } //Update ResourceManager GameManager.resourceMan.UpdateWaterDemand(totalWaterDemand); GameManager.resourceMan.UpdatePowerDemand(totalPowerDemand); GameManager.resourceMan.UpdateTotalHousingSlots(totalHousingSlots); GameManager.resourceMan.UpdateOccupiedHousingSlots(occuppiedHousingSlots); //Computing production of infraStructure buildings float totalWaterProduction = 0.0f; float totalPowerProduction = 0.0f; //Compute production for all infra buildings foreach (InfrastructureBuilding building in GameManager.buildingsMan.powerProductionBuildings) { building.ComputeProduction(); totalPowerProduction += building.GetMaxProduction(); } foreach (InfrastructureBuilding building in GameManager.buildingsMan.waterProductionBuildings) { building.ComputeProduction(); totalWaterProduction += building.GetMaxProduction(); } //Update ResourcesManager GameManager.resourceMan.UpdateAvailableWater(totalWaterProduction); GameManager.resourceMan.UpdateAvailablePower(totalPowerProduction); //Allocate resources to buildings based on production and priority float totalWaterConsumption = 0.0f; float totalPowerConsumption = 0.0f; foreach (Building building in GameManager.buildingsMan.constructedBuildings) { BasicResources resources = new BasicResources(); resources.power = Mathf.Clamp(building.GetStats().requiredResources.power, 0.0f, totalPowerProduction - totalPowerConsumption); resources.water = Mathf.Clamp(building.GetStats().requiredResources.water, 0.0f, totalWaterProduction - totalWaterConsumption); totalPowerConsumption += resources.power; totalWaterConsumption += resources.water; building.AllocateResources(resources); } //update ResourceManager GameManager.resourceMan.UpdateWaterConsumption(totalWaterConsumption); GameManager.resourceMan.UpdatePowerConsumption(totalPowerConsumption); //Divide load on infrastructure buildings and assign it float powerDemandToMaxProductionRatio = Mathf.Min(totalPowerDemand / totalPowerProduction, 1.0f); float waterDemandToMaxProductionRatio = Mathf.Min(totalWaterDemand / totalWaterProduction, 1.0f); foreach (InfrastructureBuilding building in GameManager.buildingsMan.powerProductionBuildings) { building.SetLoad(powerDemandToMaxProductionRatio); } foreach (InfrastructureBuilding building in GameManager.buildingsMan.waterProductionBuildings) { building.SetLoad(waterDemandToMaxProductionRatio); } yield return(new WaitForSeconds(timeBetweenUpdates)); } else { yield return(new WaitForFixedUpdate()); } } }
public void UpdateOccupiedHousingSlots(HousingSlots slots) { resources.occuppiedHousingSlots.AssignNew(slots); }
public void UpdateTotalHousingSlots(HousingSlots slots) { resources.totalHousingSlots.AssignNew(slots); }
public void AssignNew(HousingSlots newSlots) //since we can't overload the assignment op and we sometimes want to deep copy an object { low = newSlots.low; middle = newSlots.middle; high = newSlots.high; }
public HousingSlots(HousingSlots newSlots) { AssignNew(newSlots); }