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:
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:
foodRequired = (population * multiplier) / 10
Since a population less than 9 is rare, this will usually be:
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:
foodConsumed = min(foodStored, population)
The foodStored is updated, and the netFoodProduction is calculated:
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.
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:
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