public void SellPhase() { // Get all goods up for sale. _productSupply = Populous.SellPhase(); // Reset Shortfall to zero. Shortfall = new ProductAmountCollection(); // Fill Surplus preemtively, we'll remove bought products later. _surplus = ProductSupply.Copy(); // While we're at it, also get total demand of all products _productDemand = Populous.TotalDemand(); // And the hypothetical total production available. _productionCapacity = Populous.TotalProduction(); }
public void LossPhase() { // Carry out losses. var losses = Populous.LossPhase(); }
public void ConsumptionPhase() { // Kick down to populations. Populous.Consume(); }
/// <summary> /// Run through all productions that can be done and add them to the market. /// </summary> public void ProductionPhase() { // Run through production Populous.ProductionPhase(); }
/// <summary> /// Buys good from the market. /// </summary> /// <param name="buyer">The one buying the good.</param> /// <param name="good">The good they are trying to buy.</param> /// <param name="amount">How much they are trying to buy.</param> /// <returns>The Receipt of purchases</returns> public IProductAmountCollection BuyGoodsFromMarket(IPopulationGroup buyer, IProduct good, double amount) { if (buyer is null) { throw new ArgumentNullException(nameof(buyer)); } if (good is null) { throw new ArgumentNullException(nameof(good)); } if (amount <= 0) { throw new ArgumentOutOfRangeException(nameof(amount)); } // The result of the purchases. IProductAmountCollection result = new ProductAmountCollection(); // First buy from local merchants, they only accept cash. result = Populous.Merchants .BuyGood(buyer.GetCash(AcceptedCurrencies), good, amount, this); // see how much was bought. double remainder = 0; // if any was bought, update what we are seeking. if (result.Contains(good)) { remainder = amount - result.GetProductValue(good); // and complete the transaction buyer.CompleteTransaction(result); } // if no remainder, return if (remainder <= 0) { return(result); } // Then buy from everyone else via both cash and barter. foreach (var seller in Populous.GetPopsSellingProduct(good)) { // If someone is selling the good, buy or barter with them. var reciept = BuyGoods(buyer, good, remainder, seller); // if something was bought if (reciept.Count() > 0) { // remove it from the remainder remainder -= reciept.GetProductValue(good); // add it to our result result.AddProducts(reciept); } // if nothing remains, we're done. if (remainder <= 0) { return(result); } } // Finish buy going to the travelling merchants, if all else fails. foreach (var travSeller in TravellingMerchantsSelling(good)) { var reciept = travSeller.BuyGood(buyer.GetCash(AcceptedCurrencies), good, remainder, this); // if something was bought if (reciept.Count() > 0) { // remove it from remainder remainder -= reciept.GetProductValue(good); // Complete the transaction for the buyer buyer.CompleteTransaction(reciept); // add it to the result result.AddProducts(reciept); } // if nothing remains, return if (remainder <= 0) { return(result); } } // return the ultimate receipt. return(result); }
/// <summary> /// Grows the population, prioritizing those which are happiest/most successful over others. /// </summary> public void PopGrowth() { // The average growth we achieve each day. var popGrowth = 0.01; // to be divided later represents one year growth average. // Get the success of the total populous. var lifeSat = Populous.LifeNeedsSatisfaction(); var dailySat = Populous.DailyNeedsSatisfaction(); // modify growth by satisfaction. if (lifeSat >= 0.99) { // Effectively totally satisfied. // The higher the Daily need Satisfaction, the greater the pop growth. popGrowth += 0.01 * dailySat; } else { // Life sat not satisfied, remove 3 times the missing life need satisfaction. popGrowth -= 0.03 * (1 - lifeSat); // This bottoms out at -0.02. } // Randomize growth today. var variance = rand.NextDouble(-0.01, 0.01); // -0.01 to 0.01 popGrowth += variance; // Get the new pops to add (divide by our year length) var newPops = TotalPopulation * popGrowth / 360; // add fractional pops to the carryover growth carryoverGrowth += newPops % 1; // remove fraction from newPops newPops -= newPops % 1; // if carry over growth greater than 1 (positive or negative) if (Math.Abs(carryoverGrowth) > 1) { // add (or remove) the whole number value of carry over. newPops += carryoverGrowth - (carryoverGrowth % 1); // update carryoverGrowth carryoverGrowth = carryoverGrowth % 1; } // Get pops ordered by success (descending order) var popsBySuccess = Populous.Pops.OrderByDescending(x => x.Success()); // get total weight of the populous (all positive values, no negatives) double totalWeight = 0; foreach (var pop in popsBySuccess) { // get the success totalWeight += pop.Success(); } // Now, we figure out where to put the pops. foreach (var pop in popsBySuccess) { // get pop's success again var success = pop.Success(); // if pop is not successful, regardless of reason, GTFO, failing pops don't grow // and if the pop is not successful, no following pops will be either. if (success <= 0.5) { break; } // get pop growth, divided by weight, and multiplied by success var born = newPops / totalWeight * success; // modify up or down by 50% born *= (0.5 + rand.NextDouble()); // remove hanging decimals born -= born % 1; // add new pops to group pop.AddPop(born); // remove born from new pops newPops -= born; // remove the success from the total weight totalWeight -= success; } // any remainder pop, just add to the most successful pop. popsBySuccess.First().AddPop(newPops - (newPops % 1)); // any extra just drop. }