← Back to Gallery

Loading 3D viewer…

Indian stepwell (baoli) — guided

by Jorge Barbero

Dimensions
80×44×80
Blocks
154,326
Compute Time
10.8s
Generation Time
6m 53s
Model
claude-opus-5
Created
August 29, 2026
autoevalguidedlarge_structuresstepwell
Prompt

User Prompt

an Indian stepwell (baoli): a square sunken stone water tank descending four terraced levels underground, symmetrical flights of sandstone steps on each side going down to the green water, colonnaded pavilion galleries with carved pillars on each terrace, chhatri domed kiosks at the rim, ochre and pale sandstone with carved niches

Photos

Exterior
Exteriorexterior
Terrazas y agua
Terrazas y aguainterior
Pabellon de entrada
Pabellon de entradainterior
Galerias del estanque
Galerias del estanqueinterior
CraftScript Source
// === BUILD PLAN ===
// Style: Rajasthani stepwell (baoli / vav) — Chand Baori family
// Footprint: square sunken tank, rim opening 53x53, centered (40,40); ground top Y=23 (walk 24)
// Depth: rim Y23 -> water surface Y10 -> tank floor Y5  (13 levels down, 3 terraces)
//
// TOP VIEW (concentric square terraces, r = Chebyshev radius from center):
//   r>=27  ground + parapet + 4 chhatri kiosks + north entrance pavilion
//   r26-23 FLIGHT 1 (4 steps: 22,21,20,19 going in)
//   r22-20 TERRACE 1 ledge (walk 20)  + corner colonnades
//   r19-16 FLIGHT 2 (18,17,16,15)
//   r15-13 TERRACE 2 ledge (walk 16)  + corner colonnades
//   r12-9  FLIGHT 3 (14,13,12,11)
//   r8-6   TERRACE 3 ledge (walk 12)  + corner colonnades
//   r5-3   submerged steps (9,8,7)
//   r<=2   tank floor Y5, water Y6..Y10
//
// SECTION (north-south):
//        [pavilion]==== ground Y23 ====
//              \_
//                \_ steps          _/
//                  |__ terrace  __|
//                     \_      _/
//                       ~~~~~~~   water Y10
//
// MATERIALS PLAN:
//   masonry (upper): noisePalette smooth_sandstone(34)+cut_sandstone(26)+sandstone(24)
//                    +chiseled(8)+red_sandstone(8) — WHY: warm ochre ramp, carved-stone texture
//   masonry (lower): gradientPalette moss_block -> sandstone -> smooth_sandstone (Y5..Y15)
//                    — WHY: damp/algae patina at the waterline, fakes depth + age
//   pillars: cut_sandstone shaft + chiseled capital, lintels cut_sandstone — WHY: light/dark contrast vs steps
//   domes  : red_sandstone (chhatri) — WHY: ochre accent reads against pale steps
//   ground : patches sand/coarse_dirt/grass/terracotta — WHY: dry Rajasthan blotches, not confetti
// Rooms: entrance pavilion (rug, benches, shrine niche, lanterns, staircase to roof terrace)
// STAIR PLAN: pavilion walk 24 -> roof walk 30 (D=6) -> staircase(45,10,24,30,"west"), width 1
// === END PLAN ===

function ck(s){ try { print(s); } catch(e) {} }

var cx = 40, cz = 40;
var GY = 23;            // top solid ground block; walk = 24
var WATER = 10;         // water surface Y

var mason = noisePalette([
  {block:"smooth_sandstone", weight:34},
  {block:"cut_sandstone",    weight:26},
  {block:"sandstone",        weight:24},
  {block:"chiseled_sandstone",weight:8},
  {block:"red_sandstone",    weight:8}
], {seed:3, freq:0.11});

var wet = gradientPalette(5, 16, [
  {block:"moss_block",       from:0},
  {block:"sandstone",        from:0.30},
  {block:"smooth_sandstone", from:0.70}
], {noise:0.28, seed:6});

function topSolid(r){
  if (r >= 27) return GY;
  if (r == 26) return 22;
  if (r == 25) return 21;
  if (r == 24) return 20;
  if (r >= 20) return 19;   // last step of flight 1 merges into terrace 1 ledge
  if (r == 19) return 18;
  if (r == 18) return 17;
  if (r == 17) return 16;
  if (r >= 13) return 15;   // terrace 2 ledge
  if (r == 12) return 14;
  if (r == 11) return 13;
  if (r == 10) return 12;
  if (r >= 6)  return 11;   // terrace 3 ledge
  if (r == 5)  return 9;
  if (r == 4)  return 8;
  if (r == 3)  return 7;
  return 5;                 // tank floor
}

// === 1. BASE ROCK ===
ck("BASE");
fill(4, 0, 4, 76, 18, 76, "stone");

// === 2. TERRAIN (superpowers: blob + hills + flatten + patches + surface) ===
ck("TERRAIN");
var land = blob(cx, cz, 36, {irregularity:0.30, seed:9});
var h = hills({base: GY - 2, amp: 3, scale: 0.035, seed: 4});
var pad = flatten(h, {x0: cx-32, z0: cz-32, x1: cx+32, z1: cz+32}, GY, 6);
var groundMat = patches([
  {block:"sand", w:38},
  {block:"coarse_dirt", w:24},
  {block:"grass_block", w:22},
  {block:"terracotta", w:16}
], 0.05, 12);
surface(land, pad, groundMat, {sub:"dirt", deep:"stone", depth:4});

// === 3. CARVE THE PIT ===
ck("PIT");
fill(cx-26, 0, cz-26, cx+26, GY+8, cz+26, "air");

// === 4. STEPPED MASONRY MASS ===
ck("STEPS");
var x, z, t, i, r, ty;
for (x = cx-26; x <= cx+26; x++) {
  for (z = cz-26; z <= cz+26; z++) {
    r = Math.max(Math.abs(x-cx), Math.abs(z-cz));
    ty = topSolid(r);
    fill(x, ty-5, z, x, ty, z, (ty <= 15) ? wet : mason);
  }
}

// === 5. WATER TANK ===
ck("WATER");
for (x = cx-5; x <= cx+5; x++) {
  for (z = cz-5; z <= cz+5; z++) {
    r = Math.max(Math.abs(x-cx), Math.abs(z-cz));
    if (r <= 5) {
      ty = topSolid(r);
      if (ty < WATER) fill(x, ty+1, z, x, WATER, z, "water");
    }
  }
}
// algae / plants at the waterline
var wpts = [[-4,-3],[3,-4],[4,2],[-2,4],[0,-5],[5,0],[-5,1],[2,3]];
for (i = 0; i < wpts.length; i++) {
  pb(cx+wpts[i][0], 6, cz+wpts[i][1], "seagrass");
}

// === 6. TERRACE COLONNADES (corner galleries on each ledge) ===
ck("COLONNADES");
function colonnadeCorners(rr, wy, hgt) {
  var sx, sz, k, px, pz, legs;
  for (sx = -1; sx <= 1; sx += 2) {
    for (sz = -1; sz <= 1; sz += 2) {
      legs = [[rr, rr-5],[rr, rr],[rr-5, rr]];
      for (k = 0; k < legs.length; k++) {
        px = cx + sx*legs[k][0];
        pz = cz + sz*legs[k][1];
        fill(px, wy, pz, px, wy+hgt-1, pz, "cut_sandstone");
        pb(px, wy+hgt, pz, "chiseled_sandstone");
      }
      // lintels along the two legs
      fill(cx + sx*rr, wy+hgt+1, cz + sz*(rr-5), cx + sx*rr, wy+hgt+1, cz + sz*rr, "cut_sandstone");
      fill(cx + sx*(rr-5), wy+hgt+1, cz + sz*rr, cx + sx*rr, wy+hgt+1, cz + sz*rr, "cut_sandstone");
      // hanging lantern under the corner lintel
      pb(cx + sx*rr, wy+hgt, cz + sz*rr, "lantern[hanging=true]");
    }
  }
}
colonnadeCorners(21, 20, 2);
colonnadeCorners(14, 16, 2);
colonnadeCorners(7, 12, 2);

// carved niches on the terrace-3 face (relief on the tank wall)
for (t = -5; t <= 5; t += 2) {
  pb(cx+t, 11, cz-6, "chiseled_sandstone");
  pb(cx+t, 11, cz+6, "chiseled_sandstone");
  pb(cx-6, 11, cz+t, "chiseled_sandstone");
  pb(cx+6, 11, cz+t, "chiseled_sandstone");
}

// === 7. RIM PARAPET + CHHATRI KIOSKS ===
ck("RIM");
var rim = 27;
for (t = -rim; t <= rim; t++) {
  // south / east / west edges: gap in the middle for the main flights
  if (Math.abs(t) > 3) {
    pb(cx+t, GY+1, cz+rim, "sandstone_wall");
    pb(cx-rim, GY+1, cz+t, "sandstone_wall");
    pb(cx+rim, GY+1, cz+t, "sandstone_wall");
  }
  // north edge: skip where the pavilion stands
  if (Math.abs(t) > 7) pb(cx+t, GY+1, cz-rim, "sandstone_wall");
}
// lamp posts on the parapet
var lp = [[-20,20],[20,20],[-20,-20],[20,-20],[0,27],[-27,0],[27,0]];
for (i = 0; i < lp.length; i++) {
  fill(cx+lp[i][0], GY+1, cz+lp[i][1], cx+lp[i][0], GY+2, cz+lp[i][1], "cut_sandstone");
  pb(cx+lp[i][0], GY+3, cz+lp[i][1], "lantern");
}

function chhatri(bx, by, bz) {
  var offs = [[-2,-2],[2,-2],[-2,2],[2,2]];
  var k;
  for (k = 0; k < 4; k++) {
    fill(bx+offs[k][0], by, bz+offs[k][1], bx+offs[k][0], by+3, bz+offs[k][1], "cut_sandstone");
  }
  fill(bx-2, by+4, bz-2, bx+2, by+4, bz-2, "cut_sandstone");
  fill(bx-2, by+4, bz+2, bx+2, by+4, bz+2, "cut_sandstone");
  fill(bx-2, by+4, bz-2, bx-2, by+4, bz+2, "cut_sandstone");
  fill(bx+2, by+4, bz-2, bx+2, by+4, bz+2, "cut_sandstone");
  makeCylinder(bx, by+5, bz, "red_sandstone", 2, 1, true);
  makeCylinder(bx, by+6, bz, "red_sandstone", 1, 1, true);
  pb(bx, by+7, bz, "red_sandstone");
  pb(bx, by+8, bz, "sandstone_wall");
  pb(bx, by+2, bz, "lantern[hanging=true]");
}
chhatri(cx-28, GY+1, cz+28);
chhatri(cx+28, GY+1, cz+28);
chhatri(cx-28, GY+1, cz-28);
chhatri(cx+28, GY+1, cz-28);

// === 8. NORTH ENTRANCE PAVILION (interior) ===
ck("PAVILION");
var px0 = cx-7, px1 = cx+7, pz0 = cz-32, pz1 = cz-27;
var walk = GY+1;               // 24
var wallTop = walk+4;          // 28
// platform + floor
fill(px0-1, GY, pz0-1, px1+1, GY, pz1+1, "smooth_sandstone");
fill(px0, GY, pz0, px1, GY, pz1, "cut_sandstone");
// walls
makeWalls(px0, walk, pz0, px1, wallTop, pz1, mason);
// pilasters (facade relief)
for (t = -6; t <= 6; t += 3) {
  fill(cx+t, walk, pz1, cx+t, wallTop, pz1, "cut_sandstone");
  fill(cx+t, walk, pz0, cx+t, wallTop, pz0, "cut_sandstone");
}
// doorway to the well (south wall) + arch
fill(cx-1, walk, pz1, cx+1, walk+2, pz1, "air");
pb(cx-2, walk+2, pz1, "sandstone_stairs[facing=east,half=top]");
pb(cx+2, walk+2, pz1, "sandstone_stairs[facing=west,half=top]");
// windows with stone bars
var wx = [-5,-4,4,5];
for (i = 0; i < wx.length; i++) {
  fill(cx+wx[i], walk+1, pz0, cx+wx[i], walk+2, pz0, "air");
  pb(cx+wx[i], walk+1, pz0, "sandstone_wall");
  pb(cx+wx[i], walk+2, pz0, "sandstone_wall");
}
fill(px0, walk+1, cz-30, px0, walk+2, cz-30, "sandstone_wall");
fill(px1, walk+1, cz-30, px1, walk+2, cz-30, "sandstone_wall");
// side openings (colonnaded loggia feel) on the south facade flanks
fill(px0+1, walk, pz1, px0+3, walk+2, pz1, "air");
fill(px1-3, walk, pz1, px1-1, walk+2, pz1, "air");
fill(px0+2, walk, pz1, px0+2, walk+2, pz1, "cut_sandstone");
fill(px1-2, walk, pz1, px1-2, walk+2, pz1, "cut_sandstone");
// ceiling + roof terrace
fill(px0, wallTop, pz0, px1, wallTop, pz1, "cut_sandstone");
fill(px0, wallTop+1, pz0, px1, wallTop+1, pz1, "smooth_sandstone");
// cornice brackets
for (t = px0; t <= px1; t++) {
  roofStair(t, wallTop, pz1+1, "red_sandstone_stairs", "south", "top");
  roofStair(t, wallTop, pz0-1, "red_sandstone_stairs", "north", "top");
}
for (t = pz0; t <= pz1; t++) {
  roofStair(px0-1, wallTop, t, "red_sandstone_stairs", "west", "top");
  roofStair(px1+1, wallTop, t, "red_sandstone_stairs", "east", "top");
}
// roof parapet + rooftop chhatris
for (t = px0; t <= px1; t++) {
  pb(t, wallTop+2, pz0, "sandstone_wall");
  pb(t, wallTop+2, pz1, "sandstone_wall");
}
for (t = pz0; t <= pz1; t++) {
  pb(px0, wallTop+2, t, "sandstone_wall");
  pb(px1, wallTop+2, t, "sandstone_wall");
}
chhatri(cx-4, wallTop+2, cz-30);
chhatri(cx+4, wallTop+2, cz-30);

// interior stair to the roof terrace
staircase(px1-1, cz-30, walk, wallTop+2, "west", {width:1, material:"sandstone_stairs"});

// === 9. PAVILION INTERIOR ===
ck("INTERIOR");
fill(px0+1, GY, pz0+1, px1-1, GY, pz1-1, "polished_diorite");
fill(px0+1, GY, pz0+1, px1-1, GY, pz1-1, "smooth_sandstone");
rug(cx-4, walk, cz-30, 5, 3, "red", "orange");
// shrine niche on the north wall
pb(cx, walk, pz0, "chiseled_sandstone");
pb(cx, walk+1, pz0, "sandstone_wall");
pb(cx, walk+1, pz0+1, "candle[candles=3,lit=true]");
pb(cx-1, walk, pz0+1, "flower_pot");
pb(cx+1, walk, pz0+1, "decorated_pot");
// benches facing the centre
chairStair(cx-6, walk, cz-31, "sandstone_stairs", "south");
chairStair(cx-5, walk, cz-31, "sandstone_stairs", "south");
chairStair(cx-6, walk, cz-28, "sandstone_stairs", "north");
chairStair(cx-5, walk, cz-28, "sandstone_stairs", "north");
// table + water jars
pb(cx-3, walk, cz-29, "smooth_sandstone_slab");
pb(cx-3, walk+1, cz-29, "lantern");
pb(px0+1, walk, pz0+1, "cauldron[level=3]");
pb(px1-1, walk, pz0+1, "decorated_pot");
// hanging lanterns
pb(cx-4, wallTop-1, cz-30, "lantern[hanging=true]");
pb(cx+3, wallTop-1, cz-30, "lantern[hanging=true]");

// === 10. APPROACH PATH + DRY VEGETATION ===
ck("DETAIL");
fill(cx-2, GY, cz-27, cx+2, GY, cz-26, "smooth_sandstone");
for (t = 0; t < 26; t++) {
  pb(cx-1, GY, cz-33-0, "dirt_path");
}
fill(cx-2, GY, pz0-6, cx+2, GY, pz0-1, "dirt_path");

function acacia(bx, bz) {
  var by = GY+1;
  fill(bx, by, bz, bx, by+4, bz, "acacia_log");
  makeCylinder(bx, by+5, bz, "acacia_leaves", 3, 1, true);
  makeCylinder(bx, by+6, bz, "acacia_leaves", 2, 1, true);
  pb(bx, by+4, bz, "acacia_log");
}
acacia(cx-33, cz+14);
acacia(cx+32, cz-12);
acacia(cx+16, cz+33);
acacia(cx-30, cz-16);

var bush = [[-31,5],[-29,9],[30,4],[28,-6],[9,31],[-12,30],[22,-30],[-24,-29],[31,20],[-33,-6],[14,-32],[-8,32]];
for (i = 0; i < bush.length; i++) {
  pb(cx+bush[i][0], GY+1, cz+bush[i][1], (i % 3 === 0) ? "dead_bush" : "short_grass");
}
pb(cx-34, GY+1, cz+2, "cactus");
pb(cx+34, GY+1, cz+9, "cactus");
ck("DONE");

Static Renders

Indian stepwell (baoli) — guided isometric viewisometric
Indian stepwell (baoli) — guided front viewfront
Indian stepwell (baoli) — guided side viewside
Indian stepwell (baoli) — guided back viewback
Indian stepwell (baoli) — guided top viewtop