Skip to content

Tokeyo Town v2: terrain + shaped buildings + roads + AI + rebalance#28

Draft
bjamba wants to merge 7 commits into
feature/tokeyo-townfrom
feature/tokeyo-town-v2
Draft

Tokeyo Town v2: terrain + shaped buildings + roads + AI + rebalance#28
bjamba wants to merge 7 commits into
feature/tokeyo-townfrom
feature/tokeyo-town-v2

Conversation

@bjamba
Copy link
Copy Markdown
Owner

@bjamba bjamba commented May 20, 2026

Builds on #27. Addresses all five v1 playtest issues.

What changed

Issue Fix
Too zoomed out / no roads / one-size buildings Tile size scales with map size; map floor 12 / cap 48; new road tool (4 coin/tile); 1×1, 2×1, 2×2 footprints
Bare biomes Procedural terrain layer — water, sand, grass, rock, trees, flowers, generated by value noise seeded by townId
Glyph-on-brick buildings Composable iso-prism recipes (stories + roof types + ornaments). Cottages look like cottages, lighthouses look like lighthouses
Disconnected townsfolk Each gets a home, picks errands to other buildings, pauses 3-10s, returns home, prefers road tiles
Coin > everything Coin earn 4× nerf; knowledge 2× nerf; industry 1.6× nerf; building costs 2-3×; major buildings require multiple scarce resources

Schema migration

Save schema bumped to v2. v1 saves decode cleanly — terrain regenerates from the townId seed (deterministic).

ADR-0006 addendum (A1-A8) covers each decision

Verification

  • swift build
  • swift test ✅ — 130 tests pass (8 new)
  • swiftformat --lint .
  • bash scripts/check.sh
  • ./build.sh && open Tokade.app

🤖 Generated with Claude Code

bjamba and others added 7 commits May 20, 2026 10:21
Major overhaul addressing v1 playtest feedback:

1. Procedural terrain (water/sand/grass/rock/tree/flower) seeded by townId.
   Same repo → same landscape every time. Buildings can only sit on
   grass/sand; trees & rocks block placement until terraformed.

2. Building shapes are drawn, not stickered. Composable iso-prism
   recipes (stories + roof types + ornaments). Cottages look like
   cottages, lighthouses look like lighthouses. No glyph on the world.

3. Variable footprints (1×1, 2×1, 2×2). Landmarks demand multiple
   scarce resources, not just coin.

4. Roads + terraforming tool sidebar — road, plant tree, clear tree
   (refunds lumber), level rock, plant flower, lantern. Roads bias
   townsfolk pathing.

5. Townsfolk actually do things — each has a home building, picks
   errands to other buildings, pauses 3-10s on arrival, returns home,
   prefers road tiles when walking.

6. Resource rebalance (coin 1/1k → 1/4k tokens, knowledge 1/5 → 1/10
   reads, industry 1/5 → 1/8 bashes). Building costs bumped 2-3x; major
   buildings require ≥2 distinct scarce resources (enforced by a test).

7. Zoom + camera — tile size scales with map size; map floor 12, cap 48.

Save schema bumped to v2 with backward-compatible decoder that
regenerates terrain from the townId seed for v1 saves.

ADR-0006 gets an addendum (A1-A8) documenting every decision.
130 tests pass (8 new for terrain, footprints, multi-resource costs,
v1 save migration, AI walkable-neighbor pathing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Second iteration on the v1 MVP. Nine items addressed:

1. Cardinal-only townsfolk movement. AI commits to a single `nextStep`
   neighbor each tick; renderer interpolates only between current and
   nextStep, never to the ultimate goal — no more diagonal motion.

2. Undo / Redo with a 50-action stack. Every player action snapshots
   first. Header buttons disable when their stack is empty.

3. Building badges — small marker circle with the catalog glyph drawn
   beside each building. Silhouette stays clean, meaning stays readable.

4. Per-tile sub-detail: grass tufts on grass, ripple arcs on sand,
   seeded by townId so it's stable per town.

5. Zoom (3 levels: 0.75 / 1.0 / 1.5) + pan toggle. Plumbed through all
   projection math.

6. Roads look like roads — narrow asphalt strip with sidewalk underlay
   and a 4-bit neighbor mask drives the visual variant. Straights get a
   center dash; Ts/curves/crosses/dead-ends emerge naturally. Roads
   extend into adjacent building edges.

7. More home variants: each biome now has 9 buildings (was 8) with at
   least 2 home types. New: Row House (plain), Yurt (desert), Stone
   Lodge (tundra), Forest Cabin (forest), Bungalow (beach). The
   `Building.isHome` flag replaces hardcoded id lists in the store.

8. Pier must touch water — placement rejected unless a footprint tile
   is adjacent to a water tile.

9. Terrain elevation tiers (-1 / 0 / 1 / 2). Renderer lifts each tile
   diamond and draws cliff side-faces between elevation drops. New
   tools: ⛰ Raise / 🕳 Lower (6 industry each). canBuild now requires
   every tile in a footprint share elevation. Tier transitions
   auto-flip terrain kind (lower to -1 → water; raise to 2 → rock).

The universal "Remove" tool also clears road / flower / decor now, not
just buildings.

ADR-0006 gets a v3 addendum (B1-B9). 134 tests pass (4 new for
elevation, cardinal AI, mixed-elevation footprint rejection, multiple
home variants).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Roads: dark asphalt with light concrete sidewalk, single palette
  across all biomes (was biome-tinted, beach especially looked like
  boardwalk planks). Tighter strip widths so roads read as roads, not
  blobs. Yellow dashed lane stripe on straight runs. Junctions stay
  strictly perpendicular.

- Building icons back on top of the roof apex, bigger, with a soft
  dark halo behind for legibility against any roof color. Drops the
  side badge entirely.

- Pan is now a sidebar tool ("✥ Pan") alongside Remove and the rest.
  Killed the separate header toggle so all modal switches live in one
  place. A "Current: <tool>" indicator floats in the canvas top-left
  so the active tool is always visible.

- Tier-2 elevation no longer auto-converts to grey rock. The renderer
  draws a 4-faced pyramid on top of the tile in the tile's ground
  color (grass green / sand tan / etc.). Tundra peaks get a snow cap.
  Lower-back-down does NOT change tile kind, so a forested mountain
  becomes a forested hill becomes a forested patch of grass.

134 tests pass; swiftformat clean; scripts/check.sh clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tail

Five small but important fixes:

1. Roads now run along the iso axes — strip arms go from tile center
   to edge midpoints, so a straight road appears as a single 45°
   stripe parallel to the tile's edges (NW↔SE or NE↔SW). Junctions
   stay perpendicular. Previous diamond-strip layout (NS strip ran
   vertically on screen) is gone.

2. Plain cottage now matches its 🏠 glyph — yellow walls, red roof,
   dark trim. Same approach can be extended to other buildings whose
   glyph/silhouette palette feels off.

3. Townsfolk vanish as they cross into a building tile (and while
   paused inside one) instead of visibly approaching the iso diamond's
   center. They walk to the tile boundary, "duck inside," and reappear
   walking out — no more diagonal entry artifacts.

4. New `BuildingShape.Detail` axis: planks / windows / sails / bell /
   slats. Drawn by the renderer over the building's stories:
   - Pier: top planks + corner posts (was a low boring slab)
   - Plain cottage: a small window pane on each front face
   - Ice fishing hut: horizontal slat lines
   - Windmill: 4-arm cross-sails on top
   - Shrines (all 4 biomes): bell suspended on a cord under the spire

5. Raise/Lower costs moved from 6 industry → 30 coin, so terrain
   shaping is accessible from day one (industry was one of the
   slowest-earning resources).

All 134 tests pass; swiftformat clean; scripts/check.sh clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Screenshot critique + the new tool rules. Concretely:

- Roads: drop the sidewalk underlay and per-tile center cap. Only the
  dark asphalt arms remain, one per connecting direction. Yellow
  dashed lane stripe now draws along every connecting arm (so curves,
  Ts, crosses, and dead-ends all have lane markings, not just straights).
  Dead-ends and isolated tiles get a small square cap so they don't
  vanish to a point.

- Building glyphs: halo dropped (was reading as a UI sticker), glyph
  shrunk to ~10pt at zoom 1 so the building silhouette wins.

- Aquarium: rectangular tank with porthole windows, flat roof. The
  old dome read as water spilling out of the building.

- Lighthouse: stories now *narrow* as they rise (was widening). Slimmer
  silhouette so it doesn't dwarf neighbouring cottages.

- Pier: new `extendsIntoWater` flag on Building. Pier footprint may
  straddle land + water. Special placement rule: must include at least
  one water tile and one land tile, elevation match skipped. Visually
  the deck extends over the water edge.

- Beach coastline: terrain generator biases elevation downward toward
  one map edge (seeded by townId) so beach biomes form a continuous
  shoreline instead of scattered ponds.

- Universal hover highlight: a yellow / red tile outline + soft fill
  follows the cursor for every non-build tool (remove, road, plant,
  fell, level, raise, lower, flower, lantern). Red when the action
  would fail (wrong tile, too expensive, etc.); yellow when it would
  succeed.

- No road on mountain peaks (elev == 2 blocks placement).
- No raise/lower on road tiles (would break the road graphic).
- Sidebar subtitles dropped; cleaner labels.

All 134 tests pass; swiftformat clean; scripts/check.sh clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The .confirmationDialog used for the 'Start a new town?' prompt
steals focus when shown, which dismisses the MenuBarExtra panel — same
class of bug as the old NSOpenPanel folder picker. Replace it with an
inline overlay panel inside the canvas. Same buttons, same
behaviour, but lives inside the app window so the panel stays open.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Roads now build a single stroked centerline Path per tile, then
  stroke it at road-width with rounded line caps/joins. Adjacent-pair
  connections (N+E, E+S, S+W, W+N) emit a quadratic Bezier through
  the tile center, so L-curves are visibly smooth instead of sharp
  90° corners. Opposite pairs stay straight; T/cross/dead-end still
  draw straight arms. Yellow dashes follow the same path.

- IsoMath.unproject used `.rounded(.down)` (floor) which is wrong for
  iso tile picking — at the center of tile (3, 4) the cursor landed
  there, but anywhere slightly to the negative side rolled over to
  (2, 4). Switched to `.rounded()` (nearest) so the hovered tile
  matches the clicked tile.

- Hover used to require a drag because `DragGesture(minimumDistance:0)
  .onChanged` only fires once dragging starts. Added an
  `.onContinuousHover` modifier that updates `hoverTile` from mouse
  position alone — the highlight tracks the cursor as expected.

- Single-tile hover highlight is now always yellow. The red "invalid"
  variant was misleading (read as a hard block when it was really
  just "this won't do anything"). Build-tool placement preview still
  uses red overlay for invalid footprints — that's an actual hard
  block.

134 tests pass; swiftformat clean; scripts/check.sh clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant