← Back to Gallery

Loading 3D viewer…

Ottoman Hammam (guided)

by Jorge Barbero

Dimensions
88×44×76
Blocks
79,371
Compute Time
12.1s
Generation Time
7m 50s
Edits
4
Model
claude-opus-5
Created
August 23, 2026
ottomanhammamdomeinteriorguidedautoeval
Prompt

User Prompt

an Ottoman stone hammam (bathhouse): squat sandstone block with a large ribbed central dome over the hot room flanked by two smaller domes, arched entrance portal with a stepped muqarnas hood, star-shaped skylight holes, interior with a raised octagonal marble navel-stone, water basins in wall niches, a stair up to a raised gallery, warm lantern light

Enhanced Prompt

guided condition: prepare_build + docs (build-rules Essential, shape-techniques Dome Layer Tables, interior-design Furniture Catalog, block-palettes Gradient & Volume, worldedit-api shape wrappers/staircase/terrain superpowers). Ottoman hammam, three domed rooms in line, pilastered sandstone facade, marble interior, gallery + staircase, star skylights.

Photos

Exterior
Exteriorexterior
Camekan + gallery
Camekan + galleryinterior
Hot room
Hot roominterior
CraftScript Source
// === BUILD PLAN ===
// Style: Ottoman hammam (bathhouse), squat masonry mass + lead domes
// Footprint: 3 domed rooms in a line + 2 link corridors + projecting entrance portal
//   Room W camekan  X21..31 Z29..39 (11x11) dome R5
//   Room C sicaklik X35..49 Z27..41 (15x15) RIBBED dome R7  <- main
//   Room E kulhan   X53..63 Z29..39 (11x11) dome R5 + chimney
//   Portal: projecting hood X23..29 Z25..28 on north face of W
// Height: floorY=9 walkY=10; walls W/E top y=18, C top y=18; domes apex 23 / 25
//
// GROUND FLOOR (top-down, 1 char = 1 block, schematic):
//   ....#####PPP#####...........................
//   ....#  camekan  #===#   sicaklik   #===#  kulhan  #
//   ....#  gallery  #   #   O navel    #   #  furnace #
//   ....#  benches  #===#   basins     #===#  wood    #
//   ....#############   #################   ###########
// Legend: # wall, P portal, = link corridor, O navel stone
//
// FRONT ELEVATION (north):
//        ___              _____              ___
//      /     \          /       \          /     \      <- lead domes (ribbed centre)
//     |=======|        |=========|        |=======|      <- cornice
//     | || || |  |^|   |  || ||  |        | || || |      <- pilasters + portal hood
//     |_||_||_|_|_|____|__||_||__|________|_||_||_|
//
// MATERIALS PLAN:
//   ground   : terrain() sand/coarse_dirt/grass patches, flat pad y=8   - WHY: never bury the build
//   base     : gradientPalette cut_sandstone -> sandstone -> smooth_sandstone up walls, noise 0.2 - WHY: fake AO, big walls die flat
//   pilasters: chiseled_sandstone + cut_sandstone caps                  - WHY: relief every 4 blocks (wall_depth)
//   domes    : gradientPalette andesite->polished_andesite->smooth_stone (lead patina); ribs in cut_sandstone
//   interior : quartz_block / smooth_quartz / quartz_bricks marble + prismarine basins
//   accents  : lanterns, orange+yellow stained glass star skylights, oak gallery
// Rooms: camekan (benches, tables, carpets, upper wooden gallery via staircase),
//        sicaklik (octagonal navel stone, 4 niche basins, water channels),
//        kulhan (furnace, cauldrons, log pile, chimney)
// STAIR PLAN: camekan walk 10 -> gallery walk 15 (D=5) -> staircase(30,37,10,15,"north"), 6 cells, width 2
// === END PLAN ===

var floorY = 9, walkY = 10;
var padY = 8;

// ---------- TERRAIN ----------
var mat = patches([{block:'sand',weight:45},{block:'coarse_dirt',weight:20},{block:'grass_block',weight:20},{block:'sandstone',weight:15}], 0.05, 21);
terrain({ cx:42, cz:34, radius:40, baseY:padY, amp:3, scale:0.045, seed:23,
          surface:[{block:'sand',weight:45},{block:'coarse_dirt',weight:20},{block:'grass_block',weight:20},{block:'sandstone',weight:15}],
          sub:'sandstone', deep:'sandstone', depth:4,
          pads:[{cx:42, cz:34, r:28, y:padY, falloff:8}] });

// ---------- PALETTES ----------
var wallPal = gradientPalette(floorY, 18, [
  {block:'cut_sandstone', from:0},
  {block:'sandstone', from:0.35},
  {block:'smooth_sandstone', from:0.75}], {noise:0.22, seed:9});
var leadPal = gradientPalette(16, 26, [
  {block:'andesite', from:0},
  {block:'polished_andesite', from:0.45},
  {block:'smooth_stone', from:0.8}], {noise:0.18, seed:4});
var marblePal = noisePalette([{block:'quartz_block',weight:55},{block:'smooth_quartz',weight:30},{block:'quartz_bricks',weight:15}], {seed:12, freq:0.14});

// ---------- helpers ----------
function box(x1,z1,x2,z2,topY,pal){
  // walls (1 thick) from floorY to topY
  makeWalls(x1, floorY, z1, x2, topY, z2, pal);
  // floor
  fill(x1, floorY, z1, x2, floorY, z2, 'smooth_sandstone');
}
function clearInside(x1,z1,x2,z2,topY){
  fill(x1+1, walkY, z1+1, x2-1, topY+8, z2-1, 'air');
}
function marbleFloor(x1,z1,x2,z2){
  fill(x1, floorY, z1, x2, floorY, z2, marblePal);
}
function dome(cx, cy, cz, R, pal, ribBlock, ribbed){
  var dy, dx, dz, outerR, innerR, dist2, ang, isRib;
  for (dy = 0; dy <= R; dy++){
    outerR = Math.round(Math.sqrt(R*R - dy*dy));
    innerR = Math.round(Math.sqrt(Math.max(0, (R-1)*(R-1) - dy*dy)));
    for (dx = -outerR; dx <= outerR; dx++){
      for (dz = -outerR; dz <= outerR; dz++){
        dist2 = dx*dx + dz*dz;
        if (dist2 <= outerR*outerR + outerR && !(dist2 <= innerR*innerR)){
          isRib = false;
          if (ribbed && dy < R){
            ang = Math.atan2(dz, dx);
            var k = Math.abs(((ang + Math.PI) / (Math.PI/4)) % 1);
            if (k < 0.16 || k > 0.84) isRib = true;
          }
          var frac = dy / R;
          var jit = ((cx+dx)*7 + (cz+dz)*13 + dy*3) % 5;
          var shell = (frac + jit*0.03 < 0.35) ? 'andesite' : ((frac + jit*0.03 < 0.75) ? 'polished_andesite' : 'smooth_stone');
          pb(cx+dx, cy+dy, cz+dz, isRib ? ribBlock : shell);
        }
      }
    }
  }
}
function starSkylight(cx, cy, cz, R){
  // small star of stained glass near the apex of a dome
  var pts = [[0,0],[1,0],[-1,0],[0,1],[0,-1],[2,0],[-2,0],[0,2],[0,-2]];
  var i, dx, dz, dy, r;
  for (i = 0; i < pts.length; i++){
    dx = pts[i][0]; dz = pts[i][1];
    r = Math.sqrt(dx*dx + dz*dz);
    dy = Math.round(Math.sqrt(Math.max(0, R*R - r*r)));
    pb(cx+dx, cy+dy, cz+dz, (i%3===0) ? 'orange_stained_glass' : 'yellow_stained_glass');
  }
}
function pilasterRow(x, z1, z2, topY, step){
  var z;
  for (z = z1; z <= z2; z += step){
    fill(x, floorY, z, x, topY-1, z, 'chiseled_sandstone');
    pb(x, topY, z, 'cut_sandstone');
    ps(x, topY+1, z, 'sandstone_slab[type=bottom]');
  }
}
function pilasterRowX(z, x1, x2, topY, step){
  var x;
  for (x = x1; x <= x2; x += step){
    fill(x, floorY, z, x, topY-1, z, 'chiseled_sandstone');
    pb(x, topY, z, 'cut_sandstone');
    ps(x, topY+1, z, 'sandstone_slab[type=bottom]');
  }
}
function niche(x, y, z, dirAxis, inward){
  // recessed arched niche 1 wide x 3 tall, carved into a wall; inward = +1/-1 along axis
  var i;
  for (i = 0; i < 3; i++){
    if (dirAxis === 'x') pb(x + inward, y+i, z, 'air'); else pb(x, y+i, z + inward, 'air');
  }
  if (dirAxis === 'x') pb(x + inward, y+3, z, 'chiseled_sandstone'); else pb(x, y+3, z + inward, 'chiseled_sandstone');
}

// ---------- ROOM SHELLS ----------
var topW = 18, topC = 18, topE = 18;
box(20, 28, 32, 40, topW, wallPal);        // camekan shell
box(34, 26, 50, 42, topC, wallPal);        // sicaklik shell
box(52, 28, 64, 40, topE, wallPal);        // kulhan shell
// link corridors
box(31, 32, 35, 36, 14, wallPal);
box(49, 32, 53, 36, 14, wallPal);

clearInside(20, 28, 32, 40, topW);
clearInside(34, 26, 50, 42, topC);
clearInside(52, 28, 64, 40, topE);
clearInside(31, 32, 35, 36, 14);
clearInside(49, 32, 53, 36, 14);

// corridor roofs (barrel-ish: slab + stair haunches)
var cx2;
for (cx2 = 32; cx2 <= 34; cx2++){
  fill(cx2, 14, 33, cx2, 14, 35, 'smooth_sandstone');
  roofStair(cx2, 14, 32, 'cut_sandstone_stairs', 'north');
  roofStair(cx2, 14, 36, 'cut_sandstone_stairs', 'south');
}
for (cx2 = 50; cx2 <= 52; cx2++){
  fill(cx2, 14, 33, cx2, 14, 35, 'smooth_sandstone');
  roofStair(cx2, 14, 32, 'cut_sandstone_stairs', 'north');
  roofStair(cx2, 14, 36, 'cut_sandstone_stairs', 'south');
}
// doorways between rooms (2 tall, clear)
fill(32, walkY, 33, 32, walkY+2, 35, 'air');
fill(34, walkY, 33, 34, walkY+2, 35, 'air');
fill(50, walkY, 33, 50, walkY+2, 35, 'air');
fill(52, walkY, 33, 52, walkY+2, 35, 'air');
fill(31, floorY, 32, 35, floorY, 36, 'smooth_sandstone');
fill(49, floorY, 32, 53, floorY, 36, 'smooth_sandstone');
fill(32, floorY, 33, 34, floorY, 35, 'polished_diorite');
fill(50, floorY, 33, 52, floorY, 35, 'polished_diorite');

// ---------- FACADE RELIEF (pilasters + string course + cornice) ----------
pilasterRow(20, 29, 39, topW, 3);   // camekan west face
pilasterRow(64, 29, 39, topE, 3);   // kulhan east face
pilasterRowX(28, 21, 31, topW, 3);  // camekan north
pilasterRowX(40, 21, 31, topW, 3);  // camekan south
pilasterRowX(28, 53, 63, topE, 3);  // kulhan north
pilasterRowX(40, 53, 63, topE, 3);  // kulhan south
pilasterRowX(26, 35, 49, topC, 4);  // sicaklik north
pilasterRowX(42, 35, 49, topC, 4);  // sicaklik south
pilasterRow(34, 27, 41, topC, 4);
pilasterRow(50, 27, 41, topC, 4);

// string course band
function band(x1,z1,x2,z2,y){
  var x, z;
  for (x = x1; x <= x2; x++){ ps(x, y, z1, 'cut_sandstone_slab[type=top]'); ps(x, y, z2, 'cut_sandstone_slab[type=top]'); }
  for (z = z1; z <= z2; z++){ ps(x1, y, z, 'cut_sandstone_slab[type=top]'); ps(x2, y, z, 'cut_sandstone_slab[type=top]'); }
}
band(20, 28, 32, 40, 14);
band(52, 28, 64, 40, 14);
band(34, 26, 50, 42, 15);

// cornice: upside-down stairs ringing each wall top
function cornice(x1,z1,x2,z2,y){
  var x, z;
  for (x = x1; x <= x2; x++){ roofStair(x, y, z1-1, 'sandstone_stairs', 'south'); roofStair(x, y, z2+1, 'sandstone_stairs', 'north'); }
  for (z = z1-1; z <= z2+1; z++){ roofStair(x1-1, y, z, 'sandstone_stairs', 'east'); roofStair(x2+1, y, z, 'sandstone_stairs', 'west'); }
}
cornice(20, 28, 32, 40, topW+1);
cornice(52, 28, 64, 40, topE+1);
cornice(34, 26, 50, 42, topC+1);

// flat roof deck around the domes
fill(20, topW+1, 28, 32, topW+1, 40, 'smooth_sandstone');
fill(52, topE+1, 28, 64, topE+1, 40, 'smooth_sandstone');
fill(34, topC+1, 26, 50, topC+1, 42, 'smooth_sandstone');

// ---------- DOMES ----------
var domeBaseW = topW + 1, domeBaseC = topC + 1, domeBaseE = topE + 1;
// drums (octagon-ish ring) under each dome for a real Ottoman profile
function drum(cx, cz, r, y, h){
  var dx, dz, d2;
  var yy;
  for (yy = y; yy < y + h; yy++){
    for (dx = -r; dx <= r; dx++){
      for (dz = -r; dz <= r; dz++){
        d2 = dx*dx + dz*dz;
        if (d2 <= r*r + r && d2 >= (r-1)*(r-1)) pb(cx+dx, yy, cz+dz, 'cut_sandstone');
      }
    }
  }
}
drum(26, 34, 6, domeBaseW, 2);
drum(58, 34, 6, domeBaseE, 2);
drum(42, 34, 8, domeBaseC, 3);

dome(26, domeBaseW+2, 34, 6, leadPal, 'cut_sandstone', false);
dome(58, domeBaseE+2, 34, 6, leadPal, 'cut_sandstone', false);
dome(42, domeBaseC+3, 34, 8, leadPal, 'cut_sandstone', true);   // RIBBED main dome

// hollow the dome interiors (open to the rooms below)
function openDome(cx, cy, cz, R){
  var dy, dx, dz, innerR, d2;
  for (dy = 0; dy < R; dy++){
    innerR = Math.round(Math.sqrt(Math.max(0, (R-1)*(R-1) - dy*dy)));
    for (dx = -innerR; dx <= innerR; dx++)
      for (dz = -innerR; dz <= innerR; dz++){
        d2 = dx*dx + dz*dz;
        if (d2 <= innerR*innerR) pb(cx+dx, cy+dy, cz+dz, 'air');
      }
  }
}
openDome(26, domeBaseW+2, 34, 6);
openDome(58, domeBaseE+2, 34, 6);
openDome(42, domeBaseC+3, 34, 8);
// open the ceiling ring so the domes read from inside
fill(21, domeBaseW, 29, 31, domeBaseW+1, 39, 'air');
fill(53, domeBaseE, 29, 63, domeBaseE+1, 39, 'air');
fill(35, domeBaseC, 27, 49, domeBaseC+2, 41, 'air');
// re-close the outer deck ring that the openings punched
function reDeck(x1,z1,x2,z2,y,cx,cz,r){
  var x, z, d2;
  for (x = x1; x <= x2; x++)
    for (z = z1; z <= z2; z++){
      d2 = (x-cx)*(x-cx) + (z-cz)*(z-cz);
      if (d2 > (r+1)*(r+1)) pb(x, y, z, 'smooth_sandstone');
    }
}
reDeck(21, 29, 31, 39, domeBaseW, 26, 34, 6);
reDeck(53, 29, 63, 39, domeBaseE, 58, 34, 6);
reDeck(35, 27, 49, 41, domeBaseC, 42, 34, 8);

// star skylights
starSkylight(26, domeBaseW+2, 34, 6);
starSkylight(58, domeBaseE+2, 34, 6);
starSkylight(42, domeBaseC+3, 34, 8);
// glowstone hidden just outside the skylight glass = warm shafts of light
pb(42, domeBaseC+3+8+1, 34, 'glowstone');
pb(26, domeBaseW+2+6+1, 34, 'glowstone');

// ---------- ENTRANCE PORTAL (projecting, stepped muqarnas hood) ----------
box(23, 24, 29, 28, 17, wallPal);
clearInside(23, 24, 29, 28, 17);
fill(24, floorY, 25, 28, floorY, 27, 'polished_diorite');
// pointed arch opening on the north face
fill(25, walkY, 24, 27, walkY+3, 24, 'air');
pb(25, walkY+4, 24, 'air'); pb(27, walkY+4, 24, 'air'); pb(26, walkY+4, 24, 'air'); pb(26, walkY+5, 24, 'air');
roofStair(24, walkY+4, 24, 'sandstone_stairs', 'west');
roofStair(28, walkY+4, 24, 'sandstone_stairs', 'east');
roofStair(25, walkY+5, 24, 'sandstone_stairs', 'west');
roofStair(27, walkY+5, 24, 'sandstone_stairs', 'east');
// stepped muqarnas hood: receding upside-down stair courses inside the portal recess
var s;
for (s = 0; s < 4; s++){
  var hx1 = 25 + Math.floor(s/2), hx2 = 27 - Math.floor(s/2);
  var hy = walkY + 6 + s;
  var hz;
  for (hz = 25; hz <= 27; hz++){
    ps(hx1, hy, hz, 'chiseled_sandstone');
    ps(hx2, hy, hz, 'chiseled_sandstone');
  }
  roofStair(hx1-1, hy, 25, 'cut_sandstone_stairs', 'west');
  roofStair(hx2+1, hy, 25, 'cut_sandstone_stairs', 'east');
}
// hood cap + finial
fill(23, 17, 24, 29, 17, 28, 'smooth_sandstone');
cornice(24, 25, 28, 27, 18);
fill(25, 18, 25, 27, 18, 27, 'cut_sandstone');
pb(26, 19, 26, 'chiseled_sandstone');
pb(26, 20, 26, 'sandstone_wall');
pb(26, 21, 26, 'lantern[hanging=false]');
// door into the camekan through the shared north wall of room W
fill(25, walkY, 28, 27, walkY+2, 28, 'air');
fill(24, floorY, 28, 28, floorY, 28, 'polished_diorite');
// portal doors
ps(26, walkY, 24, 'dark_oak_door[facing=north,half=lower,hinge=left]');
ps(26, walkY+1, 24, 'dark_oak_door[facing=north,half=upper,hinge=left]');
pb(24, walkY+3, 23, 'lantern[hanging=false]');
pb(28, walkY+3, 23, 'lantern[hanging=false]');

// ---------- CAMEKAN INTERIOR (room W) ----------
marbleFloor(21, 29, 31, 39);
fill(21, floorY, 29, 31, floorY, 39, marblePal);
// wall face in marble up to the string course
fill(21, walkY, 29, 31, walkY+3, 29, 'smooth_quartz');
fill(21, walkY, 39, 31, walkY+3, 39, 'smooth_quartz');
fill(21, walkY, 29, 21, walkY+3, 39, 'smooth_quartz');
// central octagonal pool
var px, pz;
for (px = 24; px <= 28; px++)
  for (pz = 32; pz <= 36; pz++){
    var dd = Math.abs(px-26) + Math.abs(pz-34);
    if (dd <= 3){ pb(px, floorY, pz, 'water'); }
    if (dd === 4){ pb(px, floorY, pz, 'polished_diorite'); }
  }
pb(26, floorY+1, 34, 'water');
pb(26, floorY+2, 34, 'sandstone_wall');
pb(26, floorY+3, 34, 'lantern[hanging=false]');
// benches (stair seats) along the west wall + low tables
var bz;
for (bz = 31; bz <= 37; bz++) chairStair(22, walkY, bz, 'dark_oak_stairs', 'east');
pb(23, walkY, 31, 'dark_oak_fence'); ps(23, walkY+1, 31, 'red_carpet');
pb(23, walkY, 37, 'dark_oak_fence'); ps(23, walkY+1, 37, 'red_carpet');
// carpets
var rx, rz;
for (rx = 29; rx <= 30; rx++) for (rz = 31; rz <= 37; rz++) ps(rx, walkY, rz, ((rx+rz)%2===0)?'red_carpet':'orange_carpet');
// potted plants + towels (banners) + storage
pb(22, walkY, 29, 'flower_pot'); pb(30, walkY, 29, 'flower_pot');
pb(22, walkY, 39, 'barrel[facing=up]'); pb(23, walkY, 39, 'barrel[facing=up]');
// GALLERY floor (north strip) at y=14, walk 15
fill(21, 14, 29, 31, 14, 31, 'dark_oak_planks');
fill(29, 14, 32, 31, 14, 32, 'dark_oak_planks');   // landing patch
// gallery support beams
var gx;
for (gx = 21; gx <= 31; gx += 3){ fill(gx, walkY, 32, gx, 13, 32, 'dark_oak_fence'); }
// gallery railing
for (gx = 21; gx <= 28; gx++) pb(gx, 15, 32, 'dark_oak_fence');
pb(28, 15, 32, 'dark_oak_fence');
// STAIRCASE camekan floor -> gallery
staircase(30, 37, walkY, 15, 'north', {width:2, material:'dark_oak_stairs', rail:true, support:'cut_sandstone'});
// gallery furniture
placeBed(23, 15, 30, 'red', 'north');
pb(25, 15, 30, 'dark_oak_fence'); ps(25, 16, 30, 'white_carpet');
chairStair(26, 15, 30, 'dark_oak_stairs', 'west');
pb(22, 15, 30, 'lantern[hanging=false]');
for (gx = 21; gx <= 31; gx += 4) pb(gx, 17, 30, 'lantern[hanging=true]');
// lantern ring in camekan
pb(22, walkY+4, 31, 'lantern[hanging=true]');
pb(30, walkY+4, 31, 'lantern[hanging=true]');
pb(22, walkY+4, 37, 'lantern[hanging=true]');
pb(30, walkY+4, 37, 'lantern[hanging=true]');

// ---------- SICAKLIK INTERIOR (room C) ----------
marbleFloor(35, 27, 49, 41);
fill(35, walkY, 27, 49, walkY+4, 27, 'smooth_quartz');
fill(35, walkY, 41, 49, walkY+4, 41, 'smooth_quartz');
fill(35, walkY, 27, 35, walkY+4, 41, 'smooth_quartz');
fill(49, walkY, 27, 49, walkY+4, 41, 'smooth_quartz');
// raised octagonal navel stone (gobek tasi) centred (42,34)
var nx, nz, dman;
for (nx = 37; nx <= 47; nx++)
  for (nz = 29; nz <= 39; nz++){
    dman = Math.abs(nx-42) + Math.abs(nz-34);
    if (dman <= 7 && Math.abs(nx-42) <= 5 && Math.abs(nz-34) <= 5){
      pb(nx, floorY+1, nz, (dman <= 3) ? 'quartz_block' : 'smooth_quartz');
    }
  }
for (nx = 40; nx <= 44; nx++) for (nz = 32; nz <= 36; nz++) pb(nx, floorY+2, nz, (((nx+nz)%2)===0) ? 'quartz_bricks' : 'polished_diorite');
pb(42, floorY+2, 34, 'sea_lantern');
// corner columns supporting the dome + arched openings
var corners = [[36,28],[48,28],[36,40],[48,40]];
var ci;
for (ci = 0; ci < corners.length; ci++){
  fill(corners[ci][0], walkY, corners[ci][1], corners[ci][0], 16, corners[ci][1], 'quartz_pillar[axis=y]');
  pb(corners[ci][0], 17, corners[ci][1], 'chiseled_quartz_block');
}
// water basins in wall niches (4), each: recess + cauldron + water + brass tap
function basin(x, z, axis, inward){
  niche(x, walkY, z, axis, inward);
  var bx = (axis === 'x') ? x + inward : x;
  var bz = (axis === 'z') ? z + inward : z;
  ps(bx, walkY, bz, 'cauldron');
  pb(bx, walkY+1, bz, 'quartz_slab[type=bottom]');
  pb(bx, walkY+2, bz, 'lantern[hanging=true]');
  pb(bx, floorY, bz, 'prismarine_bricks');
}
basin(35, 31, 'x', -1);
basin(35, 37, 'x', -1);
basin(49, 31, 'x',  1);
basin(49, 37, 'x',  1);
// warm water channels in the floor
var wc;
for (wc = 37; wc <= 47; wc++){ pb(wc, floorY, 28, 'water'); pb(wc, floorY, 40, 'water'); }
pb(36, floorY, 28, 'prismarine_bricks'); pb(48, floorY, 28, 'prismarine_bricks');
pb(36, floorY, 40, 'prismarine_bricks'); pb(48, floorY, 40, 'prismarine_bricks');
// hanging lanterns under the dome springing
var li;
var lanternPts = [[38,30],[46,30],[38,38],[46,38],[42,29],[42,39]];
for (li = 0; li < lanternPts.length; li++){
  pb(lanternPts[li][0], 17, lanternPts[li][1], 'chain');
  pb(lanternPts[li][0], 16, lanternPts[li][1], 'lantern[hanging=true]');
}
// marble benches around the walls
var mb;
for (mb = 30; mb <= 38; mb += 2){ chairStair(36, walkY, mb, 'quartz_stairs', 'east'); chairStair(48, walkY, mb, 'quartz_stairs', 'west'); }

// ---------- KULHAN INTERIOR (room E: furnace/service) ----------
fill(53, floorY, 29, 63, floorY, 39, 'polished_blackstone_bricks');
fill(53, walkY, 29, 63, walkY+3, 29, 'smooth_sandstone');
ps(58, walkY, 30, 'furnace[facing=south,lit=true]');
ps(59, walkY, 30, 'furnace[facing=south,lit=true]');
ps(57, walkY, 30, 'furnace[facing=south,lit=true]');
pb(58, walkY+1, 30, 'iron_trapdoor[facing=south,half=top,open=false]');
ps(55, walkY, 31, 'cauldron'); ps(56, walkY, 31, 'cauldron');
var lg;
for (lg = 0; lg < 4; lg++){ pb(61, walkY+lg%2, 36+Math.floor(lg/2), 'oak_log[axis=x]'); pb(62, walkY+lg%2, 36+Math.floor(lg/2), 'oak_log[axis=x]'); }
pb(54, walkY, 38, 'barrel[facing=up]'); pb(55, walkY, 38, 'barrel[facing=up]');
pb(56, walkY+3, 34, 'lantern[hanging=true]');
pb(60, walkY+3, 34, 'lantern[hanging=true]');
// chimney stack
fill(62, floorY, 30, 63, 26, 31, 'cut_sandstone');
fill(62, walkY, 30, 63, 24, 31, 'air');
cornice(62, 30, 63, 31, 26);
pb(62, 27, 30, 'campfire[lit=true]');

// ---------- EXTERIOR: courtyard, path, planting ----------
// paved forecourt north of the portal
var fx, fz;
for (fx = 20; fx <= 34; fx++)
  for (fz = 16; fz <= 24; fz++){
    var dxx = (fx-26), dzz = (fz-22);
    if (dxx*dxx*0.5 + dzz*dzz < 60) pb(fx, padY, fz, (((fx+fz)%4)===0) ? 'polished_diorite' : 'smooth_sandstone');
  }
// path from forecourt east along the facade
for (fx = 20; fx <= 66; fx++) { pb(fx, padY, 22, 'smooth_sandstone'); pb(fx, padY, 23, 'sandstone'); }
// street fountain
makeCylinder(70, padY, 34, 'cut_sandstone', 4, 1, false);
makeCylinder(70, padY+1, 34, 'sandstone_wall', 4, 1, true);
makeCylinder(70, padY+1, 34, 'water', 3, 1, false);
pb(70, padY+1, 34, 'quartz_pillar[axis=y]');
pb(70, padY+2, 34, 'quartz_pillar[axis=y]');
pb(70, padY+3, 34, 'water');
// cypress-like trees + shrubs
var trees = [[17,20],[17,44],[70,22],[70,46],[36,50],[48,50]];
var ti;
for (ti = 0; ti < trees.length; ti++){
  var tx = trees[ti][0], tz = trees[ti][1];
  fill(tx, padY+1, tz, tx, padY+7, tz, 'spruce_log[axis=y]');
  makeSphere(tx, padY+8, tz, 'spruce_leaves[persistent=true]', 2, 3, 2, true);
  makeSphere(tx, padY+6, tz, 'spruce_leaves[persistent=true]', 2, 2, 2, true);
}
// dry shrubs scattered by noise (noisyScatter's entry formats crash on this build)
var sx, sz, nv;
for (sx = 14; sx <= 74; sx++){
  for (sz = 14; sz <= 56; sz++){
    if (sx >= 18 && sx <= 66 && sz >= 20 && sz <= 44) continue;
    nv = noise2d('perlin', sx, sz, {freq:0.35, seed:7});
    if (nv > 0.83) pb(sx, padY+1, sz, 'dead_bush');
    else if (nv < 0.12) pb(sx, padY+1, sz, 'grass');
  }
}
// lamp posts along the path (hand-built: wall post + lantern)
function post(x, z){
  var i;
  for (i = 0; i < 3; i++) pb(x, padY+1+i, z, 'cut_sandstone_wall');
  pb(x, padY+4, z, 'chiseled_sandstone');
  pb(x, padY+5, z, 'lantern[hanging=true]');
}
post(22, 21); post(46, 21); post(62, 21); post(34, 21);
// ---------- CEILING FIX: seal the deck, leave only a round oculus under each dome ----------
function sealCeiling(x1, z1, x2, z2, y1, y2, cx, cz, holeR){
  var x, z, y, d2;
  for (y = y1; y <= y2; y++)
    for (x = x1; x <= x2; x++)
      for (z = z1; z <= z2; z++){
        d2 = (x-cx)*(x-cx) + (z-cz)*(z-cz);
        if (d2 > holeR*holeR) pb(x, y, z, 'smooth_sandstone');
        else pb(x, y, z, 'air');
      }
}
sealCeiling(21, 29, 31, 39, 19, 20, 26, 34, 4);   // camekan
sealCeiling(53, 29, 63, 39, 19, 20, 58, 34, 4);   // kulhan
sealCeiling(35, 27, 49, 41, 19, 21, 42, 34, 6);   // sicaklik
// re-lay the outer roof deck edge so the seal reads as one surface
fill(20, 19, 28, 32, 19, 28, 'smooth_sandstone');
fill(20, 19, 40, 32, 19, 40, 'smooth_sandstone');
fill(52, 19, 28, 64, 19, 28, 'smooth_sandstone');
fill(52, 19, 40, 64, 19, 40, 'smooth_sandstone');
fill(34, 19, 26, 50, 19, 26, 'smooth_sandstone');
fill(34, 19, 42, 50, 19, 42, 'smooth_sandstone');

// entry steps
var st;
for (st = 0; st < 2; st++) roofStair(24+st*0, padY+1, 23, 'sandstone_stairs', 'north');
for (fx = 24; fx <= 28; fx++) roofStair(fx, padY+1, 23, 'sandstone_stairs', 'north');

Static Renders

Ottoman Hammam (guided) isometric viewisometric
Ottoman Hammam (guided) front viewfront
Ottoman Hammam (guided) side viewside
Ottoman Hammam (guided) back viewback
Ottoman Hammam (guided) top viewtop