fogón

← Medieval3D assetfogon/muralla-con-puerta

Muralla con puerta

by fogonCC016822 blocks
Muralla con puertaDrag to turn it
// «Muralla con puerta» · gpt-6-sol (medium)
// A straight section of thick grey stone city wall that spans the whole width (x 0..47), crenellated on top, with a big arched gateway in the middle closed by a raised dark iron portcullis grid half lowered, two small square towers framing the gate a bit taller than the wall, and red banners with a gold stripe hanging on both towers.

const stone = "#918b7d";
const light = "#aaa396";
const dark = "#746e63";
const mortar = "#625e55";
const moss = "#68745c";
const iron = "#25282c";
const ironEdge = "#44484b";
const red = "#9f2630";
const redLight = "#bb3940";
const gold = "#e1b951";

// Main wall and the two projecting square towers.
box(0, 20, 0, 47, 29, 26, stone);
box(8, 16, 0, 17, 27, 34, stone);
box(30, 16, 0, 39, 27, 34, stone);

// Subtle variation across the masonry, before adding architectural details.
forEach((x, y, z, color) => {
  if (color !== stone) return;
  const n = rand();
  if (n < 0.045) set(x, y, z, light);
  else if (n < 0.095) set(x, y, z, dark);
  else if (n < 0.103 && z < 13) set(x, y, z, moss);
});

// Open the gateway all the way through the wall. Its upper half is arched.
for (let z = 0; z <= 22; z++) {
  let halfWidth = z <= 14 ? 5.9
    : 5.9 * Math.sqrt(Math.max(0, 1 - Math.pow((z - 14) / 8, 2)));
  for (let x = 18; x <= 29; x++) {
    if (Math.abs(x - 23.5) <= halfWidth) {
      box(x, 19, z, x, 30, z, null);
    }
  }
}

// Large, staggered stone courses on the visible faces.
function courses(y, x0, x1, top) {
  for (let z = 3; z < top; z += 5) {
    for (let x = x0; x <= x1; x++) {
      if (get(x, y, z)) set(x, y, z, dark);
    }
  }
  for (let z = 0; z < top; z += 5) {
    const offset = (Math.floor(z / 5) % 2) * 3;
    for (let x = x0 + offset; x <= x1; x += 6) {
      for (let dz = 1; dz <= 2; dz++) {
        if (get(x, y, z + dz)) set(x, y, z + dz, mortar);
      }
    }
  }
}
courses(20, 0, 47, 26);
courses(16, 8, 17, 34);
courses(16, 30, 39, 34);

// Deeply outlined gateway: straight jambs and individual arch stones.
for (const x of [17, 30]) {
  box(x, 19, 0, x, 20, 15, dark);
  for (let z = 2; z <= 14; z += 4) box(x, 18, z, x, 18, z, light);
}
for (let z = 14; z <= 22; z++) {
  const half = 5.9 * Math.sqrt(Math.max(0, 1 - Math.pow((z - 14) / 8, 2)));
  const left = Math.floor(23.5 - half);
  const right = Math.ceil(23.5 + half);
  if (left >= 17) set(left, 19, z, z % 3 === 0 ? light : dark);
  if (right <= 30) set(right, 19, z, z % 3 === 0 ? light : dark);
}
box(18, 19, 22, 29, 20, 23, dark);
box(22, 18, 22, 25, 18, 23, light);

// Wall walk, parapet and widely spaced crenellations.
box(0, 19, 27, 47, 20, 29, dark);
box(0, 19, 29, 47, 20, 29, light);
box(0, 29, 27, 47, 30, 29, dark);
for (let x = 0; x <= 47; x += 5) {
  if (x >= 17 && x <= 30) continue;
  box(x, 19, 30, Math.min(x + 2, 47), 20, 32, stone);
  box(x, 19, 32, Math.min(x + 2, 47), 20, 32, light);
}

// Tower cornices and stout crenellated crowns.
for (const [a, b] of [[8, 17], [30, 39]]) {
  box(a - 1, 15, 33, b + 1, 28, 34, dark);
  box(a - 1, 15, 34, b + 1, 28, 34, light);
  box(a - 1, 15, 35, b + 1, 28, 36, stone);
  for (let x = a - 1; x <= b + 1; x += 4) {
    box(x, 15, 37, Math.min(x + 2, b + 1), 16, 40, stone);
    box(x, 15, 40, Math.min(x + 2, b + 1), 16, 40, light);
    box(x, 27, 37, Math.min(x + 2, b + 1), 28, 40, stone);
  }
  for (let y = 17; y <= 26; y += 4) {
    box(a - 1, y, 37, a, Math.min(y + 2, 26), 40, stone);
    box(b, y, 37, b + 1, Math.min(y + 2, 26), 40, stone);
  }
  // Narrow, black arrow slit low on the front of each tower.
  const c = Math.floor((a + b) / 2);
  box(c, 15, 10, c, 15, 16, dark);
  box(c, 14, 11, c, 14, 15, iron);
  box(c - 1, 14, 13, c + 1, 14, 13, iron);
  set(c, 14, 17, light);
}

// A half-raised portcullis, suspended inside the passage.
for (const x of [19, 22, 25, 28]) {
  for (let z = 9; z <= 20; z++) {
    if (!get(x, 22, z)) set(x, 22, z, iron);
  }
  set(x, 22, 9, ironEdge);
  set(x, 22, 8, iron);
}
for (const z of [10, 14, 18]) {
  for (let x = 18; x <= 29; x++) {
    if (!get(x, 22, z)) set(x, 22, z, iron);
  }
}
for (const z of [10, 14, 18]) {
  for (const x of [19, 22, 25, 28]) {
    if (get(x, 22, z) === iron) set(x, 21, z, ironEdge);
  }
}
box(18, 22, 20, 29, 22, 20, ironEdge);

// Red hanging banners with a broad gold heraldic stripe.
for (const c of [12, 34]) {
  box(c - 3, 13, 32, c + 3, 14, 32, "#473325");
  set(c - 3, 12, 32, gold);
  set(c + 3, 12, 32, gold);
  for (let z = 20; z <= 30; z++) {
    for (let x = c - 2; x <= c + 2; x++) {
      if (z === 20 && x === c) continue; // Notched, split lower edge.
      set(x, 14, z, x === c ? gold : x === c - 2 ? "#78232b" : red);
    }
  }
  box(c - 2, 13, 30, c + 2, 13, 30, redLight);
  box(c - 2, 13, 21, c + 2, 13, 21, gold);
  for (const z of [24, 27]) {
    set(c, 13, z, "#f3d37c");
  }
}