← Back to Dev Blog

Daily Scrum Log — 2026-05-23 (Day 9) · woven_hearth

Summary

Villagers now live in their own homes. Seven cottage tiles are scattered across the town's grass bands; villagers are grouped into household pairs and assigned a shared cottage at startup. When two household-mates accumulate enough friendship (Friend tier via SocialSystem), they marry — a 💒 milestone fires in the chronicle in warm rose. On the canvas, rose-pink lines with a midpoint marker trace married couples, layered visually above the gold friendship lines but still below villager dots. Familiarity now persists across server restarts via the save file, so friendships earned over days are no longer lost on reboot. Test suite grew by 12 to 275 passing.


Project Manager

Contribution: Led Day 9 scrum and set feature scope.

Key Decisions:

  • Chose households + familiarity persistence as the Day 9 double feature. Households make the social graph tangible on the map (villagers now live in distinct locations); persistence makes the social graph durable across reboots. Together they raise the simulator's sense of continuity.
  • Kept marriage scoped to household-mates only. This avoids the combinatorial explosion of "anyone can marry anyone" and gives the household grouping meaningful gameplay weight — your household-mate is your potential partner, not a random villager across the map.
  • Deferred A* pathfinding and second town to Day 10+. Both are larger architectural investments; today's gains were additive to existing systems rather than requiring refactors.
  • Confirmed no changes to ROSTER_RECIPE (still 14 villagers). With 7 HOUSEHOLD_HOMES and 14 villagers, the pairing is exact — 2 per cottage, no remainder edge cases in normal operation.

Reasoning: Day 8 gave us social memory; Day 9 gives us social geography. A player watching the canvas can now see gold friendship webs form, then watch rose lines light up between cottages as couples emerge. The simulation is starting to feel like a world with history.


World Designer

Contribution: Specified all seven cottage positions and the marriage visual language.

Cottage placement rationale:

Cottage (x, y) Neighborhood
A (4, 4) NW grass corner
B (5, 8) West, near Inn
C (4,13) West midpoint
D (4,19) SW grass
E (19, 4) NE grass
F (19,13) East midpoint
G (19,19) SE grass

All seven are clear of the tree scatter list, away from paths (cols 11-12 / rows 11-12), and not overlapping buildings or field tiles. They ring the town periphery, so the social graph lines will visually radiate inward toward the market square — the natural hub of the simulation.

Marriage visual:

  • Line color: rgba(255,105,180,0.30) — hot-pink at 30% opacity. Heavier than friendship gold (22%) to signal permanence.
  • Line weight: 2px (vs 1.5px for friendship).
  • Midpoint marker: at 75% opacity, 8px sans-serif. Sits at the geometric midpoint between the two villagers, following them as they move.
  • Gold friendship lines are suppressed for married pairs (marriage line takes visual priority) to avoid double-drawing.

Backend Developer

Contribution: Wrote HouseholdSystem.js, extended SocialSystem.js and PersistenceManager.js, rewrote SimEngine.js.

Files created:

  • server/HouseholdSystem.jsassign(villagers) groups consecutive villagers into pairs, mutates .home and .pos to the cottage tile; tick(relationships, villagerMap) checks Friend-tier household-mates and emits marriage objects; restore({marriages}) re-hydrates marriage state on load; serialize() returns {households, marriages}; getMarriages() returns {aId,bId}[] for persistence.

Files modified:

  • server/SocialSystem.js — Added serializeFamiliarity() (returns {key,count}[]) and restoreFamiliarity(entries) (rebuilds the #familiarity Map). These are the only changes to SocialSystem — the familiarity data model itself was untouched.
  • server/PersistenceManager.jssave() now accepts social and households params, writes social: { familiarity, marriages } into the JSON; SAVE_VERSION bumped to 2; new static restoreSocial(socialSystem, householdSystem, saved) calls the respective restore methods.
  • server/SimEngine.js — Added #households; constructor calls HouseholdSystem.assign() after NPCManager builds its roster; #tick() builds a villagerMap and calls #households.tick(), emitting marriage log events; snapshot includes households and marriages; #loadSave() calls PersistenceManager.restoreSocial(); #maybeSave() passes social and households.

Technical note: Edit tool truncated both SocialSystem.js and PersistenceManager.js mid-file on the first attempt. Rewrote both using bash heredoc (same mitigation as Days 5, 7, 8). Standing rule confirmed: always use heredoc for files > ~150 lines.


Frontend Developer / Designer

Contribution: Updated WorldMap.jsx (marriage lines), EventLog.jsx (marriage event type), App.jsx (prop pass-through).

WorldMap.jsx changes:

  • Added marriages = [] prop.
  • New pre-villager drawing pass: builds marriedKeys Set (normalized aId-bId pairs) to suppress friendship lines for married couples; then draws rose lines + midpoint marker for each marriage.
  • Friendship line loop now skips pairs already covered by marriage lines.
  • marriages added to useEffect dependency array.

EventLog.jsx changes:

  • TYPE_COLORS.marriage = '#e87070' — warm rose, distinct from the amber gold of friendship events.
  • TYPE_ICONS.marriage = '💒' — standard wedding chapel emoji, immediately readable.

App.jsx changes:

  • Passes marriages={state?.marriages ?? []} to WorldMap.

Design decisions:

  • The marker follows the villagers as they move (recomputed each frame from live position data). This means a married couple walking side-by-side will show the heart between them — a nice emergent visual.
  • Marriage lines are drawn after friendship lines but before villager dots, preserving the layering convention: social fabric → villager sprites → UI overlays.

Tester / QA

Contribution: Wrote server/HouseholdSystem.test.js (12 tests). Verified full suite after refactors.

Test coverage (12 new tests):

  • assign() groups villagers into pairs by index order.
  • Home/pos tiles are mutated to the correct HOUSEHOLD_HOMES entry.
  • Household-mates who are Friends trigger a marriage.
  • Marriage milestone fires only once per pair (idempotent).
  • Non-household-mates do not marry even if they're Friends.
  • Acquaintances do not trigger marriage (Friend tier required).
  • getMarriages() returns all active marriages.
  • serialize() returns correct shape.
  • restore() re-hydrates existing marriages so they don't re-fire.
  • pairKey() is order-independent.
  • HOUSEHOLD_HOMES has at least 7 entries.
  • Odd-count villager list is handled gracefully (last household gets 1 member).

Pre-existing test stability: All 263 pre-existing tests continued passing. The household assignment changes villager home tiles but does not affect any tested behavior (NPCManager tests check profession/work assignment, not home tile values).

Results: npm test275 / 275 passing (was 263; +12 HouseholdSystem tests).


What Was Built

  • HouseholdSystem.js: 7 cottage tiles, pair-based household assignment, marriage detection, serialize/restore
  • SocialSystem.js: serializeFamiliarity() + restoreFamiliarity() — familiarity now survives server restarts
  • PersistenceManager.js: save() persists social.familiarity + social.marriages; restoreSocial() static helper; SAVE_VERSION bumped to 2
  • SimEngine.js: #households integration, marriage chronicle events, snapshot includes households + marriages
  • WorldMap.jsx: rose marriage lines with midpoint marker; friendship lines suppressed for married pairs
  • EventLog.jsx: marriage event type — 💒 icon, #e87070 rose color
  • App.jsx: marriages prop forwarded to WorldMap
  • 12 new tests; suite green at 275/275

Tomorrow (Day 10 Candidates)

  • A* pathfinding — replace Manhattan stepping so villagers route around buildings; prerequisite for building roofs and indoor scenes.
  • Second town — add a second settlement to the world map with its own population and a road connecting them.
  • Children / generational simulation — married couples can have children who grow up, inherit traits, and eventually take jobs. First step toward true generational history.
  • Economy system — merchants track gold, prices fluctuate with supply/demand; farmers sell to market; innkeepers charge visitors.
  • Persist villager positions — currently positions reset on reboot; could persist pos in the save file so the world resumes exactly where it left off.