// === BUILD PLAN ===
// Style: polar research icebreaker, HOUSE-FORWARD layout with a long open aft working deck.
// Orientation: keel along Z, BOW at +Z (rule 15 — the iso sees the +Z/+X faces, so the bow
// quarter is the money shot). Centreline X=46. Length 81 (Z30..110), beam 19 -> ~4.3:1,
// which matches the doc's "beam = 1/3 length" band for a beamy icebreaker.
//
// SIDE PROFILE (stern left, bow right):
// 42 [MACK]
// 37 ___BRIDGE___
// 32 __ _| L3 |_
// 27 |A | | L2 |
// 23 __|F |___|______L1_______|________
// 22 === AFT WORKING DECK ==== FOREDECK ====\ <- raked stem rides ONTO the floe
// 18 ~~~~~~~~ ice sheet / waterline ~~~~~~~
// 08 \________ elliptical hull + keel ______/
//
// HULL CROSS-SECTION (doc formula, NOT a linear bevel): full beam AT the waterline,
// narrowing to the keel on an ELLIPSE -> colBot = WL+1 - depth*sqrt(1-(dx/half)^2)
// .....#########..... deck (cambered: centre strip +1 slab)
// ....#.........#.... orange topsides
// ...#...........#... black boot-top AT the waterline
// ....#.........#.... red antifouling
// ......#.....#......
// .........K......... K = keel strip (dark, explicit — flat-bottom ships look wrong)
//
// MATERIALS PLAN (part -> palette -> WHY):
// below WL : red_terracotta/red_concrete — WHY: antifouling, duller than the topsides on purpose
// boot top : black_concrete — WHY: one hard dark line makes the waterline READ
// topsides : orange_concrete/orange_terracotta — WHY: polar orange, the single loudest cue
// house : white/smooth_quartz noise — WHY: maximum value contrast above the orange
// mack : red + white band + black cap — WHY: the classic funnel banding, read from far
// deck : gray/light_gray/andesite — WHY: steel plate; green working-deck paint patches
// floe : patches blue_ice/packed_ice/snow — WHY: BIG floe blotches, ridges where it is shoved
// Rooms: BRIDGE (helm, console bank, chart table, radar, chairs) + WET LAB on L1
// (benches, microscope-ish, sample crates, chart wall)
// STAIR PLAN: staircase(38,?,...) on the port side deck: 23->28 then 28->33, each flush onto
// the deck above; nothing else is ever placed in that lane.
// === END PLAN ===
var CK = [];
function ck(m) { CK.push(m); }
ck('PLAN');
var WL = 17, iceY = 18, CXc = 46;
// ---------- palettes ----------
var below = noisePalette([
{ block: 'red_terracotta', weight: 52 },
{ block: 'red_concrete', weight: 30 },
{ block: 'brown_terracotta', weight: 18 }
], { seed: 41, freq: 0.10 });
var above = noisePalette([
{ block: 'orange_concrete', weight: 58 },
{ block: 'orange_terracotta', weight: 27 },
{ block: 'red_concrete', weight: 15 }
], { seed: 47, freq: 0.12 });
var housePal = noisePalette([
{ block: 'white_concrete', weight: 60 },
{ block: 'smooth_quartz', weight: 24 },
{ block: 'light_gray_concrete', weight: 16 }
], { seed: 53, freq: 0.13 });
var deckPal = noisePalette([
{ block: 'gray_concrete', weight: 42 },
{ block: 'light_gray_concrete', weight: 28 },
{ block: 'andesite', weight: 18 },
{ block: 'green_concrete', weight: 12 }
], { seed: 59, freq: 0.16 });
var floeMat = patches([
{ block: 'packed_ice', w: 36 },
{ block: 'snow_block', w: 32 },
{ block: 'blue_ice', w: 18 },
{ block: 'ice', w: 14 }
], 0.04, 13);
// ---------- SEA + FLOE ----------
fill(0, 1, 0, 95, 3, 127, 'gravel');
fill(0, 4, 0, 95, WL, 127, 'water');
var rid = hills({ base: iceY, amp: 2.6, scale: 0.07, seed: 29 });
var floeH = function (x, z) {
var v = Math.round(rid(x, z));
if (v < iceY) { v = iceY; }
return v;
};
surface(function (x, z) { return true; }, floeH, floeMat,
{ sub: 'packed_ice', deep: 'water', depth: 2, bounds: { x0: 0, z0: 0, x1: 95, z1: 127 } });
ck('FLOE');
// ---------- BROKEN LEAD astern (meander -> fractal, never a straight cut) ----------
var wake = meander(46, 0, 48, 34, { amplitude: 9, bends: 3, seed: 17 });
var lx4, lz4, dd4, hw4;
for (lz4 = 0; lz4 <= 36; lz4++) {
for (lx4 = 24; lx4 <= 70; lx4++) {
dd4 = wake(lx4, lz4);
hw4 = 10 - lz4 * 0.13;
if (dd4 < hw4) {
fill(lx4, iceY, lz4, lx4, iceY + 3, lz4, 'air');
pb(lx4, WL, lz4, 'water');
}
}
}
var bf, bx4, bz4;
for (bf = 0; bf < 60; bf++) {
bx4 = 26 + (bf * 11) % 40;
bz4 = 1 + (bf * 7) % 32;
if (wake(bx4, bz4) < 9 - bz4 * 0.12) {
ps(bx4, iceY, bz4, (bf % 3 === 0) ? 'ice' : 'packed_ice');
if (bf % 4 === 0) { ps(bx4 + 1, iceY, bz4, 'blue_ice'); ps(bx4, iceY, bz4 + 1, 'packed_ice'); }
if (bf % 6 === 0) { ps(bx4, iceY + 1, bz4, 'packed_ice_slab'); }
}
}
ck('LEAD');
// ---------- HULL: elliptical cross-sections + explicit KEEL + cambered deck ----------
function hBeam(z) {
if (z < 30 || z > 110) { return -1; }
if (z < 36) { return 5 + (z - 30) * 0.7; }
if (z <= 92) { return 9; }
if (z <= 102) { return 9 - (z - 92) * 0.4; }
if (z <= 108) { return 5 - (z - 102) * 0.55; }
return 1.5;
}
function hBot(z) {
var y = 8;
if (z > 88) { y = 8 + Math.round((z - 88) * 12 / 22); }
if (z < 38) { y = 8 + Math.round((38 - z) * 0.55); }
return y;
}
function hTop(z) {
if (z <= 96) { return 21; }
return 21 + Math.round((z - 96) * 4 / 14);
}
var sz5, dx5, half5, bot5, top5, curve5, colB, xx5;
for (sz5 = 30; sz5 <= 110; sz5++) {
half5 = Math.round(hBeam(sz5));
if (half5 < 0) { continue; }
bot5 = hBot(sz5);
top5 = hTop(sz5);
curve5 = (WL + 1) - bot5;
if (curve5 < 1) { curve5 = 1; }
for (dx5 = -half5; dx5 <= half5; dx5++) {
xx5 = CXc + dx5;
var ratio = (half5 === 0) ? 0 : (Math.abs(dx5) / half5);
var sq = 1 - ratio * ratio;
if (sq < 0) { sq = 0; }
colB = Math.round((WL + 1) - curve5 * Math.sqrt(sq));
if (colB < bot5) { colB = bot5; }
if (colB > top5) { colB = top5; }
if (colB > WL) {
fill(xx5, colB, sz5, xx5, top5, sz5, above);
} else {
fill(xx5, colB, sz5, xx5, WL - 1, sz5, below);
pb(xx5, WL, sz5, 'black_concrete');
fill(xx5, WL + 1, sz5, xx5, top5, sz5, above);
}
// stair/slab curve transition on the outermost wet column (half=top follows the convex bilge)
if (Math.abs(dx5) === half5 - 1 && colB - 1 > bot5 && colB - 1 < WL) {
ps(xx5, colB - 1, sz5, 'red_sandstone_stairs[facing=' + ((dx5 < 0) ? 'east' : 'west') + ',half=top]');
}
}
// KEEL strip (explicit — flat-bottom ships look wrong)
pb(CXc, bot5 - 1, sz5, 'polished_blackstone');
if (half5 >= 6) { pb(CXc - 1, bot5 - 1, sz5, 'polished_blackstone'); pb(CXc + 1, bot5 - 1, sz5, 'polished_blackstone'); }
// DECK with camber (centre strip crowned with a slab)
fill(CXc - half5, top5 + 1, sz5, CXc + half5, top5 + 1, sz5, deckPal);
if (half5 >= 4) {
ps(CXc - 1, top5 + 2, sz5, 'smooth_stone_slab[type=bottom]');
ps(CXc, top5 + 2, sz5, 'smooth_stone_slab[type=bottom]');
ps(CXc + 1, top5 + 2, sz5, 'smooth_stone_slab[type=bottom]');
}
// bulwark + rail
if (half5 >= 2) {
pb(CXc - half5, top5 + 2, sz5, above(CXc - half5, top5 + 2, sz5));
pb(CXc + half5, top5 + 2, sz5, above(CXc + half5, top5 + 2, sz5));
ps(CXc - half5, top5 + 3, sz5, (sz5 % 3 === 0) ? 'iron_bars' : 'light_gray_stained_glass_pane');
ps(CXc + half5, top5 + 3, sz5, (sz5 % 3 === 0) ? 'iron_bars' : 'light_gray_stained_glass_pane');
}
}
// reinforced ice-knife stem
var st5;
for (st5 = 0; st5 <= 9; st5++) {
pb(CXc, 15 + st5, 103 + st5 - 1, 'polished_blackstone');
pb(CXc, 16 + st5, 103 + st5 - 1, 'black_concrete');
if (st5 < 7) {
pb(CXc - 1, 15 + st5, 103 + st5 - 1, 'polished_blackstone');
pb(CXc + 1, 15 + st5, 103 + st5 - 1, 'polished_blackstone');
}
}
// ice belt (a darker band at the waterline both sides, real icebreaker detail)
var ib;
for (ib = 34; ib <= 104; ib++) {
var hbb = Math.round(hBeam(ib));
if (hbb < 2) { continue; }
pb(CXc - hbb, WL + 1, ib, 'black_concrete');
pb(CXc + hbb, WL + 1, ib, 'black_concrete');
}
// draft marks / name plate
ps(CXc - 9, WL + 3, 96, 'white_concrete'); ps(CXc - 9, WL + 5, 92, 'white_concrete');
ps(CXc + 9, WL + 3, 96, 'white_concrete'); ps(CXc + 9, WL + 5, 92, 'white_concrete');
ck('HULL');
// ---------- SHOVED ICE at the bow + cracks ----------
var kx5, kz5;
for (kz5 = 100; kz5 <= 122; kz5++) {
for (kx5 = 30; kx5 <= 62; kx5++) {
if ((kx5 * 3 + kz5 * 5) % 9 < 3) { pb(kx5, iceY + 1, kz5, 'packed_ice'); }
if ((kx5 * 5 + kz5 * 3) % 13 < 2) { pb(kx5, iceY + 2, kz5, 'snow_block'); }
if ((kx5 + kz5 * 2) % 19 === 0) { ps(kx5, iceY + 1, kz5, 'packed_ice_slab'); }
}
}
for (kz5 = 104; kz5 <= 124; kz5++) {
kx5 = 46 + Math.round(Math.sin(kz5 * 0.42) * 5);
pb(kx5, iceY, kz5, 'water');
pb(kx5 + 1, iceY, kz5, 'ice');
}
ck('SHOVE');
// ---------- SUPERSTRUCTURE (house FORWARD of midships) ----------
// L1
fill(37, 23, 64, 55, 27, 86, housePal);
fill(38, 23, 65, 54, 27, 85, 'air');
fill(36, 28, 62, 56, 28, 88, deckPal);
var wz5;
for (wz5 = 66; wz5 <= 84; wz5 += 2) {
fill(37, 24, wz5, 37, 25, wz5, 'light_blue_stained_glass');
fill(55, 24, wz5, 55, 25, wz5, 'light_blue_stained_glass');
}
fill(40, 24, 86, 52, 25, 86, 'light_blue_stained_glass');
fill(41, 23, 64, 43, 24, 64, 'air');
// L2
fill(38, 29, 66, 54, 32, 86, housePal);
fill(39, 29, 67, 53, 32, 85, 'air');
fill(37, 33, 64, 55, 33, 88, deckPal);
for (wz5 = 68; wz5 <= 84; wz5 += 2) {
fill(38, 30, wz5, 38, 31, wz5, 'light_blue_stained_glass');
fill(54, 30, wz5, 54, 31, wz5, 'light_blue_stained_glass');
}
fill(41, 30, 86, 51, 31, 86, 'light_blue_stained_glass');
// L3 + BRIDGE (forward end, wraparound glass)
fill(39, 34, 72, 53, 37, 87, housePal);
fill(40, 34, 73, 52, 37, 86, 'air');
fill(38, 38, 70, 54, 38, 89, housePal);
fill(41, 35, 87, 51, 36, 87, 'light_blue_stained_glass');
fill(39, 35, 74, 39, 36, 86, 'light_blue_stained_glass');
fill(53, 35, 74, 53, 36, 86, 'light_blue_stained_glass');
// bridge WINGS, carried on columns (rule: never floating)
fill(33, 33, 80, 38, 33, 85, deckPal);
fill(54, 33, 80, 59, 33, 85, deckPal);
var wgi;
for (wgi = 80; wgi <= 85; wgi++) {
ps(33, 34, wgi, 'iron_bars'); ps(59, 34, wgi, 'iron_bars');
}
fill(33, 34, 80, 38, 34, 80, 'iron_bars');
fill(54, 34, 80, 59, 34, 80, 'iron_bars');
fill(33, 34, 85, 38, 34, 85, 'iron_bars');
fill(54, 34, 85, 59, 34, 85, 'iron_bars');
fill(34, 29, 82, 34, 32, 82, 'white_concrete');
fill(58, 29, 82, 58, 32, 82, 'white_concrete');
ps(34, 28, 82, 'iron_bars'); ps(58, 28, 82, 'iron_bars');
// mast + radar over the bridge
fill(46, 39, 78, 46, 48, 78, 'iron_block');
fill(43, 44, 78, 49, 44, 78, 'iron_bars');
fill(46, 44, 75, 46, 44, 81, 'iron_bars');
makeSphere(46, 47, 78, 'white_concrete', 2, false);
ps(46, 49, 78, 'lightning_rod[facing=up]');
ps(43, 43, 78, 'redstone_lamp'); ps(49, 43, 78, 'redstone_lamp');
ps(44, 40, 76, 'sea_lantern'); ps(48, 40, 76, 'sea_lantern');
ps(39, 39, 86, 'sea_lantern'); ps(53, 39, 86, 'sea_lantern');
ps(39, 39, 72, 'sea_lantern'); ps(53, 39, 72, 'sea_lantern');
ck('HOUSE');
// ---------- MACK / FUNNEL (aft end of the house, rectangular casing) ----------
fill(41, 29, 56, 51, 40, 62, 'red_concrete');
fill(42, 29, 57, 50, 40, 61, 'air');
fill(41, 35, 56, 51, 36, 62, 'white_concrete');
fill(42, 35, 57, 50, 36, 61, 'air');
fill(41, 41, 56, 51, 41, 62, 'black_concrete');
fill(43, 42, 58, 49, 42, 60, 'gray_concrete');
fill(44, 42, 59, 48, 42, 59, 'campfire[lit=true]');
// company mark on the funnel
fill(45, 32, 55, 47, 33, 55, 'white_concrete');
fill(45, 32, 63, 47, 33, 63, 'white_concrete');
fill(41, 28, 56, 51, 28, 62, deckPal);
// exhaust pipes
fill(40, 42, 57, 40, 45, 57, 'iron_bars');
fill(52, 42, 61, 52, 45, 61, 'iron_bars');
ck('FUNNEL');
// ---------- AFT WORKING DECK: painted heli circle, A-frame, containers, moon pool ----------
var px5, pz5, ddx5, ddz5, rr5;
for (px5 = 36; px5 <= 56; px5++) {
for (pz5 = 36; pz5 <= 54; pz5++) {
ddx5 = px5 - 46; ddz5 = pz5 - 45;
rr5 = ddx5 * ddx5 + ddz5 * ddz5;
if (rr5 <= 64 && rr5 >= 49) { pb(px5, 22, pz5, 'yellow_concrete'); }
if (rr5 < 49) { pb(px5, 22, pz5, 'gray_concrete'); }
}
}
fill(44, 22, 43, 44, 22, 47, 'white_concrete');
fill(48, 22, 43, 48, 22, 47, 'white_concrete');
fill(45, 22, 45, 47, 22, 45, 'white_concrete');
// the parked helicopter (red/white, nose to +Z)
fill(43, 23, 44, 45, 24, 50, 'white_concrete');
fill(43, 23, 48, 45, 24, 50, 'red_concrete');
fill(43, 23, 50, 45, 24, 50, 'light_blue_stained_glass');
fill(44, 24, 38, 44, 24, 43, 'white_concrete');
fill(44, 24, 37, 44, 26, 37, 'red_concrete');
ps(43, 25, 37, 'iron_bars'); ps(45, 25, 37, 'iron_bars');
fill(44, 25, 45, 44, 25, 47, 'gray_concrete');
pb(44, 26, 46, 'iron_block');
var rb5;
for (rb5 = 1; rb5 <= 6; rb5++) {
ps(44 + rb5, 26, 46, 'light_gray_stained_glass_pane');
ps(44 - rb5, 26, 46, 'light_gray_stained_glass_pane');
ps(44, 26, 46 + rb5, 'light_gray_stained_glass_pane');
ps(44, 26, 46 - rb5, 'light_gray_stained_glass_pane');
}
ps(43, 22, 46, 'iron_bars'); ps(45, 22, 46, 'iron_bars');
ps(43, 22, 48, 'iron_bars'); ps(45, 22, 48, 'iron_bars');
// stern A-frame gantry
fill(38, 23, 33, 38, 32, 33, 'yellow_concrete');
fill(54, 23, 33, 54, 32, 33, 'yellow_concrete');
fill(38, 33, 33, 54, 33, 33, 'yellow_concrete');
fill(46, 33, 33, 46, 33, 28, 'iron_block');
fill(46, 28, 28, 46, 32, 28, 'iron_bars');
pb(46, 27, 28, 'barrel[facing=up]');
ps(41, 32, 33, 'yellow_concrete'); ps(51, 32, 33, 'yellow_concrete');
// moon pool hatch + winches
fill(43, 22, 56, 49, 22, 60, 'iron_block');
fill(44, 22, 57, 48, 22, 59, 'black_concrete');
ps(43, 23, 56, 'iron_trapdoor[facing=north,half=bottom,open=true]');
ps(49, 23, 60, 'iron_trapdoor[facing=south,half=bottom,open=true]');
// container stacks + lashings
function box5(x, z, col, len, wide) {
fill(x, 23, z, x + wide, 25, z + len, col);
fill(x, 26, z, x + wide, 26, z + len, 'gray_concrete');
ps(x, 24, z, 'iron_trapdoor[facing=north,half=bottom,open=false]');
var q;
for (q = z; q <= z + len; q++) { if (q % 2 === 0) { ps(x - 1, 24, q, 'iron_bars'); } }
}
box5(38, 92, 'blue_concrete', 5, 2);
box5(52, 92, 'lime_concrete', 5, 2);
box5(38, 62, 'cyan_concrete', 4, 2);
box5(52, 62, 'orange_concrete', 4, 2);
box5(41, 100, 'red_concrete', 3, 2);
// foredeck crane
fill(40, 23, 90, 40, 34, 90, 'gray_concrete');
fill(52, 23, 90, 52, 34, 90, 'gray_concrete');
fill(40, 35, 90, 52, 35, 90, 'gray_concrete');
fill(46, 35, 90, 46, 35, 99, 'iron_block');
fill(46, 31, 99, 46, 34, 99, 'iron_bars');
pb(46, 30, 99, 'chest[facing=north]');
// windlass + bollards + fittings
fill(43, 23, 104, 49, 24, 106, 'gray_concrete');
ps(46, 25, 105, 'lantern[hanging=false]');
var dfz;
for (dfz = 34; dfz <= 106; dfz += 8) {
pb(CXc - Math.round(hBeam(dfz)) + 1, 23, dfz, 'anvil[facing=north]');
pb(CXc + Math.round(hBeam(dfz)) - 1, 23, dfz, 'anvil[facing=north]');
}
for (dfz = 38; dfz <= 102; dfz += 14) {
ps(CXc - Math.round(hBeam(dfz)) + 2, 23, dfz, 'cauldron');
ps(CXc + Math.round(hBeam(dfz)) - 2, 23, dfz, 'cauldron');
}
// lifeboats in davits
fill(35, 29, 70, 35, 30, 74, 'orange_concrete');
fill(57, 29, 70, 57, 30, 74, 'orange_concrete');
ps(35, 31, 70, 'iron_bars'); ps(35, 31, 74, 'iron_bars');
ps(57, 31, 70, 'iron_bars'); ps(57, 31, 74, 'iron_bars');
fill(35, 32, 70, 35, 32, 74, 'gray_concrete');
fill(57, 32, 70, 57, 32, 74, 'gray_concrete');
ck('DECKGEAR');
// ---------- STAIRS (port side deck lane, nothing else placed there) ----------
staircase(38, 60, 23, 28, 'north', { width: 1, material: 'iron_block', rail: 'iron_bars' });
staircase(40, 66, 28, 33, 'north', { width: 1, material: 'iron_block', rail: 'iron_bars' });
fill(40, 34, 73, 40, 35, 73, 'air');
ck('STAIRS');
// ---------- INTERIORS ----------
// BRIDGE (floor 33, walk 34, ceiling 38)
fill(40, 33, 73, 52, 33, 86, 'polished_andesite');
rug(43, 34, 78, 6, 5, 'blue', 'gray');
var bcz;
for (bcz = 42; bcz <= 50; bcz++) { }
for (bcz = 41; bcz <= 51; bcz++) {
pb(bcz, 34, 85, 'gray_concrete');
ps(bcz, 35, 85, 'light_gray_stained_glass_pane');
}
ps(45, 34, 84, 'lectern[facing=north]');
pb(46, 34, 84, 'observer[facing=north]');
ps(47, 34, 84, 'daylight_detector');
chairStair(45, 34, 83, 'dark_oak_stairs', 'north');
chairStair(47, 34, 83, 'dark_oak_stairs', 'north');
pb(41, 34, 76, 'dark_oak_fence'); pb(41, 35, 76, 'light_gray_carpet');
pb(41, 34, 77, 'dark_oak_fence'); pb(41, 35, 77, 'light_gray_carpet');
ps(42, 34, 76, 'cartography_table');
pb(51, 34, 76, 'barrel[facing=up]'); pb(51, 34, 77, 'chest[facing=east]');
ps(51, 34, 80, 'bell[facing=west,attachment=single_wall]');
shelfWall(50, 34, 74, 'east', 3, 2);
ps(44, 37, 79, 'lantern[hanging=true]'); ps(48, 37, 79, 'lantern[hanging=true]');
ps(46, 37, 84, 'lantern[hanging=true]');
// WET LAB on L1 (floor 22, walk 23, ceiling 27)
fill(38, 22, 65, 54, 22, 85, 'light_gray_concrete');
rug(42, 23, 70, 6, 5, 'white', 'light_gray');
fill(39, 23, 68, 39, 23, 76, 'smooth_quartz');
var lbz;
for (lbz = 68; lbz <= 76; lbz++) { ps(39, 24, lbz, 'smooth_quartz_slab[type=bottom]'); }
ps(39, 24, 70, 'brewing_stand'); ps(39, 24, 73, 'brewing_stand');
pb(39, 23, 78, 'barrel[facing=up]'); pb(39, 23, 79, 'barrel[facing=up]');
ps(53, 23, 68, 'smithing_table'); pb(53, 23, 69, 'chest[facing=east]');
pb(53, 23, 70, 'chest[facing=east]');
ps(53, 23, 74, 'cartography_table'); ps(53, 23, 75, 'lectern[facing=west]');
fill(44, 23, 80, 48, 23, 80, 'spruce_fence');
fill(44, 24, 80, 48, 24, 80, 'white_carpet');
chairStair(45, 23, 79, 'spruce_stairs', 'north');
chairStair(47, 23, 79, 'spruce_stairs', 'north');
chairStair(45, 23, 81, 'spruce_stairs', 'south');
chairStair(47, 23, 81, 'spruce_stairs', 'south');
box5(50, 82, 'yellow_concrete', 1, 1);
ps(42, 26, 72, 'lantern[hanging=true]'); ps(50, 26, 72, 'lantern[hanging=true]');
ps(46, 26, 80, 'lantern[hanging=true]'); ps(46, 26, 66, 'lantern[hanging=true]');
ps(41, 23, 84, 'potted_fern'); ps(51, 23, 84, 'flower_pot');
ck('INTERIOR');
// ---------- SCIENCE CAMP ON THE FLOE + scene detail ----------
// tents
// proper ridge tents: closed roof of stairs, filled gable ends, real doorway, lit inside
function tent(tx, tz, wl, rf, wide, lng) {
var q, r, hw;
fill(tx, iceY + 1, tz, tx + wide, iceY + 1, tz + lng, 'spruce_planks');
fill(tx, iceY + 2, tz, tx + wide, iceY + 3, tz + lng, wl);
fill(tx + 1, iceY + 2, tz + 1, tx + wide - 1, iceY + 3, tz + lng - 1, 'air');
hw = Math.ceil((wide + 1) / 2);
for (q = tz; q <= tz + lng; q++) {
for (r = 0; r < hw; r++) {
roofStair(tx + r, iceY + 4 + r, q, rf, 'west');
roofStair(tx + wide - r, iceY + 4 + r, q, rf, 'east');
}
pb(tx + hw - 1, iceY + 3 + hw, q, 'stripped_spruce_log[axis=z]');
}
for (r = 0; r < hw; r++) {
for (q = tx + r; q <= tx + wide - r; q++) {
pb(q, iceY + 4 + r, tz, wl);
pb(q, iceY + 4 + r, tz + lng, wl);
}
}
fill(tx + 2, iceY + 2, tz + lng, tx + 2, iceY + 3, tz + lng, 'air');
ps(tx + 2, iceY + 2, tz + lng, 'spruce_trapdoor[facing=north,half=bottom,open=true]');
ps(tx + 1, iceY + 2, tz + 1, 'lantern[hanging=false]');
pb(tx + wide - 1, iceY + 2, tz + 1, 'barrel[facing=up]');
pb(tx + wide - 1, iceY + 2, tz + 2, 'chest[facing=east]');
ps(tx + 1, iceY + 2, tz + lng - 1, 'red_carpet');
pb(tx + 1, iceY + 1, tz - 1, 'oak_fence');
ps(tx + 1, iceY + 2, tz - 1, 'red_wall_banner[facing=north]');
}
tent(20, 69, 'red_wool', 'red_nether_brick_stairs', 4, 6);
tent(65, 83, 'orange_wool', 'red_sandstone_stairs', 4, 6);
// ice-core drill rig
fill(70, iceY + 1, 60, 70, iceY + 7, 60, 'iron_block');
fill(74, iceY + 1, 60, 74, iceY + 7, 60, 'iron_block');
fill(70, iceY + 8, 60, 74, iceY + 8, 60, 'iron_block');
fill(72, iceY + 2, 60, 72, iceY + 7, 60, 'iron_bars');
pb(72, iceY + 1, 60, 'cauldron');
pb(70, iceY + 1, 62, 'barrel[facing=up]'); pb(71, iceY + 1, 62, 'barrel[facing=up]');
// fuel drums + sledges + marker flag line
fill(26, iceY + 1, 92, 30, iceY + 1, 93, 'spruce_slab[type=bottom]');
pb(26, iceY + 2, 92, 'barrel[facing=up]'); pb(27, iceY + 2, 92, 'barrel[facing=up]');
pb(28, iceY + 2, 93, 'barrel[facing=up]');
var fg5;
for (fg5 = 0; fg5 < 8; fg5++) {
pb(64 + (fg5 % 2) * 2, iceY + 1, 44 + fg5 * 5, 'oak_fence');
pb(64 + (fg5 % 2) * 2, iceY + 2, 44 + fg5 * 5, 'oak_fence');
ps(64 + (fg5 % 2) * 2, iceY + 2, 45 + fg5 * 5, 'red_wall_banner[facing=south]');
}
// snow dusting + meltwater pools
var sn, snx, snz;
for (sn = 0; sn < 150; sn++) {
snx = (sn * 19) % 96;
snz = (sn * 31) % 128;
if (snx > 34 && snx < 58 && snz > 28 && snz < 112) { continue; }
ps(snx, floeH(snx, snz) + 1, snz, 'snow');
}
for (sn = 0; sn < 30; sn++) {
snx = 4 + (sn * 17) % 26;
snz = 46 + (sn * 23) % 70;
pb(snx, iceY, snz, 'water'); pb(snx + 1, iceY, snz, 'water');
}
for (sn = 0; sn < 24; sn++) {
snx = 62 + (sn * 13) % 30;
snz = 96 + (sn * 11) % 28;
pb(snx, iceY, snz, 'water'); pb(snx, iceY, snz + 1, 'water');
}
ck('SCENE');
ck('DONE');