Settlers scale with empty homes: fast catch-up, slowing near full

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-19 20:35:15 +01:00
parent 8fbab37a56
commit 632a12e8bc
3 changed files with 11 additions and 10 deletions

View file

@ -35,8 +35,8 @@ Alpha. One season, bandit raids plus two friendly events, six buildings.
Construction also saws planks, which higher building levels need, and
builds fittings from them: one-off upgrades a building takes once it's high
enough (shelving, a well pump, weapon racks, enchanted chests…). Population eats food,
pays taxes, and fills the houses (empty homes draw settlers, about a
quarter of all homes a day, plus slow family growth); it promotes the settlement
pays taxes, and fills the houses (empty homes draw settlers, half of
them a day, so it slows as the houses fill, plus slow family growth); it promotes the settlement
(hamlet, village at 40, town at 90, city at 150), which raises building
level caps and gives everyone bank slots.
- **Prayer:** enemies drop bones; burying them gives prayer points and

View file

@ -482,9 +482,9 @@ TIERS = [
{"name": "City", "pop": 150, "cap": 99, "houses": 8},
]
TIER_SLOTS = 2
# Growth: empty homes draw settlers (a share of all the homes, every day, while
# any stand empty), and families grow a little on their own.
SETTLERS_PER_HOME = 0.25
# Growth: empty homes draw settlers, fast while many stand empty and slower as
# they fill, and families grow a little on their own however full the city is.
SETTLERS_PER_EMPTY_HOME = 0.5
FAMILY_GROWTH = 0.05
RAID_GROUPS = ["the Red Hand", "the Hollow Crows", "the Blackwater gang", "the Ashen Wolves",
@ -1437,7 +1437,7 @@ def _start_next(world: dict, now: float) -> None:
def growth_per_day(world: dict) -> float:
"""New townsfolk a day while there's room: settlers for the homes, plus families."""
pop = world["city"]["population"]
growth = SETTLERS_PER_HOME * housing(world) + FAMILY_GROWTH * pop
growth = SETTLERS_PER_EMPTY_HOME * max(0.0, housing(world) - pop) + FAMILY_GROWTH * pop
return growth * city_rate(world, "growth") * (1.25 if fitted(world, "furniture") else 1)

View file

@ -315,13 +315,14 @@ class CityTest(unittest.TestCase):
city["population"] = 22.0
city["buildings"]["houses"]["level"] = 2
city["stockpile"] = {"bread": 10_000}
self.assertAlmostEqual(game.growth_per_day(world), 0.25 * 65 + 0.05 * 22)
self.assertAlmostEqual(game.growth_per_day(world), 0.5 * 43 + 0.05 * 22)
for _hour in range(24):
game._city_hour(world, T0)
self.assertGreater(city["population"], 38)
for _hour in range(48):
game._city_hour(world, T0)
self.assertEqual(city["population"], 65)
# Slower as the homes fill, but never down to nothing.
self.assertLess(game.growth_per_day(world), 0.5 * 43)
city["population"] = 64.0
self.assertAlmostEqual(game.growth_per_day(world), 0.5 + 3.2)
def test_fed_city_grows_to_housing_and_pays_tax(self):
world = world_with()