Lane E S18 gate 4: THE GLASSHOUSE TIER — the hail-net frame, and the apex made reachable

S16 shipped the glasshouse and priced it at $320. e.test said the rest in its
own words: "nothing in the sim wrecks a glasshouse yet — the value is inert
data". main.js bills collateral off a broken rig corner's baked key, and a
glasshouse rightly offers no anchors, so the most expensive object in the game
could not cost anybody a cent — RULE 2's mirror image, a price with no key that
can reach it.

DESIGN.md line 179 named the missing asset: hail nets rigged OVER glass. You
tie to the frame that straddles it. hail_net_frame_01 / _wrecked: a powder-coat
portal frame clear of the glasshouse on all four sides, head at 2.75 m to clear
the 2.28 ridge, four welded eyes at 2.690 baking collateral 'glasshouse'.

The tell is a POSITION, not a defect — the frame's numbers are good and the
hazard is where it stands. Pinned as geometry off two GLBs (footprint strictly
contains the glass; head clears the ridge) rather than as paint on one. The 20 m
read is metalness: powder-coat at 0.05 renders bright where every trusted
galvanised steel at 0.90 goes near-black with no environment map (S17's measured
lesson, applied on purpose this time).

Rung 0.80, proposal, A rules: it earns the highest rung below the honest post
(engineered frame, four footings, the only structure built to be tied to) and is
de-rated 20% for section, not condition. It usually holds — that is the tier:
the corner failure that costs a shackle on a sail post costs $320 here.

The root deliberately carries NO collateral_key. structFor() takes the first
match, so a frame claiming the glass's key would bill the panes and wreck the
frame, both papers agreeing and both wrong. That omission is gate 5 in one line.

Wreck racks at one end (0.45 in at the head, 0.45 out at the feet) after the
first cut still read as a clean level rectangle in the render. Carries no glass:
the glasshouse swaps independently. Unpriced by ruling.

ANCHOR_TYPE widened with 'hail_net_frame' (contracts.js is A's — revert and tell
me; corroded_post precedent). Manifest unambiguous: 0.80, glasshouse, 4 sources.

Determinism held: runs 2 and 3 are 56/56 byte-identical. NOTE the shipped GLBs
were exported by Blender 5.1.2 and this box has 5.0.1 — the 45-binary churn that
causes is semantically nil (60 nm accessor drift, PNGs losing sRGB/gAMA/cHRM
with identical pixels) and was reverted, not shipped. Documented in the header.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
type-two 2026-07-25 19:45:42 +10:00
parent e6d4c36daa
commit 00e6b288c8
7 changed files with 465 additions and 3 deletions

View File

@ -1,5 +1,5 @@
{
"blender": "5.1.2",
"blender": "5.0.1",
"assets": [
{
"name": "ref_capsule",
@ -817,6 +817,73 @@
"status": "PASS",
"problems": []
},
{
"name": "hail_net_frame_01",
"dims": [
3.42,
3.02,
2.766
],
"tris": 328,
"nodes": [
"footings",
"hail_net_frame_01",
"legs",
"net_anchor_01",
"net_anchor_02",
"net_anchor_03",
"net_anchor_04",
"net_roll",
"top_frame"
],
"anchors": [
{
"node": "net_anchor_01",
"anchor_type": "hail_net_frame",
"rating_hint": 0.8,
"collateral": "glasshouse"
},
{
"node": "net_anchor_02",
"anchor_type": "hail_net_frame",
"rating_hint": 0.8,
"collateral": "glasshouse"
},
{
"node": "net_anchor_03",
"anchor_type": "hail_net_frame",
"rating_hint": 0.8,
"collateral": "glasshouse"
},
{
"node": "net_anchor_04",
"anchor_type": "hail_net_frame",
"rating_hint": 0.8,
"collateral": "glasshouse"
}
],
"status": "PASS",
"problems": []
},
{
"name": "hail_net_frame_01_wrecked",
"dims": [
4.3007,
3.02,
2.7832
],
"tris": 480,
"nodes": [
"footings",
"hail_net_frame_01_wrecked",
"legs",
"net_down",
"top_frame"
],
"anchors": [],
"status": "PASS",
"problems": []
},
{
"name": "pool_kit_01",
"dims": [
@ -955,5 +1022,42 @@
"problems": []
}
],
"debris": []
"debris": [
{
"file": "BlueCrate_v2.glb",
"dims": [
0.36,
0.36,
0.29
],
"sane": true
},
{
"file": "BlackTub_v2.glb",
"dims": [
0.36,
0.54,
0.2
],
"sane": true
},
{
"file": "WhiteTub_v2.glb",
"dims": [
0.36,
0.54,
0.2
],
"sane": true
},
{
"file": "WoodenBin_v2.glb",
"dims": [
0.35,
0.36,
0.31
],
"sane": true
}
]
}

View File

@ -20,6 +20,25 @@ Outputs (resolved from this file, so no absolute home paths):
tools/blender/contact_sheet.png verification render vs the 1.7 m capsule
tools/blender/asset_report.json measured dims / tris / node names
BLENDER VERSION IS PART OF THE OUTPUT (SPRINT18, E measured, not guessed).
The shipped GLBs were exported by Blender **5.1.2** (glTF I/O v5.1.20), which
`asset_report.json` records in its `blender` field check it before you
build. On Blender 5.0.1 (I/O v5.0.21) this script is still perfectly
deterministic three consecutive full runs gave 56/56 byte-identical
artifacts but its output DIFFERS from the shipped files in two ways, and
both are cosmetic:
· GLB accessor min/max drift in the 7th decimal (~6e-8 m, i.e. 60 nm).
Node graph, mesh topology, materials and every custom prop are
bit-identical; only float formatting of the bounds moves.
· The generated PNGs lose their sRGB/gAMA/cHRM chunks 73 bytes per file.
IDAT pixel data decompresses bit-identically; the newer exporter simply
writes colour-space chunks that 5.0.x omits.
So a full run on the wrong Blender rewrites all 45 binaries with no change
anybody asked for, and quietly DROPS the colour-space chunks. If your `git
status` shows every GLB and texture modified after adding one asset, that is
this and not your work: `git checkout --` the ones you did not author, and
commit only the new files. Better: build on 5.1.2 and the churn is zero.
Idiom follows ~/Documents/Destroyulater/3D-STORE/racks_to_glb.py:
reset_to_empty() per asset -> build under a root empty AT THE ORIGIN ->
join by group -> stamp custom props -> export_scene.gltf(export_yup=True,
@ -150,6 +169,23 @@ PAL = {
# a pool is the one water in the game that is
# supposed to look inviting
"deck_board": "#A8845C", # decking oil, a shade lighter than fence timber
"net_frame_white": "#E6E7E1", # SPRINT18 gate 4 — the hail-net frame's
# powder-coat, and the BRIGHTEST entry in this
# palette on purpose. The reason is metalness,
# not lightness — S17's measured lesson applied
# deliberately this time. Galvanised ships at
# metallic 0.90, and with no environment map a
# near-mirror has nothing to mirror, so every
# steel you are ALLOWED to trust renders
# near-black at yard distance (measured: rgb
# 49,51,49 at 20 m). Powder-coat is paint —
# metallic 0.05, diffuse — so this frame reads
# as a white cage standing over the glass from
# the far fence, and can never be misread as
# the galvanised steel of an honest sail post.
"net_mesh": "#3A4340", # knitted HDPE hail mesh: dark, matte, and the
# only large dark mass any yard carries up at
# 2.7 m. Rolled it is a bar; down it is a heap.
}
# Rainwater caught in a sail is not swimming-pool blue. It's shallow, murky, it
@ -1916,6 +1952,283 @@ def build_glasshouse_01_wrecked(name):
return root
# ---------------------------------------------------------------------------
# THE HAIL-NET FRAME (SPRINT18 gate 4 — the glasshouse tier's LIVE half)
# ---------------------------------------------------------------------------
# SPRINT16 shipped the glasshouse and priced it at 320. SPRINT18 read the gate
# and found the thing the price was waiting on, written in e.test's own words:
# "nothing in the sim wrecks a glasshouse yet — the value is inert data". The
# apex could not be reached. main.js bills collateral off a BROKEN RIG CORNER
# (`world.anchor(c.anchorId).collateral`), and a glasshouse deliberately offers
# no anchors — correctly, it is the one rule pinned from every direction — so
# the most expensive object in the game could not cost anybody a cent. That is
# the free-failure bug inverted: not a hazard billing nothing by accident, but
# a hazard that cannot bill at all by construction.
#
# DESIGN.md line 179 already named the missing asset: "Jobs: hail nets and mesh
# sails rigged OVER glass, where your own failure is the worst debris of all."
# You do not tie to the glasshouse. You tie to the frame that STRADDLES it —
# and every corner of that frame is a corner whose failure drops steel, cloth
# and hardware through fourteen panes.
#
# So this is the tier, and its teaching is new. Every other trap in this game
# punishes you with a bad number: the carport beam at 0.22, the fascia at 0.35,
# the corroded post at 0.55 whose real capacity you cannot read. This one is
# GOOD hardware — purpose-built, plumb, on its own footings, factory eyes —
# and it is the most dangerous anchor in the game because of WHERE IT STANDS.
# The rating is not the hazard. The position is.
NET_FRAME = dict(
CLEAR_X=0.30, # portal stands this far clear of each gable end
CLEAR_Y=0.45, # legs stand this far outside the long walls, on soil
HEAD_H=2.75, # head-beam height. MUST clear the ridge (2.28) — a frame
# that fouled the glass it protects is a joke, and
# e.test measures the clearance off the two shipped GLBs.
TUBE=0.032, # 32 mm net-frame section
PAD=0.22, # footing pad
)
# The rung. PROPOSAL — Lane A rules the number, same as every rung before it.
#
# Ladder as shipped: 0.22 carport beam < 0.30 carport post < 0.35 house fascia
# < 0.45 swing frame < 0.55 corroded post < 0.65 pergola < 1.00 sail post.
# This goes at 0.80, and the argument has two halves:
#
# · WHY IT OUT-RATES THE PERGOLA (0.65) BY A DISTANCE. The pergola is a deck
# structure screwed to a house and it flexes; the corroded post's capacity
# is unknowable; the swing frame stands on grass. This is an engineered
# portal frame on four real footings with welded eyes, and it is the only
# structure in the palette that was BUILT to be tied to. Rating it near the
# bad steel would be the lie the corroded post exists to punish, inverted:
# honest steel de-rated for looking dangerous.
# · WHY IT IS NOT THE SAIL POST (1.00). The section is 32 mm sized for hail
# mesh — a couple of hundred grams per square metre, and near-zero drag
# because mesh SPILLS wind rather than catching it. A 25 m² impermeable
# shade sail in a southerly is a load one order of magnitude larger. 0.80
# is a 20% de-rate for "engineered for a load you are about to exceed".
#
# And 0.80 is chosen so that IT USUALLY HOLDS. That is the point of the tier,
# not a softness in it: a corner that fails one night in five costs you nothing
# on a sail post and 320 dollars here. The player who learns "0.80 is fine" on
# every other yard is exactly the player this yard is for. The lesson is not
# "don't trust this steel" — the steel is fine. It is "the same failure has a
# different price depending on what is underneath it", which is the sentence
# DESIGN.md line 179 has been waiting for an asset to say.
NET_FRAME_RATING = 0.80
def _net_frame(name, root, steel, conc, mesh_m, *, wrecked=False):
"""The portal frame, shared by intact and wreck so the two cannot drift.
The wreck fails at the -x portal ONLY: its feet kick out of their pads and
its head beam comes down onto the glasshouse ridge. +x stands, holding the
eave rails up, which is why the wreck keeps the intact height a hail-net
frame does not fall over, it folds at one end, and the end it folds is the
end that empties the glass."""
G, N = GLASSHOUSE, NET_FRAME
hx = G["W"] / 2 + N["CLEAR_X"] # 1.60 — clear of the gable ends
hy = G["D"] / 2 + N["CLEAR_Y"] # 1.40 — clear of the long walls
H, r, pad_h = N["HEAD_H"], N["TUBE"] / 2, 0.06
def foot(sx, sy):
"""Where the leg meets the ground. Wrecked -x feet are OUT of the pad —
a foot beside its own footing is the most legible steel failure there
is, and it costs one offset to say."""
if wrecked and sx < 0:
return (sx * hx - 0.45, sy * hy, pad_h + (0.14 if sy > 0 else 0.0))
return (sx * hx, sy * hy, pad_h)
def head(sx, sy):
"""Where the leg meets the top frame. The wrecked -x portal has come
down and is RESTING ON THE RIDGE (2.28) rather than passing through it:
the glasshouse's own wreck keeps its aluminium frame standing at full
height, so a beam that ended up below the ridge line would be inside
it. Lying ACROSS the ridge is both true and non-interpenetrating.
The head comes IN (+x, dragged by the sail) while the feet kick OUT
(-x) the portal RACKS into a parallelogram, the carport's failure
mode on a lighter section. The offsets are deliberately large (0.45
each way, ~22° of lean over 2.3 m) because I looked at 0.30/0.16 in
the render and the top frame still read as a clean level rectangle:
a 0.43 m drop on a 2.77 m frame of 32 mm tube is invisible in
perspective, and a wreck you cannot see is not a wreck."""
if wrecked and sx < 0:
return (sx * hx + 0.45, sy * hy * 0.90, G["RIDGE_H"] + 0.05)
return (sx * hx, sy * hy, H)
def mid(sx):
a, b = head(sx, -1), head(sx, 1)
return ((a[0] + b[0]) / 2, 0.0, (a[2] + b[2]) / 2)
pads, legs = [], []
for sx in (-1, 1):
for sy in (-1, 1):
pads.append(add_box(f"{name}_pad_{sx}_{sy}", (N["PAD"], N["PAD"], pad_h),
(sx * hx, sy * hy, pad_h / 2), conc))
legs.append(add_tube_between(f"{name}_leg_{sx}_{sy}",
foot(sx, sy), head(sx, sy), r, steel, verts=8))
join_group(pads, "footings", root)
join_group(legs, "legs", root)
top = []
for sx in (-1, 1): # portal head beams, spanning y
top.append(add_tube_between(f"{name}_head_{sx}", head(sx, -1), head(sx, 1),
r, steel, verts=8))
for sy in (-1, 1): # eave rails, spanning x
top.append(add_tube_between(f"{name}_eave_{sy}", head(-1, sy), head(1, sy),
r, steel, verts=8))
# The tensioning wire down the middle, deliberately thinner than the frame:
# at 20 m the gauge difference is the "made for a net" read, and it is the
# honest reason the whole thing rates 0.80 instead of 1.00.
top.append(add_tube_between(f"{name}_ridge_line", mid(-1), mid(1),
r * 0.35, steel, verts=6))
join_group(top, "top_frame", root)
if not wrecked:
# Rolled along the +y eave, because the JOB is to rig it. A deployed
# net would be a finished yard, and this asset exists to be worked on.
join_group([add_tube_between(f"{name}_roll", (-hx, hy, H - 0.11),
(hx, hy, H - 0.11), 0.085, mesh_m, verts=10)],
"net_roll", root)
else:
# YOUR debris, not the storm's. The net has come off its lashings at the
# collapsed end and is draped down over the glass and heaped out past
# the footing — deterministic scatter, so the same wreck twice.
rng = rng_for(name)
drape = []
pts = [(hx * 0.85, hy, H - 0.10),
(hx * 0.10, hy * 0.92, H - 0.78),
(-hx * 0.55, hy * 0.80, G["RIDGE_H"] * 0.55),
(-hx - 0.28, hy * 0.55, 0.24),
(-hx - 0.80, hy * 0.20, 0.06)]
for i in range(len(pts) - 1):
drape.append(add_tube_between(f"{name}_net_sag_{i}", pts[i], pts[i + 1],
0.055, mesh_m, verts=6))
for i in range(9):
a = rng.uniform(0, math.tau)
rr = rng.uniform(0.05, 0.45)
drape.append(add_box(
f"{name}_net_heap_{i}",
(rng.uniform(0.22, 0.50), rng.uniform(0.16, 0.40), rng.uniform(0.03, 0.09)),
(-hx - 0.58 + math.cos(a) * rr, hy * 0.20 + math.sin(a) * rr * 0.8,
rng.uniform(0.02, 0.07)),
mesh_m, rot=(0, 0, rng.uniform(0, math.pi))))
join_group(drape, "net_down", root)
return hx, hy
def build_hail_net_frame_01(name):
"""The hail-net frame — four good anchors in the worst place in the game.
The glasshouse tier's live half (SPRINT18 gate 4). This is what DESIGN.md
line 179 means by "hail nets and mesh sails rigged OVER glass": a portal
frame that straddles the glasshouse, clear of it on all four sides, with a
head height that clears the ridge and a rolled mesh net waiting to go up.
THE TELL, and it is a position rather than a defect. Every reading of every
other trap in this game is a bad number on the object. This object's numbers
are GOOD 0.80, plumb, four footings, welded eyes and what the player has
to read instead is the plan view: the frame BRACKETS the glass. e.test pins
that geometrically off the two shipped GLBs (frame footprint strictly
contains the glasshouse footprint; head height strictly clears the ridge),
because "it stands over the glass" has to be a measurement, not a vibe.
The 20 m read is the powder-coat: white, matte, metallic 0.05, against a
palette where every trustworthy steel is metallic 0.90 and therefore renders
near-black. A white cage over a glass box, visible from the far fence.
WHAT THE ANCHORS SAY. All four bake collateral="glasshouse". They are the
only nodes in the palette whose collateral names a DIFFERENT structure than
the one they sit on (the house's fascia→"gutter" is the precedent, and it is
the same shape: the anchor names what its failure TAKES, not what it is).
Break a corner here and the sail, the shackle and the turnbuckle go through
fourteen panes: your own failure is the worst debris of all, wired as data.
AND WHAT THIS ROOT DELIBERATELY DOES NOT CARRY: collateral_key. See below
it is the whole of gate 5 in one omission.
"""
root = add_empty(name)
# Powder-coat is PAINT, so metallic stays near zero. This is not a style
# choice, it is the S17 measurement: high metalness with no environment map
# renders near-black, and this asset's entire long-range tell is that it is
# the brightest thing in the yard.
steel = get_material("Mat_NetFrame", PAL["net_frame_white"], 0.50, metallic=0.05)
mesh_m = get_material("Mat_HailNet", PAL["net_mesh"], 0.85, metallic=0.0)
conc = get_material("Mat_Concrete", PAL["concrete"], 0.95)
hx, hy = _net_frame(name, root, steel, conc, mesh_m)
# The four eyes, at the four corners of the top frame — where a net corner
# ties, and therefore where a sail corner will be tied instead.
for i, (sx, sy) in enumerate(((-1, -1), (1, -1), (1, 1), (-1, 1))):
e = add_empty(f"net_anchor_{i + 1:02d}",
(sx * hx, sy * hy, NET_FRAME["HEAD_H"] - 0.06), root, size=0.18)
e["anchor_type"] = "hail_net_frame"
e["rating_hint"] = NET_FRAME_RATING
e["collateral"] = "glasshouse"
e["why"] = ("sound steel, and the most expensive corner on the board: it is "
"rated for hail mesh, and everything it drops lands on glass")
stamp(root, name, "structure")
root["site_hint"] = "glasshouse"
root["is_anchor_trap"] = True
root["rated_for"] = ("knitted hail mesh, ~0.2 kg/m2, near-zero drag — mesh spills "
"wind. A 25 m2 impermeable sail is an order of magnitude more.")
# ⚠️ NO collateral_key ON THIS ROOT, AND THAT IS THE POINT (gate 5).
#
# world.js resolves a collateral key to a structure with structFor(), which
# returns the FIRST structure in site order whose key matches. If this frame
# claimed collateral_key="glasshouse" — which looks like the helpful thing
# to do, since its anchors bill that key — then in a yard where the frame is
# authored before the glasshouse, every failure would bill "the glasshouse"
# for 320 dollars and then WRECK THE FRAME: the player watches their own
# frame fold while the invoice charges them for panes that are still in
# their rebates. The bill and the wreck would agree with each other and
# both be wrong, which is the only kind of wrong this repo cannot see.
#
# So exactly ONE structure owns a key, and it is the one that owns the
# price. This frame POINTS at the key and never claims it. The pointer
# lives in a field nothing resolves, so it can document intent without
# arming anything.
root["collateral_target"] = "glasshouse"
root["rigs_over"] = "glasshouse_01"
return root
def build_hail_net_frame_01_wrecked(name):
"""The frame after the corner you trusted let go.
The -x portal has folded: both its feet are out of their pads, and its head
beam is lying across the glasshouse ridge with the net draped down over the
glass and heaped out past the footing. The +x portal stands, holding the
eave rails at full height so this wreck is the same height as the intact
frame, which is the honest read: a portal frame folds at one end, it does
not lie down.
It carries NO GLASS. The glasshouse has its own wreck variant and swaps
independently; a net-frame wreck that shipped shards would draw them twice
the moment both swapped on the same night, and would also quietly claim
the glass's failure as its own. e.test pins the absence.
UNPRICED, BY RULING the bike/jacaranda pattern. A folded portal frame is
obviously a repair bill, but the player is being taught about the glass, and
one broken corner can only name one collateral key. Inventing a second bill
with no mechanism to split it between them is exactly the guess the invoice
exists to refuse. Price it when a break can bill two things."""
root = add_empty(name)
steel = get_material("Mat_NetFrame", PAL["net_frame_white"], 0.50, metallic=0.05)
mesh_m = get_material("Mat_HailNet", PAL["net_mesh"], 0.85, metallic=0.0)
conc = get_material("Mat_Concrete", PAL["concrete"], 0.95)
_net_frame(name, root, steel, conc, mesh_m, wrecked=True)
stamp(root, name, "structure")
root["broken_variant_of"] = "hail_net_frame_01"
# No anchor survives the wreck — the fascia rule, sixth application. An
# anchor that outlives its structure is the free-failure bug in a costume.
root["collateral_target"] = "glasshouse"
return root
# ---------------------------------------------------------------------------
# THE POOL KIT (SPRINT16 gate 5 — the compliant ring whose steel all says no)
# ---------------------------------------------------------------------------
@ -3824,6 +4137,25 @@ ASSETS = [
dict(name="glasshouse_01_wrecked", fn=build_glasshouse_01_wrecked,
dims=((3.4, 5.4), (2.6, 3.8), (2.15, 2.40)),
nodes=["frame", "door", "panes_left", "shards"]),
# SPRINT18 gate 4 — the glasshouse tier's live half. Every band here is a
# design claim about the glass underneath it, which is why they are tight:
# x and y floors must both EXCEED the glasshouse's ceilings (2.8 / 2.1), or
# the frame has stopped straddling the thing it bills; z must clear the
# ridge (2.40 ceiling) or a frame built to protect glass is resting on it.
dict(name="hail_net_frame_01", fn=build_hail_net_frame_01,
dims=((3.30, 3.55), (2.90, 3.15), (2.70, 2.85)),
nodes=["footings", "legs", "top_frame", "net_roll",
"net_anchor_01", "net_anchor_02", "net_anchor_03", "net_anchor_04"]),
# Folded at one end, not felled: the SAME z band as the intact frame,
# because the +x portal stands and holds the eave rails up. If z ever
# collapses, someone has laid a portal frame down flat and it never does
# that. x runs WIDE on the -x side — the net heaped out past the footing,
# and the wreck apron a yard author has to keep clear.
# 4.10 floor, not 4.30: the measured span is 4.30 and it is set by the NET
# HEAP, not by the racked feet, so it must not sit on the band boundary.
dict(name="hail_net_frame_01_wrecked", fn=build_hail_net_frame_01_wrecked,
dims=((4.10, 5.30), (2.90, 3.15), (2.70, 2.85)),
nodes=["footings", "legs", "top_frame", "net_down"]),
# The compliance ring. z is pinned tight around 1.2 m because the height
# IS the flavour (AS 1926.1); y reaches past the ring for the ajar gate.
dict(name="pool_kit_01", fn=build_pool_kit_01,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 MiB

After

Width:  |  Height:  |  Size: 5.0 MiB

View File

@ -80,6 +80,16 @@ export const FACTORY_ANCHOR_RATINGS = Object.freeze({
"sail_post_corroded/top_anchor"
]
},
"hail_net_frame": {
"collateral": "glasshouse",
"rating_hint": 0.8,
"sources": [
"hail_net_frame_01/net_anchor_01",
"hail_net_frame_01/net_anchor_02",
"hail_net_frame_01/net_anchor_03",
"hail_net_frame_01/net_anchor_04"
]
},
"house": {
"collateral": "gutter",
"rating_hint": 0.35,

View File

@ -100,10 +100,26 @@ export const PHASES = ['forecast', 'prep', 'storm', 'aftermath'];
* can't inspect the inside of). One rating for the whole type, per the
* manifest rule. The GLB wears the tell (rust, a sagging pad eye); the type
* string is the player's pre-rig read of the same fact.
*
* `hail_net_frame` (SPRINT18 gate 4, E): the frame that straddles a glasshouse
* so a hail net can be rigged OVER the glass (DESIGN.md line 179). It is the
* first anchor word in this enum whose danger is not in its own number.
* rating_hint 0.80 the highest rung below the honest post, and it EARNS it:
* an engineered portal frame on four real footings with welded eyes, the only
* structure in the palette that was built to be tied to. The 20% de-rate is
* for section, not condition (32 mm sized for hail mesh, which spills wind;
* a 25 impermeable sail is an order of magnitude more load).
* What makes it the most dangerous anchor in the game is that its baked
* `collateral` names the GLASSHOUSE, not itself the `house`"gutter"
* precedent, and the same shape: an anchor names what its failure TAKES, not
* what it is. Break a corner here and the sail, the shackle and the turnbuckle
* go through fourteen panes at $320. The type string is the player's pre-rig
* read of a hazard that is a POSITION, and the reason it must not be typed
* `post`: "post" promises a corner whose failure costs a shackle.
*/
export const ANCHOR_TYPE = Object.freeze([
'house', 'tree', 'post', 'carport', 'carport_post', 'swing_frame', 'pergola',
'corroded_post',
'corroded_post', 'hail_net_frame',
]);
// ---------------------------------------------------------------------------

Binary file not shown.

Binary file not shown.