Author Topic: Food  (Read 1326 times)

Offline Hooman

  • Administrator
  • Hero Member
  • *****
  • Posts: 4954
Food
« on: August 16, 2008, 05:56:08 AM »
Here's a bit about how the food system works.

Food Production
------------------
The game loops through all the buildings, and calls a virtual function to determine how much food the building produces. For everything but the agridome, this function just returns 0. For the agridome, it takes the current "production capacity" of the building, and then multiplies it by the morale effect. The morale bonus is actually stored as M_FOOD_BONUS * 256 / 100, which is specified in Morale.txt. The exact calculation is as follows:
Code: [Select]
foodProduced = ((((M_FOOD_BONUS * 256) / 100) * productionCapacity) + 127) / 256 + productionCapacity

Note that the +127 is used for (almost) normal rounding, since by default, the "rounding" by the /256 is by truncation. It should actually be 128 for normal rounding though, since anything >= 0.5 should be rounded up, and as it is, anything <= 0.5 is rounded down.

The sum of that value for each building (that is enabled) is the total production, which is added to the stored amount. Note that the morale bonus is applied to the output of each building, and then summed, rather than summing the production capacity of each building and then applying the morale bonus. The main difference is rounding. The way it's done can lead to a greater difference between the actual value, and the "perfect" unrounded value.


Food Consumption
---------------------
Your total population is counted up (workers + scientists + kids). A consumption multiplier is chosen based on your population. For a population > 9, the multiplier is 9, and for a population <= 9, the multiplier is 10. The amount of food needed is then:
Code: [Select]
foodRequired = (population * multiplier) / 10
Since a population less than 9 is rare, this will usually be:
Code: [Select]
foodRequired = (population * 9) / 10

If foodRequired <= foodStored then nobody will starve.

The amount required isn't the same as the amount consumed however. Even though you need at least 9/10 of a unit of food for each person to prevent starvation, each person will still each 1 whole unit of food, if it is available. That is:
Code: [Select]
foodConsumed = min(foodStored, population)

The foodStored is updated, and the netFoodProduction is calculated:
Code: [Select]
foodStored = foodStored - foodConstumed
netFoodProduction = newFoodStored - oldFoodStored


Starvation
------------
If the required amount of food is not met, then people are starved off in the following manner.
Code: [Select]
foodConsumption = foodStored
foodLacking = foodRequired - foodStored
if (population < 4) then
  Starve(1)
else
  Starve(foodLacking / 2)
end if

The function that does the actual starving works like this:
Code: [Select]
Starve(int numPeopleToStarve)
  numStarvedKids = 0
  numStarvedWorkers = 0
  numStarvedScientists = 0

  if (numPeopleToStarve >= population)
    numPeopleToStarve = population
  end if

  while (numPeopleToStarve > 0)
    switch(Player.starvationCase)
      case 0, 4:  // Kids
        if (numKidsStarved < Player.numKids)
          numKidsStarved++
          numPeopleToStarve--
        end if
      case 1, 2:  // Scientists
        if (numScientistsStarved < Player.numScientists)
          numScientistsStarved++
          numPeopleToStarve--
        end if
      case 3:  // Workers
        if (numWorkersStarved < Player.numWorkers)
          numWorkersStarved++
          numPeopleToStarve--
        end if
    end switch

    Player.starvationCase = (Player.StarvationCase + 1) mod 5
  end while  

  Player.numKids = Player.numKids - numStarvedKids
  Player.numWorkers = Player.numWorkers - numStarvedWorkers
  Player.numScientists = Player.numScientists - numStarvedScientists

  OutputDeaths(numStarvedKids, numStarvedWorkers, numStarvedScientists) // Also updates morale

End Function