DramaticShapeVoxelMod archival mirror · read-only
47369c24fe2680f1ff5b0bd22088353e663f06eb

fixed tops of walls in houses

DramaticShape · 2026-08-08 · parent 787d93a0e4

fixed tops of walls in houses

Changed files

CHANGELOG.md                  |  36 ++++++++++++++++++++++
 data/voxel_heights.lua        |  52 ++++++++++++++++++++++++--------
 lib/ChunkMesher.lua           |  11 +++++++
 lib/Structures.lua            |  74 +++++++++++++++++++++++++++++++---------------
 lib/TileShape.lua             |  35 ++++++++++++++++++----
 tests/dramatic_shape_test.lua | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 267 insertions(+), 41 deletions(-)

Diff

diff --git a/CHANGELOG.md b/CHANGELOG.md
index bca1656..4a0426d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -131,6 +131,42 @@
   strips the way a facade's does) and no voxels: the recess removes as
   many faces as it exposes.
 
+### Fixed
+
+- **The Pokemon Center's steps climb.** The Cable Club stairs, cut into
+  the back wall of all eleven Centers, were built as a stairwell sunk
+  into the floor -- they lead UP to the Center's second floor. The
+  head-on stair reading was right and stays: a drawn ROW is a step and
+  drawn row is depth row, 1:1 into the opening, the drawing's own band
+  table landing exactly on four steps and its black edge columns walling
+  the opening. Only the sign of the rise was wrong, and two things follow
+  from it. The risers turn around -- a flight descending away from you
+  closes its steps from below and shows you their backs, one climbing
+  away shows you their fronts -- and the black edge columns become the
+  walls of the opening the flight climbs into, running from each tread up
+  to the top of the wall band rather than down from the floor to it. The
+  top step lands level with that band, in the dark rows the artist drew
+  there, so the flight fills the opening it leaves by. The descending
+  class (`stair_down_n`) is unchanged and still available; the Centers
+  now pin `stair_n`.
+
+- **Nothing is hung on the TOP of an interior wall.** A wall band is 16px
+  of art folded upright over a run two drawn rows deep, so it folds
+  entirely onto its south face and has no drawn row left to lay flat on
+  top -- and the top then repeated the face. The town house's town-map
+  poster (cell (3,0)) and its window ((5,0)), and the Pokemon Center's
+  pokeball poster ((3,0) and (4,0)), each came out lying across the top
+  of the wall as well as hanging on it: a picture you look DOWN on.
+
+  What is really up there is the wall's own capping course, which is
+  exactly the plain panel the decorated column's neighbours draw --
+  `wall_top` in `data/voxel_heights.lua` names it per tileset (HOUSE caps
+  with the blank course, POKECENTER with the striped panel cell (9,0)
+  draws). Per tileset rather than per tile because one room caps with one
+  course, and because "plain" is a fact about the drawing that no
+  measurement of the geometry can recover. Only the top face is
+  redirected; the poster still faces the room.
+
 ## 1.8.0
 
 ### Added
diff --git a/data/voxel_heights.lua b/data/voxel_heights.lua
index 2bb11c5..74b605a 100644
--- a/data/voxel_heights.lua
+++ b/data/voxel_heights.lua
@@ -50,6 +50,9 @@
 --   stair_down_e / _down_w  a sunken stairwell: the cell opens into a
 --                           hole with steps descending toward the named
 --                           side -- stairs that lead DOWN a floor
+--   stair_n / stair_down_n  the same two flights running into the map
+--                           rather than across it, for a staircase drawn
+--                           HEAD-ON: a drawn row is a step, not a column
 --   relief                  a prop drawn from above (a console on the
 --                           floor): the drawing stays flat and the
 --                           pixels inside its black outline extrude a
@@ -129,6 +132,16 @@
 -- measured rather than drawn, by flooding the panel tile's own stripe out
 -- from behind them; see CLUB below.
 --
+-- And `wall_top` (not a class either): the tile every `wall` cell's TOP
+-- face wears, whatever the cell itself draws.  An interior wall band is
+-- 16px of art folded upright, and a fully folded run has no drawn row left
+-- over to lay flat on top -- so the top repeated the FACE, and the town-map
+-- poster and the window of a house came out lying across the top of the
+-- wall as well as hanging on it.  What is really up there is the wall's own
+-- capping course, which is exactly the plain panel the decorated column's
+-- neighbours draw: name that tile and every wall in the tileset caps with
+-- it.  The face is untouched -- the poster still faces the room.
+--
 -- Whole BUILDINGS are not tile pins -- one drawing packs a roof seen from
 -- above, a facade seen face-on and sloped ends as diagonal silhouettes,
 -- and no single class covers that.  They live in the `buildings` list at
@@ -860,6 +873,12 @@ return {
       -- the wall band stays one 16px face: blank courses, the window,
       -- the framed picture, and the schoolhouse blackboard (72-75/88-91)
       wall = { 0, 36, 45, 46, 52, 61, 62, 72, 73, 75, 88, 89, 90, 91 },
+      -- and it caps with the blank course.  Cells (3,0) and (5,0) of the
+      -- town house are the town-map poster (45/46 over 61/62) and the
+      -- window (36 over 52); without this the top of the wall wore the
+      -- poster and the glass, laid flat, instead of the plain panel their
+      -- own left-hand neighbour draws
+      wall_top = 0,
       -- stools: a seat-high box that also seats Daisy
       stool = { 2, 3, 18, 19 },
       -- the dining table (top edge 38/41 also caps the bookcases);
@@ -905,21 +924,28 @@ return {
       -- two flanks -- see `prop` below.
       wall = { 2, 3, 4, 5, 6, 16, 18, 19, 20, 21, 22, 40, 41,
                76, 77 },
+      -- and it caps with the striped panel, the tile cell (9,0) draws.
+      -- The pokeball poster spans cells (3,0) and (4,0) (2/3 over 18/19),
+      -- and without this the top of the wall wore the poster lying flat as
+      -- well as hanging it on the face
+      wall_top = 40,
       -- THE CABLE CLUB STEPS, cut into the back wall at cells (10,0) and
-      -- (12,0) of every Center -- a flight going DOWN, away from the room,
-      -- and the reason `stair_down_n` exists at all: the profile's other
-      -- stairs run east or west and are drawn from the SIDE, where a drawn
-      -- column is a step; these are drawn HEAD-ON, where a drawn row is,
-      -- and no rotation of the east/west reading produces that.
+      -- (12,0) of every Center -- a flight going UP, away from the room, to
+      -- the Center's second floor, and the reason the head-on stair classes
+      -- exist at all: the profile's other stairs run east or west and are
+      -- drawn from the SIDE, where a drawn column is a step; these are drawn
+      -- HEAD-ON, where a drawn row is, and no rotation of the east/west
+      -- reading produces that.
       --
       -- The drawing is its own band table, and it lands exactly on an even
-      -- four-step division of the cell: 4 white rows (the near tread), a
-      -- black nosing, 3 grey, a nosing, 3 checker, then 4 black rows -- the
-      -- dark the flight leaves into, which is also what the far end wall
-      -- wears.  Its first and last COLUMNS are the well's black side walls.
-      -- Drawn row = depth row throughout; the rise is the only number the
-      -- head-on view cannot state, and it takes the class height over the
-      -- four steps like every other flight here.
+      -- four-step division of the cell: 4 white rows (the near tread, the
+      -- one at floor level), a black nosing, 3 grey, a nosing, 3 checker,
+      -- then 4 black rows -- the dark the flight climbs into, which is the
+      -- top step, level with the wall band it is cut through.  Its first and
+      -- last COLUMNS are the opening's black side walls.  Drawn row = depth
+      -- row throughout; the rise is the only number the head-on view cannot
+      -- state, and it takes the class height over the four steps like every
+      -- other flight here.
       --
       -- Pinned as one cell (the class resolves off the top-left tile) but
       -- all four ids carry it, and the scan says they cannot reach anything
@@ -927,7 +953,7 @@ return {
       -- Centers, and the Celadon Hotel on the same id places none of them.
       -- 94 is also the map's warp tile; pins are look-only, so the warp is
       -- untouched and the steps stay walk-through.
-      stair_down_n = { 92, 93, 94, 95 },
+      stair_n = { 92, 93, 94, 95 },
       -- the counters, half a cell high: top band (8) and the one cell of
       -- it that carries the push bell (10, lifted off as a figure below --
       -- the pin stays as the degradation path), front face (24/25, the
diff --git a/lib/ChunkMesher.lua b/lib/ChunkMesher.lua
index 4167656..d036467 100644
--- a/lib/ChunkMesher.lua
+++ b/lib/ChunkMesher.lua
@@ -301,6 +301,14 @@ local function runGeometry(map, bodyOnly, masks, sink, waterSink)
     return tile
   end
 
+  -- The capping course an interior wall wears on its TOP face (see
+  -- TileShape.wallTop). A wall band folds entirely onto its own face, so
+  -- the top had nothing left to lay flat and repeated the face -- a house's
+  -- town-map poster and window, and a Center's pokeball poster, came out
+  -- lying across the top of the wall as well as hanging on it. Only the top
+  -- is redirected: the face still draws what the map draws.
+  local wallTop = TileShape.wallTop(tileset.id)
+
   -- one atlas-rect UV, optionally cropped to art rows [vTop, vBot] of 8
   local function uvRect(tile, vTop, vBot)
     local ax = (tile % perRow) * 8
@@ -650,6 +658,9 @@ local function runGeometry(map, bodyOnly, masks, sink, waterSink)
                     and (north - 1) or north
             end
             topTile = S.tileAt[keyOf(tx, row)]
+            -- ...unless the tileset names the course its walls cap with,
+            -- which every wall cell wears whatever it draws on its face
+            if wallTop and s.class == "wall" then topTile = wallTop end
           end
           -- water's surface, and only water's: the recessed sheet itself,
           -- never the ground's shoreline bands around it. A cell an object
diff --git a/lib/Structures.lua b/lib/Structures.lua
index 814364d..33e3fbd 100644
--- a/lib/Structures.lua
+++ b/lib/Structures.lua
@@ -1992,6 +1992,10 @@ end
 -- walls) wear the matching slice of that drawing -- the railing's
 -- diagonal lands along the stepped silhouette -- while treads sample the
 -- art band drawn at their own height.
+--
+-- stair_n / stair_down_n are the same pair of flights running INTO the
+-- map rather than across it, for a staircase drawn head-on; that changes
+-- the art reading enough to need its own branch below.
 local STAIR_STEPS = 4
 
 local STAIR_SHADE = { south = 1.0, north = 0.68, tread = 1.0,
@@ -2004,8 +2008,8 @@ local function stairCell(S, map, data, cx, cy, s)
   local atlasW = map.tileset.imageWidth or 128
   local atlasH = map.tileset.imageHeight or 48
   local quads = S.objectQuads
-  local north = s.class == "stair_down_n"
-  local down = north or s.class == "stair_down_e"
+  local north = s.class == "stair_n" or s.class == "stair_down_n"
+  local down = s.class == "stair_down_n" or s.class == "stair_down_e"
              or s.class == "stair_down_w"
   local east = s.class == "stair_e" or s.class == "stair_down_e"
   local mx, mz = cx * 16, cy * 16
@@ -2077,6 +2081,17 @@ local function stairCell(S, map, data, cx, cy, s)
   -- COLUMNS are its black side walls, and its top band is the darkness the
   -- flight leaves by, which is what the far end wants to wear.
   --
+  -- A flight CLIMBING away (`stair_n`) is the same reading with the sign of
+  -- the rise flipped -- bands still run south to north, drawn row is still
+  -- depth row, the nosing still serves twice.  Two things follow from the
+  -- sign.  The risers turn around: a flight descending away from you closes
+  -- its steps from below and shows you their backs, one climbing away shows
+  -- you their FRONTS, so they face south.  And the drawing's black side
+  -- columns stop being a well's walls and become the walls of the opening
+  -- the flight climbs into: they run from each tread UP to the top of the
+  -- wall band rather than down from the floor.  At the last step the flight
+  -- has reached that top and there is no opening left to wall.
+  --
   -- Every quad here is split at the cell's own 8px seam, in x and in rows
   -- both: `uv` resolves ONE tile per corner, and these four tiles are not
   -- neighbours in the atlas, so a quad that spans a seam interpolates
@@ -2087,7 +2102,8 @@ local function stairCell(S, map, data, cx, cy, s)
     for i = 0, STAIR_STEPS - 1 do
       local a0 = 16 - (i + 1) * runD           -- band i, in art rows
       local a1 = a0 + runD
-      local yTop = -(i + 1) * rise
+      local yTop = (down and -1 or 1) * (i + 1) * rise
+      local ry = (down and -1 or 1) * i * rise        -- the step behind it
       local z0b, z1b = mz + a0, mz + a1
 
       for _, H in ipairs(HALVES) do
@@ -2097,44 +2113,56 @@ local function stairCell(S, map, data, cx, cy, s)
         -- lies on its front lip exactly where the artist drew it
         face({ wx0, yTop, z0b }, { wx1, yTop, z0b },
              { wx1, yTop, z1b }, { wx0, yTop, z1b },
-             ax0, a1, ax1, a0, STAIR_SHADE.wellTread)
-
-        -- the riser under that lip.  It faces NORTH -- a flight descending
-        -- away from you turns its risers away with it, and they close the
-        -- steps from below rather than being looked at.  One art row tall,
-        -- so it needs none of `banded`'s row splitting; written straight
-        -- keeps the geometry flush at the seam while the art stays inside
-        -- its tile
-        local ry = -i * rise
-        face({ wx1, yTop, z1b }, { wx0, yTop, z1b },
-             { wx0, ry, z1b }, { wx1, ry, z1b },
-             ax1, a1 - 1, ax0, a1, STAIR_SHADE.riser)
+             ax0, a1, ax1, a0,
+             down and STAIR_SHADE.wellTread or STAIR_SHADE.tread)
+
+        -- the riser at that lip, one art row tall -- so it needs none of
+        -- `banded`'s row splitting, and written straight keeps the geometry
+        -- flush at the seam while the art stays inside its tile.  Facing
+        -- north when the flight descends (the steps are closed from below,
+        -- not looked at) and south when it climbs
+        if down then
+          face({ wx1, yTop, z1b }, { wx0, yTop, z1b },
+               { wx0, ry, z1b }, { wx1, ry, z1b },
+               ax1, a1 - 1, ax0, a1, STAIR_SHADE.riser)
+        else
+          face({ wx0, ry, z1b }, { wx1, ry, z1b },
+               { wx1, yTop, z1b }, { wx0, yTop, z1b },
+               ax0, a1 - 1, ax1, a1, STAIR_SHADE.riser)
+        end
 
         -- the deep end, closing the opening this flight is cut into: from
         -- the floor of the well up to the top of the wall band beside it,
-        -- in the drawing's own black top rows
-        if i == STAIR_STEPS - 1 then
+        -- in the drawing's own black top rows.  A climbing flight has no
+        -- such end -- its top tread stands at the wall's own height and
+        -- fills the opening
+        if down and i == STAIR_STEPS - 1 then
           face({ wx1, -h, mz }, { wx0, -h, mz },
                { wx0, h, mz }, { wx1, h, mz },
                ax1, 3.9, ax0, 0.1, STAIR_SHADE.wellEnd)
         end
       end
 
-      -- the well's side walls above this tread, wearing the drawing's own
-      -- black edge columns -- the excavation is walled in its own texels
+      -- the opening's side walls beside this tread, wearing the drawing's
+      -- own black edge columns -- excavation or recess, it is walled in its
+      -- own texels.  Descending they run from the tread up to the floor,
+      -- climbing from the tread up to the top of the wall band
+      local wallTop = down and 0 or h
       local function sideWall(px, sx0, sx1, inward)
         local c
         if inward then                                  -- west wall, faces E
           c = { { px, yTop, z1b }, { px, yTop, z0b },
-                { px, 0, z0b }, { px, 0, z1b } }
+                { px, wallTop, z0b }, { px, wallTop, z1b } }
         else                                            -- east wall, faces W
           c = { { px, yTop, z0b }, { px, yTop, z1b },
-                { px, 0, z1b }, { px, 0, z0b } }
+                { px, wallTop, z1b }, { px, wallTop, z0b } }
         end
         face(c[1], c[2], c[3], c[4], sx0, a1, sx1, a0, STAIR_SHADE.wellN)
       end
-      sideWall(mx, 0.1, 1.3, true)
-      sideWall(mx + 16, 14.7, 15.9, false)
+      if wallTop > yTop then
+        sideWall(mx, 0.1, 1.3, true)
+        sideWall(mx + 16, 14.7, 15.9, false)
+      end
     end
     return
   end
diff --git a/lib/TileShape.lua b/lib/TileShape.lua
index c0c19ce..a4270ea 100644
--- a/lib/TileShape.lua
+++ b/lib/TileShape.lua
@@ -125,11 +125,13 @@ local FALLBACK_HEIGHTS = {
   stair_w = 16,
   stair_down_e = 16,
   stair_down_w = 16,
-  -- a stairwell descending toward the BACK of the map, drawn head-on
-  -- instead of from the side (the Centers' Cable Club steps).  Its own
-  -- class because the art reading is not the east/west one turned: there
-  -- a drawn COLUMN is a step and a drawn row is height, here a drawn ROW
-  -- is a step and drawn row = depth row, 1:1 down the well
+  -- a flight running toward the BACK of the map, drawn head-on instead of
+  -- from the side (the Centers' Cable Club steps).  Its own class because
+  -- the art reading is not the east/west one turned: there a drawn COLUMN
+  -- is a step and a drawn row is height, here a drawn ROW is a step and
+  -- drawn row = depth row, 1:1 into the opening.  `stair_n` climbs away
+  -- from the room, `stair_down_n` descends into a well
+  stair_n = 16,
   stair_down_n = 16,
 }
 
@@ -221,6 +223,7 @@ local ART = {
   stair_w = "stair",
   stair_down_e = "stair",
   stair_down_w = "stair",
+  stair_n = "stair",
   stair_down_n = "stair",
 }
 
@@ -761,6 +764,28 @@ function TileShape.bookcaseRelief(tilesetId)
   return not (entry and entry.bookcase_relief == false)
 end
 
+--- What every `wall` cell's TOP face wears in this tileset (a tileset
+--- entry's wall_top).  Returns a tile id, or nil to leave the top alone.
+---
+--- A wall band is 16px of art folded upright over a run two drawn rows
+--- deep, so it folds ENTIRELY onto its face and has no row left to lay
+--- flat on top -- the top then repeats the face, and a house's town-map
+--- poster and window came out lying across the top of the wall as well as
+--- hanging on it.  What is up there is the wall's capping course, which is
+--- the plain panel the decorated column's own neighbours draw; naming it
+--- per tileset is the whole fix, because "plain" is a fact about the
+--- drawing that nothing in the geometry can measure.
+---
+--- Per tileset rather than per tile: one room caps with one course, and a
+--- list keyed by the decorated tiles would have to be extended every time
+--- a map hung something new on a wall already covered.
+function TileShape.wallTop(tilesetId)
+  local s = load()
+  local entry = s and s.tilesets and s.tilesets[tilesetId]
+  local tile = entry and entry.wall_top
+  return type(tile) == "number" and tile or nil
+end
+
 -- Drop the cache: a mod that shadows data/voxel_heights.lua or a tileset
 -- record needs the next lookup to re-resolve (hot reload, mod toggle).
 function TileShape.invalidate()
diff --git a/tests/dramatic_shape_test.lua b/tests/dramatic_shape_test.lua
index 2f3ed88..aa6cde0 100644
--- a/tests/dramatic_shape_test.lua
+++ b/tests/dramatic_shape_test.lua
@@ -7002,6 +7002,106 @@ end)()
   T.check(ball.stars == nil, "and the stars burn out on their own")
 end)()
 
+-- ------- an interior wall caps with its own plain course
+--
+-- A wall band is 16px of art over a run two drawn rows deep, so it folds
+-- ENTIRELY onto its south face and has no drawn row left to lay flat on
+-- top. The top therefore repeated the face: the town house's town-map
+-- poster and window, and the Pokemon Center's pokeball poster, came out
+-- lying across the top of the wall as well as hanging on it -- a picture
+-- you look DOWN on from the voxel camera.
+--
+-- `wall_top` names the capping course per tileset (the plain panel the
+-- decorated column's own neighbours draw), and it is a fact about the
+-- drawing that no measurement of the geometry can recover -- nothing
+-- distinguishes "poster" from "panel" but knowing which is which.
+;(function()
+  local Mesher = run.loader.exports.DRAMATIC_SHAPE.lib.require("ChunkMesher")
+  local Struct = run.loader.exports.DRAMATIC_SHAPE.lib.require("Structures")
+  local Shape = run.loader.exports.DRAMATIC_SHAPE.lib.require("TileShape")
+
+  T.eq(Shape.wallTop("HOUSE"), 0,
+    "the town house caps its walls with the blank course")
+  T.eq(Shape.wallTop("POKECENTER"), 40,
+    "and a Center with its striped panel -- the tile cell (9,0) draws")
+  T.eq(Shape.wallTop("DS_NO_SUCH_TILESET"), nil,
+    "a tileset that says nothing keeps the top it always had")
+
+  local FLOOR = 1
+  local function topTiles(tilesetId, rows)
+    local map = {
+      id = "DS_TEST_WALLTOP_" .. tilesetId,
+      tileset = { id = tilesetId, image = "gfx/tilesets/ds_test.png",
+                  tilesPerRow = 16, imageWidth = 128, imageHeight = 48,
+                  blocks = {}, grassTile = -1 },
+      def = { width = 4, height = 2, tileset = tilesetId },
+      walkable = { [FLOOR] = true },
+      waterTiles = {},
+      doorTiles = {},
+      tileAt = function(_, tx, ty)
+        local r = rows[ty + 1]
+        return (r and r[tx + 1]) or FLOOR
+      end,
+      cellTile = function(self, cx, cy) return self:tileAt(cx * 2, cy * 2 + 1) end,
+      isWaterCell = function() return false end,
+      isWalkableCell = function(self, cx, cy)
+        return self:cellTile(cx, cy) == FLOOR
+      end,
+      inBounds = function(_, cx, cy)
+        return cx >= 0 and cy >= 0 and cx < 4 and cy < 2
+      end,
+    }
+    Struct.invalidate(map.id)
+    local verts = Mesher.geometry(map, true, nil)
+    -- the flat quads standing at wall height, keyed by the column they cap
+    local out = {}
+    for i = 1, #verts, 4 do
+      local a, b, c, d = verts[i], verts[i + 1], verts[i + 2], verts[i + 3]
+      if a[2] == b[2] and b[2] == c[2] and c[2] == d[2] and a[2] == 16 then
+        local ax = math.floor(math.min(a[4], b[4], c[4], d[4]) * 128 + 0.5)
+        local ay = math.floor(math.min(a[5], b[5], c[5], d[5]) * 48 + 0.5)
+        local tx = math.floor(math.min(a[1], b[1], c[1], d[1]) / 8)
+        out[tx] = out[tx] or (math.floor(ay / 8) * 16 + math.floor(ax / 8))
+      end
+    end
+    return out, verts
+  end
+
+  -- BLUES_HOUSE's back wall: blank panel, the town-map poster (45/46 over
+  -- 61/62) at cell (3,0)'s block, the window (36 over 52) at (5,0)'s
+  local houseTops, houseVerts = topTiles("HOUSE", {
+    { 0, 0, 45, 46, 36, 36, 0, 0 },
+    { 0, 0, 61, 62, 52, 52, 0, 0 },
+  })
+  for tx = 0, 7 do
+    T.eq(houseTops[tx], 0,
+      ("column %d of the house's back wall caps with the blank course"):format(tx))
+  end
+
+  -- and the FACE is untouched: the poster still hangs in the room, which is
+  -- the half of this the fix must not take with it
+  local hung = {}
+  for _, v in ipairs(houseVerts) do
+    hung[math.floor(math.floor(v[5] * 48 + 0.5) / 8) * 16
+         + math.floor(math.floor(v[4] * 128 + 0.5) / 8)] = true
+  end
+  T.check(hung[45] and hung[46] and hung[61] and hung[62],
+    "the town-map poster is still drawn on the wall it hangs on")
+  T.check(hung[36] and hung[52], "and so is the window")
+
+  -- VIRIDIAN_POKECENTER's back wall: the striped panel with the pokeball
+  -- poster (2/3 over 18/19) spanning cells (3,0) and (4,0)
+  local pcTops = topTiles("POKECENTER", {
+    { 40, 40, 40, 2, 3, 40, 40, 40 },
+    { 40, 40, 40, 18, 19, 40, 40, 40 },
+  })
+  for tx = 0, 7 do
+    T.eq(pcTops[tx], 40,
+      ("column %d of the Center's back wall caps with the striped panel")
+      :format(tx))
+  end
+end)()
+
 Pipelines.reset()
 run.release()