← Back to Gallery

Loading 3D viewer…

Ottoman Hammam (indexed)

by Jorge Barbero

Dimensions
88×44×76
Blocks
67,881
Compute Time
1.0s
Generation Time
2m 19s
Model
claude-opus-5
Created
August 23, 2026
ottomanhammamdomeinteriorindexedautoeval
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

indexed condition: prepare_build + search_docs({action:"related"}) routing (returned Roof intrusion into rooms, Wizard Tower Interior, Natural Terrain Superpowers, bridge sections) then read of those sections. Independent design: cross-plan hammam, camekan with gallery ring, ribbed dome hot room, two halvet corner cells.

CraftScript Source
// === BUILD PLAN ===
// Style: Ottoman hammam, cross-plan: camekan (domed hall + gallery ring) -> passage -> sicaklik (ribbed dome)
//        with two halvet (private cell) domes budding off the far side
// Footprint:
//   camekan  X20..34 Z30..44 outer (13x13 inside)  dome R6, walls top y=20
//   passage  X34..38 Z35..39                        vault y=15
//   sicaklik X38..54 Z28..44 outer (15x15 inside)   RIBBED dome R7, walls top y=19
//   halvets  X54..60 Z29..35 and X54..60 Z37..43    small domes R3, walls top y=15
//   porch    columned portico X22..32 Z26..30 with stepped muqarnas hood over the door
// Height: floorY=9 walkY=10; gallery walk y=16; dome apexes 27 (camekan) / 27 (sicaklik)
//
// GROUND FLOOR (schematic, 1 char ~ 1 block):
//   .......ppppppppp..............................
//   ......#####D#####.............................
//   ......#  camekan #====#   sicaklik    #==# h #
//   ......#  pool    #    #  O navel O    #  #####
//   ......#  gallery #====#   basins      #==# h #
//   ......###########     ################   #####
// Legend: p portico, D door, O navel stone, h halvet cell, = passage
//
// SECTION (north-south through the two big rooms):
//        .-'''-.            .-'''-.        <- domes on drums, ribs on the sicaklik one
//       /       \          /       \
//      | gallery |        |  navel  |
//      |___|_|___|________|____|____|
//
// MATERIALS PLAN:
//   ground  : terrain() sand/coarse_dirt pads at y=8       - WHY: flat pad, build never buried
//   walls   : gradientPalette sandstone->cut_sandstone->smooth_sandstone (noise .2) - WHY: fake AO on big blank walls
//   relief  : chiseled_sandstone pilasters + terracotta string band + stair cornice - WHY: wall_depth, kill the flat box
//   domes   : deepslate/andesite lead ramp; ribs cut_sandstone on the main dome     - WHY: lead-vs-stone contrast
//   interior: quartz marble mix + prismarine basins + dark_oak gallery              - WHY: cool marble vs warm wood
//   light   : lanterns, star skylights of orange/yellow stained glass in each dome
// Rooms: camekan (octagonal pool, benches, carpets, gallery ring w/ staircase),
//        sicaklik (raised octagonal navel stone, 4 niche basins, marble benches),
//        halvets (private cells: basin + bench + lantern)
// STAIR PLAN: camekan walk 10 -> gallery walk 16 (D=6) -> staircase(32,41,10,16,"north"), 7 cells, width 2
// === END PLAN ===

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

// ---------- 1. TERRAIN (superpowers, flat pad under the whole building) ----------
terrain({ cx:40, cz:36, radius:38, baseY:padY, amp:3, scale:0.05, seed:77,
          surface:[{block:'sand',weight:50},{block:'coarse_dirt',weight:25},{block:'grass_block',weight:15},{block:'sandstone',weight:10}],
          sub:'sandstone', deep:'sandstone', depth:4,
          pads:[{cx:40, cz:36, r:30, y:padY, falloff:7}] });

// ---------- palettes ----------
var stonePal = gradientPalette(floorY, 20, [
  {block:'sandstone', from:0},
  {block:'cut_sandstone', from:0.4},
  {block:'smooth_sandstone', from:0.8}], {noise:0.2, seed:31});
var marble = noisePalette([{block:'quartz_block',weight:50},{block:'smooth_quartz',weight:35},{block:'quartz_bricks',weight:15}], {seed:5, freq:0.13});

// ---------- generic room builder ----------
// Builds shell + floor + SOLID ceiling deck, then (optionally) a drum + dome with a clean oculus.
function room(x1, z1, x2, z2, topY, floorBlock){
  makeWalls(x1, floorY, z1, x2, topY, z2, stonePal);
  fill(x1, floorY, z1, x2, floorY, z2, floorBlock);
  fill(x1+1, walkY, z1+1, x2-1, topY, z2-1, 'air');     // interior bounds only (walls stay)
  fill(x1, topY+1, z1, x2, topY+1, z2, 'smooth_sandstone'); // SOLID deck - no sky gaps
}
function domeOn(cx, cz, deckY, R, ribbed){
  var dy, dx, dz, outerR, innerR, d2, ang, k, isRib, frac, jit, shell;
  // drum ring, 2 courses
  for (dy = 0; dy < 2; dy++)
    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, deckY+1+dy, cz+dz, 'cut_sandstone');
      }
  var baseY = deckY + 3;
  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++){
        d2 = dx*dx + dz*dz;
        if (d2 <= outerR*outerR + outerR && !(d2 <= innerR*innerR)){
          isRib = false;
          if (ribbed && dy < R - 1){
            ang = Math.atan2(dz, dx);
            k = Math.abs(((ang + Math.PI) / (Math.PI/4)) % 1);
            if (k < 0.15 || k > 0.85) isRib = true;
          }
          frac = dy / R;
          jit = ((cx+dx)*5 + (cz+dz)*11 + dy) % 4;
          shell = (frac + jit*0.04 < 0.4) ? 'deepslate' : ((frac + jit*0.04 < 0.8) ? 'andesite' : 'polished_andesite');
          pb(cx+dx, baseY+dy, cz+dz, isRib ? 'cut_sandstone' : shell);
        }
      }
  }
  // hollow the dome + drum + punch a clean circular oculus through the deck (radius R-2)
  var hr = R - 2;
  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++)
        if (dx*dx + dz*dz <= innerR*innerR) pb(cx+dx, baseY+dy, cz+dz, 'air');
  }
  for (dy = deckY; dy <= deckY + 2; dy++)
    for (dx = -hr; dx <= hr; dx++)
      for (dz = -hr; dz <= hr; dz++)
        if (dx*dx + dz*dz <= hr*hr + 1) pb(cx+dx, dy, cz+dz, 'air');
  // star skylight in the crown + hidden glowstone above it
  var pts = [[0,0],[1,0],[-1,0],[0,1],[0,-1],[1,1],[-1,-1],[2,0],[0,2],[-2,0],[0,-2]];
  var i, r2, yy;
  for (i = 0; i < pts.length; i++){
    r2 = Math.sqrt(pts[i][0]*pts[i][0] + pts[i][1]*pts[i][1]);
    yy = baseY + Math.round(Math.sqrt(Math.max(0, R*R - r2*r2)));
    pb(cx+pts[i][0], yy, cz+pts[i][1], (i % 3 === 0) ? 'orange_stained_glass' : 'yellow_stained_glass');
  }
  pb(cx, baseY + R + 1, cz, 'glowstone');
}
function pilasters(x1, z1, x2, z2, topY, step){
  var x, z;
  for (x = x1; x <= x2; x += step){
    fill(x, floorY, z1, x, topY-1, z1, 'chiseled_sandstone');
    fill(x, floorY, z2, x, topY-1, z2, 'chiseled_sandstone');
    ps(x, topY, z1, 'cut_sandstone_slab[type=top]');
    ps(x, topY, z2, 'cut_sandstone_slab[type=top]');
  }
  for (z = z1; z <= z2; z += step){
    fill(x1, floorY, z, x1, topY-1, z, 'chiseled_sandstone');
    fill(x2, floorY, z, x2, topY-1, z, 'chiseled_sandstone');
    ps(x1, topY, z, 'cut_sandstone_slab[type=top]');
    ps(x2, topY, z, 'cut_sandstone_slab[type=top]');
  }
}
function bandRing(x1, z1, x2, z2, y, blockId){
  var x, z;
  for (x = x1; x <= x2; x++){ pb(x, y, z1, blockId); pb(x, y, z2, blockId); }
  for (z = z1; z <= z2; z++){ pb(x1, y, z, blockId); pb(x2, y, z, blockId); }
}
function corniceRing(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'); }
}

// ---------- 2. ROOMS ----------
var topCam = 20, topSic = 19, topHal = 15, topPas = 14;
room(20, 30, 34, 44, topCam, 'smooth_sandstone');   // camekan
room(38, 28, 54, 44, topSic, 'smooth_sandstone');   // sicaklik
room(54, 29, 60, 35, topHal, 'polished_andesite');  // halvet north
room(54, 37, 60, 43, topHal, 'polished_andesite');  // halvet south
room(34, 35, 38, 39, topPas, 'polished_diorite');   // passage camekan-sicaklik
room(52, 32, 56, 34, topPas, 'polished_diorite');   // no-op link (kept solid, decorative buttress)

// doorways (1 wide x 2 tall, kept clear)
fill(34, walkY, 36, 34, walkY+2, 38, 'air');
fill(38, walkY, 36, 38, walkY+2, 38, 'air');
fill(54, walkY, 31, 54, walkY+2, 33, 'air');
fill(54, walkY, 39, 54, walkY+2, 41, 'air');

// ---------- 3. FACADE RELIEF ----------
pilasters(20, 30, 34, 44, topCam, 3);
pilasters(38, 28, 54, 44, topSic, 4);
bandRing(20, 30, 34, 44, 15, 'terracotta');
bandRing(38, 28, 54, 44, 15, 'terracotta');
corniceRing(20, 30, 34, 44, topCam + 1);
corniceRing(38, 28, 54, 44, topSic + 1);
corniceRing(54, 29, 60, 35, topHal + 1);
corniceRing(54, 37, 60, 43, topHal + 1);
// small arched windows high on the sicaklik walls
var wz;
for (wz = 31; wz <= 41; wz += 5){
  ps(38, 16, wz, 'orange_stained_glass');
  ps(54, 16, wz, 'orange_stained_glass');
  pb(38, 17, wz, 'sandstone_slab[type=bottom]');
  pb(54, 17, wz, 'sandstone_slab[type=bottom]');
}

// ---------- 4. DOMES ----------
domeOn(27, 37, topCam + 1, 6, false);   // camekan dome
domeOn(46, 36, topSic + 1, 7, true);    // sicaklik RIBBED dome
domeOn(57, 32, topHal + 1, 3, false);   // halvet domes
domeOn(57, 40, topHal + 1, 3, false);
// passage barrel vault
var pv;
for (pv = 35; pv <= 37; pv++){
  roofStair(35, topPas, pv, 'cut_sandstone_stairs', 'west');
  roofStair(37, topPas, pv, 'cut_sandstone_stairs', 'east');
}

// ---------- 5. PORTICO + MUQARNAS PORTAL (north face of the camekan) ----------
var col;
for (col = 22; col <= 32; col += 4){
  fill(col, floorY, 27, col, 15, 27, 'quartz_pillar[axis=y]');
  pb(col, 16, 27, 'chiseled_quartz_block');
}
fill(21, 16, 26, 33, 16, 28, 'smooth_sandstone');
fill(21, 17, 26, 33, 17, 28, 'cut_sandstone');
corniceRing(22, 27, 32, 28, 17);
fill(21, padY+1, 27, 33, padY+1, 29, 'polished_diorite');
// door + stepped muqarnas hood above it
fill(26, walkY, 30, 28, walkY+2, 30, 'air');
ps(27, walkY, 30, 'dark_oak_door[facing=north,half=lower,hinge=left]');
ps(27, walkY+1, 30, 'dark_oak_door[facing=north,half=upper,hinge=left]');
var h;
for (h = 0; h < 4; h++){
  var hy = walkY + 3 + h;
  var half = 3 - h;
  var hx;
  for (hx = 27 - half; hx <= 27 + half; hx++) pb(hx, hy, 29, 'chiseled_sandstone');
  roofStair(27 - half - 1, hy, 29, 'cut_sandstone_stairs', 'west');
  roofStair(27 + half + 1, hy, 29, 'cut_sandstone_stairs', 'east');
}
pb(27, walkY + 7, 29, 'sandstone_wall');
pb(27, walkY + 8, 29, 'lantern[hanging=false]');

// ---------- 6. CAMEKAN INTERIOR ----------
fill(21, floorY, 31, 33, floorY, 43, marble);
fill(21, walkY, 31, 33, walkY+3, 31, 'smooth_quartz');
fill(21, walkY, 43, 33, walkY+3, 43, 'smooth_quartz');
fill(21, walkY, 31, 21, walkY+3, 43, 'smooth_quartz');
fill(33, walkY, 31, 33, walkY+3, 43, 'smooth_quartz');
// octagonal pool with a small jet
var px, pz, dman;
for (px = 24; px <= 30; px++)
  for (pz = 34; pz <= 40; pz++){
    dman = Math.abs(px-27) + Math.abs(pz-37);
    if (dman <= 3) pb(px, floorY, pz, 'water');
    else if (dman === 4) pb(px, floorY, pz, 'polished_diorite');
  }
pb(27, floorY+1, 37, 'water');
pb(27, floorY, 37, 'prismarine_bricks');
// benches + carpets + props
var bz2;
for (bz2 = 33; bz2 <= 41; bz2 += 2){
  chairStair(22, walkY, bz2, 'dark_oak_stairs', 'east');
  chairStair(32, walkY, bz2, 'dark_oak_stairs', 'west');
}
var cxx, czz;
for (cxx = 24; cxx <= 30; cxx++) { ps(cxx, walkY, 32, 'red_carpet'); ps(cxx, walkY, 42, 'orange_carpet'); }
pb(23, walkY, 32, 'flower_pot'); pb(31, walkY, 32, 'flower_pot');
pb(23, walkY, 42, 'barrel[facing=up]'); pb(24, walkY, 42, 'barrel[facing=up]');
// GALLERY ring at y=15 (walk 16), 3 deep on the east + north sides
fill(21, 15, 31, 33, 15, 33, 'dark_oak_planks');
fill(30, 15, 34, 33, 15, 41, 'dark_oak_planks');
// posts under the gallery
var gp;
for (gp = 21; gp <= 33; gp += 3) fill(gp, walkY, 33, gp, 14, 33, 'dark_oak_fence');
for (gp = 35; gp <= 41; gp += 3) fill(30, walkY, gp, 30, 14, gp, 'dark_oak_fence');
// railings (leave the stair landing clear)
for (gp = 21; gp <= 29; gp++) pb(gp, 16, 33, 'dark_oak_fence');
for (gp = 34; gp <= 40; gp++) pb(30, 16, gp, 'dark_oak_fence');
// staircase to the gallery, aimed inside the room, along the east wall
staircase(32, 41, walkY, 16, 'north', {width:2, material:'dark_oak_stairs', rail:true, support:'cut_sandstone'});
// gallery furnishings
placeBed(23, 16, 32, 'red', 'east');
pb(26, 16, 32, 'dark_oak_fence'); ps(26, 17, 32, 'white_carpet');
chairStair(27, 16, 32, 'dark_oak_stairs', 'west');
pb(22, 16, 32, 'lantern[hanging=false]');
pb(32, 16, 36, 'lectern[facing=west]');
var lz;
for (lz = 33; lz <= 41; lz += 4){ pb(21, 18, lz, 'lantern[hanging=true]'); pb(33, 18, lz, 'lantern[hanging=true]'); }

// ---------- 7. SICAKLIK INTERIOR ----------
fill(39, floorY, 29, 53, floorY, 43, marble);
fill(39, walkY, 29, 53, walkY+4, 29, 'smooth_quartz');
fill(39, walkY, 43, 53, walkY+4, 43, 'smooth_quartz');
fill(39, walkY, 29, 39, walkY+4, 43, 'smooth_quartz');
fill(53, walkY, 29, 53, walkY+4, 43, 'smooth_quartz');
// raised octagonal navel stone at (46,36)
var nx, nz, dm;
for (nx = 41; nx <= 51; nx++)
  for (nz = 31; nz <= 41; nz++){
    dm = Math.abs(nx-46) + Math.abs(nz-36);
    if (dm <= 7 && Math.abs(nx-46) <= 5 && Math.abs(nz-36) <= 5) pb(nx, floorY+1, nz, (dm <= 4) ? 'quartz_block' : 'smooth_quartz');
  }
for (nx = 44; nx <= 48; nx++)
  for (nz = 34; nz <= 38; nz++)
    pb(nx, floorY+2, nz, (((nx+nz) % 2) === 0) ? 'quartz_bricks' : 'calcite');
pb(46, floorY+2, 36, 'sea_lantern');
// niche basins (4) carved 1 deep into the marble walls
function nicheBasin(x, z, dx, dz){
  var i;
  for (i = 0; i < 3; i++) pb(x + dx, walkY + i, z + dz, 'air');
  pb(x + dx, walkY + 3, z + dz, 'chiseled_sandstone');
  ps(x + dx, walkY, z + dz, 'cauldron');
  pb(x + dx, floorY, z + dz, 'prismarine_bricks');
  pb(x + dx, walkY + 2, z + dz, 'lantern[hanging=true]');
}
nicheBasin(39, 32, -1, 0);
nicheBasin(39, 40, -1, 0);
nicheBasin(53, 32,  1, 0);
nicheBasin(53, 40,  1, 0);
// corner columns + marble benches
var cor = [[40,30],[52,30],[40,42],[52,42]];
var ci2;
for (ci2 = 0; ci2 < cor.length; ci2++){
  fill(cor[ci2][0], walkY, cor[ci2][1], cor[ci2][0], 17, cor[ci2][1], 'quartz_pillar[axis=y]');
  pb(cor[ci2][0], 18, cor[ci2][1], 'chiseled_quartz_block');
}
var mb2;
for (mb2 = 32; mb2 <= 40; mb2 += 2){ chairStair(40, walkY, mb2, 'quartz_stairs', 'east'); chairStair(52, walkY, mb2, 'quartz_stairs', 'west'); }
// warm-water channel + hanging lanterns
var wcx;
for (wcx = 41; wcx <= 51; wcx++){ pb(wcx, floorY, 30, 'water'); pb(wcx, floorY, 42, 'water'); }
var lp = [[42,32],[50,32],[42,40],[50,40]];
var lpi;
for (lpi = 0; lpi < lp.length; lpi++){
  pb(lp[lpi][0], 18, lp[lpi][1], 'chain');
  pb(lp[lpi][0], 17, lp[lpi][1], 'lantern[hanging=true]');
}

// ---------- 8. HALVET CELLS ----------
function halvet(x1, z1, x2, z2){
  var cx = Math.floor((x1+x2)/2), cz = Math.floor((z1+z2)/2);
  fill(x1+1, floorY, z1+1, x2-1, floorY, z2-1, 'polished_andesite');
  ps(cx, walkY, cz+1, 'cauldron');
  pb(cx, floorY, cz+1, 'prismarine_bricks');
  chairStair(cx-1, walkY, cz-1, 'quartz_stairs', 'east');
  pb(cx+1, walkY, cz-1, 'quartz_slab[type=bottom]');
  pb(cx, 13, cz, 'chain');
  pb(cx, 12, cz, 'lantern[hanging=true]');
}
halvet(54, 29, 60, 35);
halvet(54, 37, 60, 43);

// ---------- 9. EXTERIOR ----------
// paved forecourt + street
var fx, fz, dxx, dzz;
for (fx = 16; fx <= 40; fx++)
  for (fz = 18; fz <= 28; fz++){
    dxx = fx - 27; dzz = fz - 24;
    if (dxx*dxx*0.45 + dzz*dzz < 70) pb(fx, padY, fz, (((fx + fz) % 5) === 0) ? 'polished_diorite' : 'smooth_sandstone');
  }
for (fz = 18; fz <= 60; fz++){ pb(16, padY, fz, 'smooth_sandstone'); pb(17, padY, fz, 'sandstone'); }
// street fountain + water trough
makeCylinder(24, padY, 20, 'cut_sandstone', 3, 1, false);
makeCylinder(24, padY+1, 20, 'sandstone_wall', 3, 1, true);
makeCylinder(24, padY+1, 20, 'water', 2, 1, false);
pb(24, padY+1, 20, 'quartz_pillar[axis=y]');
pb(24, padY+2, 20, 'water');
// lamp posts
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(20, 25); post(34, 25); post(18, 46); post(62, 30);
// cypress-ish trees and shrubs
var trees = [[18,32],[18,42],[36,22],[64,36],[62,46],[30,50]];
var ti, tx, tz;
for (ti = 0; ti < trees.length; ti++){
  tx = trees[ti][0]; tz = trees[ti][1];
  fill(tx, padY+1, tz, tx, padY+6, tz, 'spruce_log[axis=y]');
  makeSphere(tx, padY+7, tz, 'spruce_leaves[persistent=true]', 2, 3, 2, true);
  makeSphere(tx, padY+5, tz, 'spruce_leaves[persistent=true]', 2, 2, 2, true);
}
var sx, sz, nv;
for (sx = 12; sx <= 72; sx++)
  for (sz = 14; sz <= 60; sz++){
    if (sx >= 16 && sx <= 62 && sz >= 24 && sz <= 46) continue;
    nv = noise2d('perlin', sx, sz, {freq:0.3, seed:19});
    if (nv > 0.85) pb(sx, padY+1, sz, 'dead_bush');
  }
// entry steps up to the portico
var ex;
for (ex = 24; ex <= 30; ex++) roofStair(ex, padY+1, 26, 'sandstone_stairs', 'north');

Static Renders

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