This whole page is an illustration. It shows making copies while the world runs (an army), and every name and number on it is made up to show the language.

What the boss is

Imagine a clearing in a forest with a troll king in the middle of it, a hulking figure half again a person's height. While visitors fight him, a bar across the top middle of each nearby visitor's screen shows his name and how much health he has left: a dark red groove 340 pixels wide with a bright red fill that shortens as he is hurt. The moment his health falls below half, twenty trolls appear in a ring 6 m round him, evenly spaced, each with a stance of its own: some stand guard at their places, some charge the nearest visitor, some circle round to the side. If he heals and falls below half again, no second army comes. When a visitor is badly hurt, the edges of their own picture glow red, more strongly the nearer they are to death, with a brief brighter flash at each blow; nobody else sees that visitor's glow.

The listing

// Everything on this page is an illustration.
enum stanceKind { guard, charge, flank }

// ===== A troll: a design, copied while the world runs =====
part troll
  field stance: stanceKind = guard
  field health: fraction = 1, within: 0 ..= 1, mutable: true, lives: server
  part body: people.trollFigure
    being(self)
  on(created, {
    match stance {
      case guard  { start(npcbehave.guard(body, post: self.place, on: walkable)); }
      case charge { start(npcbehave.pursue(body, nearest(visitors), on: walkable)); }
      case flank  { start(npcbehave.flank(body, nearest(visitors), by: 8 m, on: walkable)); }
    }
  })

// ===== The boss =====
part boss, at: (120, land.height((120, 0, 480)), 480)
  field health   : fraction = 1, within: 0 ..= 1, mutable: true, lives: server
  field summoned: bool = false, mutable: true, lives: server
  part body: people.trollKing
    being(self)
  part army                                           // empty at load; filled while the world runs

  on(became(health < 0.5), {
    if !summoned {
      set(summoned, true);
      each i in 0 ..< 20 {
        spawn(troll(stance: oneOf([guard, charge, flank], seed: i)),
              under: army, at: ring(self, 6 m, i / 20));     // army.troll[0] ... troll[19]
      }
    }
  })

// ===== The health bar: a HUD element in each nearby visitor's picture =====
part barStyles
  field groove: style = style(like: panel, background: rgba(40, 10, 10, 200), radius: 3 px)
  field fill   : style = style(like: panel, background: rgba(200, 30, 20, 255), radius: 3 px)

part bossBar
  field picture: image
  derive(picture, layout(anchored([
    column([
        text("The Troll King"),
        stack([box([], style: barStyles.groove, anchor: (0, 0, 1, 1)),
               box([], style: barStyles.fill,   anchor: (0, 0, boss.health, 1))],
              size: (340 px, 12 px))],
      style: styles.hudGlass, gap: 4 px, visible: distance(you, boss) < 40 m,
      anchor: (0.5, 0), pivot: (0.5, 0), offset: (0 px, 14 px), size: (360 px, auto))])))

// ===== The red edge: a meta effect, each visitor's own =====
part hurtEdge
  field low      : fraction = 0, within: 0 ..= 1, lives: client                    // from the visitor's own health
  field flash    : fraction = 0, within: 0 ..= 1, mutable: true, lives: client     // a brief flash at each blow
  field strength : fraction = 0, within: 0 ..= 1, lives: client
  field picture  : image
  derive(low, { if you.health < 0.3 { (0.3 - you.health) / 0.3 } else { 0 } })
  derive(strength, min(1, low + flash))
  derive(picture, layout(anchored([
    box([], anchor: (0, 0, 0, 1), size: (48 px, auto),
        fill: linear((0 px, 0 px), rgba(200, 0, 0, 160 * strength), (48 px, 0 px), rgba(200, 0, 0, 0))),
    box([], anchor: (1, 0, 1, 1), pivot: (1, 0), size: (48 px, auto),
        fill: linear((48 px, 0 px), rgba(200, 0, 0, 160 * strength), (0 px, 0 px), rgba(200, 0, 0, 0)))])))
                                                        // and the top and bottom edges likewise
  on(message(struck, cost, of: you), {
    set(flash, min(1, cost * 4));
    start(transition(flash, to: 0, over: real(0.8 s)));
  })

// ===== Each visitor's picture: the world, then the glow, then the HUD =====
composite(viewingCamera.picture,
  over: [layer(hurtEdge.picture, blend: add), layer(hud.picture), layer(bossBar.picture)],
  order: [world, hud, browser])

Walking through it

The troll: one design, three stances

troll is a design with an own field stance, an enum of three cases. When a copy is made, its start act (Loading) uses a match over the stance (Control flow), which must name every case, to start one mind from the npcbehave package (Package behaviors). npcbehave.guard stands for the package's guard character (hold a post, investigate, chase what it sees, go back), and pursuing is one of its steering behaviors; a flanking mind is not in the package, so npcbehave.flank is a name a world could not yet use.

Spawning twenty, once

became(health < 0.5) is a condition as a trigger: it fires once, at the moment the health falls below half, however often the health changes. The acting block (Blocks) first checks summoned, so a boss healed and hurt again does not summon twice, then loops with Cone's each i in 0 ..< 20, the numbers 0 to 19 (Control flow: each). Each turn is one spawn (Actions: spawn and remove): a copy of troll made while the world runs, as a child of army, numbered like a list's elements (army.troll[0] to army.troll[19]), at the i-th of twenty places round a ring 6 m from the boss. oneOf([guard, charge, flank], seed: i) draws each troll's stance from a seed of its own, so every machine makes the same army: troll 7 is always a flanker. Because army is the boss's child, removing the boss removes the army (Parts: a path carries ownership).

The health bar

bossBar holds an image defined by a layout: an anchored column, pinned to the top middle of the screen 14 px down, in the HUD's dark-glass style, shown only to a visitor within 40 m of the boss. you is the being whose picture this is (Overlays). Inside, a stack of two boxes: the groove filling the stack, and the fill pinned from the left edge to boss.health of the way across, so the bar shortens as the field falls with no line anywhere moving it. The layout is a value: recomputed when the health changes, laid out again only where it changed.

The red edge

A meta effect is an image over the whole picture whose strength follows the visitor's state (Overlays: meta effects). Its strength is the author's formula over two values (Subscriptions: several effects on one value): low, a subscription of the visitor's health that rises from 0 at 30% health to 1 at none, and flash, set at each blow in proportion to its cost and faded out over 0.8 s. The fade counts real time, the person's, not the world's, because it is about the person (Values: clocks). All three values have lives: client: each visitor's machine keeps its own, and no one else's picture glows (Distribution). The glow itself is two boxes 48 px wide at the left and right edges, each filled with a straight-line gradient from red at the edge to clear.

The visitor's picture

The last expression is the composite (Images: compositing): the camera's picture, the glow added over it (light added, as a glow is), then the HUD and the boss bar laid over by their transparency. The browser's own controls are always composited last, whatever the world writes.

← A villager | Contents | A shopkeeper's dialogue →