← Back to Gallery

Loading 3D viewer…

Hanseatic Speicher warehouse (indexed)

by Jorge Barbero

Dimensions
96×64×96
Blocks
162,295
Compute Time
7.7s
Generation Time
5m 6s
Model
claude-opus-5
Created
August 23, 2026
hanseaticwarehousebrickautoevalindexedlayered
Prompt

User Prompt

a Hanseatic canal-side brick warehouse (Speicher) in a Baltic old town: tall narrow four-storey dark red brick building with a stepped crow gable facing the water, a projecting timber hoist beam and winch at the top gable, rows of small shuttered loading hatches stacked vertically, a stone quay with mooring bollards below, and an interior of timber floors, stacked crates and barrels, with a wooden staircase connecting the levels

Enhanced Prompt

indexed condition — prepare_build + search_docs({action:"related"}) graph routing -> Timber Framing (arch §4), Stepped Setbacks (arch §8), Deliberate Asymmetry, Gable ridge cap (solid, never top-slab), Fill gable triangles (pitfall 13), placeGableRoof helpers, Roof overhang support (§22), LAYERED masks workflow (§14), facade to +Z (§15). LAYERED process: placeholder wool masses -> clearMasked hollow/carve -> replaceMasked texture last.

Photos

From the canal
From the canalexterior
Warehouse row
Warehouse rowexterior
Weighing hall
Weighing hallinterior
Turret stairwell
Turret stairwellinterior
Cloth store
Cloth storeinterior
CraftScript Source
// === BUILD PLAN ===
// Style: Hanseatic Backsteingotik terrace (Lubeck/Gdansk Speicher row)
// Process: LAYERED + MASKS (build-rules 14) — solid placeholder wool masses, hollow and
//          carve with clearMasked(onlyMaterial), texture LAST with replaceMasked.
// Footprint: DELIBERATELY ASYMMETRIC composite (arch-guide 4: no perfect symmetry) =
//   A) tall main Speicher  X30..46 (17w) Z22..44 (23d), 4 storeys, crest Y45
//   B) lower neighbour     X48..58 (11w) Z28..44 (17d), 3 storeys, crest Y36   <- STEPPED SETBACK
//   C) stair turret        X22..29 (8w)  Z30..38 (9d),  full height, own gable  <- bump-out
//   + gangway bridge over the 1-block alley at x=47, quay + canal on +Z (rule 15).
//
// GROUND FLOOR (top-down, 1 char = 1 block, Z down = toward canal):
//   Z22   ##########NNNN#########        N = rear crow gable
//   Z30   ####TTTT##..........####       T = stair turret (placeStairwell U-turn)
//   Z34   #TTT>>D...............#####    D = turret door into store, > = flight
//   Z36   ####..........o.......#=#B##   o = internal door to neighbour, = alley
//   Z44   ######GGGGGG####------dd###    G = cargo gate, d = neighbour door
//   Z46..Z62 quay + bollards ; Z63+ canal
//
// FRONT ELEVATION (z=44) — crow steps + timber hoist ERKER (Ladeluke):
//        ___                     the erker projects z44->z47 and carries the beam,
//     __|EEE|__                  so the overhang is SUPPORTED, not floating (rule 22)
//   _|   |h|   |_    h = hatch
//  |     |h|     |
//  |  GGGGGG     |
//
// MATERIALS PLAN (part -> palette -> WHY):
//   plinth  : stone_bricks/andesite/mossy         — WHY: tide-line stone, reads wet & heavy
//   walls   : gradientPalette stone_bricks->bricks->granite->red_terracotta, noise .35
//             — WHY: value ramp fakes shadow at the base and sun at the crest (volume, not confetti)
//   roof    : oxidized/weathered/exposed COPPER stairs
//             — WHY: green-blue patina is the true Hanseatic roof and is the COMPLEMENT of red
//               brick; a red roof on red walls would read monochrome
//   timber  : dark_oak_log frame + spruce_planks infill on the erker/gangway — warm accent
//   ridge   : SOLID deepslate_bricks beam placed AFTER every clear — WHY: ridge_gap is the
//             classic failure and a top-slab ridge leaves a sky slot
// Rooms: A-F1 weighing hall / A-F2 barrel store / A-F3 cloth store / A-F4 grain loft
//        B-F1 chandler's shop / B-F2+B-F3 stores / C = stairwell with landings
// STAIR PLAN: ALL vertical circulation lives in turret C -> placeStairwell(24,32,...) U-turns
//   12->17, 18->23, 24->29. Nothing else is ever placed in x23..29 / z31..38.
// === END PLAN ===

var CK = [];
function ck(m) { CK.push(m); }
ck('PLAN');

// ---------- Y levels ----------
var GY = 10, waterY = 9;
var yF = [11, 17, 23, 29];              // floor slab Y per storey
var yW = [12, 18, 24, 30];              // walk Y per storey
var aTop = 34, aRoof = 35;              // main: wall top / roof base  -> ridge 43, crest 45
var bTop = 28, bRoof = 29;              // neighbour: wall top / roof base -> ridge 34, crest 36
var cTop = 34, cRoof = 35;              // turret

var AX1 = 30, AX2 = 46, AZ1 = 22, AZ2 = 44, ACX = 38;
var BX1 = 48, BX2 = 58, BZ1 = 28, BZ2 = 44, BCX = 53;
var CX1 = 22, CX2 = 29, CZ1 = 30, CZ2 = 38;

var PH = 'blue_wool';                    // wall placeholder

// ---------- palettes (applied LAST) ----------
var wallPal = gradientPalette(11, aTop, [
  { block: 'stone_bricks', from: 0 },
  { block: 'bricks', from: 0.10 },
  { block: 'granite', from: 0.55 },
  { block: 'red_terracotta', from: 0.88 }
], { noise: 0.35, seed: 17 });

var plinthPal = noisePalette([
  { block: 'stone_bricks', weight: 34 },
  { block: 'andesite', weight: 26 },
  { block: 'mossy_stone_bricks', weight: 22 },
  { block: 'cracked_stone_bricks', weight: 18 }
], { seed: 6, freq: 0.14 });

var roofPal = noisePalette([
  { block: 'oxidized_copper_stairs', weight: 46 },
  { block: 'weathered_copper_stairs', weight: 34 },
  { block: 'exposed_copper_stairs', weight: 20 }
], { seed: 23, freq: 0.15 });

var floorPal = noisePalette([
  { block: 'spruce_planks', weight: 50 },
  { block: 'dark_oak_planks', weight: 30 },
  { block: 'stripped_spruce_wood', weight: 20 }
], { seed: 31, freq: 0.19 });

var quayPal = noisePalette([
  { block: 'stone_bricks', weight: 30 },
  { block: 'cobblestone', weight: 26 },
  { block: 'andesite', weight: 24 },
  { block: 'mossy_cobblestone', weight: 20 }
], { seed: 44, freq: 0.12 });

// ---------- TERRAIN ----------
var hh = hills({ base: GY, amp: 3, scale: 0.05, seed: 11 });
var padFn = flatten(hh, { x0: 14, z0: 14, x1: 68, z1: 62 }, GY, 8);
var landMask = blob(44, 38, 46, { irregularity: 0.38, seed: 21 });
var gmat = patches([
  { block: 'grass_block', w: 66 },
  { block: 'gravel', w: 18 },
  { block: 'coarse_dirt', w: 16 }
], 0.05, 7);
surface(landMask, padFn, gmat, { sub: 'dirt', deep: 'stone', depth: 4 });
ck('TERRAIN');

// ---------- CANAL + STEPPED QUAY ----------
fill(2, 4, 63, 94, 24, 94, 'air');
fill(2, 5, 63, 94, 6, 94, 'gravel');
fill(2, 7, 63, 94, waterY, 94, 'water');
fill(10, 6, 46, 74, GY, 62, quayPal);
fill(10, 6, 62, 74, GY, 62, 'stone_bricks');
// slipway steps down into the water (asymmetric, on the east side)
var sstep;
for (sstep = 0; sstep < 4; sstep++) {
  fill(60, GY - sstep, 62 + sstep, 66, GY - sstep, 62 + sstep, 'stone_brick_stairs[facing=south,half=top]');
}
// mooring bollards + iron rings
var bolls = [32, 38, 44, 52, 58, 26];
var bi;
for (bi = 0; bi < bolls.length; bi++) {
  pb(bolls[bi], GY + 1, 60, 'stripped_dark_oak_log');
  ps(bolls[bi], GY + 2, 60, 'dark_oak_slab[type=bottom]');
  ps(bolls[bi], GY + 1, 61, 'iron_trapdoor[facing=north,half=bottom,open=true]');
}
ck('QUAY');

// ---------- LAYER 1: SOLID PLACEHOLDER MASSES ----------
fill(AX1, 11, AZ1, AX2, aTop, AZ2, PH);
fill(BX1, 11, BZ1, BX2, bTop, BZ2, PH);
fill(CX1, 11, CZ1, CX2, cTop, CZ2, PH);
ck('MASS');

// ---------- LAYER 2: HOLLOW BY PART (masks — never touches neighbours) ----------
var si;
for (si = 0; si < 4; si++) {
  var top = (si === 3) ? aTop : (yF[si + 1] - 1);
  clearMasked(AX1 + 1, yW[si], AZ1 + 1, AX2 - 1, top, AZ2 - 1, onlyMaterial(PH));
}
for (si = 0; si < 3; si++) {
  var btop = (si === 2) ? bTop : (yF[si + 1] - 1);
  clearMasked(BX1 + 1, yW[si], BZ1 + 1, BX2 - 1, btop, BZ2 - 1, onlyMaterial(PH));
}
for (si = 0; si < 4; si++) {
  var ctop = (si === 3) ? cTop : (yF[si + 1] - 1);
  clearMasked(CX1 + 1, yW[si], CZ1 + 1, CX2 - 1, ctop, CZ2 - 1, onlyMaterial(PH));
}
ck('HOLLOW');

// ---------- LAYER 3: CARVE OPENINGS (only the wall material is cut) ----------
// main cargo gate (off-centre, asymmetry)
clearMasked(35, 12, AZ2, 40, 15, AZ2, onlyMaterial(PH));
// stacked loading hatches on the crow-gable front, one per upper storey
var hi;
for (hi = 1; hi < 4; hi++) {
  clearMasked(37, yW[hi], AZ2, 39, yW[hi] + 1, AZ2, onlyMaterial(PH));
}
// hoist opening in the gable itself (the erker will plug it)
clearMasked(37, 40, AZ2, 39, 42, AZ2, onlyMaterial(PH));
// main long-wall windows — WEST only where the turret is not, EAST all the way (asymmetric)
var wz, wi2;
for (wi2 = 0; wi2 < 4; wi2++) {
  var wy = yW[wi2] + 1;
  var eastZ = [25, 29, 33, 37, 41];
  for (wz = 0; wz < eastZ.length; wz++) {
    clearMasked(AX2, wy, eastZ[wz], AX2, wy + 1, eastZ[wz], onlyMaterial(PH));
  }
  clearMasked(AX1, wy, 25, AX1, wy + 1, 25, onlyMaterial(PH));
  clearMasked(AX1, wy, 41, AX1, wy + 1, 41, onlyMaterial(PH));
}
// rear gable-end slit windows
clearMasked(34, 25, AZ1, 34, 26, AZ1, onlyMaterial(PH));
clearMasked(42, 25, AZ1, 42, 26, AZ1, onlyMaterial(PH));
// turret <-> main doorways at every level, plus turret windows
for (wi2 = 0; wi2 < 4; wi2++) {
  clearMasked(CX2, yW[wi2], 34, AX1, yW[wi2] + 1, 34, onlyMaterial(PH));
  clearMasked(CX1, yW[wi2] + 1, 33, CX1, yW[wi2] + 2, 33, onlyMaterial(PH));
}
// turret ground door to the lane
clearMasked(25, 12, CZ2, 26, 13, CZ2, onlyMaterial(PH));
// neighbour: shop door + windows + internal connection to the main store
clearMasked(52, 12, BZ2, 53, 13, BZ2, onlyMaterial(PH));
for (wi2 = 0; wi2 < 3; wi2++) {
  var by2 = yW[wi2] + 1;
  clearMasked(BX2, by2, 32, BX2, by2 + 1, 32, onlyMaterial(PH));
  clearMasked(BX2, by2, 38, BX2, by2 + 1, 38, onlyMaterial(PH));
  clearMasked(50, by2, BZ2, 50, by2 + 1, BZ2, onlyMaterial(PH));
  clearMasked(56, by2, BZ2, 56, by2 + 1, BZ2, onlyMaterial(PH));
}
clearMasked(AX2, 12, 36, BX1, 13, 36, onlyMaterial(PH));
// gangway over the alley at storey 2
clearMasked(AX2, 18, 39, BX1, 19, 39, onlyMaterial(PH));
ck('CARVE');

// ---------- LAYER 4: TEXTURE LAST ----------
// plinth band first (3 rows), then everything else that is still placeholder
replaceMasked(CX1 - 1, 11, AZ1 - 1, BX2 + 1, 13, BZ2 + 1, plinthPal, onlyMaterial(PH));
// timber floors + ground slab (they are still placeholder slabs inside the mass)
replaceMasked(AX1 + 1, 11, AZ1 + 1, AX2 - 1, 11, AZ2 - 1, plinthPal, onlyMaterial(PH));
replaceMasked(BX1 + 1, 11, BZ1 + 1, BX2 - 1, 11, BZ2 - 1, plinthPal, onlyMaterial(PH));
var fi;
for (fi = 1; fi < 4; fi++) {
  replaceMasked(AX1 + 1, yF[fi], AZ1 + 1, AX2 - 1, yF[fi], AZ2 - 1, floorPal, onlyMaterial(PH));
  replaceMasked(CX1 + 1, yF[fi], CZ1 + 1, CX2 - 1, yF[fi], CZ2 - 1, floorPal, onlyMaterial(PH));
}
for (fi = 1; fi < 3; fi++) {
  replaceMasked(BX1 + 1, yF[fi], BZ1 + 1, BX2 - 1, yF[fi], BZ2 - 1, floorPal, onlyMaterial(PH));
}
// all remaining placeholder = brickwork
replaceMasked(CX1 - 1, 11, AZ1 - 1, BX2 + 1, aTop + 1, BZ2 + 1, wallPal, onlyMaterial(PH));
ck('TEXTURE');

// ---------- WALL DEPTH: lesenes, blind arcading, cornices (built in final material) ----------
var lz2, lx2;
for (lz2 = 25; lz2 <= 41; lz2 += 4) {
  fill(AX2 + 1, 11, lz2, AX2 + 1, aTop - 1, lz2 + 1, wallPal);
  ps(AX2 + 1, aTop, lz2, 'brick_stairs[facing=west,half=top]');
  ps(AX2 + 1, aTop, lz2 + 1, 'brick_stairs[facing=west,half=top]');
}
for (lz2 = 23; lz2 <= 27; lz2 += 4) {
  fill(AX1 - 1, 11, lz2, AX1 - 1, aTop - 1, lz2 + 1, wallPal);
}
for (lz2 = 39; lz2 <= 43; lz2 += 4) {
  fill(AX1 - 1, 11, lz2, AX1 - 1, aTop - 1, lz2 + 1, wallPal);
}
for (lz2 = 31; lz2 <= 41; lz2 += 5) {
  fill(BX2 + 1, 11, lz2, BX2 + 1, bTop - 1, lz2 + 1, wallPal);
}
// dogtooth string-courses at each floor line (both blocks read as shadow lines)
var bandYs = [16, 22, 28];
var bj2, cz2;
for (bj2 = 0; bj2 < bandYs.length; bj2++) {
  for (cz2 = AZ1; cz2 <= AZ2; cz2++) {
    if (cz2 % 2 === 1) {
      ps(AX1 - 1, bandYs[bj2], cz2, 'brick_slab[type=top]');
      ps(AX2 + 1, bandYs[bj2], cz2, 'brick_slab[type=top]');
    }
  }
  for (lx2 = AX1; lx2 <= AX2; lx2++) {
    if (lx2 % 2 === 1) {
      ps(lx2, bandYs[bj2], AZ2 + 1, 'brick_slab[type=top]');
      ps(lx2, bandYs[bj2], AZ1 - 1, 'brick_slab[type=top]');
    }
  }
}
for (cz2 = BZ1; cz2 <= BZ2; cz2++) {
  if (cz2 % 2 === 1) { ps(BX2 + 1, 22, cz2, 'brick_slab[type=top]'); ps(BX2 + 1, 16, cz2, 'brick_slab[type=top]'); }
}
// eave corbels (rule 22 — the overhang must be supported)
for (cz2 = AZ1 + 1; cz2 <= AZ2 - 1; cz2++) {
  ps(AX1 - 1, aTop, cz2, 'brick_slab[type=top]');
  ps(AX2 + 1, aTop, cz2, 'brick_slab[type=top]');
}
for (cz2 = BZ1 + 1; cz2 <= BZ2 - 1; cz2++) {
  ps(BX1 - 1, bTop, cz2, 'brick_slab[type=top]');
  ps(BX2 + 1, bTop, cz2, 'brick_slab[type=top]');
}
ck('RELIEF');

// ---------- ROOFS (direct, palette fed per stair so facing survives) ----------
placeGableRoof(AX1, AX2, AZ1 + 1, AZ2 - 1, aRoof, 'oxidized_copper_stairs', 'oxidized_copper_slab', 'bricks');
var rz2, rs;
for (rz2 = AZ1 + 1; rz2 <= AZ2 - 1; rz2++) {
  for (rs = 0; rs < 9; rs++) {
    roofStair(AX1 - 1 + rs, aRoof + rs, rz2, roofPal(AX1 - 1 + rs, 0, rz2), 'west');
    roofStair(AX2 + 1 - rs, aRoof + rs, rz2, roofPal(AX2 + 1 - rs, 0, rz2), 'east');
  }
}
placeGableRoof(BX1, BX2, BZ1 + 1, BZ2 - 1, bRoof, 'weathered_copper_stairs', 'weathered_copper_slab', 'bricks');
for (rz2 = BZ1 + 1; rz2 <= BZ2 - 1; rz2++) {
  for (rs = 0; rs < 6; rs++) {
    roofStair(BX1 - 1 + rs, bRoof + rs, rz2, roofPal(BX1 - 1 + rs, 0, rz2), 'west');
    roofStair(BX2 + 1 - rs, bRoof + rs, rz2, roofPal(BX2 + 1 - rs, 0, rz2), 'east');
  }
}
placeGableRoof(CX1, CX2, CZ1 + 1, CZ2 - 1, cRoof, 'weathered_copper_stairs', 'weathered_copper_slab', 'bricks');
for (rz2 = CZ1 + 1; rz2 <= CZ2 - 1; rz2++) {
  for (rs = 0; rs < 4; rs++) {
    roofStair(CX1 - 1 + rs, cRoof + rs, rz2, roofPal(CX1 - 1 + rs, 0, rz2), 'west');
    roofStair(CX2 + 1 - rs, cRoof + rs, rz2, roofPal(CX2 + 1 - rs, 0, rz2), 'east');
  }
}
ck('ROOF');

// ---------- ATTIC CLEAR (step-by-step so the slopes survive) ----------
var sa;
for (sa = 0; sa < 8; sa++) { fill(AX1 + sa, aRoof + sa, AZ1 + 1, AX2 - sa, aRoof + sa, AZ2 - 1, 'air'); }
for (sa = 0; sa < 5; sa++) { fill(BX1 + sa, bRoof + sa, BZ1 + 1, BX2 - sa, bRoof + sa, BZ2 - 1, 'air'); }
for (sa = 0; sa < 3; sa++) { fill(CX1 + sa, cRoof + sa, CZ1 + 1, CX2 - sa, cRoof + sa, CZ2 - 1, 'air'); }
// SOLID ridge beams — placed AFTER every clear so nothing can re-open a ridge_gap
fill(ACX, aRoof + 8, AZ1, ACX, aRoof + 8, AZ2, 'deepslate_bricks');
fill(BCX, bRoof + 5, BZ1, BCX, bRoof + 5, BZ2, 'deepslate_bricks');
fill(25, cRoof + 3, CZ1, 26, cRoof + 3, CZ2, 'deepslate_bricks');
ck('RIDGE');

// ---------- CROW-STEPPED GABLES ----------
function crow(x1, x2, cxc, zp, crest, baseY) {
  var gx, d, st, ty;
  for (gx = x1; gx <= x2; gx++) {
    d = Math.abs(gx - cxc);
    st = Math.floor(d / 2);
    ty = crest - 2 * st;
    if (ty < baseY) { ty = baseY; }
    fill(gx, baseY, zp, gx, ty, zp, wallPal);
    ps(gx, ty + 1, zp, 'stone_brick_slab[type=bottom]');
  }
}
crow(AX1, AX2, ACX, AZ2, 45, aRoof);
crow(AX1, AX2, ACX, AZ1, 45, aRoof);
crow(BX1, BX2, BCX, BZ2, 36, bRoof);
crow(BX1, BX2, BCX, BZ1, 36, bRoof);
crow(CX1, CX2, 25, CZ2, 38, cRoof);
crow(CX1, CX2, 25, CZ1, 38, cRoof);
// blind pointed niches in the main gable (Backsteingotik), asymmetric heights
var nn = [34, 36, 40, 42];
var nh2 = [39, 42, 42, 39];
var ni2;
for (ni2 = 0; ni2 < nn.length; ni2++) {
  fill(nn[ni2], aRoof + 1, AZ2, nn[ni2], nh2[ni2], AZ2, 'red_nether_bricks');
  ps(nn[ni2], nh2[ni2] + 1, AZ2, 'brick_stairs[facing=north,half=top]');
}
// re-cut the hoist opening (the crow fill closed it)
fill(37, 40, AZ2, 39, 42, AZ2, 'air');
ck('GABLES');

// ---------- GLAZING + SHUTTERS ----------
var gz2;
for (wi2 = 0; wi2 < 4; wi2++) {
  var gy = yW[wi2] + 1;
  var ez2 = [25, 29, 33, 37, 41];
  for (gz2 = 0; gz2 < ez2.length; gz2++) {
    fillMasked(AX2, gy, ez2[gz2], AX2, gy + 1, ez2[gz2], 'glass_pane', onlyAir());
    ps(AX2 + 2, gy, ez2[gz2], 'spruce_trapdoor[facing=west,half=bottom,open=true]');
  }
  fillMasked(AX1, gy, 25, AX1, gy + 1, 25, 'glass_pane', onlyAir());
  fillMasked(AX1, gy, 41, AX1, gy + 1, 41, 'glass_pane', onlyAir());
  ps(AX1 - 2, gy, 25, 'spruce_trapdoor[facing=east,half=bottom,open=true]');
  ps(AX1 - 2, gy, 41, 'spruce_trapdoor[facing=east,half=bottom,open=true]');
  fillMasked(CX1, gy + 1, 33, CX1, gy + 2, 33, 'glass_pane', onlyAir());
}
for (wi2 = 0; wi2 < 3; wi2++) {
  var by3 = yW[wi2] + 1;
  fillMasked(BX2, by3, 32, BX2, by3 + 1, 32, 'glass_pane', onlyAir());
  fillMasked(BX2, by3, 38, BX2, by3 + 1, 38, 'glass_pane', onlyAir());
  fillMasked(50, by3, BZ2, 50, by3 + 1, BZ2, 'glass_pane', onlyAir());
  fillMasked(56, by3, BZ2, 56, by3 + 1, BZ2, 'glass_pane', onlyAir());
}
// hatch shutters, hinged open on the facade
for (hi = 1; hi < 4; hi++) {
  ps(36, yW[hi], AZ2, 'dark_oak_trapdoor[facing=east,half=bottom,open=true]');
  ps(40, yW[hi], AZ2, 'dark_oak_trapdoor[facing=west,half=bottom,open=true]');
  ps(38, yW[hi] - 1, AZ2 + 1, 'spruce_slab[type=top]');
  ps(37, yW[hi] - 1, AZ2 + 1, 'spruce_slab[type=top]');
  ps(39, yW[hi] - 1, AZ2 + 1, 'spruce_slab[type=top]');
}
// doors
ps(35, 12, AZ2, 'dark_oak_door[facing=south,half=lower,hinge=left]');
ps(35, 13, AZ2, 'dark_oak_door[facing=south,half=upper,hinge=left]');
ps(40, 12, AZ2, 'dark_oak_door[facing=south,half=lower,hinge=right]');
ps(40, 13, AZ2, 'dark_oak_door[facing=south,half=upper,hinge=right]');
ps(52, 12, BZ2, 'spruce_door[facing=south,half=lower,hinge=left]');
ps(52, 13, BZ2, 'spruce_door[facing=south,half=upper,hinge=left]');
ps(25, 12, CZ2, 'spruce_door[facing=south,half=lower,hinge=left]');
ps(25, 13, CZ2, 'spruce_door[facing=south,half=upper,hinge=left]');
// stone gate arch surround
ps(34, 12, AZ2, 'stone_bricks'); ps(34, 13, AZ2, 'stone_bricks'); ps(34, 14, AZ2, 'stone_bricks');
ps(41, 12, AZ2, 'stone_bricks'); ps(41, 13, AZ2, 'stone_bricks'); ps(41, 14, AZ2, 'stone_bricks');
ps(35, 16, AZ2, 'stone_brick_stairs[facing=east,half=bottom]');
ps(40, 16, AZ2, 'stone_brick_stairs[facing=west,half=bottom]');
fill(36, 16, AZ2, 39, 16, AZ2, 'stone_bricks');
ck('OPENINGS');

// ---------- STAIRS: all circulation in the turret (U-turn stairwells) ----------
placeStairwell(24, 32, yW[0], yF[1], 'spruce_stairs', 'spruce_fence', 'spruce_planks', 'south');
placeStairwell(24, 32, yW[1], yF[2], 'spruce_stairs', 'spruce_fence', 'spruce_planks', 'south');
placeStairwell(24, 32, yW[2], yF[3], 'spruce_stairs', 'spruce_fence', 'spruce_planks', 'south');
ck('STAIRS');

// ---------- INTERIORS ----------
function crate2(x, y, z, n) {
  var k;
  for (k = 0; k < n; k++) { pb(x, y + k, z, 'barrel[facing=up]'); }
}
function bale(x, y, z, col) {
  pb(x, y, z, col); pb(x + 1, y, z, col); pb(x, y, z + 1, col);
  pb(x, y + 1, z, 'hay_block[axis=y]');
}
function lamp(x, y, z) { ps(x, y, z, 'lantern[hanging=true]'); }

// A-F1 weighing hall
rug(36, yW[0], 38, 5, 4, 'red', 'brown');
ps(38, yW[0], 41, 'anvil[facing=north]');
pb(37, yW[0], 41, 'stripped_spruce_log'); ps(37, yW[0] + 1, 41, 'spruce_slab[type=bottom]');
ps(34, yW[0], 40, 'lectern[facing=east]');
chairStair(35, yW[0], 40, 'spruce_stairs', 'west');
pb(33, yW[0], 40, 'barrel[facing=up]');
crate2(44, yW[0], 41, 2); crate2(45, yW[0], 41, 1); crate2(44, yW[0], 39, 2);
crate2(32, yW[0], 27, 2); crate2(33, yW[0], 27, 1);
pb(45, yW[0], 35, 'chest[facing=west]'); pb(45, yW[0], 34, 'chest[facing=west]');
bale(42, yW[0], 25, 'brown_wool');
ps(44, yW[0], 30, 'cartography_table'); pb(45, yW[0], 30, 'composter');
lamp(38, 16, 36); lamp(43, 16, 40); lamp(33, 16, 32); lamp(40, 16, 26);

// A-F2 barrel store
crate2(32, yW[1], 25, 3); crate2(33, yW[1], 25, 2); crate2(32, yW[1], 26, 2);
crate2(44, yW[1], 25, 3); crate2(45, yW[1], 25, 2);
crate2(44, yW[1], 40, 2); crate2(45, yW[1], 40, 3); crate2(44, yW[1], 41, 1);
crate2(32, yW[1], 41, 2);
bale(36, yW[1], 27, 'brown_wool'); bale(40, yW[1], 30, 'brown_wool');
rug(36, yW[1], 35, 4, 4, 'orange', 'brown');
ps(38, yW[1], 41, 'smithing_table'); pb(37, yW[1], 41, 'barrel[facing=up]');
lamp(38, 22, 33); lamp(43, 22, 38); lamp(33, 22, 29);

// A-F3 cloth store
bale(33, yW[2], 25, 'white_wool'); bale(36, yW[2], 25, 'light_blue_wool');
bale(40, yW[2], 25, 'red_wool'); bale(43, yW[2], 25, 'green_wool');
bale(33, yW[2], 39, 'yellow_wool'); bale(43, yW[2], 39, 'purple_wool');
shelfWall(41, yW[2], 42, 'west', 5, 2);
ps(38, yW[2], 41, 'lectern[facing=south]');
chairStair(38, yW[2], 40, 'dark_oak_stairs', 'south');
pb(36, yW[2], 41, 'chest[facing=south]'); pb(35, yW[2], 41, 'barrel[facing=up]');
rug(36, yW[2], 33, 5, 5, 'blue', 'white');
ps(44, yW[2], 33, 'flower_pot'); ps(33, yW[2], 33, 'potted_fern');
lamp(38, 28, 30); lamp(38, 28, 38); lamp(43, 28, 35);

// A-F4 grain loft + hoist gear
bale(34, yW[3], 25, 'brown_wool'); bale(41, yW[3], 25, 'brown_wool');
bale(34, yW[3], 31, 'brown_wool'); bale(43, yW[3], 33, 'brown_wool');
crate2(44, yW[3], 26, 2); crate2(32, yW[3], 37, 2);
fill(37, aTop - 1, 40, 39, aTop - 1, 40, 'stripped_spruce_log[axis=x]');
ps(37, aTop - 2, 40, 'spruce_fence'); ps(39, aTop - 2, 40, 'spruce_fence');
pb(38, aTop - 2, 40, 'stripped_spruce_log[axis=x]');
pb(38, yW[3], 39, 'barrel[facing=up]');
placeBed(33, yW[3], 42, 'red', 'north');
pb(32, yW[3], 42, 'spruce_fence'); pb(32, yW[3] + 1, 42, 'oak_pressure_plate');
ps(32, yW[3] + 2, 42, 'lantern[hanging=false]');
ps(35, yW[3], 36, 'crafting_table'); pb(34, yW[3], 36, 'chest[facing=south]');
rug(37, yW[3], 33, 4, 3, 'gray', 'brown');
lamp(38, 33, 31); lamp(42, 33, 38);

// B (neighbour) — chandler's shop + stores
rug(50, yW[0], 39, 5, 4, 'green', 'brown');
fill(50, yW[0], 42, 53, yW[0], 42, 'dark_oak_fence');
fill(50, yW[0] + 1, 42, 53, yW[0] + 1, 42, 'dark_oak_pressure_plate');
pb(54, yW[0], 42, 'barrel[facing=up]');
shelfWall(50, yW[0], 30, 'east', 5, 2);
chairStair(52, yW[0], 40, 'dark_oak_stairs', 'north');
ps(55, yW[0], 41, 'lectern[facing=west]');
pb(56, yW[0], 36, 'chest[facing=west]'); crate2(56, yW[0], 34, 2);
ps(51, yW[0], 34, 'cauldron'); pb(52, yW[0], 34, 'composter');
lamp(53, 16, 38); lamp(53, 16, 32);
crate2(50, yW[1], 31, 3); crate2(51, yW[1], 31, 2); crate2(56, yW[1], 31, 2);
crate2(50, yW[1], 41, 2); crate2(56, yW[1], 41, 3);
bale(52, yW[1], 35, 'white_wool');
rug(52, yW[1], 39, 3, 3, 'brown', 'white');
lamp(53, 22, 36);
bale(50, yW[2], 31, 'light_gray_wool'); bale(55, yW[2], 31, 'brown_wool');
crate2(50, yW[2], 41, 2); crate2(56, yW[2], 40, 2);
ps(53, yW[2], 41, 'barrel[facing=up]');
rug(52, yW[2], 35, 3, 3, 'red', 'brown');
lamp(53, 27, 37);
ck('INTERIOR');

// ---------- HOIST ERKER (timber, projects and SUPPORTS the beam) ----------
fill(36, 39, AZ2 + 1, 40, 39, AZ2 + 3, 'spruce_planks');
fill(36, 40, AZ2 + 1, 36, 43, AZ2 + 3, 'dark_oak_log[axis=y]');
fill(40, 40, AZ2 + 1, 40, 43, AZ2 + 3, 'dark_oak_log[axis=y]');
fill(37, 40, AZ2 + 3, 39, 43, AZ2 + 3, 'spruce_planks');
fill(37, 40, AZ2 + 1, 39, 40, AZ2 + 2, 'air');
fill(36, 44, AZ2 + 1, 40, 44, AZ2 + 3, 'dark_oak_log[axis=x]');
// little gable cap on the erker
var es;
for (es = 0; es < 3; es++) {
  roofStair(36 + es, 44 + es, AZ2 + 1, 'dark_oak_stairs', 'west');
  roofStair(40 - es, 44 + es, AZ2 + 1, 'dark_oak_stairs', 'east');
  roofStair(36 + es, 44 + es, AZ2 + 2, 'dark_oak_stairs', 'west');
  roofStair(40 - es, 44 + es, AZ2 + 2, 'dark_oak_stairs', 'east');
  roofStair(36 + es, 44 + es, AZ2 + 3, 'dark_oak_stairs', 'west');
  roofStair(40 - es, 44 + es, AZ2 + 3, 'dark_oak_stairs', 'east');
}
fill(38, 46, AZ2 + 1, 38, 46, AZ2 + 3, 'stripped_dark_oak_log[axis=z]');
// projecting beam + winch + rope + hanging crate
fill(38, 43, AZ2 + 3, 38, 43, AZ2 + 6, 'stripped_spruce_log[axis=z]');
ps(38, 42, AZ2 + 4, 'spruce_stairs[facing=south,half=top]');
ps(37, 43, AZ2 + 5, 'spruce_fence'); ps(39, 43, AZ2 + 5, 'spruce_fence');
var ry2;
for (ry2 = 27; ry2 <= 42; ry2++) { pb(38, ry2, AZ2 + 6, 'iron_bars'); }
pb(38, 26, AZ2 + 6, 'barrel[facing=up]');
ps(38, 25, AZ2 + 6, 'spruce_slab[type=top]');
// braces so the erker is visibly carried
ps(36, 38, AZ2 + 1, 'dark_oak_stairs[facing=south,half=top]');
ps(40, 38, AZ2 + 1, 'dark_oak_stairs[facing=south,half=top]');
ps(38, 38, AZ2 + 2, 'dark_oak_stairs[facing=south,half=top]');
ck('ERKER');

// ---------- GANGWAY over the alley ----------
fill(47, 17, 38, 47, 17, 40, 'spruce_planks');
fill(47, 21, 38, 47, 21, 40, 'spruce_planks');
pb(47, 18, 37, 'dark_oak_log[axis=y]'); pb(47, 19, 37, 'dark_oak_log[axis=y]');
pb(47, 18, 41, 'dark_oak_log[axis=y]'); pb(47, 19, 41, 'dark_oak_log[axis=y]');
ps(47, 20, 37, 'glass_pane'); ps(47, 20, 41, 'glass_pane');
ps(47, 16, 39, 'dark_oak_stairs[facing=north,half=top]');

// ---------- EXTERIOR ----------
var lz3, lx3;
for (lz3 = AZ2 + 1; lz3 <= 62; lz3++) {
  for (lx3 = 32; lx3 <= 44; lx3++) {
    pb(lx3, GY, lz3, ((lx3 * 7 + lz3 * 5) % 11 === 0) ? 'gravel' : 'cobblestone');
  }
}
for (lx3 = 22; lx3 <= 60; lx3++) { pb(lx3, GY, 46, 'cobblestone'); pb(lx3, GY, 47, 'cobblestone'); }
for (lz3 = 30; lz3 <= 46; lz3++) { pb(20, GY, lz3, 'cobblestone'); pb(21, GY, lz3, 'cobblestone'); }
lampPost(33, GY + 1, 49, 4, 'dark_oak_fence');
lampPost(43, GY + 1, 49, 4, 'dark_oak_fence');
lampPost(21, GY + 1, 42, 4, 'dark_oak_fence');
lampPost(56, GY + 1, 50, 4, 'dark_oak_fence');
// quayside crane (timber A-frame) — a real dock prop, not floating
fill(50, GY + 1, 54, 50, GY + 7, 54, 'dark_oak_log[axis=y]');
fill(54, GY + 1, 54, 54, GY + 7, 54, 'dark_oak_log[axis=y]');
fill(50, GY + 8, 54, 54, GY + 8, 54, 'dark_oak_log[axis=x]');
fill(52, GY + 8, 54, 52, GY + 8, 58, 'stripped_spruce_log[axis=z]');
for (ry2 = GY + 3; ry2 <= GY + 7; ry2++) { pb(52, ry2, 58, 'iron_bars'); }
pb(52, GY + 2, 58, 'barrel[facing=up]');
ps(51, GY + 8, 55, 'dark_oak_stairs[facing=south,half=top]');
ps(53, GY + 8, 55, 'dark_oak_stairs[facing=south,half=top]');
// dockside goods, nets, fish barrels
crate2(35, GY + 1, 50, 2); crate2(36, GY + 1, 50, 1); crate2(35, GY + 1, 51, 1);
crate2(42, GY + 1, 52, 2); crate2(43, GY + 1, 52, 1);
bale(46, GY + 1, 50, 'brown_wool');
pb(41, GY + 1, 49, 'chest[facing=south]');
ps(29, GY + 1, 50, 'barrel[facing=up]'); ps(30, GY + 1, 50, 'barrel[facing=up]');
// weathering, moss, greenery
var vg2, gx3, gz3;
for (vg2 = 0; vg2 < 34; vg2++) {
  gx3 = 14 + (vg2 * 9) % 56;
  gz3 = 47 + (vg2 * 5) % 14;
  if (vg2 % 3 === 0) { ps(gx3, GY + 1, gz3, 'moss_carpet'); }
  else if (vg2 % 3 === 1) { pb(gx3, GY, gz3, 'mossy_cobblestone'); }
  else { ps(gx3, GY + 1, gz3, 'brown_carpet'); }
}
for (vg2 = 46; vg2 <= 62; vg2 += 2) { ps(12, GY, vg2, 'vine[south=true]'); }
for (vg2 = 0; vg2 < 26; vg2++) {
  gx3 = 16 + (vg2 * 13) % 48;
  gz3 = 14 + (vg2 * 7) % 8;
  ps(gx3, GY + 1, gz3, (vg2 % 4 === 0) ? 'oak_leaves[persistent=true]' : 'short_grass');
}
for (vg2 = 0; vg2 < 14; vg2++) {
  ps(18 + (vg2 * 4) % 44, GY + 1, 16 + (vg2 * 3) % 6, (vg2 % 2 === 0) ? 'blue_orchid' : 'dandelion');
}
// flower boxes under the neighbour's shop windows (arch-guide 4)
ps(50, 14, BZ2 + 1, 'spruce_trapdoor[facing=north,half=bottom,open=true]');
pb(50, 14, BZ2 + 1, 'flower_pot');
ps(56, 14, BZ2 + 1, 'spruce_trapdoor[facing=north,half=bottom,open=true]');
// moored barge
fill(30, waterY, 65, 36, waterY, 67, 'spruce_slab[type=bottom]');
ps(29, waterY, 66, 'spruce_stairs[facing=east,half=bottom]');
ps(37, waterY, 66, 'spruce_stairs[facing=west,half=bottom]');
pb(33, waterY + 1, 66, 'barrel[facing=up]'); pb(34, waterY + 1, 66, 'barrel[facing=up]');
pb(32, waterY + 1, 65, 'dark_oak_fence'); pb(32, waterY + 2, 65, 'dark_oak_fence');
pb(44, waterY + 1, 66, 'stripped_dark_oak_log'); pb(44, waterY, 66, 'stripped_dark_oak_log');
ck('EXTERIOR');
ck('DONE');

Static Renders

Hanseatic Speicher warehouse (indexed) isometric viewisometric
Hanseatic Speicher warehouse (indexed) front viewfront
Hanseatic Speicher warehouse (indexed) side viewside
Hanseatic Speicher warehouse (indexed) back viewback
Hanseatic Speicher warehouse (indexed) top viewtop