# Procedural woodland lodges

A reusable Minecraft Java **1.21.1** generator. It composes connected room stacks, roof envelopes, circulation, extensions and landscapes from a constrained grammar. It does not execute or import any reference generator.

## Run

Use the supplied container's Python environment and MCIO installation. No downloads are needed.

```sh
python generate.py
python generate.py --seed 31 --output my_lodge.litematic
python generate.py --seed 21 --set topology=ell --set floors=2 --set wing_floors=1 --set tower=timber
python generate.py --seed 907 --config parameters.json --output custom.litematic
python sample_batch.py
python render_batch.py
python -m pytest -q test
```

Without arguments, generation writes **`output.litematic`**, one region, using seed **20260924**. The adjacent `output.json` records the seed, original overrides, resolved parameters, dimensions, volumes, connection interfaces, room purposes, furnishing coordinates and geometry signatures. Room and interface coordinates are in planning space; add the recorded `origin` to obtain schematic cell indices. Each sample has the same pair of files. Export timestamps are zero; placement and palette construction have deterministic order. Identical seed and configuration produce identical schematic bytes in this environment.

`--config` accepts an object of parameter overrides, for example:

```json
{"topology":"twin","floors":2,"wing_floors":1,"porch":"full","terrain":"terrace"}
```

The Python API exposes both planning and generation:

```python
from pathlib import Path
from generate import generate
from lodge.plan import resolve, DOMAINS, LIMITS

plan = resolve(21, {"topology": "ell", "floors": 2})
build = generate(21, {"topology": "ell", "floors": 2}, Path("lodge.litematic"))
print(build.plan.record())
print(build.validation)
```

For exact replay of an exported record, use `generate(record["seed"], record["overrides"])`. The resolved record also contains derived fields such as `wrap_side`; it is descriptive rather than an input override dictionary. If custom resource limits were used, pass `limits=record["limits"]` too. The planning and material/detail phases each use a local seeded random source. There is no unseeded randomness, random retry loop, seed-specific patch, or fallback building.

## Architectural parameters

Seeds are signed 64-bit integers, including both endpoints. Boolean seeds are rejected. Unspecified choices are sampled uniformly from the listed domains before dependent choices are resolved. Major topologies have equal initial sampling weight; towers, ridge directions, roof profiles and terrain are exercised directly.

| Parameter | Domain | Geometry or dependency |
| --- | --- | --- |
| `topology` | `single`, `ell`, `twin`, `courtyard`, `staggered` | Main stack; one side wing; two offset side wings; two forward wings; or side plus rear wing. |
| `width`, `depth` | 15/17/19; 17/19/21 | Main exterior dimensions in blocks. Both ridge directions work with each dimension. |
| `floors` | 1, 2, 3 | Full main storeys, plus a furnished vaulted attic. Floors are six blocks apart. |
| `ridge` | `x`, `z` | Main ridge direction; also changes local room and stair orientation. |
| `profile` | `chalet`, `steep`, `bell` | One-rise, two-rise, or flared lower roof with steeper upper courses. |
| `wing_size` | 9, 11, 13 | Side/rear wing width. Side depths additionally sample 11/13/15; rear depths 9/11/13. Courtyard wings have longer forward projections. |
| `wing_floors` | 1, 2 | Cannot exceed the main full-storey count. Upper wing levels have supported ladders. |
| `wing_ridge` | `parallel`, `cross` | Wing ridges relative to the main roof. |
| `placement` | `front`, `middle`, `rear` | Attachment setback. Twin wings add a two-block asymmetry. Courtyard rules replace this with forward setbacks of five or seven blocks. |
| `tower` | `none`, `stone`, `timber` | Rear tower, attached to the rear wing when one exists. Stone towers have an east lookout balcony. Timber towers have steeper hipped caps. |
| `tower_extra`, `tower_width` | 1/2; 9/11 | Tower storeys above the main full-storey count, capped at five; square tower width. |
| `conservatory` | `false`, `true` | Glazed hipped winter garden on the exposed east interface, with planting/work furnishings. Width samples 7/9; depth fits its host. |
| `porch` | `entry`, `full`, `wrap` | Seven-block entrance canopy, full front canopy, or front plus side gallery. A wrap needs a free side. |
| `balcony` | `false`, `true` | Supported front balcony with a complete upper door; requires at least two full main storeys. |
| `dormers` | 0, 1, 2 | Cross-gabled, accessible attic reading bays, on opposing roof slopes. |
| `terrain` | `garden`, `terrace`, `cliff` | Occupied base height 4, 7 or 16; connected foundations, retaining work and approach length respond. |
| `approach` | `straight`, `landing` | Five-block-wide stair ascent, optionally interrupted by a three-block landing. |
| `entrance` | `center`, `left`, `right` | Door and approach offset, including balcony alignment. |
| `layout` | `open`, `cross`, `suites` | Open living floors, transverse room divisions with arches, or deeper front rooms with upper privacy doors. |
| `stair_side` | `left`, `right` | Two-wide main stair position, side aisles and return landings. |
| `palette` | `honey`, `ivory`, `ochre` | Harmonized plaster, timber, floor, glazing and textile families. |
| `trees` | 3, 4, 5 | Reserved peripheral conifer sites, plus seeded understory. |

Dependencies are implemented in `lodge/plan.py`. Invalid explicit combinations raise `ValueError` with the conflicting parameter and allowed alternatives. The built-in sampler resolves the same constraints without retrying. For example, it narrows wing heights after choosing main height, removes balcony availability for one-storey cottages, and selects a free interface for wraparound galleries. Two side wings rule out a wrap. If an ell, a conservatory and a wrap are requested together, the side wing is placed on the east to preserve the west gallery.

Inactive parameters remain in the uniform record schema: wing settings do not change a building without wings; tower settings do not change a building without a tower. They are not counted as structural variation. Random wing handedness, individual lengths, setbacks and tree heights are visible in the resolved volumes/sites. No total design-space size is calculated.

Default resource caps are horizontal axes **112**, height **96**, and **900,000 cells**. Bounds are derived before placement from the selected masses, roofs, chimney, trees, gardens and approach, then checked against the caps. The Python `limits` argument can change positive resource caps and the tree-height interval within 10..32; the default tree interval is 15..24. The six-block storey module is fixed. Nothing is silently clipped.

## Design and reference use

All eight supplied source snapshots and original images informed the design. They are historical reference material, not runtime dependencies or selected building presets.

| Reference | Reachable contribution |
| --- | --- |
| ref-1 | Tall stacked living volumes, strongly pitched roof, attic bays, low entrance canopy and vertical timber rhythm. |
| ref-2 | Broad compound lodge, crossing ridges, offset wings, long porch, domestic room organization. |
| ref-3 | Compact hearth house, projecting porch/gallery, stone chimney and connected working rooms. |
| ref-4 | Masonry watchtower, upper lookout deck, timber tower cap and terraced approach. |
| ref-5 | Elevated crag setting, continuous supported ascent, retaining ledges and planted rock base. |
| ref-6 | Courtyard and staggered inn compositions, multiple roof heights, functional wings and rear towers. |
| ref-7 | Attached glass winter garden, sealed hipped glazing and planted workroom. |
| ref-8 | Tall central gable, lower flanking wings, heraldic cloth, generous approach and upper guest accommodation. |

The shared vocabulary is restrained cream or ivory infill, structural timber belts and posts, thick dark slate roofs, masonry foundations, supported warm lanterns and evergreen planting. Cross-gables are unions of envelopes: a low roof cannot replace a higher room wall or cut through an occupied volume. Separate stair, doorway, window and furniture reservations prevent later decoration from occupying required space. Glazing is installed after stairs, chimneys and porches so clear circulation space can still receive windows; actual structures decide which openings fit.

`generate.py` is the public entry point. `lodge/plan.py` makes dimensioned architectural decisions. `lodge/geometry.py` realizes terrain, envelopes, interfaces, circulation, furnishings and vegetation. `lodge/validation.py` checks final blocks. `blocks.py` retains the provided bounded placement and deterministic MCIO export/reload helpers. New attachment rules can add volumes/interfaces without adding another complete building script.

Main floors use actual supported two-wide stairs with three clear blocks above their treads. Wing and tower ladders have solid backing through their served levels. Room purposes include cooking/dining, parlours, workrooms, libraries, sleeping rooms, tower storage/map rooms and greenhouse work. Furnishing density is bounded; bed access, stair returns and dormer approaches remain open. Window glass and both sides of every opening are checked after furnishing.

## Validation and artifacts

Run `python -m pytest -q test`. The suite covers **104 seeds** (0..99, signed seed endpoints, the default, and 20260923), **eight targeted configurations**, byte determinism, semantic round trips, resource/parameter rejection and a clean-directory CLI invocation. It checks final geometry, not just declared room edges:

- Vanilla block names, explicit property domains and export bounds.
- Door/bed pairs, ladder backing, lantern/plant attachment, stair supports, foundations and clear openings.
- Exterior-to-room traversal with two-cell body clearance, oriented stair ascent/descent, operable doors and ladders; every usable interior floor cell is checked, including dormer bays.
- Room lighting near the floor, sleeping furniture with access, and actual cooking/crafting equipment in kitchens.
- Exterior-air flood against the closed envelope. Slate stairs/slabs, fences, plants and other porous features do not count as full roof seals.
- Deliberately broken doors, beds, stair headroom, ladder support, windows, entrances and roofs must be rejected.

Round-trip comparisons use `blockstates_equivalent`, comparing parsed names and property mappings rather than property order. Several exported/reloaded scenes repeat the physical validation. Temporary test files and render-cut schematics live beneath `test/` and are removed automatically.

The 40-seed structural audit observes **40 distinct final geometry signatures** and covers every major branch. Signatures use actual roof occupancy, floor support and room obstruction coordinates, with material noise collapsed. The delivered **11 samples** have **11 distinct observed geometry signatures**. These are finite observed results, not exhaustive coverage or a proof over every possible seed.

[`samples/manifest.json`](samples/manifest.json) records exact replay inputs, resolved choices, validation results and file digests. `python sample_batch.py` rebuilds that batch. The examples mix features across the reference family: cliff courtyards, conservatories on tower cottages, staggered watchtower inns, small woodland cottages and tall flanked lodges.

[`previews/index.html`](previews/index.html) is the labelled gallery. `python render_batch.py` produces front/rear views for every sample and ground-floor/stair cutaways for seven representative samples. Source paths, seeds and architectural labels are in the manifest/gallery. The images render the actual schematics; cutaways are inspection views, not additional playable outputs.

## Practical limits

Validation is bounded and repeatable, not exhaustive. The traversal model conservatively treats two-block air/door/ladder columns as usable and explicitly checks stair directions; it is not a running Minecraft server or full player collision simulator. Shader lighting, smoke particles and block-entity rendering are outside the supplied renderer. Furnishings use vanilla block states; container inventories, lectern books and custom banner NBT are not populated.

The grammar uses orthogonal rectangular volumes, fixed-height floors, straight interior flights and straight or landing-interrupted outdoor ascents. It does not generate curved walls, spiral stairs or cliff switchbacks. Main attics are vaulted rooms; tower heights and roof profiles stay within the bounded lodge scale. Ground-level interfaces connect wings; independent ladders serve their upper floors. These are implemented scope limits, not unfinished export or validation work.
