Went through the main thread and opted to split the population model discussion out of it and into its own topic especially with the development efforts very rapidly approaching this point.
So with that a few notes/thoughts/whatever.
I've opted to take Hooman's suggestion and go with what I called 'flat numbers'. There's no need to build a 'Person' object. That stated, it's also entirely probable that a PopulationPool object, as I originally envisioned, may not be necessary either. Much like the Energy Value, population can be treated as a "You have this much, this is how much you need to operate a structure."
I ran across an old topic that Hooman posted (http://forum.outpost2.net/index.php/topic,3807.0.html) regarding Outpost 2's population model. I'll repost the relevant code here:
/* -- Growth -- */
/* New Workers */
if (colonyState.active.numUniversities > 0 && colonyState.pop.num.kids > 0)
{
growth.workers += num.kids;
divisor = num.workers + num.scientists + num.kids;
if (divisor <= 160)
divisor = 160;
divisor = ((divisor / 40) * 3 + 36) * 4;
newPop.workers = growth.workers / divisor;
growth.workers = growth.workers % divisor;
num.workers += newPop.workers;
num.kids -= newPop.workers;
}
/* New Kids */
if (colonyState.active.numNurseries > 0 && num.workers + num.scientists > num.kids)
{
growth.kids += num.scientists / 4 + num.workers / 2;
divisor = colonyState.moraleLevel->fertRate;
newPop.kids = growth.kids / divisor;
growth.kids = growth.kids % divisor;
num.kids += newPop.kids;
}
/* -- Deaths -- */
/* Kid Deaths */
if (num.kids > 0)
{
death.kids += num.kids;
divisor = colonyState.moraleLevel->deathRate / 2 + colonyState.active.numNurseries * 40 + medCenterCapacity;
diePop.kids = death.kids / divisor;
death.kids = death.kids % divisor;
num.kids -= diePop.kids;
if (num.kids == 0)
{
death.kids = 0;
growth.workers = 0;
}
}
/* Worker Deaths */
if (num.workers > 0)
{
death.workers += num.workers;
divisor = colonyState.moraleLevel->deathRate + medCenterCapacity;
diePop.workers = death.workers / divisor;
death.workers = death.workers % divisor;
num.workers -= diePop.workers;
if (num.workers == 0)
death.workers = 0;
}
/* Scientist Deaths */
if (num.scientists > 0)
{
death.scientists += num.scientists;
divisor = colonyState.moraleLevel->deathRate + medCenterCapacity;
diePop.scientists = death.scientists / divisor;
death.scientists = death.scientists % divisor;
num.scientists -= diePop.scientists;
if (num.scientists == 0)
death.scientists = 0;
}
I have a fairly basic grasp of this but the real problem is in understanding some of the divisor numbers, particularly in the 'growth' section (lots of magic numbers there). This should be simulated to see what kind of populations would develop under a number of conditions including tweaks to the divisor (something that difficulty can/should have an effect on plus any research enhancements).
Additionally, OP1 had a Morale range from 0 - 1000, OP2, as I recall, is 0 - 100. Not sure how it would affect this code or if 0 - 100 is sufficient considering OP1's initial implementation.
Anyway, thoughts?
So it can be done using numerical models but I'm finding it exceedingly difficult to make it work. Perhaps I'm stuck in OOP mode but it would seem a lot easier to think about these as individual objects each considering age, gender, health and role.
When I did some basic math, since only a few values are stored, roughly 10,000 'person' objects with three int's and one bool will only really take up a few hundred KiB of memory (140 for the raw info itself) with a bit more for vtables and whatnot. E.g., a 'person' object costs a bit more memory than just the sum of its parts.
Anyway, point being I tested it with up to 30,000 'person' objects and found that the program only takes about 1.5Mib memory (not sure why so much) but ultimately in the grand scheme of things it's a negligible amount of memory for handling this. Also, it runs through the objects very fast, withing a few nanoseconds to update each individual person object in group of 30,000. I suspect late games to have somewhere in the realm of 4 - 5K populations, I don't really know why the would get any larger than that, if that.
Okay, so, here's the real problem. Savegames.
If I went minimalistic with the population saving information, it would look something like this in XML:
<person age="400" health="100" gender="0" role="2" />
With 30,000 population we're looking at a savegame size of 1.6MiB not accounting for other information including structures, etc.
Not sure if I should just go the route of writing out that information as human readable XML (could take awhile to save and load due to DOM processing) or if I should just write it out as a binary stream and save that between <population></population> tags (reduces 30,000 population to a little under 500KiB).
I know this one is really super 100% technical but it's kind of a reasonable thing to consider earlier on. I may simply go with human readable XML for now, can always add binary output later... it's not like storage space is at a premium anymore. :-\