// === BUILD PLAN ===
// Style: Victorian cast-iron & glass palm house (botanical glasshouse) in a park
// Footprint: cross/dumbbell plan — W wing 18x13 + octagonal rotunda (r=11) + E wing 18x13
// Height: plinth Y11-13, glazed walls to Y19, barrel vault crown Y26; rotunda drum to Y25, dome crown Y36, cupola Y40
//
// GROUND PLAN (top-down, X right, Z down):
// z24 ################ ####
// x16 D....palm nave....# ((( OCTAGON ))) #....palm nave....D x72
// z36 ################ ####
// Legend: # glazed wall w/ iron ribs, D arched double door, ((( ))) octagon drum
//
// SECTION (through nave, looking east):
// .-~~~-. barrel vault (glass + green iron ribs), crown Y26
// | | glazing Y14..19 between brick pilasters
// |#####| red brick plinth Y12..13
//
// MATERIALS PLAN:
// plinth : bricks(60)+granite(20)+mossy_stone_bricks(20) — WHY: warm red base grounds the glass box
// ribs : green_concrete(55)+green_terracotta(25)+dried_kelp_block(20) — WHY: dark green painted ironwork, contrast vs glass
// glazing : glass(70)+white_stained_glass(18)+light_blue_stained_glass(12) via noise — WHY: fake old uneven panes
// floor : smooth_stone / polished_andesite / stone_bricks mix + podzol planting beds
// gallery : spruce planks + iron_bars railing
// Rooms: planting nave W (palms, ferns, benches), rotunda (pond, 4 giant palms, gallery ring at walk Y20), planting nave E
// STAIR PLAN: rotunda gallery Δ = walk12 -> walk20 (=8) -> staircase(24,30,12,20,"east",{width:2}) then bridge deck into ring
// PROCESS: LAYERED — form in wool placeholders, carve with masks, texture last with replaceMasked
// === END PLAN ===
var CX = 44, CZ = 30, OR = 11;
var WX1 = 16, WX2 = 33; // west wing X span
var EX1 = 55, EX2 = 72; // east wing X span
var WZ1 = 24, WZ2 = 36; // wing Z span
var groundY = 10, floorY = 11, walkY = 12;
var plinthTop = 13;
var wallTopY = 19; // top of glazed wall / vault spring base
var SPRING = 20;
var drumTop = 25; // octagon drum top / dome base
var DOME_R = 11;
var galFloorY = 19, galWalkY = 20;
var brickPal = palette([{block:"bricks",weight:60},{block:"granite",weight:20},{block:"mossy_stone_bricks",weight:20}]);
var ironPal = palette([{block:"green_concrete",weight:55},{block:"green_terracotta",weight:25},{block:"dried_kelp_block",weight:20}]);
var glassPal = noisePalette([{block:"glass",weight:70},{block:"white_stained_glass",weight:18},{block:"light_blue_stained_glass",weight:12}], {freq:0.16, seed:9});
var floorPal = palette([{block:"smooth_stone",weight:45},{block:"polished_andesite",weight:30},{block:"stone_bricks",weight:25}]);
function inOctR(x, z, R) {
var dx = Math.abs(x - CX), dz = Math.abs(z - CZ);
return dx <= R && dz <= R && (dx + dz) <= Math.floor(R * 1.45);
}
function onOctEdge(x, z) {
if (!inOctR(x, z, OR)) return false;
return !(inOctR(x + 1, z, OR) && inOctR(x - 1, z, OR) && inOctR(x, z + 1, OR) && inOctR(x, z - 1, OR));
}
function inWing(x, z) {
return z >= WZ1 && z <= WZ2 && ((x >= WX1 && x <= WX2) || (x >= EX1 && x <= EX2));
}
function inFootprint(x, z) { return inWing(x, z) || inOctR(x, z, OR); }
// arch openings between wings and rotunda (both levels)
function isArchOpening(x, z, y) {
return Math.abs(z - CZ) <= 6 && (x <= CX - 9 || x >= CX + 9) && y >= walkY && y <= 23;
}
// === TERRAIN ===
var land = blob(CX, CZ, 40, {irregularity: 0.35, seed: 4});
var hf = hills({base: 9, amp: 3, seed: 12});
var pad = flatten(hf, {x0: 10, z0: 17, x1: 78, z1: 43}, groundY, 9);
var groundMat = patches(["grass_block", "grass_block", "coarse_dirt", "podzol"], 0.06, 5);
surface(land, pad, groundMat, {sub: "dirt", deep: "stone", depth: 4});
// === CLEAR + FLOOR ===
var x, y, z, i, dx, dz, dy, d;
for (x = WX1 - 1; x <= EX2 + 1; x++) {
for (z = WZ1 - 1; z <= WZ2 + 1; z++) {
if (!inFootprint(x, z)) continue;
fill(x, floorY, z, x, 42, z, "air");
pb(x, floorY, z, floorPal);
pb(x, floorY - 1, z, "stone_bricks");
}
}
for (x = CX - OR - 1; x <= CX + OR + 1; x++) {
for (z = CZ - OR - 1; z <= CZ + OR + 1; z++) {
if (!inOctR(x, z, OR)) continue;
fill(x, floorY, z, x, 42, z, "air");
pb(x, floorY, z, floorPal);
pb(x, floorY - 1, z, "stone_bricks");
}
}
// === FORM (placeholders) ===
// wing walls
function wingShell(x1, x2, doorX) {
var xx, yy, zz;
for (xx = x1; xx <= x2; xx++) {
for (yy = walkY; yy <= wallTopY; yy++) {
pb(xx, yy, WZ1, "blue_wool");
pb(xx, yy, WZ2, "blue_wool");
}
}
for (zz = WZ1; zz <= WZ2; zz++) {
for (yy = walkY; yy <= wallTopY; yy++) pb(doorX, yy, zz, "blue_wool");
}
}
wingShell(WX1, WX2, WX1);
wingShell(EX1, EX2, EX2);
// octagon drum
for (x = CX - OR; x <= CX + OR; x++) {
for (z = CZ - OR; z <= CZ + OR; z++) {
if (!onOctEdge(x, z)) continue;
for (y = walkY; y <= drumTop; y++) {
if (isArchOpening(x, z, y)) continue;
pb(x, y, z, "blue_wool");
}
}
}
// barrel vaults
function vault(x1, x2) {
var xx, ddz, ddy, dd;
for (xx = x1; xx <= x2; xx++) {
for (ddz = -8; ddz <= 8; ddz++) {
for (ddy = 0; ddy <= 8; ddy++) {
dd = Math.sqrt(ddz * ddz + ddy * ddy);
if (dd >= 5.6 && dd < 6.6) pb(xx, SPRING + ddy, CZ + ddz, "red_wool");
}
}
}
}
vault(WX1 - 1, WX2);
vault(EX1, EX2 + 1);
// close vault ends (tympana) at outer ends of each wing
function tympanum(xx) {
var ddz, ddy, dd;
for (ddz = -6; ddz <= 6; ddz++) {
for (ddy = 0; ddy <= 6; ddy++) {
dd = Math.sqrt(ddz * ddz + ddy * ddy);
if (dd < 6.0) pb(xx, SPRING + ddy, CZ + ddz, "blue_wool");
}
}
}
tympanum(WX1 - 1);
tympanum(EX2 + 1);
// close vault-to-drum junction above the arch openings
function junction(xx) {
var ddz, ddy, dd;
for (ddz = -6; ddz <= 6; ddz++) {
for (ddy = 0; ddy <= 6; ddy++) {
dd = Math.sqrt(ddz * ddz + ddy * ddy);
if (dd < 6.0 && SPRING + ddy > 23) pb(xx, SPRING + ddy, CZ + ddz, "blue_wool");
}
}
}
junction(WX2 + 1);
junction(EX1 - 1);
// dome over the rotunda — DIRECT materials in stepped shrinking rings.
// (masks do not see makeSphere writes, so the wool placeholder survived the texture pass;
// building the cap straight in glass + green iron rings also reads cleaner than a raw voxel sphere)
var domeR = [11, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2];
var ri;
for (ri = 0; ri < domeR.length; ri++) {
makeCylinder(CX, drumTop + ri, CZ, (ri % 3 === 0) ? ironPal : glassPal, domeR[ri], 1, true);
}
makeCylinder(CX, drumTop + domeR.length, CZ, ironPal, 2, 1, false);
// guarantee the rotunda volume under the dome is OPEN (no leftover shell blocking the hall/gallery)
for (x = CX - OR; x <= CX + OR; x++) {
for (z = CZ - OR; z <= CZ + OR; z++) {
if (inOctR(x, z, OR - 1)) fill(x, walkY, z, x, drumTop + domeR.length - 1, z, "air");
}
}
// === CARVE (masks) ===
// door openings: west and east ends, 2 wide x 3 tall arched
clearMasked(WX1 - 1, walkY, CZ - 1, WX1, walkY + 2, CZ + 1, onlyMaterial("blue_wool"));
clearMasked(EX2, walkY, CZ - 1, EX2 + 1, walkY + 2, CZ + 1, onlyMaterial("blue_wool"));
// === TEXTURE (replaceMasked, placeholders last) ===
// 1. brick plinth rows
replaceMasked(0, walkY, 0, 87, plinthTop, 59, brickPal, onlyMaterial("blue_wool"));
// 2. iron ribs — vertical mullions every 3 blocks on wing walls, meridians on drum
for (x = WX1; x <= EX2; x++) {
if (x % 3 !== 1) continue;
replaceMasked(x, plinthTop + 1, WZ1 - 1, x, wallTopY, WZ2 + 1, ironPal, onlyMaterial("blue_wool"));
}
for (z = WZ1; z <= WZ2; z++) {
if (z % 3 !== 0) continue;
replaceMasked(WX1 - 1, plinthTop + 1, z, EX2 + 1, wallTopY, z, ironPal, onlyMaterial("blue_wool"));
}
for (x = CX - OR; x <= CX + OR; x++) {
if ((x - CX) % 4 !== 0) continue;
replaceMasked(x, plinthTop + 1, CZ - OR, x, drumTop, CZ + OR, ironPal, onlyMaterial("blue_wool"));
}
for (z = CZ - OR; z <= CZ + OR; z++) {
if ((z - CZ) % 4 !== 0) continue;
replaceMasked(CX - OR, plinthTop + 1, z, CX + OR, drumTop, z, ironPal, onlyMaterial("blue_wool"));
}
// cornice band at the top of the glazed wall
replaceMasked(0, wallTopY, 0, 87, wallTopY, 59, ironPal, onlyMaterial("blue_wool"));
// 3. remaining wall placeholder -> glazing
replaceMasked(0, 0, 0, 87, 55, 59, glassPal, onlyMaterial("blue_wool"));
// 4. vault + dome: ribs then glass
for (x = WX1 - 1; x <= EX2 + 1; x++) {
if (x % 4 !== 0) continue;
replaceMasked(x, SPRING, WZ1 - 2, x, SPRING + 8, WZ2 + 2, ironPal, onlyMaterial("red_wool"));
}
for (x = CX - DOME_R; x <= CX + DOME_R; x++) {
if ((x - CX) % 4 !== 0) continue;
replaceMasked(x, drumTop, CZ - DOME_R, x, drumTop + DOME_R + 1, CZ + DOME_R, ironPal, onlyMaterial("red_wool"));
}
for (z = CZ - DOME_R; z <= CZ + DOME_R; z++) {
if ((z - CZ) % 4 !== 0) continue;
replaceMasked(CX - DOME_R, drumTop, z, CX + DOME_R, drumTop + DOME_R + 1, z, ironPal, onlyMaterial("red_wool"));
}
replaceMasked(0, 0, 0, 87, 55, 59, glassPal, onlyMaterial("red_wool"));
// === EXTERIOR RELIEF: pilasters, cornices, door surrounds, cupola ===
for (x = WX1; x <= EX2; x++) {
if (x % 3 !== 1) continue;
if (x > WX2 + 1 && x < EX1 - 1) continue;
for (y = walkY; y <= wallTopY; y++) {
pb(x, y, WZ1 - 1, y <= plinthTop ? brickPal : ironPal);
pb(x, y, WZ2 + 1, y <= plinthTop ? brickPal : ironPal);
}
ps(x, wallTopY + 1, WZ1 - 1, "stone_brick_slab[type=top]");
ps(x, wallTopY + 1, WZ2 + 1, "stone_brick_slab[type=top]");
ps(x, plinthTop + 1, WZ1 - 1, "granite_wall");
ps(x, plinthTop + 1, WZ2 + 1, "granite_wall");
}
// plinth cap course all round the wings
for (x = WX1 - 1; x <= EX2 + 1; x++) {
if (x > WX2 + 1 && x < EX1 - 1) continue;
ps(x, plinthTop + 1, WZ1 - 1, "stone_brick_slab[type=bottom]");
ps(x, plinthTop + 1, WZ2 + 1, "stone_brick_slab[type=bottom]");
}
// octagon buttress piers
for (x = CX - OR; x <= CX + OR; x++) {
for (z = CZ - OR; z <= CZ + OR; z++) {
if (!onOctEdge(x, z)) continue;
if ((x + z) % 5 !== 0) continue;
if (isArchOpening(x, z, walkY)) continue;
for (y = walkY; y <= plinthTop + 2; y++) pb(x, y, z, brickPal);
}
}
// cupola lantern on the dome
makeCylinder(CX, drumTop + DOME_R, CZ, ironPal, 3, 1, false);
makeCylinder(CX, drumTop + DOME_R + 1, CZ, glassPal, 3, 3, true);
makeCone(CX, drumTop + DOME_R + 4, CZ, ironPal, 4, 4, false);
pb(CX, drumTop + DOME_R + 8, CZ, "lightning_rod");
// === DOORS ===
function archDoor(dx0, dz0, facing) {
ps(dx0, walkY, dz0, "dark_oak_door[facing=" + facing + ",half=lower,hinge=left]");
ps(dx0, walkY + 1, dz0, "dark_oak_door[facing=" + facing + ",half=upper,hinge=left]");
ps(dx0, walkY, dz0 + 1, "dark_oak_door[facing=" + facing + ",half=lower,hinge=right]");
ps(dx0, walkY + 1, dz0 + 1, "dark_oak_door[facing=" + facing + ",half=upper,hinge=right]");
pb(dx0, walkY + 2, dz0, "green_concrete");
pb(dx0, walkY + 2, dz0 + 1, "green_concrete");
pb(dx0, walkY + 3, dz0, glassPal);
pb(dx0, walkY + 3, dz0 + 1, glassPal);
}
archDoor(WX1, CZ - 1, "west");
archDoor(EX2, CZ - 1, "east");
// door surround brickwork
for (y = walkY; y <= walkY + 4; y++) {
pb(WX1, y, CZ - 2, brickPal); pb(WX1, y, CZ + 2, brickPal);
pb(EX2, y, CZ - 2, brickPal); pb(EX2, y, CZ + 2, brickPal);
}
ps(WX1, walkY + 4, CZ - 1, "stone_brick_slab[type=top]");
ps(WX1, walkY + 4, CZ, "stone_brick_slab[type=top]");
ps(EX2, walkY + 4, CZ - 1, "stone_brick_slab[type=top]");
ps(EX2, walkY + 4, CZ, "stone_brick_slab[type=top]");
// === GALLERY RING + STAIRCASE ===
for (x = CX - OR; x <= CX + OR; x++) {
for (z = CZ - OR; z <= CZ + OR; z++) {
if (inOctR(x, z, OR - 1) && !inOctR(x, z, 6)) {
pb(x, galFloorY, z, "spruce_planks");
}
}
}
// bridge deck from the west arch into the ring
fill(WX2 - 2, galFloorY, CZ - 1, CX - OR + 1, galFloorY, CZ + 2, "spruce_planks");
// railing on the inner edge of the ring
for (x = CX - OR; x <= CX + OR; x++) {
for (z = CZ - OR; z <= CZ + OR; z++) {
if (!inOctR(x, z, OR - 1) || inOctR(x, z, 6)) continue;
if (inOctR(x + 1, z, 6) || inOctR(x - 1, z, 6) || inOctR(x, z + 1, 6) || inOctR(x, z - 1, 6)) {
pb(x, galWalkY, z, "iron_bars");
pb(x, galWalkY + 1, z, "iron_bars");
}
}
}
// support columns under the ring
for (x = CX - OR; x <= CX + OR; x++) {
for (z = CZ - OR; z <= CZ + OR; z++) {
if (!inOctR(x, z, OR - 1) || inOctR(x, z, 8)) continue;
if ((x + z) % 6 !== 0) continue;
for (y = walkY; y < galFloorY; y++) pb(x, y, z, "green_concrete");
}
}
staircase(24, CZ, walkY, galWalkY, "east", {width: 2, material: "spruce_stairs"});
// railing beside the stair run
for (x = 23; x <= 33; x++) {
pb(x, walkY + Math.min(8, Math.max(0, x - 23)), CZ - 1, "iron_bars");
}
// === INTERIOR: planting hall ===
function palm(px, py, pz, hh) {
var k, tx, ty, dirs, ddx, ddz;
for (k = 0; k < hh; k++) {
tx = px + (k > hh * 0.6 ? 1 : 0);
pb(tx, py + k, pz, k < 2 ? "jungle_log" : "stripped_jungle_log");
}
tx = px + 1; ty = py + hh - 1;
dirs = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [-1, -1], [1, -1], [-1, 1]];
for (k = 0; k < dirs.length; k++) {
ddx = dirs[k][0]; ddz = dirs[k][1];
ps(tx + ddx, ty, pz + ddz, "jungle_leaves[persistent=true]");
ps(tx + ddx * 2, ty - 1, pz + ddz * 2, "jungle_leaves[persistent=true]");
ps(tx + ddx * 3, ty - 2, pz + ddz * 3, "jungle_leaves[persistent=true]");
}
ps(tx, ty + 1, pz, "jungle_leaves[persistent=true]");
ps(tx, ty, pz, "jungle_leaves[persistent=true]");
}
function bed(x1, z1, x2, z2) {
var xx, zz;
for (xx = x1; xx <= x2; xx++) {
for (zz = z1; zz <= z2; zz++) {
pb(xx, floorY, zz, (xx + zz) % 3 === 0 ? "coarse_dirt" : "podzol");
if ((xx * 3 + zz * 7) % 5 === 0) ps(xx, walkY, zz, "fern");
else if ((xx * 5 + zz) % 7 === 0) pb(xx, walkY, zz, "azalea");
else if ((xx + zz * 2) % 6 === 0) ps(xx, walkY, zz, "grass");
}
}
// brick kerb
for (xx = x1 - 1; xx <= x2 + 1; xx++) {
ps(xx, walkY, z1 - 1, "brick_slab[type=bottom]");
ps(xx, walkY, z2 + 1, "brick_slab[type=bottom]");
}
for (zz = z1 - 1; zz <= z2 + 1; zz++) {
ps(x1 - 1, walkY, zz, "brick_slab[type=bottom]");
ps(x2 + 1, walkY, zz, "brick_slab[type=bottom]");
}
}
// west nave beds + palms
bed(WX1 + 2, WZ1 + 2, WX1 + 6, WZ1 + 4);
bed(WX1 + 2, WZ2 - 4, WX1 + 6, WZ2 - 2);
bed(WX1 + 10, WZ1 + 2, WX1 + 14, WZ1 + 4);
bed(WX1 + 10, WZ2 - 4, WX1 + 14, WZ2 - 2);
palm(WX1 + 3, walkY, WZ1 + 3, 7);
palm(WX1 + 12, walkY, WZ2 - 3, 8);
palm(WX1 + 12, walkY, WZ1 + 3, 6);
// east nave beds + palms
bed(EX1 + 3, WZ1 + 2, EX1 + 7, WZ1 + 4);
bed(EX1 + 3, WZ2 - 4, EX1 + 7, WZ2 - 2);
bed(EX1 + 11, WZ1 + 2, EX1 + 14, WZ1 + 4);
bed(EX1 + 11, WZ2 - 4, EX1 + 14, WZ2 - 2);
palm(EX1 + 4, walkY, WZ1 + 3, 8);
palm(EX1 + 12, walkY, WZ2 - 3, 7);
palm(EX1 + 5, walkY, WZ2 - 3, 6);
// benches along the naves
for (i = 0; i < 4; i++) {
chairStair(WX1 + 4 + i * 6, walkY, CZ - 1, "spruce_stairs", "south");
chairStair(EX1 + 4 + i * 5, walkY, CZ + 1, "spruce_stairs", "north");
}
// rotunda: pond, giant palms, tree ferns
makeCylinder(CX, floorY, CZ, "prismarine_bricks", 5, 1, false);
makeCylinder(CX, floorY, CZ, "water", 4, 1, false);
makeCylinder(CX, floorY + 1, CZ, "prismarine_wall", 5, 1, true);
pb(CX, floorY + 1, CZ, "prismarine_bricks");
pb(CX, floorY + 2, CZ, "prismarine_bricks");
ps(CX, floorY + 3, CZ, "water");
for (i = 0; i < 4; i++) {
ps(CX + (i === 0 ? 2 : i === 1 ? -2 : 0), floorY + 1, CZ + (i === 2 ? 2 : i === 3 ? -2 : 0), "lily_pad");
}
palm(CX - 8, walkY, CZ - 7, 11);
palm(CX + 7, walkY, CZ + 6, 12);
palm(CX - 8, walkY, CZ + 6, 10);
palm(CX + 7, walkY, CZ - 7, 11);
bed(CX - 9, CZ - 8, CX - 6, CZ - 5);
bed(CX + 6, CZ + 4, CX + 9, CZ + 7);
bed(CX - 9, CZ + 4, CX - 6, CZ + 7);
bed(CX + 6, CZ - 8, CX + 9, CZ - 5);
// gallery planters + benches on the ring
for (i = 0; i < 6; i++) {
pb(CX - 9 + i * 3, galWalkY, CZ - 8, "flower_pot");
pb(CX - 9 + i * 3, galWalkY, CZ + 8, "flower_pot");
}
chairStair(CX + 8, galWalkY, CZ, "spruce_stairs", "west");
chairStair(CX - 8, galWalkY, CZ, "spruce_stairs", "east");
// === LIGHTING ===
function hangLantern(lx, ly, lz, chainN) {
var k;
for (k = 0; k < chainN; k++) ps(lx, ly - k, lz, "chain[axis=y]");
ps(lx, ly - chainN, lz, "lantern[hanging=true]");
}
for (i = 0; i < 5; i++) {
hangLantern(WX1 + 3 + i * 4, SPRING - 1, CZ, 2);
hangLantern(EX1 + 2 + i * 4, SPRING - 1, CZ, 2);
}
hangLantern(CX, drumTop + 6, CZ, 6);
hangLantern(CX - 6, drumTop + 2, CZ - 6, 4);
hangLantern(CX + 6, drumTop + 2, CZ + 6, 4);
// standing lanterns on brick posts along the central path
for (i = 0; i < 6; i++) {
x = WX1 + 5 + i * 2;
}
for (i = 0; i < 4; i++) {
pb(CX - 10 + i * 7, walkY, CZ - 3, "bricks");
ps(CX - 10 + i * 7, walkY + 1, CZ - 3, "lantern");
}
// gallery lanterns on the railing posts
for (i = 0; i < 4; i++) {
pb(CX - 9 + i * 6, galWalkY, CZ - 5, "green_concrete");
ps(CX - 9 + i * 6, galWalkY + 1, CZ - 5, "lantern");
}
// === EXTERIOR LANDSCAPING ===
// gravel path from the west door out into the park
for (x = WX1 - 14; x < WX1; x++) {
for (z = CZ - 2; z <= CZ + 2; z++) {
dz = Math.abs(z - CZ);
if (dz <= 2 - (x < WX1 - 9 ? 1 : 0)) {
pb(x, groundY, z, (x + z) % 4 === 0 ? "cobblestone" : "gravel");
fill(x, groundY + 1, z, x, groundY + 3, z, "air");
}
}
}
for (x = EX2 + 1; x <= EX2 + 12; x++) {
for (z = CZ - 2; z <= CZ + 2; z++) {
if (Math.abs(z - CZ) <= 2) {
pb(x, groundY, z, (x + z) % 4 === 0 ? "cobblestone" : "gravel");
fill(x, groundY + 1, z, x, groundY + 3, z, "air");
}
}
}
// lamp posts along the paths
function lamp(lx, lz) {
pb(lx, groundY + 1, lz, "cobblestone_wall");
pb(lx, groundY + 2, lz, "cobblestone_wall");
pb(lx, groundY + 3, lz, "green_concrete");
ps(lx, groundY + 4, lz, "lantern");
}
lamp(WX1 - 5, CZ - 4); lamp(WX1 - 5, CZ + 4);
lamp(EX2 + 5, CZ - 4); lamp(EX2 + 5, CZ + 4);
lamp(CX - 14, CZ - 14); lamp(CX + 14, CZ + 14);
// flower parterre beds outside
function parterre(px, pz) {
var xx, zz;
for (xx = px; xx < px + 5; xx++) {
for (zz = pz; zz < pz + 5; zz++) {
if ((xx - px === 0 || xx - px === 4 || zz - pz === 0 || zz - pz === 4)) {
ps(xx, groundY + 1, zz, "stone_brick_slab[type=bottom]");
} else {
pb(xx, groundY, zz, "coarse_dirt");
ps(xx, groundY + 1, zz, (xx + zz) % 3 === 0 ? "red_tulip" : ((xx + zz) % 3 === 1 ? "oxeye_daisy" : "allium"));
}
}
}
}
parterre(WX1 - 12, CZ - 12);
parterre(WX1 - 12, CZ + 8);
parterre(EX2 + 6, CZ - 12);
parterre(EX2 + 6, CZ + 8);
// hedges + park trees
for (x = WX1 - 13; x <= EX2 + 13; x += 1) {
if (x % 2 === 0) continue;
if (x > WX1 - 2 && x < EX2 + 2) continue;
ps(x, groundY + 1, CZ - 17, "oak_leaves[persistent=true]");
ps(x, groundY + 1, CZ + 17, "oak_leaves[persistent=true]");
}
function parkTree(tx, tz, hh) {
var k;
for (k = 1; k <= hh; k++) pb(tx, groundY + k, tz, "oak_log");
makeSphere(tx, groundY + hh + 1, tz, "oak_leaves[persistent=true]", 3, false);
}
parkTree(WX1 - 10, CZ - 16, 5);
parkTree(EX2 + 9, CZ + 15, 6);
parkTree(CX - 20, CZ + 18, 5);
parkTree(CX + 18, CZ - 18, 6);
// benches in the park
chairStair(WX1 - 6, groundY + 1, CZ - 6, "spruce_stairs", "south");
chairStair(EX2 + 6, groundY + 1, CZ + 6, "spruce_stairs", "north");