// === BUILD PLAN ===
// Subject: COLOSSAL BIGHORN RAM statue on a windswept rocky ledge (ORGANIC)
// Scale: ~30 long (z27..70), ~32 tall (y21..53), 18 wide. Ledge pad Y20, hooves Y21, cliff falls away at z>58.
//
// SIDE SILHOUETTE (z ->, y up): horn spiral curls back-down-forward past the jaw
// ...ooo... o = horn coil (1.5 turns, r6.5->3)
// ...#####HH...H H = head + blunt muzzle held HIGH
// ..#########NN. N = short thick neck
// .###########RR R = woolly chest ruff (wool, lighter)
// .#####BBBB#### B = barrel body (rx8 ry7 rz13) + withers hump
// ..P##.......## P = pale grey RUMP patch (low z)
// LL LL L = short sturdy legs (7 tall, tapered, black hooves)
//
// FRONT SILHOUETTE: broad chest, horns flare OUTWARD (x offset grows with the coil)
// o.........o
// .o..HHH..o.
// ..#####..
// .#######.
// L.....L
//
// MATERIALS PLAN:
// hide : brown_terracotta(40)+orange_terracotta(25)+brown_concrete(20)+dark_oak_planks(15) - WHY: tan-brown with natural variation
// back : darker (brown_concrete/dark_oak) driven by a hash -> fakes top-light shading (volume)
// rump : light_gray_terracotta+light_gray_concrete+smooth_stone - WHY: the pale bighorn rump patch reads at a glance
// ruff : white_wool+light_gray_wool - WHY: woolly texture contrast against smooth terracotta
// horns : smooth_sandstone+light_gray_terracotta with DARK GROWTH RINGS every 6 samples - WHY: the diagnostic feature
// legs : brown_concrete + blackstone hooves
// rock : hills()+blob()+flatten() pad, patches stone/andesite/gravel + snow + dead bushes (windswept)
// === END PLAN ===
// ---------- helpers ----------
function wob(x, y, z) {
var s = Math.sin(x * 12.9898 + y * 78.233 + z * 37.719) * 43758.5453;
return s - Math.floor(s);
}
function ellip(cx, cy, cz, rx, ry, rz, matFn, wobAmt) {
var x, y, z, dx, dy, dz, v;
for (x = Math.floor(cx - rx - 1); x <= Math.ceil(cx + rx + 1); x++) {
for (y = Math.floor(cy - ry - 1); y <= Math.ceil(cy + ry + 1); y++) {
for (z = Math.floor(cz - rz - 1); z <= Math.ceil(cz + rz + 1); z++) {
dx = (x - cx) / rx; dy = (y - cy) / ry; dz = (z - cz) / rz;
v = dx * dx + dy * dy + dz * dz;
if (v <= 1 + (wob(x, y, z) - 0.5) * wobAmt) pb(x, y, z, matFn(x, y, z));
}
}
}
}
function blobSph(cx, cy, cz, r, matFn) { ellip(cx, cy, cz, r, r, r, matFn, 0.12); }
// ---------- palettes ----------
var hidePal = noisePalette([{ block: 'brown_terracotta', weight: 40 }, { block: 'orange_terracotta', weight: 25 }, { block: 'brown_concrete', weight: 20 }, { block: 'dark_oak_planks', weight: 15 }], { seed: 17 });
var palePal = noisePalette([{ block: 'light_gray_terracotta', weight: 50 }, { block: 'light_gray_concrete', weight: 25 }, { block: 'smooth_stone', weight: 25 }], { seed: 4 });
var darkPal = noisePalette([{ block: 'brown_concrete', weight: 55 }, { block: 'dark_oak_planks', weight: 25 }, { block: 'brown_terracotta', weight: 20 }], { seed: 23 });
var woolPal = noisePalette([{ block: 'white_wool', weight: 45 }, { block: 'light_gray_wool', weight: 35 }, { block: 'smooth_quartz', weight: 20 }], { seed: 31 });
var hornPal = noisePalette([{ block: 'smooth_sandstone', weight: 45 }, { block: 'light_gray_terracotta', weight: 30 }, { block: 'cut_sandstone', weight: 25 }], { seed: 12 });
// hide with rump patch + top-lit darker back + lighter belly (palette by VOLUME, not random confetti)
function hide(x, y, z) {
if (z <= 31 && y >= 30 && y <= 40) return palePal(x, y, z); // pale grey rump patch
var t = wob(x, y, z);
if (y >= 39 && t < 0.45) return darkPal(x, y, z); // shaded/darker back line
if (y <= 29 && t < 0.35) return 'brown_terracotta'; // belly
return hidePal(x, y, z);
}
// ---------- TERRAIN: windswept rocky ledge with a drop on the sea side (+Z) ----------
var hb = hills({ base: 0, amp: 5, scale: 0.055, seed: 21 });
var ledge = function (x, z) {
var b0 = 20;
if (z > 58) { b0 = 20 - (z - 58) * 1.5; if (b0 < 2) b0 = 2; }
if (x < 14) b0 = b0 - (14 - x) * 0.7;
return b0 + hb(x, z) * 0.7;
};
var pad = flatten(ledge, { x0: 26, z0: 24, x1: 54, z1: 56 }, 20, 9);
var land = blob(40, 34, 40, { irregularity: 0.35, seed: 9 });
var rockPat = patches([{ block: 'stone', w: 34 }, { block: 'andesite', w: 22 }, { block: 'cobblestone', w: 16 }, { block: 'gravel', w: 16 }, { block: 'moss_block', w: 6 }, { block: 'coarse_dirt', w: 6 }], 0.07, 5);
var screePat = patches([{ block: 'gravel', w: 45 }, { block: 'cobblestone', w: 25 }, { block: 'stone', w: 30 }], 0.09, 15);
surface(land, pad, function (x, z) { return (pad(x, z) < 14) ? screePat(x, z) : rockPat(x, z); }, { sub: 'stone', deep: 'deepslate', depth: 5 });
// ---------- LEGS (short, sturdy, tapered, black hooves) ----------
function leg(lx, lz) {
fill(lx, 25, lz, lx + 3, 28, lz + 3, darkPal); // upper leg 4x4
fill(lx, 22, lz + 1, lx + 2, 24, lz + 2, darkPal); // cannon bone 3x2
fill(lx, 21, lz, lx + 2, 21, lz + 2, 'blackstone'); // hoof
pb(lx + 1, 22, lz, 'blackstone'); pb(lx + 1, 22, lz + 3, 'blackstone');
}
leg(34, 46); leg(43, 46); // front pair
leg(34, 31); leg(43, 31); // rear pair
// ---------- BODY: barrel + haunches + withers hump ----------
ellip(40, 34, 40, 8, 7, 13, hide, 0.10); // barrel body
ellip(40, 33, 31, 7.5, 6.5, 6, hide, 0.10); // hindquarters / haunch mass
ellip(40, 40, 45, 7, 4.5, 7, hide, 0.10); // withers hump (bighorn shoulder)
pb(40, 30, 27, 'brown_concrete'); // short tail
pb(40, 29, 26, 'brown_concrete'); pb(40, 28, 26, 'dark_oak_planks');
// ---------- WOOLLY CHEST RUFF ----------
ellip(40, 37, 50, 8.5, 5.5, 4.5, function (x, y, z) { return woolPal(x, y, z); }, 0.22);
ellip(40, 41, 51, 6.5, 4, 3.5, function (x, y, z) { return woolPal(x, y, z); }, 0.22);
// ---------- NECK (short, thick, angled up) + HEAD held HIGH ----------
var s, u, nx, ny, nz;
for (s = 0; s <= 12; s++) {
u = s / 12;
ny = 41 + u * 6;
nz = 50 + u * 9;
blobSph(40, ny, nz, 6 - u * 1.6, hide);
}
ellip(40, 47.5, 62, 4.6, 4.2, 5.2, hide, 0.10); // skull
ellip(40, 45.5, 67, 3.2, 3.0, 3.6, function (x, y, z) { // broad blunt muzzle
return (wob(x, y, z) < 0.5) ? 'brown_concrete' : 'dark_oak_planks';
}, 0.08);
pb(38, 45, 70, 'black_concrete'); pb(42, 45, 70, 'black_concrete'); // nostrils
fill(38, 43, 69, 42, 43, 69, 'black_concrete'); // mouth line
// eyes (amber ring + dark pupil)
pb(36, 49, 64, 'orange_terracotta'); pb(35, 49, 63, 'black_concrete');
pb(44, 49, 64, 'orange_terracotta'); pb(45, 49, 63, 'black_concrete');
// ears, swept back under the horn bases
ellip(34, 47, 59, 2.2, 1.2, 3, function () { return 'brown_concrete'; }, 0.1);
ellip(46, 47, 59, 2.2, 1.2, 3, function () { return 'brown_concrete'; }, 0.1);
// ---------- HORNS: massive curled spiral, 1.5 turns, coiling down-back-forward ----------
function horn(hx, side) {
var i, t, th, r, cy = 46, cz = 58, px, py, pz, rad, ring;
for (i = 0; i <= 96; i++) {
t = i / 96;
th = (90 + t * 540) * Math.PI / 180; // 1.5 turns
r = 9.0 - t * 4.6; // WIDER coil so the turns separate and the spiral reads
py = cy + Math.sin(th) * r;
pz = cz + Math.cos(th) * r;
px = hx + side * (t * 4.2); // flares outward as it coils
rad = 2.3 - t * 1.0; // THINNER horn tube -> visible gap between the coils
ring = (i % 8 < 2); // growth rings
blobSph(px, py, pz, rad, ring
? function (x, y, z) { return (wob(x, y, z) < 0.6) ? 'brown_terracotta' : 'light_gray_terracotta'; }
: function (x, y, z) { return hornPal(x, y, z); });
}
}
horn(35, -1);
horn(45, 1);
// horn bosses where they meet the skull
blobSph(36, 50, 60, 2.4, function (x, y, z) { return hornPal(x, y, z); });
blobSph(44, 50, 60, 2.4, function (x, y, z) { return hornPal(x, y, z); });
// ---------- LEDGE DRESSING: boulders, alpine scrub, snow, wind-bent detail ----------
blobSph(24, 22, 30, 4, function (x, y, z) { return rockPat(x, z); });
blobSph(56, 23, 44, 5, function (x, y, z) { return rockPat(x, z); });
blobSph(30, 21, 52, 3, function (x, y, z) { return rockPat(x, z); });
var bx, bz, hh;
for (bx = 12; bx <= 68; bx += 3) {
for (bz = 10; bz <= 62; bz += 3) {
hh = Math.round(pad(bx, bz));
if (hh < 6) continue;
var w2 = wob(bx, hh, bz);
if (w2 < 0.18) pb(bx, hh + 1, bz, 'dead_bush');
else if (w2 < 0.34) pb(bx, hh + 1, bz, 'short_grass');
else if (w2 < 0.42) pb(bx, hh + 1, bz, 'stone');
else if (w2 < 0.48) ps(bx, hh + 1, bz, 'snow[layers=2]');
}
}
// a couple of wind-stunted spruces on the ledge
placeTree(18, Math.round(pad(18, 20)) + 1, 20, 'spruce');
placeTree(62, Math.round(pad(62, 26)) + 1, 26, 'spruce');
// snow dusting on the ram's back
var sx2, sz2;
for (sx2 = 33; sx2 <= 47; sx2++) {
for (sz2 = 30; sz2 <= 50; sz2++) {
if (wob(sx2, 99, sz2) < 0.10) ps(sx2, 42, sz2, 'snow[layers=1]');
}
}