/// <summary> /// Performs a lifecycle on the current population /// </summary> public void Next() { if (CurrentPopulation.Species.Count == 0) { Populate(); } if (EvaluationFunction == null) { throw new Exception("EvaluationFuntion has to be set first!"); } if (Mutator == null) { throw new Exception("Mutator has to be set first!"); } //Evaluate Members CurrentPopulation.EvaluateMembers(EvaluationFunction); //Perform lifecycle DoSelection(); Reproduce(); //Fire event LifecycleFinishedEvent?.Invoke(CurrentPopulation); }
public void CreateNewPopulation() { CurrentPopulation = Algorithm.SeedPopulation(BaseCitiesSequence, _populationSize); CurrentPopulation.ForEach(e => e.CalculateCost()); SetBestSequence(); Generation = 0; }
// Makes a new generation by invoking the crossover method on the current population. private void MakeCrossovers() { List <Agent> children = new List <Agent>(); GenerationCount++; children = CurrentPopulation.MakeCrossovers(GeneticSettings.Crossover, GeneticSettings.PopulationSize, GeneticSettings.RandomNumberGenerator); CurrentPopulation = new Population(children, GenerationCount); }
/// <summary> /// Perform mining on all faction owned colonies. /// </summary> /// <param name="P">Binding list of factions</param> public static void MinePlanets(BindingList <Faction> P) { foreach (Faction CurrentFaction in P) { foreach (Population CurrentPopulation in CurrentFaction.Populations) { if (CurrentPopulation.Planet.GeoSurveyList.ContainsKey(CurrentFaction) == true) { /// <summary> /// see what I mean about superflous? going to keep it like this for right now however. /// </summary> if (CurrentPopulation.Planet.GeoSurveyList[CurrentFaction] == true) { /// <summary> /// Calculate the construction time cycle sliver of the year to use. all production is done annually so this must be adjusted here. /// Potential place to save some cpu cycles? /// </summary> float TimeAdjust = (float)Constants.Colony.ConstructionCycle / (float)Constants.TimeInSeconds.Year; float CurrentMining = CurrentPopulation.CalcTotalMining() * TimeAdjust; /// <summary> /// Don't run this loop if no mining can be done. /// </summary> if (CurrentMining > 0.0f) { for (int mineralIterator = 0; mineralIterator < (int)Constants.Minerals.MinerialNames.MinerialCount; mineralIterator++) { float MineAmount = CurrentMining * CurrentPopulation.Planet.MinerialAccessibility[mineralIterator]; /// <summary> /// no negative minerals. hopefully. /// </summary> if (CurrentPopulation.Planet.MinerialReserves[mineralIterator] < MineAmount) { MineAmount = CurrentPopulation.Planet.MinerialReserves[mineralIterator]; } /// <summary> /// Add to population stockpile and take from planetary reserves. /// </summary> CurrentPopulation.Minerials[mineralIterator] = CurrentPopulation.Minerials[mineralIterator] + MineAmount; CurrentPopulation.Planet.MinerialReserves[mineralIterator] = CurrentPopulation.Planet.MinerialReserves[mineralIterator] - MineAmount; /// <summary> /// Ultra-paranoia check here. /// </summary> if (CurrentPopulation.Planet.MinerialReserves[mineralIterator] < 0.0f) { CurrentPopulation.Planet.MinerialReserves[mineralIterator] = 0.0f; } } } } } } } }
public object Clone() { return(new BionicModel() { Attributes = (NamedModelEntityCollection <Parameter>)Attributes.Clone(), FitnessCriterion = (Criterion)FitnessCriterion.Clone(), FunctionalConstraints = (NamedModelEntityCollection <Constraint>)FunctionalConstraints.Clone(), CurrentPopulation = (Population)CurrentPopulation.Clone(), CurrentGeneration = CurrentGeneration }); }
public Population(char[] target, float mutationRate, int popMax) { this.Target = target; this.MutationRate = mutationRate; this.PopMax = popMax; for (int i = 0; i < popMax; i++) { CurrentPopulation.Add(new DNA(target.Length)); } }
// Makes selection on the current population and updates the average fitness and convergence. private void MakeSelection() { CurrentPopulation.MakeSelection(GeneticSettings.Selector, GeneticSettings.SelectionSize, GeneticSettings.RandomNumberGenerator); double totalFitness = 0; for (int i = 0; i < CurrentPopulation.Agents.Count; i++) { totalFitness += CurrentPopulation.Agents[i].Fitness; } CurrentAverageFitnessSelection = totalFitness / CurrentPopulation.Agents.Count; ConvergencePercent = CurrentPopulation.GetConvergencePercent(); }
public void PrintDebugScores() { var best10 = CurrentPopulation.OrderByDescending((x) => x.CurrentScore).Take(10); Debug.Log($"Best 10 of generation {CurrentGeneration}"); var str = ""; foreach (var entry in best10) { str += $"{entry.CurrentScore}\n"; } Debug.Log(str); }
/// <summary> /// Do all fuel refining on planets and later on gas giant harvesters. /// </summary> /// <param name="P">list of factions.</param> public static void RefineFuel(BindingList <Faction> P) { foreach (Faction CurrentFaction in P) { #warning Implement gas giant harvesters here. foreach (Population CurrentPopulation in CurrentFaction.Populations) { /// <summary> /// Skip this population. /// </summary> if (CurrentPopulation.IsRefining == false) { continue; } float TimeAdjust = (float)Constants.Colony.ConstructionCycle / (float)Constants.TimeInSeconds.Year; float CurrentRefining = CurrentPopulation.CalcTotalRefining() * TimeAdjust; /// <summary> /// If the planet has no refineries or no sorium then no refining happens. /// </summary> if (CurrentRefining > 0.0f && CurrentPopulation.Minerials[(int)Constants.Minerals.MinerialNames.Sorium] > 0.0f) { /// <summary> /// 1 sorium = 2000 fuel /// </summary> float SoriumRequirement = CurrentRefining / Constants.Colony.SoriumToFuel; if (CurrentPopulation.Minerials[(int)Constants.Minerals.MinerialNames.Sorium] < SoriumRequirement) { SoriumRequirement = CurrentPopulation.Minerials[(int)Constants.Minerals.MinerialNames.Sorium]; CurrentRefining = SoriumRequirement * Constants.Colony.SoriumToFuel; } /// <summary> /// Convert Sorium into fuel. /// </summary> CurrentPopulation.Minerials[(int)Constants.Minerals.MinerialNames.Sorium] = CurrentPopulation.Minerials[(int)Constants.Minerals.MinerialNames.Sorium] - SoriumRequirement; CurrentPopulation.FuelStockpile = CurrentPopulation.FuelStockpile + CurrentRefining; } else if (CurrentRefining > 0.0f) { String Entry = String.Format("Insufficient Sorium on {0} to continue refining.", CurrentPopulation); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); } } } }
public void UpdatePopulation() { var min = CurrentPopulation.First(y => CalculateCF(y) == CurrentPopulation.Min(x => CalculateCF(x))); if (CalculateCF(CurrentBlueChild) > CalculateCF(min)) { CurrentPopulation[CurrentPopulation.IndexOf(min)] = CurrentBlueChild; min = CurrentPopulation.First(y => CalculateCF(y) == CurrentPopulation.Min(x => CalculateCF(x))); } if (CalculateCF(CurrentYellowChild) > CalculateCF(min)) { CurrentPopulation[CurrentPopulation.IndexOf(min)] = CurrentYellowChild; } }
public (List <int>, float) GetTheBestChromosome() { var best = CurrentPopulation.First(y => CalculateCF(y) == CurrentPopulation.Max(x => CalculateCF(x))); List <int> cf_names = new List <int>(); for (int i = 0; i < best.Count; i++) { if (best[i] == 1) { cf_names.Add(i); } } var cf = CalculateCF(best); return(cf_names, cf); }
private void SetBestIndividual() { var bestIndividual = CurrentPopulation.First(); for (int i = 1; i < MaxPopulationCount; i++) { var currentIndividual = CurrentPopulation[i]; if ((OptimizationTarget == OptimizationTarget.Maximum && currentIndividual.Result > bestIndividual.Result) || (OptimizationTarget == OptimizationTarget.Minimum && currentIndividual.Result < bestIndividual.Result)) { bestIndividual = currentIndividual; } } BestIndividual = bestIndividual; }
public void CreateNewPopulation() { CurrentPopulation = Enumerable.Range(0, Algorithm.SeedingPopulationCount) .Select(_ => GetRandomIndividual()) .ToList(); ApplyBounds(CurrentPopulation); if (OptimizationTarget == OptimizationTarget.Minimum) { BestIndividual = CurrentPopulation.OrderBy(e => e.Cost).First(); } else { BestIndividual = CurrentPopulation.OrderByDescending(e => e.Cost).First(); } Generation = 0; }
/// <summary> /// Performs lifecycles untill the fitness is reached /// </summary> /// <param name="fitness">The fitness to be reached</param> public Network TrainUntil(double fitness) { if (EvaluationFunction == null) { throw new Exception("EvaluationFuntion has to be set first!"); } if (Mutator == null) { throw new Exception("Mutator has to be set first!"); } //Perform lifecycles untill the fitness is reached while (CurrentPopulation.MaxFitness < fitness) { Next(); } return(new Network(CurrentPopulation.GetFittestMember())); }
public void GetCurrentFittestCoefficients() { Chromosome bestChromosome = CurrentPopulation.First(); foreach (Chromosome c in CurrentPopulation) { if (c.Fitness > bestChromosome.Fitness) { bestChromosome = c; } } Tuple <double, double, double> cf = bestChromosome.GetCoefficients(); List <double> coefficients = new List <double>(); coefficients.Add(cf.Item1); coefficients.Add(cf.Item2); coefficients.Add(cf.Item3); SaveData(coefficients, "FunctionCoefficients"); }
// Make mutations on the current population. private void MakeMutations() { CurrentPopulation.MakeMutations(GeneticSettings.Mutator, GeneticSettings.MutationProbabiltyAgents, GeneticSettings.MutationProbabilityGenes, GeneticSettings.RandomNumberGenerator); }
/// <summary> /// Main process loop for performing a crossover on a population. /// </summary> protected void Process() { int maxLoop = 100; int eliteCount = 0; //reset the number of evaluations _evaluations = 0; //now that we know how many children we are to be creating, in the case of 'Delete Last' //we copy the current generation across and add new children where they are greater than //the worst solution. if (_replacementMethodS == ReplacementMethod.DeleteLast) { //copy everything accross including the elites NewPopulation.Solutions.Clear(); NewPopulation.Solutions.AddRange(CurrentPopulation.Solutions); } else { //just copy the elites, this will take all elites //TODO: Sort out what we do if we overfill the population with elites var elites = CurrentPopulation.GetElites(); eliteCount = elites.Count(); if (elites != null && eliteCount > 0) { NewPopulation.Solutions.AddRange(elites); } } _currentPopulationSize = CurrentPopulation.Solutions.Count; _numberOfChildrenToGenerate = _currentPopulationSize - eliteCount; while (_numberOfChildrenToGenerate > 0) { //emergency exit if (maxLoop <= 0) { throw new ChromosomeException("Unable to create a suitable child. If duplicates have been disallowed then consider increasing the chromosome length or increasing the number of elites."); } //these will hold the children Chromosome c1 = null; Chromosome c2 = null; //select some parents var parents = CurrentPopulation.SelectParents(); var p1 = parents[0]; var p2 = parents[1]; //crossover PerformCrossover(p1, p2, CrossoverProbability, out c1, out c2); if (AddChild(c1)) { _numberOfChildrenToGenerate--; } else { //unable to create child maxLoop--; } //see if we can add the secomd if (_numberOfChildrenToGenerate > 0) { if (AddChild(c2)) { _numberOfChildrenToGenerate--; } else { //unable to create child maxLoop--; } } } }
/// <summary> /// Handles ordnance factory construction. /// </summary> /// <param name="P">List of factions.</param> public static void OrdnanceFactoryBuild(BindingList <Faction> P) { /// <summary> /// Subtract the construction cycle from the construction tick. /// </summary> foreach (Faction CurrentFaction in P) { foreach (Population CurrentPopulation in CurrentFaction.Populations) { /// <summary> /// How much construction work per day does this colony do? default should be 5 day construction cycle. /// </summary> float CurrentIndustry = CurrentPopulation.CalcTotalOrdnanceIndustry() * Constants.Colony.ConstructionCycleFraction; float BuildPercentage = 0.0f; foreach (MissileBuildQueueItem CurrentConstruction in CurrentPopulation.MissileBuildQueue) { /// <summary> /// Check to see if this item is in the current build queue, or has to wait for capacity to free up. /// </summary> if ((BuildPercentage + CurrentConstruction.buildCapacity) <= 100.0f) { BuildPercentage = BuildPercentage + CurrentConstruction.buildCapacity; } else { break; } /// <summary> /// Calculate Completion Estimate: /// </summary> float BPRequirement = (float)Math.Floor(CurrentConstruction.numToBuild) * (float)CurrentConstruction.costPerItem; float DaysInYear = (float)Constants.TimeInSeconds.RealYear / (float)Constants.TimeInSeconds.Day; float YearsOfProduction = (BPRequirement / CurrentConstruction.buildCapacity); if (CurrentConstruction.buildCapacity != 0.0f && YearsOfProduction < Constants.Colony.TimerYearMax) { int TimeToBuild = (int)Math.Floor(YearsOfProduction * DaysInYear); DateTime EstTime = GameState.Instance.GameDateTime; TimeSpan TS = new TimeSpan(TimeToBuild, 0, 0, 0); EstTime = EstTime.Add(TS); CurrentConstruction.completionDate = EstTime; } /// <summary> /// This construction project is paused right now. /// </summary> if (CurrentConstruction.inProduction == false) { continue; } /// <summary> /// how much of total industry does this build project use? /// </summary> float DevotedIndustry = (CurrentConstruction.buildCapacity / 100.0f) * CurrentIndustry; float Completion = DevotedIndustry / (float)CurrentConstruction.costPerItem; /// <summary> /// Do I have the minerals to build this missile? /// </summary> bool CanBuild = CurrentPopulation.MineralRequirement(CurrentConstruction.ordnanceDef.minerialsCost, Completion); if (CanBuild == false) { String Entry = String.Format("Insufficent Minerals to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } /// <summary> /// Adjust number to build downward to reflect construction happening. /// </summary> CurrentConstruction.numToBuild = CurrentConstruction.numToBuild - Completion; CurrentPopulation.HandleBuildItemCost(CurrentConstruction.costPerItem, CurrentConstruction.ordnanceDef.minerialsCost, Completion); CurrentPopulation.LoadMissileToStockpile(CurrentConstruction.ordnanceDef, Completion); } /// <summary> /// Cleanup the CBQ here. /// </summary> for (int MBQIterator = 0; MBQIterator < CurrentPopulation.MissileBuildQueue.Count; MBQIterator++) { if (CurrentPopulation.MissileBuildQueue[MBQIterator].numToBuild <= 0.0f) { CurrentPopulation.MissileBuildQueue.RemoveAt(MBQIterator); MBQIterator--; } } } } }
/// <summary> /// Processes construction factory work for every faction. /// </summary> /// <param name="P">List of factions.</param> public static void ConstructionFactoryBuild(BindingList <Faction> P) { /// <summary> /// Subtract the construction cycle from the construction tick. /// </summary> foreach (Faction CurrentFaction in P) { foreach (Population CurrentPopulation in CurrentFaction.Populations) { /// <summary> /// How much construction work per day does this colony do? default should be 5 day construction cycle. /// </summary> float CurrentIndustry = CurrentPopulation.CalcTotalIndustry() * Constants.Colony.ConstructionCycleFraction; float BuildPercentage = 0.0f; foreach (ConstructionBuildQueueItem CurrentConstruction in CurrentPopulation.ConstructionBuildQueue) { /// <summary> /// Check to see if this item is in the current build queue, or has to wait for capacity to free up. /// </summary> if ((BuildPercentage + CurrentConstruction.buildCapacity) <= 100.0f) { BuildPercentage = BuildPercentage + CurrentConstruction.buildCapacity; } else { break; } /// <summary> /// Calculate Completion Estimate: /// </summary> float BPRequirement = (float)Math.Floor(CurrentConstruction.numToBuild) * (float)CurrentConstruction.costPerItem; float DaysInYear = (float)Constants.TimeInSeconds.RealYear / (float)Constants.TimeInSeconds.Day; float YearsOfProduction = (BPRequirement / CurrentConstruction.buildCapacity); if (CurrentConstruction.buildCapacity != 0.0f && YearsOfProduction < Constants.Colony.TimerYearMax) { int TimeToBuild = (int)Math.Floor(YearsOfProduction * DaysInYear); DateTime EstTime = GameState.Instance.GameDateTime; TimeSpan TS = new TimeSpan(TimeToBuild, 0, 0, 0); EstTime = EstTime.Add(TS); CurrentConstruction.completionDate = EstTime; } /// <summary> /// This construction project is paused right now. /// </summary> if (CurrentConstruction.inProduction == false) { continue; } /// <summary> /// how much of total industry does this build project use? /// </summary> float DevotedIndustry = (CurrentConstruction.buildCapacity / 100.0f) * CurrentIndustry; float Completion = DevotedIndustry / (float)CurrentConstruction.costPerItem; bool CIRequired = false; bool MineRequired = false; bool CanBuild = false; /// <summary> /// Conventional industry must also be used. /// </summary> if (CurrentConstruction.buildType == ConstructionBuildQueueItem.CBType.PlanetaryInstallation) { if ((int)CurrentConstruction.installationBuild.Type >= (int)Installation.InstallationType.ConvertCIToConstructionFactory && (int)CurrentConstruction.installationBuild.Type <= (int)Installation.InstallationType.ConvertCIToOrdnanceFactory) { CIRequired = true; CanBuild = CurrentPopulation.CIRequirement(Completion); if (CanBuild == false) { String Entry = String.Format("Insufficent Conventional Industry to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksCI, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } } if ((int)CurrentConstruction.installationBuild.Type == (int)Installation.InstallationType.ConvertMineToAutomated) { MineRequired = true; CanBuild = CurrentPopulation.MineRequirement(Completion); if (CanBuild == false) { String Entry = String.Format("Insufficent Mines to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksCI, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } } } /// <summary> /// Check mineral costs to see if this can be built. /// </summary> switch (CurrentConstruction.buildType) { #warning PDC construction needs to be implemented here and slightly further down. case ConstructionBuildQueueItem.CBType.PlanetaryInstallation: CanBuild = CurrentPopulation.MineralRequirement(CurrentConstruction.installationBuild.MinerialsCost, Completion); break; case ConstructionBuildQueueItem.CBType.ShipComponent: CanBuild = CurrentPopulation.MineralRequirement(CurrentConstruction.componentBuild.minerialsCost, Completion); break; case ConstructionBuildQueueItem.CBType.PDCConstruction: break; case ConstructionBuildQueueItem.CBType.PDCPrefab: break; case ConstructionBuildQueueItem.CBType.PDCAssembly: break; case ConstructionBuildQueueItem.CBType.PDCRefit: break; case ConstructionBuildQueueItem.CBType.MaintenanceSupplies: CanBuild = CurrentPopulation.MineralRequirement(Constants.Colony.MaintenanceMineralCost, Completion); break; } if (CanBuild == false) { String Entry = String.Format("Insufficent Minerals to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } /// <summary> /// Adjust number to build downward to reflect construction happening. /// </summary> CurrentConstruction.numToBuild = CurrentConstruction.numToBuild - Completion; /// <summary> /// Handle the cost and build the item. /// </summary> switch (CurrentConstruction.buildType) { case ConstructionBuildQueueItem.CBType.PlanetaryInstallation: if (CIRequired == false && MineRequired == false) { CurrentPopulation.HandleBuildItemCost(CurrentConstruction.costPerItem, CurrentConstruction.installationBuild.MinerialsCost, Completion); } else if (CIRequired == true && MineRequired == false) { CurrentPopulation.HandleBuildItemCost(CurrentConstruction.costPerItem, CurrentConstruction.installationBuild.MinerialsCost, Completion, CIRequired, MineRequired); } else if (CIRequired == false && MineRequired == true) { CurrentPopulation.HandleBuildItemCost(CurrentConstruction.costPerItem, CurrentConstruction.installationBuild.MinerialsCost, Completion, CIRequired, MineRequired); } CurrentPopulation.AddInstallation(CurrentConstruction.installationBuild, Completion); break; case ConstructionBuildQueueItem.CBType.ShipComponent: CurrentPopulation.HandleBuildItemCost(CurrentConstruction.costPerItem, CurrentConstruction.componentBuild.minerialsCost, Completion); CurrentPopulation.AddComponentsToStockpile(CurrentConstruction.componentBuild, Completion); break; case ConstructionBuildQueueItem.CBType.PDCConstruction: break; case ConstructionBuildQueueItem.CBType.PDCPrefab: break; case ConstructionBuildQueueItem.CBType.PDCAssembly: break; case ConstructionBuildQueueItem.CBType.PDCRefit: break; case ConstructionBuildQueueItem.CBType.MaintenanceSupplies: CurrentPopulation.HandleBuildItemCost(CurrentConstruction.costPerItem, Constants.Colony.MaintenanceMineralCost, Completion); CurrentPopulation.AddMSP(Completion); break; } } /// <summary> /// Cleanup the CBQ here. /// </summary> for (int CBQIterator = 0; CBQIterator < CurrentPopulation.ConstructionBuildQueue.Count; CBQIterator++) { if (CurrentPopulation.ConstructionBuildQueue[CBQIterator].numToBuild <= 0.0f) { CurrentPopulation.ConstructionBuildQueue.RemoveAt(CBQIterator); CBQIterator--; } } } } }
private void SetBestSequence() { BestSequence = CurrentPopulation .OrderBy(e => e.Cost) .First(); }
public void GetTheBestScouts(int n) { TheBestScouts = CurrentPopulation.OrderByDescending(x => CalculateCost(x)).Take(n).ToList(); }
// Invokes the calculate fitness method on the current population and private void CalculateFitness() { CurrentPopulation.CalculateFitness(GeneticSettings.FitnessCalculator); CurrentAverageFitnessPopulation = CurrentPopulation.AverageFitness; TopKAgents.Update(CurrentPopulation.Agents); }
/// <summary> /// Processes construction factory work for every faction. /// </summary> /// <param name="P">List of factions.</param> public static void ConstructionFactoryBuild(BindingList <Faction> P) { /// <summary> /// Subtract the construction cycle from the construction tick. /// </summary> foreach (Faction CurrentFaction in P) { foreach (Population CurrentPopulation in CurrentFaction.Populations) { /// <summary> /// How much construction work per day does this colony do? default should be 5 day construction cycle. /// </summary> float TimeAdjust = (float)Constants.Colony.ConstructionCycle / (float)Constants.TimeInSeconds.Year; float CurrentIndustry = CurrentPopulation.CalcTotalIndustry() * TimeAdjust; float BuildPercentage = 0.0f; foreach (ConstructionBuildQueueItem CurrentConstruction in CurrentPopulation.ConstructionBuildQueue) { /// <summary> /// Check to see if this item is in the current build queue, or has to wait for capacity to free up. /// </summary> if ((BuildPercentage + CurrentConstruction.buildCapacity) <= 100.0f) { BuildPercentage = BuildPercentage + CurrentConstruction.buildCapacity; } else { break; } /// <summary> /// This construction project is paused right now. /// </summary> if (CurrentConstruction.inProduction == false) { continue; } /// <summary> /// how much of total industry does this build project use? /// </summary> float DevotedIndustry = (CurrentConstruction.buildCapacity / 100.0f) * CurrentIndustry; float Completion = DevotedIndustry / (float)CurrentConstruction.costPerItem; int NumberBuilt = 0; /// <summary> /// Final bit of a construction project to complete. /// </summary> if (Completion >= CurrentConstruction.numToBuild) { NumberBuilt = (int)Math.Floor(CurrentConstruction.numToBuild); Completion = CurrentConstruction.numToBuild; } /// <summary> /// This is a new build item. /// </summary> else if (Math.Floor(CurrentConstruction.numToBuild) == CurrentConstruction.numToBuild) { /// <summary> /// This colony will build or start to build this many items. charge for all of them. /// </summary> NumberBuilt = (int)Math.Ceiling(Completion); /// <summary> /// the colony can build everything in one go. /// </summary> if (NumberBuilt >= Math.Floor(CurrentConstruction.numToBuild)) { NumberBuilt = (int)Math.Floor(CurrentConstruction.numToBuild); Completion = CurrentConstruction.numToBuild; } } /// <summary> /// This is an inprogress item, new items will be started however. /// </summary> else if ((CurrentConstruction.numToBuild - Completion) < Math.Floor(CurrentConstruction.numToBuild)) { /// <summary> /// Adjust out the current build fraction, and then calculate how many new items will be started. float CurBuildReq = (CurrentConstruction.numToBuild - (float)Math.Floor(CurrentConstruction.numToBuild)); NumberBuilt = (int)Math.Ceiling(Completion - CurBuildReq); if (NumberBuilt > Math.Floor(CurrentConstruction.numToBuild)) { NumberBuilt = (int)Math.Floor(CurrentConstruction.numToBuild); } } bool CIRequired = false; bool MineRequired = false; bool CanBuild = false; /// <summary> /// Conventional industry must also be used. /// </summary> if (CurrentConstruction.buildType == ConstructionBuildQueueItem.CBType.PlanetaryInstallation) { if ((int)CurrentConstruction.installationBuild.Type >= (int)Installation.InstallationType.ConvertCIToConstructionFactory && (int)CurrentConstruction.installationBuild.Type <= (int)Installation.InstallationType.ConvertCIToOrdnanceFactory) { CIRequired = true; CanBuild = CurrentPopulation.CIRequirement(NumberBuilt); if (CanBuild == false) { String Entry = String.Format("Insufficent Conventional Industry to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksCI, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } } if ((int)CurrentConstruction.installationBuild.Type == (int)Installation.InstallationType.ConvertMineToAutomated) { MineRequired = true; CanBuild = CurrentPopulation.MineRequirement(NumberBuilt); if (CanBuild == false) { String Entry = String.Format("Insufficent Mines to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksCI, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } } } /// <summary> /// Check mineral costs to see if this can be built. /// </summary> switch (CurrentConstruction.buildType) { #warning PDC construction needs to be implemented here and slightly further down. case ConstructionBuildQueueItem.CBType.PlanetaryInstallation: CanBuild = CurrentPopulation.MineralRequirement(CurrentConstruction.installationBuild.MinerialsCost); break; case ConstructionBuildQueueItem.CBType.ShipComponent: CanBuild = CurrentPopulation.MineralRequirement(CurrentConstruction.componentBuild.minerialsCost); break; case ConstructionBuildQueueItem.CBType.PDCConstruction: break; case ConstructionBuildQueueItem.CBType.PDCPrefab: break; case ConstructionBuildQueueItem.CBType.PDCAssembly: break; case ConstructionBuildQueueItem.CBType.PDCRefit: break; case ConstructionBuildQueueItem.CBType.MaintenanceSupplies: CanBuild = CurrentPopulation.MineralRequirement(Constants.Colony.MaintenanceMineralCost); break; } if (CanBuild == false) { String Entry = String.Format("Insufficent Minerals to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } /// <summary> /// Adjust number to build downward to reflect construction happening. /// </summary> int CompletedItems = (int)Math.Ceiling(CurrentConstruction.numToBuild); CurrentConstruction.numToBuild = CurrentConstruction.numToBuild - Completion; CompletedItems = CompletedItems - (int)Math.Ceiling(CurrentConstruction.numToBuild); switch (CurrentConstruction.buildType) { case ConstructionBuildQueueItem.CBType.PlanetaryInstallation: if (NumberBuilt != 0) { if (CIRequired == false && MineRequired == false) { CurrentPopulation.HandleBuildItemCost((CurrentConstruction.costPerItem * NumberBuilt), CurrentConstruction.installationBuild.MinerialsCost); } else if (CIRequired == true && MineRequired == false) { CurrentPopulation.HandleBuildItemCost((CurrentConstruction.costPerItem * NumberBuilt), CurrentConstruction.installationBuild.MinerialsCost, NumberBuilt, -1); } else if (CIRequired == false && MineRequired == true) { CurrentPopulation.HandleBuildItemCost((CurrentConstruction.costPerItem * NumberBuilt), CurrentConstruction.installationBuild.MinerialsCost, -1, NumberBuilt); } } CurrentPopulation.AddInstallation(CurrentConstruction.installationBuild, Completion); break; case ConstructionBuildQueueItem.CBType.ShipComponent: if (NumberBuilt != 0) { CurrentPopulation.HandleBuildItemCost((CurrentConstruction.costPerItem * NumberBuilt), CurrentConstruction.componentBuild.minerialsCost); } CurrentPopulation.AddComponentsToStockpile(CurrentConstruction.componentBuild, Completion); break; case ConstructionBuildQueueItem.CBType.PDCConstruction: break; case ConstructionBuildQueueItem.CBType.PDCPrefab: break; case ConstructionBuildQueueItem.CBType.PDCAssembly: break; case ConstructionBuildQueueItem.CBType.PDCRefit: break; case ConstructionBuildQueueItem.CBType.MaintenanceSupplies: if (NumberBuilt != 0) { CurrentPopulation.HandleBuildItemCost((CurrentConstruction.costPerItem * NumberBuilt), Constants.Colony.MaintenanceMineralCost); } CurrentPopulation.AddMSP(CompletedItems); break; } } /// <summary> /// Cleanup the CBQ here. /// </summary> for (int CBQIterator = 0; CBQIterator < CurrentPopulation.ConstructionBuildQueue.Count; CBQIterator++) { if (CurrentPopulation.ConstructionBuildQueue[CBQIterator].numToBuild == 0.0f) { CurrentPopulation.ConstructionBuildQueue.RemoveAt(CBQIterator); CBQIterator--; } } } } }
/// <summary> /// Handles ordnance factory construction. /// </summary> /// <param name="P">List of factions.</param> public static void OrdnanceFactoryBuild(BindingList <Faction> P) { /// <summary> /// Subtract the construction cycle from the construction tick. /// </summary> foreach (Faction CurrentFaction in P) { foreach (Population CurrentPopulation in CurrentFaction.Populations) { /// <summary> /// How much construction work per day does this colony do? default should be 5 day construction cycle. /// </summary> float TimeAdjust = (float)Constants.Colony.ConstructionCycle / (float)Constants.TimeInSeconds.Year; float CurrentIndustry = CurrentPopulation.CalcTotalOrdnanceIndustry() * TimeAdjust; float BuildPercentage = 0.0f; foreach (MissileBuildQueueItem CurrentConstruction in CurrentPopulation.MissileBuildQueue) { /// <summary> /// Check to see if this item is in the current build queue, or has to wait for capacity to free up. /// </summary> if ((BuildPercentage + CurrentConstruction.buildCapacity) <= 100.0f) { BuildPercentage = BuildPercentage + CurrentConstruction.buildCapacity; } else { break; } /// <summary> /// This construction project is paused right now. /// </summary> if (CurrentConstruction.inProduction == false) { continue; } /// <summary> /// how much of total industry does this build project use? /// </summary> float DevotedIndustry = (CurrentConstruction.buildCapacity / 100.0f) * CurrentIndustry; float Completion = DevotedIndustry / (float)CurrentConstruction.costPerItem; int NumberBuilt = 0; /// <summary> /// Final bit of a construction project to complete. /// </summary> if (Completion >= CurrentConstruction.numToBuild) { NumberBuilt = (int)Math.Floor(CurrentConstruction.numToBuild); Completion = CurrentConstruction.numToBuild; } /// <summary> /// This is a new build item. /// </summary> else if (Math.Floor(CurrentConstruction.numToBuild) == CurrentConstruction.numToBuild) { /// <summary> /// This colony will build or start to build this many items. charge for all of them. /// </summary> NumberBuilt = (int)Math.Ceiling(Completion); /// <summary> /// the colony can build everything in one go. /// </summary> if (NumberBuilt >= Math.Floor(CurrentConstruction.numToBuild)) { NumberBuilt = (int)Math.Floor(CurrentConstruction.numToBuild); Completion = CurrentConstruction.numToBuild; } } /// <summary> /// This is an inprogress item, new items will be started however. /// </summary> else if ((CurrentConstruction.numToBuild - Completion) < Math.Floor(CurrentConstruction.numToBuild)) { /// <summary> /// Adjust out the current build fraction, and then calculate how many new items will be started. float CurBuildReq = (CurrentConstruction.numToBuild - (float)Math.Floor(CurrentConstruction.numToBuild)); NumberBuilt = (int)Math.Ceiling(Completion - CurBuildReq); if (NumberBuilt > Math.Floor(CurrentConstruction.numToBuild)) { NumberBuilt = (int)Math.Floor(CurrentConstruction.numToBuild); } } /// <summary> /// Do I have the minerals to build this missile? /// </summary> bool CanBuild = CurrentPopulation.MineralRequirement(CurrentConstruction.ordnanceDef.minerialsCost); if (CanBuild == false) { String Entry = String.Format("Insufficent Minerals to continue build order on {0} for {1}x {2}", CurrentPopulation, CurrentConstruction.numToBuild, CurrentConstruction.Name); MessageEntry Msg = new MessageEntry(MessageEntry.MessageType.ColonyLacksMinerals, CurrentPopulation.Contact.Position.System, CurrentPopulation.Contact, GameState.Instance.GameDateTime, GameState.Instance.LastTimestep, Entry); CurrentFaction.MessageLog.Add(Msg); continue; } /// <summary> /// Adjust number to build downward to reflect construction happening. /// </summary> int CompletedItems = (int)Math.Ceiling(CurrentConstruction.numToBuild); CurrentConstruction.numToBuild = CurrentConstruction.numToBuild - Completion; CompletedItems = CompletedItems - (int)Math.Ceiling(CurrentConstruction.numToBuild); CurrentPopulation.HandleBuildItemCost((CurrentConstruction.costPerItem * NumberBuilt), CurrentConstruction.ordnanceDef.minerialsCost); CurrentPopulation.LoadMissileToStockpile(CurrentConstruction.ordnanceDef, CompletedItems); } /// <summary> /// Cleanup the CBQ here. /// </summary> for (int MBQIterator = 0; MBQIterator < CurrentPopulation.MissileBuildQueue.Count; MBQIterator++) { if (CurrentPopulation.MissileBuildQueue[MBQIterator].numToBuild == 0.0f) { CurrentPopulation.MissileBuildQueue.RemoveAt(MBQIterator); MBQIterator--; } } } } }