// === BUILD PLAN ===
// Style: Gujarati stepwell (vav) — Adalaj type: LINEAR stepped corridor + octagonal well shaft
// Footprint: trench 13 wide (x26..38) x 60 long (z10..70), centre x=32; ground top Y=26 (walk 27)
// Depth: entry Y25 -> corridor descends 1 step / 2 blocks -> landing Y7 -> water Y8 -> shaft floor Y3
//
// SIDE VIEW (north -> south):
// [torana] ___
// ####\__ __ pavilion __ pavilion __ pavilion
// \__ | | | | | |
// \__ steps \ | \ | \| ___
// \_______________________________________|~~~| octagonal shaft
// landing Y7 ~~~ water Y8, floor Y3
//
// TOP VIEW:
// z10 torana gate | z12-48 stepped corridor (11 wide) | z49-52 landing
// z53-68 well shaft with 3 ring galleries (Y12/Y17/Y22) | side retaining walls x26 & x38
//
// MATERIALS PLAN:
// walls/steps upper: noisePalette sandstone(32)+cut_sandstone(28)+smooth_sandstone(24)+chiseled(9)+red_sandstone(7)
// — WHY: ochre ramp with carved-stone speckle
// lower/damp : gradientPalette moss_block -> mud? no -> moss->sandstone->smooth (Y3..Y16)
// — WHY: algae line at the water, fakes depth
// pillars/lintels : cut_sandstone + chiseled capitals — WHY: light frame contrast against speckled walls
// domes/cornices : red_sandstone + red_sandstone_stairs — WHY: ochre accent
// ground : patches sand/coarse_dirt/grass/terracotta
// Rooms: 3 covered pavilion bays over the corridor (galleries at 2 levels), shaft ring galleries
// STAIR PLAN: corridor itself is the stair — 1 block down every 2 blocks of Z (fully navigable ramp of steps)
// === END PLAN ===
function ck(s){ try { print(s); } catch(e) {} }
var cx = 32;
var GY = 26; // top solid ground; walk 27
var WY = 8; // water surface in the shaft
var stone = noisePalette([
{block:"sandstone", weight:32},
{block:"cut_sandstone", weight:28},
{block:"smooth_sandstone", weight:24},
{block:"chiseled_sandstone",weight:9},
{block:"red_sandstone", weight:7}
], {seed:17, freq:0.10});
var damp = gradientPalette(3, 16, [
{block:"moss_block", from:0},
{block:"sandstone", from:0.35},
{block:"smooth_sandstone", from:0.75}
], {noise:0.3, seed:23});
function floorAt(z) {
if (z < 12) return GY;
if (z <= 48) return 25 - Math.floor((z - 12) / 2);
if (z <= 52) return 7;
return 3;
}
var x, z, y, t, i, k;
// === 1. BASE ROCK + TERRAIN ===
ck("TERRAIN");
fill(2, 0, 2, 61, 22, 85, "stone");
var land = blob(cx, 44, 40, {irregularity:0.28, seed:31});
var h = hills({base: GY - 2, amp: 3, scale: 0.04, seed: 12});
var pad = flatten(h, {x0: 6, z0: 4, x1: 58, z1: 82}, GY, 6);
var gmat = patches([
{block:"sand", w:34},
{block:"coarse_dirt", w:26},
{block:"grass_block", w:24},
{block:"terracotta", w:16}
], 0.055, 21);
surface(land, pad, gmat, {sub:"dirt", deep:"stone", depth:4});
// === 2. CARVE THE TRENCH + SHAFT ===
ck("TRENCH");
fill(cx-6, 0, 10, cx+6, GY+9, 70, "air");
// === 3. STEPPED CORRIDOR FLOOR ===
ck("STEPS");
for (z = 10; z <= 52; z++) {
var ft = floorAt(z);
for (x = cx-5; x <= cx+5; x++) {
fill(x, ft-4, z, x, ft, z, (ft <= 16) ? damp : stone);
}
}
// shaft floor
for (z = 53; z <= 69; z++) {
for (x = cx-5; x <= cx+5; x++) {
fill(x, 0, z, x, 3, z, damp);
}
}
// water in the shaft
fill(cx-5, 4, 53, cx+5, WY, 69, "water");
// submerged approach steps from the landing into the water
for (k = 0; k < 3; k++) {
fill(cx-5, 4+k, 53+k, cx+5, 4+k, 53+k, damp);
}
// === 4. SIDE RETAINING WALLS (with pilasters + niches) ===
ck("WALLS");
for (z = 10; z <= 69; z++) {
var fy = floorAt(z);
fill(cx-6, fy-4, z, cx-6, GY, z, stone);
fill(cx+6, fy-4, z, cx+6, GY, z, stone);
if (z % 4 === 0) { // pilaster relief every 4 blocks
fill(cx-5, fy+1, z, cx-5, GY, z, "cut_sandstone");
fill(cx+5, fy+1, z, cx+5, GY, z, "cut_sandstone");
}
if (z % 6 === 3 && z < 53) { // carved niche + lantern
pb(cx-6, fy+2, z, "chiseled_sandstone");
pb(cx+6, fy+2, z, "chiseled_sandstone");
pb(cx-5, fy+3, z, "lantern[hanging=true]");
pb(cx+5, fy+3, z, "lantern[hanging=true]");
}
}
// back wall of the shaft
fill(cx-6, 0, 70, cx+6, GY, 70, stone);
for (y = 6; y <= 22; y += 5) {
fill(cx-3, y, 70, cx+3, y, 70, "chiseled_sandstone");
}
// === 5. PAVILION BAYS OVER THE CORRIDOR (3 storeys of galleries) ===
ck("PAVILIONS");
function pavilionBay(z0, z1) {
var fy = floorAt(z0);
var zz, lv, ly;
// pillars both sides, floor -> ground level
for (zz = z0; zz <= z1; zz++) {
if ((zz - z0) % 3 === 0) {
fill(cx-5, fy+1, zz, cx-5, GY-1, zz, "cut_sandstone");
fill(cx+5, fy+1, zz, cx+5, GY-1, zz, "cut_sandstone");
pb(cx-5, GY-1, zz, "chiseled_sandstone");
pb(cx+5, GY-1, zz, "chiseled_sandstone");
}
}
// intermediate balcony galleries (2 wide each side) with railings
for (lv = 1; lv <= 2; lv++) {
ly = fy + lv * 6;
if (ly >= GY - 2) break;
fill(cx-5, ly, z0, cx-4, ly, z1, "smooth_sandstone");
fill(cx+4, ly, z0, cx+5, ly, z1, "smooth_sandstone");
for (zz = z0; zz <= z1; zz++) {
pb(cx-3, ly+1, zz, "sandstone_wall");
pb(cx+3, ly+1, zz, "sandstone_wall");
}
pb(cx-4, ly+1, z0+1, "lantern");
pb(cx+4, ly+1, z1-1, "lantern");
// navigable link: corridor floor -> gallery 1 (west side), gallery 1 -> gallery 2 (east side)
if (lv === 1) {
staircase(cx-4, z0, fy+1, ly+1, "south", {width:1, material:"sandstone_stairs"});
} else {
staircase(cx+4, z0, fy+7, ly+1, "south", {width:1, material:"sandstone_stairs"});
}
}
// roof deck at ground level + cornice + parapet + chhatri
fill(cx-6, GY, z0, cx+6, GY, z1, "cut_sandstone");
fill(cx-6, GY+1, z0, cx+6, GY+1, z1, "smooth_sandstone");
for (zz = z0; zz <= z1; zz++) {
roofStair(cx-7, GY, zz, "red_sandstone_stairs", "west", "top");
roofStair(cx+7, GY, zz, "red_sandstone_stairs", "east", "top");
pb(cx-6, GY+2, zz, "sandstone_wall");
pb(cx+6, GY+2, zz, "sandstone_wall");
}
}
pavilionBay(20, 25);
pavilionBay(32, 37);
pavilionBay(44, 49);
// === 6. WELL SHAFT RING GALLERIES ===
ck("SHAFT");
for (k = 0; k < 3; k++) {
var gy = 12 + k * 5;
fill(cx-5, gy, 54, cx-4, gy, 68, "smooth_sandstone");
fill(cx+4, gy, 54, cx+5, gy, 68, "smooth_sandstone");
fill(cx-3, gy, 67, cx+3, gy, 68, "smooth_sandstone");
for (z = 54; z <= 68; z += 3) {
fill(cx-4, gy+1, z, cx-4, gy+4, z, "cut_sandstone");
fill(cx+4, gy+1, z, cx+4, gy+4, z, "cut_sandstone");
}
for (z = 54; z <= 68; z++) {
pb(cx-3, gy+1, z, "sandstone_wall");
pb(cx+3, gy+1, z, "sandstone_wall");
}
pb(cx-4, gy+1, 56, "lantern");
pb(cx+4, gy+1, 62, "lantern");
pb(cx-4, gy+1, 65, "lantern");
}
// === 7. RIM PARAPET, TORANA GATE, CHHATRIS ===
ck("RIM");
for (z = 10; z <= 70; z++) {
pb(cx-7, GY+1, z, "sandstone_wall");
pb(cx+7, GY+1, z, "sandstone_wall");
}
fill(cx-7, GY+1, 70, cx+7, GY+1, 70, "sandstone_wall");
function chhatri(bx, by, bz, r) {
var offs = [[-r,-r],[r,-r],[-r,r],[r,r]];
var j;
for (j = 0; j < 4; j++) {
fill(bx+offs[j][0], by, bz+offs[j][1], bx+offs[j][0], by+3, bz+offs[j][1], "cut_sandstone");
}
fill(bx-r, by+4, bz-r, bx+r, by+4, bz-r, "cut_sandstone");
fill(bx-r, by+4, bz+r, bx+r, by+4, bz+r, "cut_sandstone");
fill(bx-r, by+4, bz-r, bx-r, by+4, bz+r, "cut_sandstone");
fill(bx+r, by+4, bz-r, bx+r, by+4, bz+r, "cut_sandstone");
makeCylinder(bx, by+5, bz, "red_sandstone", r, 1, true);
makeCylinder(bx, by+6, bz, "red_sandstone", r-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-10, GY+1, 56, 2);
chhatri(cx+10, GY+1, 56, 2);
chhatri(cx-10, GY+1, 66, 2);
chhatri(cx+10, GY+1, 66, 2);
// torana entrance gate at the north end
fill(cx-5, GY+1, 9, cx-5, GY+6, 9, "cut_sandstone");
fill(cx+5, GY+1, 9, cx+5, GY+6, 9, "cut_sandstone");
fill(cx-5, GY+7, 9, cx+5, GY+7, 9, "cut_sandstone");
fill(cx-5, GY+8, 9, cx+5, GY+8, 9, "chiseled_sandstone");
pb(cx-4, GY+6, 9, "sandstone_stairs[facing=east,half=top]");
pb(cx+4, GY+6, 9, "sandstone_stairs[facing=west,half=top]");
pb(cx-3, GY+7, 9, "red_sandstone");
pb(cx+3, GY+7, 9, "red_sandstone");
pb(cx, GY+9, 9, "red_sandstone");
pb(cx-2, GY+5, 9, "lantern[hanging=true]");
pb(cx+2, GY+5, 9, "lantern[hanging=true]");
// === 8. APPROACH + VEGETATION ===
ck("DETAIL");
fill(cx-3, GY, 4, cx+3, GY, 9, "dirt_path");
fill(cx-4, GY, 10, cx+4, GY, 11, "smooth_sandstone");
for (i = 0; i < 6; i++) {
fill(cx-6 - 1, GY+1, 12 + i*10, cx-7, GY+2, 12 + i*10, "cut_sandstone");
pb(cx-7, GY+3, 12 + i*10, "lantern");
fill(cx+7, GY+1, 12 + i*10, cx+7, GY+2, 12 + i*10, "cut_sandstone");
pb(cx+7, GY+3, 12 + i*10, "lantern");
}
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);
}
acacia(cx-14, 20);
acacia(cx+15, 34);
acacia(cx-16, 48);
acacia(cx+13, 12);
acacia(cx-13, 74);
var bush = [[-12,15],[-15,27],[13,22],[16,41],[-11,60],[14,63],[-17,70],[11,76],[-9,78],[18,52],[-19,36],[9,8]];
for (i = 0; i < bush.length; i++) {
pb(cx+bush[i][0], GY+1, bush[i][1], (i % 3 === 0) ? "dead_bush" : "short_grass");
}
pb(cx-20, GY+1, 44, "cactus");
pb(cx+19, GY+1, 26, "cactus");
ck("DONE");