A world is visited by people, but content never names a player. Players, their identity, the avatars fetched for them, authentication, payment and messaging are outside the content (Outside the content). What an avatar is made of, and which of its pieces are content, is on Avatars. What the content sees is beings: parts that act. A visitor drives a being; a villager's mind drives another; both perform the same named actions, and the world answers them with events. Where a visitor's act meets the content, three layers meet: the physical input (a key, a tap), which is the browser's; the named action, which is the contract; and the content's response.
Beings
A being is a part that acts. Each step of the world it is given actions (walk ahead, turn, run, jump, hail), and the engines move its body accordingly. A lantern is placed; a being moves itself. Who chooses its actions is a separate question: for a visitor's avatar it is the visitor, for a villager a mind, for a puppet world logic, and for the stand-in on the beach, nobody until a visitor takes her over.
part villager
field who : person
part body: who
being(self) // a being: it acts each step; no visitor may take it over
part beach
part standIn: people.averageWoman
being(self, possessable: true) // idle until someone takes it over
being(p: part, possessable: bool = false, targetable: bool = true)marks a part as one that acts; the call sits in the part's body and names the part, asbody(self, ...)does. Its place is execution state the engines own: its defined place is only where it starts (frames.html).possessable: whether a visitor may take this being over; it isfalseunless the call sayspossessable: true. Possession (which being a visitor's controls drive and the camera follows) is the browser's mechanism; which beings may be possessed is the world's fact.targetable: whether the world's spells and other actions aimed at a being may choose this one; it istrueunless the call saystargetable: false. A guard passestargetable: false, so the zap and the jig skip it. The server enforces it, not only the browser: an action that names such a being as its target is refused even if a changed browser sends it.- A being needs no mind. A being with no driver is given no actions, and stands idle, breathing and shifting its weight.
A handle on a being
Content must still say "the nearest visitor", "whoever asked", "the one who threw it", key a field by them and range over them. It does so with a handle on a being: an id for a body in the world, not a path, which content may compare, use as a key and measure distances from.
on(action(ask, q, to: g, by: v), ...) // v: the being that acted field asked: Table[being, bool] = false, mutable: true, lives: both // a field keyed by being npcbehave.follow(nearest(visitors), keep: 6 m) // a relation over visitors' beings
nearest(visitors) is whichever visitor-driven being is nearest at this step, without naming any visitor. me is the being driven by the visitor at this machine: on each visitor's machine it is that visitor's being, so a value worked out from it, such as occupied(post, by: me), is each visitor's own and lives on their machine (lives: client; Physics: areas). It names no one: it is a relation, as nearest(visitors) is. A being is not a player: the same person could be a villager in one world and a visitor's avatar in another, because what a being is (its who) and what drives it are separate fields.
What a being handle reads
A handle reads the being's state, as fields. The ones content may read:
| Written | Type | What it is |
|---|---|---|
v.feet, v.place | place | where its feet stand, on the ground; v.place is the same place |
v.name | text | the name it is known by |
v.height | meters | how tall its figure is |
v.who | person | a figure of its height and colors, which is enough to make a copy of it (the looking-glass's reflection). Reading more of a visitor's look stays open (Avatars) |
v.chest | place | the middle of its chest, 0.7 of its height above its feet; a spell's range is measured to it |
v.eyes | pose | where its eyes are and which way they look; a plain walker's eyes are 1.7 m up |
v.rotation | rotation | the way it faces, about up |
v.speed | speed (m/s) | how fast it moves along its heading, signed: negative backing up. In the air it is the speed it left the ground with (a walker's gait is told 0) |
v.verticalSpeed | speed (m/s) | how fast it rises (negative falling); a fall faster than 5 m/s sends it limp |
v.mode | enum | what it is doing: walking (on its feet, in the air or not), limp (a ragdoll, falling or lying), gettingUp or seated (Physics: the ragdoll) |
v.standing | bool | true while v.mode == walking: false while it is limp, lying, getting up or seated |
v.active | bool | true for a being with a body of its own (a figure that walks, jumps and is drawn); false for a plain walker, which is only eyes |
v.health | fraction | 1 whole. A hard landing costs it (Physics: landing); a fall faster than 5 m/s sends the being limp whatever its health, and an emptied health only decides where it gets up (Physics: the ragdoll) |
v.grounded | bool | whether its feet are on something |
v.onPlatform | bool | whether it stands on a platform that carries it (the balloon's basket) |
v.isProp | bool | true for a thing that is moved but does not act (a ball, a pin); a gate's when: may ask it of whatever tries to cross |
A handle is typed by what it stands for: a field that holds a guard is field guard: ?guard, the design's name, and the checker knows it has the guard's fields; it is not a bare being. A bare being is for what any being has, the fields above.
Actions: verbs with typed values and targets
An action is a named verb a being may perform, with a typed value it carries and the kind of thing it is aimed at. It is a message whose sender is a being. In an event it is a trigger:
on(action(name, value, to: target, by: v), ...) on(action(ask, q, to: g, by: v), ...) // carries a question; aimed at a guard; by being v on(action(hail, by: self), ...) // carries nothing; a being's own hail
The handler receives the value, the part or place addressed, and the being that acted. None of these is a key: the content never sees keys, only actions.
Declaring an action
A world may declare its own actions, with these fields:
action(ask,
carries: (q: question), // name and typed value
to: guard, // what it needs as a target
range: 4 m, // range, checked again on the server
offered: offered(ask, by: target), // availability
kind: once, // once, or held (a value every step, as walk)
suggestKey: 1 ..= 4) // the world's own actions only: a digit, a letter in quotes ("B") or a function key (F2)
action(walk, carries: (ahead: number, turn: number, run: bool), kind: held) // illustration
action(nextWeather, kind: once, suggestKey: "T") // carries nothing and needs no target: both left out
action(zap, carries: (eye: place), to: being, range: 25 m, kind: once, suggestKey: F2,
offered: v.standing && v.active && target.standing && target.active) // a spell on a being
| Field | Meaning |
|---|---|
| What it carries | A typed record with units and ranges, as fields have: walk carries (ahead: number, turn: number), each between -1 and 1, ask carries (q: question). carries: may be left out when the action carries nothing: nextWeather, a key that cycles the weather, is just pressed. |
| Target | One of: self (hail, drink-me), a part (a seat, a lever, a docking port), a being (zap, jab), or a place, given as a point or as a ray the engine follows (paint, a fireball). to: ray carries the ray from the visitor's eye along where they look, a start and a direction, for the handler to follow as it needs: the bowl hands it to throw, which aims where it first meets the ground or a solid within 60 m (Physics: throwing a body). It may be narrowed by type: to: part is seat. to: may be left out when the action needs no target. |
| Range | How far the target may be, range:. The server checks it, measured from the eye to the target's chest (t.chest). The browser aims inside it: its lock-on reaches 22 m, to the surface of a 0.35 m sphere round the chest, 3 m inside the zap's range: 25 m. |
| The eye | An action may carry eye:, a place the browser fills from the camera, so that range and a clear line are worked out from where the person is looking from, not from the being's head. The server believes it only within 5 m of the being's head (0.936 of its height up); beyond that it uses the head. |
| Availability | When the action is offered: sit only near a free seat, stand only while seated, ask only after the guard has offered it, bowl only while the visitor stands and has a body (offered: v.standing && v.active, v the being that would act). offered: may read target as well as v: the zap is offered only on a target that is standing and drawn. It drives the browser's hints and its action menu; the server refuses an action that is not available. |
| Once or held | Most actions happen once; walking is a value every step. |
Three tiers
| Tier | Examples | Who defines it | What a world may do |
|---|---|---|---|
| Reserved | leave, portal home, menu, mute, block | the browser | Nothing: never remove, rebind or intercept them, and never receive them. |
| Standard | walk, run, jump, use, sit, hail | the browser's environment | Adopt any, and write its own response. The response to walk, run, turn and jump is built in, needs no line from the world, and is the same on the server and in the visitor's predicting browser (Physics: the walking response). A hail may be a wave in one world and a bow in another, but the name and what it carries do not change, so a person's habits carry from world to world. |
| The world's own | ask, zap, paint; dock and thrust in space; drink-me in a dreamland | the world | Everything: name, value, target, range, availability, suggested keys. |
A space world would declare thrust along three axes and turning about three, with no jump and no run; the keys could be the same as walking's, since walk and thrust are never available together.
Input mapping
The three layers:
| Layer | What it is |
|---|---|
| 1. Physical input | A key, a stick, a gesture, a panel. The browser's, or a future overlay's. Out of the content's scope. |
| 2. A named action | What the being means to do. A world may define these, as it uses vocabulary names. Examples: walk (ahead, turn, run), jump, sit, hail; ask, carrying a question, aimed at a guard. |
| 3. The content's response | An event, a library behavior, a subscription. For example, a gait turns walk and jump into motion and a pose; on(action(hail, ...)) is a wave and a smile; a hall's handler answers ask. |
The proposals for the browser's side of the seam:
- Key bindings belong to the person, among the person's settings outside the content (Outside the content). Reserved actions are fixed by the browser, the same everywhere, so a person can always leave or mute. Standard actions use the person's own bindings, set once, in every world. A world's own actions have suggested keys, which the person may override; when a suggestion collides with the person's binding, the person wins.
- A generic action menu. A browser with no input for an action lists every action currently available by name; on a tablet with no keyboard, that menu is the main way to act.
- Targeting is the browser's. An action needing a being takes the person's locked target if there is one, else the browser locks the best candidate. A candidate is a being other than the person's own that is standing, drawn and not
targetable: false, inside a 45° cone about the camera's direction and within 22 m (to the surface of a 0.35 m sphere at its chest). Each is scored by twice its angle from the middle of the cone (as a share of 45°) plus its distance (as a share of 22 m), and the lowest wins: the being nearest the middle of the cone, then the nearest. The held target's score is multiplied by 0.75, so the lock does not flicker between two near choices. A lock is kept while the target stays within 27.5 m (1.25 times the reach) whichever way the camera turns, and is let go once it has been out of reach for 1.5 s. There is no test for a wall in between; the server's clear line settles that. The browser highlights the locked target, and content has no field for it. Content narrows the choice only bytargetableandoffered:, and cannot make an action land on something other than what the person chose. A mind picks its target directly. - One action, many sources. A key, a tap, a gamepad button, a voice command and a mind are equal sources. A villager hails a villager by the same action a person uses.
Offering an action
offer(ask, to: h) makes a world's own action available to one being, after a hail (proposed; actions.html). How the browser shows it, a panel, four buttons, a spoken menu, is the browser's. The content says what may be asked; the browser decides how to ask it.
Speech is an act
A speaker (an NPC, a door, a radio, a player, a narrator) computes its words as a pure value, then performs the act say(g, words, to: v) at a moment. It puts the words nowhere. How speech appears is the world's: the world has a rule that answers every speech act and manifests it as its designer chose:
on(spoke(speaker, words, to: v), ...) // the world's rule for every speech act
In what it shows, you names the being the visitor drives, whose picture this is, and a bubble is shown with show(element, for: d) (overlays.html). A bubble layout anchored above the speaker, a subtitle, speech from text, a chat-log line, several at once, or nothing out of earshot or through a wall: each is a way the world may show it (overlays.html). Only the act crosses the network; each visitor's machine manifests it, and the visitor's own preferences (captions, translation) may apply on top. A visitor's own speech is the same act: a player is one of the speakers.
on(action(ask, q, to: g, by: v), { // the guards' riddle
if within(v, g, 4 m) {
if asked[v] {
say(g, "You have had your question.", to: v);
} else {
set(asked[v], true);
say(g, answer(g, q), to: v);
}
}
})
to: v names the addressee, not the audience. A guard's line is addressed to the asker, and everyone near sees it: the act goes to every visitor's machine, the plate over the guard's head shows it to all, and the asker's panel takes the line as its answer because the panel acts only for its own visitor (on(spoke(g, line, to: you), ...)). So others learn by watching that a guard refuses a second question. say(g, words, voice: 118 Hz) overrides the speaker's own voice for that one line, so a speaker whose lines differ in pitch (the Worm's) gives each its own. A line of speech carries its words; the engine may compress lines on the wire, which content never sees.
What it means
Authority
The server holds the truth and may refuse at every stage:
- An action arrives tagged only with its connection, and the server turns that into the being that acted, so no browser can act for another.
- An action is refused if it is not available, out of range, or the being cannot act: sitting or limp. A spell does not stop its target from acting. It holds the target's walk, turn, run and jump (
holdIntents, Actions); the target may still cast. - A browser's targeting is advice, checked again: the browser aims at 22 m, 3 m inside the zap's
range: 25 mthat the server checks, measured from the eye to the target's chest, with a clear line (Physics: a clear line). The browser keeps a lock a little longer than it acquires one, to 27.5 m, so a lock held at the edge may be refused. - A person's own browser may show the action at once (the wave starts when the key goes down), but never its meaning: health falls only when the server says so.
Nothing a visitor can forge
Values that decide what a being may do or what a villager thinks of it live on the server, written by logic that runs there, kept there or shown only to their own visitor. A browser that claimed a better standing would have nothing to send it to.
How it connects
- Events: actions as triggers.
- Actions:
say,offer,send. - Package behaviors: minds that produce actions.
- Fields: fields keyed by being.
- Overlays: how a world shows speech; the pointer.
- Text: dialogue, lines and choices.
- Distribution: only acts cross the network.
- The riddle and a shopkeeper's dialogue.
- Avatars: the being as one piece of a visitor's avatar; Outside the content: possession, identity, the person's settings.
Open questions
- What every speaker must have. A world's speech rule reads the speaker's
title,voiceandheight, so every speaker, a door or a radio included, must have them. There is no way to state what fields a speaker offers (an interface or contract), so a world rule over all speech has no checked inputs (The riddle of the two guards). - Who declares actions: the world, with the browser choosing an input by the action's type; the world with a suggested input; or a fixed environment vocabulary worlds may only adopt. And for an action a browser has no input for: listed by name in a menu, or the world refused.
- What a being handle is: its own value type with tests such as "driven by a visitor"; visitors' beings under a root of the tree content may query but not write; or only relations allowed, never a stored handle. How content ranges over beings is closed:
each v in visitorsaround a rule, andany(visitors, v => ...)for a test (Events). - Visitor or being: only bodies a person drives lay Ariadne's thread; the content needs to say "a being a person drives" without saying which person.
- One key for two actions whose availability never overlaps (sit and stand; walk and thrust).
- How far a world may narrow targeting.
- Telling the actor about a refusal.
- May world logic make a person's being perform an action? Recommended no.
- The questions' presentation: may the content say "four buttons", or only "a choice of four"?
- Multiplayer configuration and world-defined input (group size, key and gesture mappings) are deferred, not yet explored.