What the looking-glass is

On the outside of the cottage's back wall, towards the chimney end, hangs a mirror: a pane of glass 1 m wide and 1.7 m tall, its bottom edge 0.55 m above the ground and its top 2.25 m, in a dark timber frame of bars 7 cm wide standing 5 cm off the wall. It behaves as a mirror does: walk up to it and you see yourself head to foot, with the sky and the balloon in the backyard behind you. It returns about 92% of the light, very slightly cool, as silvered glass does. Each visitor sees their own reflection.

Stand still in front of it, between 0.6 m and 5.5 m away and no more than 2.5 m to either side, facing it, for 3 seconds. The glass opens. Without any jump in the picture, it stops being a mirror and becomes a window: what you see through it is a stone corridor 300 m below the island, the mouth of the labyrinth. Where your reflection stood, a figure stands in the corridor: your own person, left behind. It waits a second and a quarter, turns round, a little quicker than a person would, and walks off down the corridor to the antechamber's door, where it vanishes. The cottage's wall now has a slot behind the glass, so you can step up to it and through: a being whose eyes cross the glass comes out at the corridor's mouth, facing the same way. At the mouth a matching window looks back up at the cottage's lawn, and while the glass is open it is a way back. Once nobody has been near either end for 10 seconds (within 15 m of the glass above, or within 30 m of the antechamber's door below) and the figure has gone, the glass closes and is a mirror again.

The listing

// ===== The glass, on the cottage's back wall =====
part cottage, at: (-16, land.height((-16, 0, 330)), 330)
  ...
  part house: ...                                       // the cottage's walls: one closed block
  field open: bool = false, mutable: true, lives: both
  field link: offset = labyrinth.entrance.mouth.worldPlace - pane.worldPlace   // from the pane to the corridor's mouth

  part frame: mirrorFrame(pane: pane, bars: 7 cm, offWall: 5 cm, backing: 3 cm), material: materials.darkTimber
  part pane : glassPane(width: 1.0 m, height: 1.7 m), rotation: rotation(180 deg),   // faces north, away from the house
              at: (1.5 m, 1.4 m, -6.034 m)                      // its center: 1.5 m along the back wall, 1.4 m up, 3.4 cm outside it
    field picture: image
  part wayIn: gate(across: pane, shift: link, when: open)

  // what the glass shows: a second camera drawn into an image the glass reads
  derive(pane.picture, {
    if open { render(camera: moved(viewingCamera, by: link, clip: pane), skip: [pane]) }
    else    { render(camera: reflected(viewingCamera, about: pane), skip: [pane]) }
  })
  derive(pane.look, screenMapped(pane.picture, tint: (0.92, 0.94, 0.95)))
  derive(house.solid, {
    if open { difference(house.shape, notch(at: pane, wide: 1.1 m, deep: 1 m)) } else { house.shape }
  })

  // opening: someone stands still before the glass, facing it, for 3 s
  field echo: ?reflection = None, mutable: true        // the reflection, while it is there
  each v in visitors {                                  // one watch for each visitor
    on(held(onIsland(v) && inFront(v, of: pane, from: 0.6 m, to: 5.5 m, across: 2.5 m)
            && facing(v, toward: pane, within: 45.57 deg) && still(v),
            for: sim(3 s)), {
      if !open {
        set(open, true);
        set(echo, Some(spawn(reflection(who: v.who), under: labyrinth.entrance,
              at: reflect(v.place, in: pane) + link, rotation: reflect(v.rotation, in: pane))));
      }
    })
  }

  // closing: nobody near either end for 10 s
  field near: bool = false
  derive(near, any(visitors, v => (onIsland(v) && distance(v, pane) < 15 m)
                                  || (occupied(underground, by: v) && distance(v, labyrinth.entry) < 30 m))
               || exists(echo))                         // the reflection is still walking
  on(held(open && !near, for: sim(10 s)), set(open, false))

// ===== The puppet: the opener's reflection, left behind =====
part reflection                                         // a design, copied only by spawn
  field who     : person
  field walking: ?handle = None, mutable: true
  part body: who
    being(self)
  on(created, set(walking, Some(start(
      npcbehave.arrive(body, labyrinth.entry, stopShort: 1.2 m,
                       delay: sim(1.25 s), turnRate: 3.05 rad/s)))))   // a figure's 1.05 rad/s turn and 2 more
  on(ended(walking), remove(self))

// ===== The way back, 300 m below =====
part labyrinth
  part entry, at: (...)                                 // the antechamber's south door: a named place
  part entrance
    part mouth: glassPane(width: 1.0 m, height: 1.7 m), at: (0 m, 1.4 m, 291 m)  // its center; faces +z, up the corridor
      field picture: image
    part wayBack: gate(across: mouth, shift: -(cottage.link), when: cottage.open)
    derive(mouth.picture,
           render(camera: moved(viewingCamera, by: -(cottage.link), clip: mouth), skip: [mouth]))
    derive(mouth.look, screenMapped(mouth.picture, tint: (0.92, 0.94, 0.95)))

Walking through it

One value drives a look, a product and two gates

open is a field of the cottage: a bool, false at first, mutable: true, with lives: both, on the server and every visitor's machine, because the visitor's own browser steps its walker through the gate ahead of the server and needs the value too (Distribution). link is the one move from the glass to the corridor's mouth, worked out as the mouth's place less the glass's, both read in world coordinates with worldPlace (Frames): 14.5 m east, down from the cottage's ground to the labyrinth's floor at -300 m, and 32.966 m north. Written once, the picture and the gate cannot disagree about it. The glass and the wall's solid are subscriptions of open, and the gate reads it with when: open. The pane faces +z of its own frame, as every pane does, so the cottage's, which hangs outside the back wall facing north, is turned half a turn; at: is its center (Cameras and views).

The second camera, drawn into an image

The pane is a drawn part whose look is a picture of the world. picture is a field of type image (Images), defined by a source, render(camera:, skip:): the world drawn again from another camera, leaving out the listed parts, so the glass never shows itself inside itself. While shut, that camera is the viewer's own reflected in the glass's plane, which is what a mirror is; while open, it is the viewer's camera moved by link, cut at the exit's plane (clip: pane names the glass's plane moved by the link and facing back), so the picture is what the viewer would see standing at the mouth (Cameras and views). viewingCamera is the camera drawing the picture being made, not the visitor's being: each visitor sees their own reflection, and a picture inside another picture is drawn from the outer picture's camera.

screenMapped(pane.picture, tint: ...) is the look the glass's surface reads: each pixel of the glass shows the pixel of the picture at the same place on the screen, dimmed by the silvering's 92%. The picture is drawn only for the patch of the screen the glass covers, at that patch's own sharpness, and not at all when the glass is behind the viewer or off the screen; none of that is in the content (Images: keep the description until the last moment). Because the open picture is the reflection's camera moved, and the figure is placed where the reflection stood, the picture changes in what it is made of, not in what it shows.

The gate and the notched wall

wayIn is a gate: a flat opening across the pane that moves any being whose eyes cross it by link, enforced by the engine in step on the server and in each visitor's own prediction (Physics: gates). Its edges are the pane's, its when: open is read at every step, and it works only while the glass is open. The house's solid, its product for physics, is the house's shape while shut and the shape with a slot 1.1 m wide and 1 m deep behind the glass cut out of it while open (difference and notch, booleans from Shape tools; the slot is as high as the house's block): a product derived again while the world runs, on the server and in every browser that predicts its own walker (Construction: one description, several products).

Opening: held for 3 s

held(c, for: d) is a condition as a trigger: it fires once c has been true for sim(3 s) without a break. The content does not write the waiting, the counting and the firing; the engine watches the condition only when its inputs change. The rule is written once for each visitor, each v in visitors. The condition is the visitor on the island, in front of the glass 0.6 to 5.5 m out and within 2.5 m of its middle, turned towards it within 45.57°, and still (under 5 cm a second, on the ground, not walking): inFront, facing and still are defined on Events. The acting block (Blocks) opens the glass and spawns the puppet: spawn(reflection(...), under: ..., at: ...) makes a copy of a design while the world runs (Actions: spawn; Designs: spawning), its person the opener's own, placed where the opener's mirror image stood and facing as its image faces: reflect(x, in: pane) reflects a place, a direction or a rotation in the pane's plane, and the link then carries the place into the corridor (Cameras and views). The opener's look is v.who, a figure of their height and colors; reading more of a visitor's look is open (Avatars). The handle of the spawned copy is kept in echo, and exists(echo) is true while the copy has not been removed.

The puppet

reflection is a design copied only by spawn. Its body is a being (being(self)) no visitor may take over, driven by world logic: a puppet (Visitors: beings). When made, it starts one behavior, npcbehave.arrive (Behaviors): wait 1.25 s, turn about at 3.05 rad/s (a figure's own turn, 1.05 rad/s, and 2 more), walk to the entry and stop 1.2 m short of it. The handle is kept in a field so a second rule can wait for the end, as it can for an animator: on(ended(walking), remove(self)). A lifetime is an animator or a behavior and a handler on its end (Actions: spawn and remove).

Closing: held absence

near is a subscription over every visitor: anyone above ground within 15 m of the glass, anyone under it within 30 m of the entry, or a puppet still walking. "Near" here is a set of places 300 m apart plus a being. held(open && !near, for: sim(10 s)) closes the glass; it opens again the same way, and each opening makes a new puppet.

The way back

At the corridor's mouth a second pane faces the other way, always a window onto the cottage's lawn (its camera the viewer's moved back up by the link), with a gate that returns a being to the front of the glass only while the cottage's glass is open (when: cottage.open). It reads another part's field, cottage.open, directly (Subscriptions: open questions).

Under the proposal of scenes and portals

The listing above puts the labyrinth in the same space as the cottage, 300 m below, and the glass as a pane and a gate that agree through one offset. Under the hypothesis of scenes and the portal proposal, the labyrinth is its own scene, with its own coordinate system, and the glass is one portal with a window and a passage, landing at an arrival the labyrinth publishes; the way back is a second portal at the corridor's mouth (Worlds, scenes and regions; Portals). The opening, the puppet and the closing are unchanged.

← The riddle of the two guards | Contents | The land →