// === 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");