Guarantee a minimum reachable share of land per preset #162

Open
opened 2026-10-11 20:23:47 +01:00 by liamjd · 0 comments
Owner

Milestone 2, item 4 ("ensure that terrains are navigable - different thresholds per terrain resource shape").

Problem

Pawns spawn in and are confined to _main_region, the largest group of tiles connected by A* edges. Everything else is walkable-looking ground that nothing can ever reach. Measured over 10 seeds (share of the whole map):

preset 32 64 128
plains 100 % 100 % 100 %
crater 70 % 99 % 100 %
canyon 45 % 47 % 81 %
island 19 % 19 % 19 % (of 23 % land)

The canyon is the clear case. Its walls are cliffs end to end, so the map is reliably cut in two and half of it is scenery. That is not a canyon a colony lives in; it is a wall down the middle. The crater does the same at small sizes, with the rim walling off the outside.

Proposal

  • @export_range(0.0, 1.0) var min_reachable_share: float on TerrainPreset: the share of land tiles the main region must cover. Land rather than the whole map, so the island is not penalised for its sea. Suggested starting values: plains 0.95, crater 0.85, canyon 0.85, island 0.80.
  • After _sample_levels(), if the main region falls short, carve ramps. Join the largest unreached region to the main one by the cheapest route, regrading the tiles along it so each step is at most max_step_levels. Repeat until the threshold is met or an iteration cap is hit. The cap stops a pathological seed from spinning.
  • Ramps should look deliberate: a straight-ish run down a canyon wall, not a random notch. For the canyon, placing them along the wall at intervals is acceptable instead of the generic search.
  • This edits _levels, so it must run before _paint_cells() and _build_navigation(). It must be deterministic: no randi(), only values derived from map_seed.

Decision needed in the implementation

Regrading up (fill) versus down (cut). Cutting into a cliff keeps the high ground intact; filling makes a causeway. Either is defensible; pick one, or decide per shape.

Acceptance criteria

  • min_reachable_share is on the preset, with a value set in each .tres.
  • For every preset at every size from #158, over 10 seeds, the main region covers at least that share of land. Before/after probe numbers go in the PR.
  • Unit tests: a hand-built _levels grid with a cliff splitting it is joined by the ramp pass, and every step along the carved route is at most max_step_levels.
  • Same seed, same map (test_terrain_seed.gd).
  • Headed screenshot of a canyon showing its ramps.

Out of scope

Player terrain manipulation (bridging, joining islands). The milestone puts that out of scope; this is the generator alone.

Depends on

#159 and #160. Terracing changes where the cliffs are, so this should be tuned after it.

Milestone 2, item 4 ("ensure that terrains are navigable - different thresholds per terrain resource shape"). ## Problem Pawns spawn in and are confined to `_main_region`, the largest group of tiles connected by A* edges. Everything else is walkable-looking ground that nothing can ever reach. Measured over 10 seeds (share of the whole map): | preset | 32 | 64 | 128 | | --- | --- | --- | --- | | plains | 100 % | 100 % | 100 % | | crater | 70 % | 99 % | 100 % | | canyon | **45 %** | **47 %** | 81 % | | island | 19 % | 19 % | 19 % (of 23 % land) | The canyon is the clear case. Its walls are cliffs end to end, so the map is reliably cut in two and half of it is scenery. That is not a canyon a colony lives in; it is a wall down the middle. The crater does the same at small sizes, with the rim walling off the outside. ## Proposal - `@export_range(0.0, 1.0) var min_reachable_share: float` on `TerrainPreset`: the share of **land** tiles the main region must cover. Land rather than the whole map, so the island is not penalised for its sea. Suggested starting values: plains 0.95, crater 0.85, canyon 0.85, island 0.80. - After `_sample_levels()`, if the main region falls short, **carve ramps**. Join the largest unreached region to the main one by the cheapest route, regrading the tiles along it so each step is at most `max_step_levels`. Repeat until the threshold is met or an iteration cap is hit. The cap stops a pathological seed from spinning. - Ramps should look deliberate: a straight-ish run down a canyon wall, not a random notch. For the canyon, placing them along the wall at intervals is acceptable instead of the generic search. - This edits `_levels`, so it must run **before** `_paint_cells()` and `_build_navigation()`. It must be deterministic: no `randi()`, only values derived from `map_seed`. ### Decision needed in the implementation Regrading up (fill) versus down (cut). Cutting into a cliff keeps the high ground intact; filling makes a causeway. Either is defensible; pick one, or decide per shape. ## Acceptance criteria - [ ] `min_reachable_share` is on the preset, with a value set in each `.tres`. - [ ] For every preset at every size from #158, over 10 seeds, the main region covers at least that share of land. Before/after probe numbers go in the PR. - [ ] Unit tests: a hand-built `_levels` grid with a cliff splitting it is joined by the ramp pass, and every step along the carved route is at most `max_step_levels`. - [ ] Same seed, same map (`test_terrain_seed.gd`). - [ ] Headed screenshot of a canyon showing its ramps. ## Out of scope Player terrain manipulation (bridging, joining islands). The milestone puts that out of scope; this is the generator alone. ## Depends on #159 and #160. Terracing changes where the cliffs are, so this should be tuned after it.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
liamjd/UntitledColonyBuilder#162
No description provided.