// === BUILD PLAN ===
// Style: Icelandic turf farmhouse (torfbaer) - rustic vernacular
// Footprint: row of 3 gabled ranges side by side, gables facing north (z=20):
// B1 smithy (int x12-16), B2 main hall + badstofa loft (int x19-25, taller), B3 kitchen (int x28-32)
// shared 2-thick turf walls x10-11 | 17-18 | 26-27 | 33-34, back turf wall z34-35, interiors z21-33
// Height: small ranges eave y12 (3 air) + turf roof to y16 ; B2 eave y14, loft floor y13, ridge y19
//
// GROUND FLOOR (top-down, x->, z down):
// TT.....TT.......TT.....TT z19 recessed white gables framed by turf
// TTW.D..TTWW.D.WWTT.D.W.TT z20 white boards, red doors, windows
// TT smithTT hall TT kitchTT
// TT == table == TT (= internal passages at z24)
// TT TT S TT TT S = staircase x24 north to loft
// TT TT loom S TT hearthTT
// TTTTTTTTTTTTTTTTTTTTTTTTTTT back turf + chimney
//
// FRONT ELEVATION:
// /\
// /\ /WW\ /\
// / \/ ll \/ \
// |W D||W D W||D W|
// ================= stone plinth
//
// MATERIALS PLAN:
// foundation: cobble(40)+mossy_cobble(35)+andesite(25) first 2 rows of every turf wall - WHY: stone-lined base, damp/moss low
// turf walls: alternating strata rows mud_bricks/packed_mud vs rooted_dirt/coarse/moss - WHY: stacked turf-strip courses
// turf roof : grass_block(75)+moss(25) stepped, ferns on steps - WHY: living grass roof, grass-side texture = turf edge
// gables : white_concrete boards, spruce barge-board trim, spruce loft band - WHY: white/dark contrast vs brown-green turf
// doors : mangrove (red). Interior floors: spruce planks (hall), packed mud (smithy), stone (kitchen)
// Rooms: Hall (long table + benches, loom, chests, bookshelves), Loft/badstofa (4 beds, chests, carpet),
// Smithy (anvil, grindstone, smithing table, blast furnace, hay), Kitchen (hearth+chimney, smoker, cauldron, hanging fish)
// STAIR PLAN: hall walk 9 -> loft walk 14 (delta 5) -> staircase(24,32,9,14,'north') straight flight along east side
// === END PLAN ===
var padY = 8, floorY = 8, walk = 9;
// === TERRAIN ===
var baseH = hills({ base: 7, amp: 2, scale: 0.06, seed: 5 });
var slopeH = function (x, z) { return baseH(x, z) + Math.max(0, (z - 37) * 0.55); };
var land = blob(23, 26, 25, { irregularity: 0.3, seed: 9 });
var pad = flatten(slopeH, { x0: 5, z0: 8, x1: 39, z1: 38 }, padY, 6);
surface(land, pad, patches([{ block: 'grass_block', w: 70 }, { block: 'moss_block', w: 15 }, { block: 'coarse_dirt', w: 15 }], 0.08, 4));
// === PALETTES ===
var stonePal = palette([{ block: 'cobblestone', weight: 40 }, { block: 'mossy_cobblestone', weight: 35 }, { block: 'andesite', weight: 25 }]);
var turfA = palette([{ block: 'mud_bricks', weight: 45 }, { block: 'packed_mud', weight: 35 }, { block: 'coarse_dirt', weight: 20 }]);
var turfB = palette([{ block: 'rooted_dirt', weight: 40 }, { block: 'coarse_dirt', weight: 35 }, { block: 'moss_block', weight: 25 }]);
var roofPal = palette([{ block: 'grass_block', weight: 75 }, { block: 'moss_block', weight: 25 }]);
function turfRow(y) { if (y <= walk + 1) return stonePal; return (y % 2 === 0) ? turfA : turfB; }
// === STRUCTURE ===
function range(x0, w, eave, floorPal) {
var xl = x0 - 2, xr = x0 + w + 1, y, s;
// walls
for (y = walk; y < eave; y++) {
fill(xl, y, 19, xr, y, 35, turfRow(y));
fill(x0, y, 21, x0 + w - 1, y, 33, 'air');
fill(x0, y, 19, x0 + w - 1, y, 19, 'air'); // recess in front of gable
fill(x0, y, 20, x0 + w - 1, y, 20, y === walk ? stonePal : 'white_concrete');
}
// turf roof (stepped), hollow inside, white gable triangle framed by turf
for (s = 0; ; s++) {
y = eave + s;
var a = xl + s, bb = xr - s;
if (a > bb) break;
fill(a, y, 19, bb, y, 36, roofPal);
var ca = x0 + s, cb = x0 + w - 1 - s;
if (ca <= cb) {
fill(ca, y, 21, cb, y, 33, 'air');
fill(ca, y, 19, cb, y, 19, 'air');
fill(ca, y, 20, cb, y, 20, 'white_concrete');
pb(ca, y, 20, 'spruce_planks'); pb(cb, y, 20, 'spruce_planks'); // barge-board trim
if (ca - 1 >= a) pb(ca - 1, y, 19, 'spruce_planks'); if (cb + 1 <= bb) pb(cb + 1, y, 19, 'spruce_planks'); // projecting barge board frames each gable
}
// grass tufts on the exposed step edges
for (var z = 19; z <= 36; z++) {
if (Math.random() < 0.3) pb(a, y + 1, z, 'moss_carpet');
if (Math.random() < 0.3 && bb !== a) pb(bb, y + 1, z, 'moss_carpet');
}
}
fill(x0, floorY, 20, x0 + w - 1, floorY, 33, floorPal);
}
var mudFloor = palette([{ block: 'packed_mud', weight: 60 }, { block: 'coarse_dirt', weight: 25 }, { block: 'cobblestone', weight: 15 }]);
var stoneFloor = palette([{ block: 'cobblestone', weight: 45 }, { block: 'stone', weight: 35 }, { block: 'andesite', weight: 20 }]);
var plankFloor = palette([{ block: 'spruce_planks', weight: 80 }, { block: 'stripped_spruce_log[axis=z]', weight: 20 }]);
range(12, 5, 12, mudFloor); // B1 smithy
range(28, 5, 12, stoneFloor); // B3 kitchen
range(19, 7, 14, plankFloor); // B2 hall (taller, built last)
// stone-lined plinth ring on the ground
var zz, xx;
for (xx = 9; xx <= 35; xx++) { pb(xx, 8, 18, stonePal); pb(xx, 8, 36, stonePal); }
for (zz = 18; zz <= 36; zz++) { pb(9, 8, zz, stonePal); pb(35, 8, zz, stonePal); }
// B2 loft floor + band on gable
fill(19, 13, 21, 25, 13, 33, 'spruce_planks');
fill(19, 13, 20, 25, 13, 20, 'spruce_planks');
// internal passages between ranges (z24)
fill(17, walk, 24, 18, walk + 1, 24, 'air');
fill(26, walk, 24, 27, walk + 1, 24, 'air');
// === DOORS & WINDOWS ===
function door(x, z) {
ps(x, walk, z, 'mangrove_door[facing=north,half=lower,hinge=left]');
ps(x, walk + 1, z, 'mangrove_door[facing=north,half=upper,hinge=left]');
}
door(15, 20); door(22, 20); door(29, 20);
pb(13, 10, 20, 'glass_pane'); pb(31, 10, 20, 'glass_pane');
pb(20, 10, 20, 'glass_pane'); pb(20, 11, 20, 'glass_pane');
pb(24, 10, 20, 'glass_pane'); pb(24, 11, 20, 'glass_pane');
pb(22, 15, 20, 'glass_pane'); pb(22, 16, 20, 'glass_pane');
pb(14, 13, 20, 'glass_pane'); pb(30, 13, 20, 'glass_pane');
// shutters
ps(12, 10, 19, 'spruce_trapdoor[facing=north,open=true,half=bottom]');
ps(32, 10, 19, 'spruce_trapdoor[facing=north,open=true,half=bottom]');
// === STAIRS (hall -> badstofa) ===
staircase(24, 32, walk, 14, 'north');
for (zz = 28; zz <= 32; zz++) pb(23, 14, zz, 'spruce_fence');
// === INTERIOR: HALL ===
for (zz = 23; zz <= 27; zz++) { pb(21, walk, zz, 'spruce_fence'); pb(21, walk + 1, zz, 'spruce_pressure_plate'); }
for (zz = 23; zz <= 27; zz += 2) { chairStair(20, walk, zz, 'spruce_stairs', 'east'); chairStair(22, walk, zz, 'spruce_stairs', 'west'); }
ps(19, walk, 31, 'loom[facing=east]');
ps(19, walk, 33, 'chest[facing=east]');
pb(19, walk, 32, 'barrel');
pb(25, walk, 21, 'bookshelf'); pb(25, walk + 1, 21, 'bookshelf'); pb(25, walk, 22, 'bookshelf'); pb(25, walk + 1, 22, 'bookshelf');
fill(20, walk, 30, 22, walk, 32, 'brown_carpet');
ps(22, 12, 24, 'lantern[hanging=true]'); ps(21, 12, 31, 'lantern[hanging=true]');
pb(19, walk, 21, 'flower_pot');
// === INTERIOR: BADSTOFA LOFT ===
placeBed(20, 14, 22, 'red', 'north');
placeBed(20, 14, 25, 'blue', 'north');
placeBed(20, 14, 28, 'white', 'north');
placeBed(20, 14, 31, 'brown', 'north');
ps(24, 14, 21, 'chest[facing=west]'); pb(24, 14, 22, 'barrel'); pb(24, 14, 24, 'barrel');
for (zz = 21; zz <= 26; zz++) pb(22, 14, zz, 'red_carpet');
ps(22, 17, 23, 'lantern[hanging=true]'); ps(22, 17, 29, 'lantern[hanging=true]');
// === INTERIOR: SMITHY ===
ps(13, walk, 23, 'anvil[facing=east]');
ps(15, walk, 23, 'grindstone[face=floor,facing=north]');
pb(12, walk, 26, 'smithing_table');
ps(12, walk, 28, 'blast_furnace[facing=east]');
pb(16, walk, 30, 'barrel'); pb(16, walk, 31, 'barrel');
ps(16, walk, 27, 'chest[facing=west]'); pb(16, walk, 28, 'crafting_table');
fill(12, walk, 32, 13, walk, 33, 'hay_block'); pb(12, walk + 1, 33, 'hay_block');
ps(14, 14, 24, 'lantern[hanging=true]'); ps(14, 14, 30, 'lantern[hanging=true]');
// === INTERIOR: KITCHEN (eldhus) ===
pb(29, walk, 33, 'cobblestone'); pb(29, walk + 1, 33, 'cobblestone');
pb(31, walk, 33, 'cobblestone'); pb(31, walk + 1, 33, 'cobblestone');
fill(29, walk + 2, 33, 31, walk + 2, 33, 'mossy_cobblestone');
ps(30, walk, 33, 'campfire[lit=true]');
fill(30, walk, 34, 30, 17, 34, 'cobblestone');
ps(30, 18, 34, 'cobblestone_wall');
ps(28, walk, 31, 'smoker[facing=east]');
ps(28, walk, 29, 'water_cauldron[level=3]');
pb(32, walk, 30, 'barrel'); pb(32, walk, 31, 'barrel'); pb(32, walk, 32, 'composter');
pb(30, walk, 27, 'spruce_fence'); pb(30, walk + 1, 27, 'spruce_pressure_plate');
chairStair(29, walk, 27, 'spruce_stairs', 'east'); chairStair(31, walk, 27, 'spruce_stairs', 'west');
ps(29, 13, 25, 'chain[axis=y]'); pb(29, 12, 25, 'dried_kelp_block');
ps(31, 13, 29, 'chain[axis=y]'); pb(31, 12, 29, 'dried_kelp_block');
ps(30, 14, 30, 'lantern[hanging=true]');
ps(30, 14, 23, 'lantern[hanging=true]');
// === EXTERIOR ===
var pathPal = palette([{ block: 'dirt_path', weight: 55 }, { block: 'gravel', weight: 25 }, { block: 'cobblestone', weight: 20 }]);
var px = [15, 22, 29], i;
for (i = 0; i < px.length; i++) for (zz = 13; zz <= 19; zz++) pb(px[i], 8, zz, pathPal);
for (xx = 10; xx <= 34; xx++) pb(xx, 8, 16, pathPal);
for (zz = 9; zz <= 15; zz++) pb(22, 8, zz, pathPal);
// lamp posts by main door
pb(20, walk, 17, 'spruce_fence'); pb(20, walk + 1, 17, 'spruce_fence'); pb(20, walk + 2, 17, 'lantern');
pb(24, walk, 17, 'spruce_fence'); pb(24, walk + 1, 17, 'spruce_fence'); pb(24, walk + 2, 17, 'lantern');
// fish drying rack (hjallur)
for (var yy = walk; yy <= 11; yy++) { pb(8, yy, 12, 'spruce_fence'); pb(13, yy, 12, 'spruce_fence'); }
fill(8, 12, 12, 13, 12, 12, 'stripped_spruce_log[axis=x]');
for (xx = 9; xx <= 12; xx++) { ps(xx, 11, 12, 'chain[axis=y]'); pb(xx, 10, 12, 'dried_kelp_block'); }
// peat / wood stack by kitchen
fill(36, walk, 21, 37, walk + 1, 23, 'packed_mud'); fill(36, walk + 2, 22, 37, walk + 2, 22, 'mud');
// stone sheepfold (rett)
var fcx = 33, fcz = 11, a2;
for (a2 = 0; a2 < 360; a2 += 8) {
var fx = Math.round(fcx + 3.6 * Math.cos(a2 * Math.PI / 180)), fz = Math.round(fcz + 3.6 * Math.sin(a2 * Math.PI / 180));
if (!(fx >= 32 && fx <= 34 && fz > fcz)) pb(fx, walk, fz, stonePal);
}
// sheep (white, brown, black)
function sheep(x, z, wool, head) { pb(x, walk, z, wool); pb(x + 1, walk, z, wool); pb(x + 1, walk + 1, z, wool); pb(x + 2, walk, z, head); }
sheep(31, 10, 'white_wool', 'brown_terracotta');
sheep(33, 12, 'brown_wool', 'black_terracotta');
sheep(16, 11, 'white_wool', 'brown_terracotta');
sheep(26, 10, 'black_wool', 'black_terracotta');
// wildflowers
var fl = ['dandelion', 'oxeye_daisy', 'allium', 'fern', 'fern', 'azure_bluet'];
for (i = 0; i < 70; i++) {
var rx = 6 + Math.floor(Math.random() * 33), rz = 8 + Math.floor(Math.random() * 9);
if (rz === 16 || rx === 22 || (rx >= 29 && rx <= 37 && rz <= 15) || (rx >= 7 && rx <= 14 && rz === 12)) continue;
pb(rx, walk, rz, fl[i % fl.length]);
}