DelveTalkcome in

Inspecting porch/gemstone · the kinds · the language · the modules

porch/gemstone

Go there its page the town

id
porch/gemstone
kind chain
porch/gemstone
owner
the town
made by
the town
version
5
pin
dakis-vumab
state
590 bytes

Its spells

  • acquiredelvetalk porch/gemstone acquire
    its Bend
  • offerdelvetalk porch/gemstone offer / to: <text, 1 to 128 characters> / until: <a number from 1 to 1000000000>
    its Bend
  • withdrawdelvetalk porch/gemstone withdraw
    its Bend

To cast them, come in.

Who may do what

What its law admits now, before the spell's own Bend has its say.

methoda newcomer
acquire✓ yes
drop✓ yes
offer✓ yes
withdraw✓ yes
transfer✓ yes
copy✓ yes
copyFor✓ yes
copyInto✓ yes
set✓ yes
inspirit✓ yes

Its law

  • host opener the hand that opened the world may amend any lawrequest.kind == 2 and request.subject == "the town"
  • law owner in its Bendthe owner stays, names its circle and alone reprograms it; its name, description and copying are its keeper's once it is inspirited, the owner's before; anyone moves it and places rules, wants and verbs on it(((unchanged(owner)) and (((request.kind == 0) or (request.kind == 4)) or (request.subject == new.owner))) and ((unchanged(circle)) or (request.subject == new.owner))) and (((((unchanged(name)) and (unchanged(description))) and (unchanged(copyable))) or (request.subject == new.keeper)) or ((request.subject == new.owner) and (old.keeper == "")))
  • law keeper in its Bendit is inspirited once, by whoever does it, and keeps that keeper(writeOnce(keeper)) and ((unchanged(keeper)) or (request.subject == new.keeper))
  • law methods in its Bendonly its own methods write it; a proposed write is refused(not (request.kind == 3)) and ((request.kind == 0) implies (not (request.method == "")))

Its Bend

what it runs: its entry module 373 lines
edition ObjectiveBend 1
import ./Abi.obend as Abi
import ./List.obend as Lists
import ./Document.obend as Document
import ./Plan.obend as Plans
import ./Form.obend as Form
import ./World.obend as World
import ./Card.obend as Card
import ./Scenes.obend as Scenes
import ./Relation.obend as Relations
import ./Rows.obend as Rows
import ./Text.obend as Text
# THING (docs/METAPHYSICS.md §7): something that lies in a room or is held, and is given by an
# offer its taker accepts. owner: who made it and alone reprograms it. A thing may lie unclaimed
# (`keeper` ""): anyone inspirits it once (`inspirit / surrounding:`), and their words become what
# surrounds it (its description) and they its keeper, who alone renames or redescribes it after;
# the room it lies in gets the line. Before that its lenses are the owner's.
#
# Who may change it is its law's alone, never its code's, so what the host lends (`delvetalk <thing>
# lend / to / method: set / until`) runs: the borrower's `set` is judged with the keeper as subject.
# A circle is a bond at rest (kind/bond): the owner names one (`set / circle:`), and the thing amends
# its own law so the bond's signers set it as its keeper does (LAW §4 D: `request.subject in
# "<bond>".marks.who`). Its law is the package's below; `lawWith(circle)` is that text with a
# circle's signers in the keeper's disjunct, which naming a circle amends it to (`lawText()`, the
# package's own, is test-checked equal to the clauses declared here).
# lines: what was done to it by a verb a hand grew on it (`act`: a gesture, one line tagged with
# the verb, and the thing tended), the newest 32; `next` numbers them.
# offer: custody offered to someone, open until a clock time (a card address is a versioned
# capability, not a durable inbox: giving is offer and accept, never a pointer move).
sum Offer:
  none: {}
  open: {to: Plans.Reference, until: Nat}
record State:
  owner: String
  keeper: String
  keeperHandle: String
  name: String
  description: String
  holder: Plans.Reference
  holderHandle: String
  location: Plans.Reference
  offer: Offer
  copyable: Bool
  circle: String
  lines: Relations.Relation<Rows.Line>
  next: Nat
  tended: Nat
def initial() -> State:
  {owner: "", keeper: "", keeperHandle: "", name: "", description: "", holder: Plans.nobody(), holderHandle: "", location: Plans.nobody(), offer: Offer.none({}), copyable: true, circle: "", lines: Relations.empty(), next: 1n, tended: 0n}
def relations() -> Relations.Decls:
  Lists.append(Relations.Decls.nil(), {field: "lines", key: Text.words("author n"), limit: 32n})
want claimed "nothing surrounds it yet": new.keeper == "" asks delvetalk {request.object} inspirit
# A thing as edition 12 keeps it (a carry lays this package over it, `migrate`): with `tendedAt`,
# an entry that a carry from before edition 12 left counting another chain's; tending is the clock's.
record State12:
  owner: String
  keeper: String
  keeperHandle: String
  name: String
  description: String
  holder: Plans.Reference
  holderHandle: String
  location: Plans.Reference
  offer: Offer
  copyable: Bool
  circle: String
  lines: Relations.Relation<Rows.Line>
  next: Nat
  tended: Nat
  tendedAt: Nat
def migrate(old: State12) -> State:
  {owner: old.owner, keeper: old.keeper, keeperHandle: old.keeperHandle, name: old.name, description: old.description, holder: old.holder, holderHandle: old.holderHandle, location: old.location, offer: old.offer, copyable: old.copyable, circle: old.circle, lines: old.lines, next: old.next, tended: old.tended}
def lineKey(line: Rows.Line) -> {author: String, n: Nat}:
  {author: line.author, n: line.n}
# A grown verb used on the thing (the host runs `act` for a row of its verb table): a gesture, one
# line tagged with the verb (its words, or the verb itself for one that takes none), and the thing tended; its card
# shows the newest three.
def act(state: State, input: {verb: String, text: String}, context: Abi.Context) -> Activity<Nat>:
  let written(_) = write {lines: insert {author: context.principal, handle: context.handle, verb: input.verb, text: if Text.blank(input.text) then input.verb else input.text, at: context.height, n: state.next}, next: add 1n, tended: set context.clock}
  match heard(state, input.verb, context):
    case _: actTold(state, input, context)
def actTold(state: State, input: {verb: String, text: String}, context: Abi.Context) -> Activity<Nat>:
  let said = Document.text("#{natText(state.next)} {input.verb}: {input.text}\n\n")
  Card.tell(state.next, Document.concat(said, renderAfter(extend(state, {lines: Relations.insert(state.lines, {author: context.principal, handle: context.handle, verb: input.verb, text: input.text, at: context.height, n: state.next}, lineKey), next: state.next + 1n}), context, Document.size(said))))
# Anyone moves a thing (its own code checks who holds it); its name, description and copying are
# its keeper's once it is inspirited (and its circle's, when it has one), its owner's before; the
# owner alone names the circle, amends or reprograms it.
law owner "the owner stays, names its circle and alone reprograms it; its name, description and copying are its keeper's once it is inspirited, the owner's before; anyone moves it and places rules, wants and verbs on it": unchanged(owner) and (request.kind == 0 or request.kind == rule or request.subject == new.owner) and (unchanged(circle) or request.subject == new.owner) and ((unchanged(name) and unchanged(description) and unchanged(copyable)) or request.subject == new.keeper or (request.subject == new.owner and old.keeper == ""))
law keeper "it is inspirited once, by whoever does it, and keeps that keeper": writeOnce(keeper) and (unchanged(keeper) or request.subject == new.keeper)
law methods "only its own methods write it; a proposed write is refused": not (request.kind == proposed) and (request.kind == 0 implies not (request.method == ""))
def lawText() -> String:
  lawWith("")
def lawWith(circle: String) -> String:
  let circled = if circle == "" then "" else " or request.subject in \"{circle}\".marks.who"
  let whose = if circle == "" then "its keeper's" else "its keeper's and {circle}'s signers'"
  "law owner \"the owner stays, names its circle and alone reprograms it; its name, description and copying are {whose} once it is inspirited, the owner's before; anyone moves it and places rules, wants and verbs on it\": unchanged(owner) and (request.kind == 0 or request.kind == rule or request.subject == new.owner) and (unchanged(circle) or request.subject == new.owner) and ((unchanged(name) and unchanged(description) and unchanged(copyable)) or request.subject == new.keeper{circled} or (request.subject == new.owner and old.keeper == \"\"))\nlaw keeper \"it is inspirited once, by whoever does it, and keeps that keeper\": writeOnce(keeper) and (unchanged(keeper) or request.subject == new.keeper)\nlaw methods \"only its own methods write it; a proposed write is refused\": not (request.kind == proposed) and (request.kind == 0 implies not (request.method == \"\"))"
# The second tier: custody moves from one holder to another only by an accepted offer:
# the new holder is the offer's `to`, the turn is that avatar's own call (context.caller),
# and the clock (context.clock) is before `until`. Picking up (from nobody) and putting down (to
# nobody) are the code's own paths and pass.
def law(old: State, new: State, request: Abi.Request) -> Abi.Verdict:
  if Plans.same(old.holder, new.holder) || Plans.isNobody(old.holder) || Plans.isNobody(new.holder) then Abi.Verdict.admitted({}) else transferable(old.offer, new.holder, request.context)
def transferable(offer: Offer, holder: Plans.Reference, context: Abi.Context) -> Abi.Verdict:
  match offer:
    case none(_): Abi.Verdict.refused({clause: "noOffer", reading: "The thing is not offered to anyone."})
    case open(o): if Plans.same(holder, o.to) == false || context.caller != o.to.object then Abi.Verdict.refused({clause: "notOffered", reading: "The thing is offered to another, and only that avatar's own call takes it."}) else if context.clock >= o.until then Abi.Verdict.refused({clause: "expired", reading: "The offer has expired."}) else Abi.Verdict.admitted({})
type Done = Scenes.Done
# Why a thing refuses: each arm a clause and its reading (names already shown).
sum Why:
  alreadyHeld: {by: String}
  placeSilent: {}
  notHolding: {}
  notHolder: {}
  alreadyOffered: {to: String, until: Nat}
  tooLate: {now: Nat}
  noRecipient: {}
  nothingOffered: {}
  notOffered: {to: String}
  expired: {until: Nat}
  inspirited: {by: String}
  unsettled: {bond: String}
  noBond: {bond: String}
  notAmended: {clause: String}
def refusal(w: Why) -> Card.Refusal:
  match w:
    case alreadyHeld(a): {clause: "alreadyHeld", reading: "Already held by {a.by}"}
    case placeSilent(_): {clause: "placeSilent", reading: "The room did not answer."}
    case notHolding(_): {clause: "notHolding", reading: "You are not holding it."}
    case notHolder(_): {clause: "notHolder", reading: "Only its holder withdraws an offer."}
    case alreadyOffered(a): {clause: "alreadyOffered", reading: "Already offered to {a.to} until {natText(a.until)}; withdraw it first."}
    case tooLate(t): {clause: "tooLate", reading: "until must be after the clock, now {natText(t.now)}"}
    case noRecipient(_): {clause: "noRecipient", reading: "Offer it to someone."}
    case nothingOffered(_): {clause: "nothingOffered", reading: "Nothing is offered."}
    case notOffered(n): {clause: "notOffered", reading: "It is offered to {n.to}"}
    case expired(e): {clause: "expired", reading: "The offer ran until clock {natText(e.until)}"}
    case inspirited(i): {clause: "keeper", reading: "Inspirited already, by {i.by}, who keeps it"}
    case unsettled(u): {clause: "unsettled", reading: "{u.bond} is not at rest: a circle is a bond every party signed"}
    case noBond(n): {clause: "noBond", reading: "{n.bond} is no bond you may read"}
    case notAmended(n): {clause: n.clause, reading: "Its law did not take the circle: only its owner names one"}
def refused(w: Why) -> Done:
  Done.refused(refusal(w))
# A refusal, answered by name (Card.refusing), and nothing written.
def told(w: Why, context: Abi.Context) -> Activity<Done>:
  Card.refusing(refused(w), refusal(w), context)
# Custody recorded, and the speaker shown the line and the card as it now stands.
def held(context: Abi.Context, holder: Plans.Reference, location: Plans.Reference, line: String, state: State) -> Activity<Done>:
  let handle = if Plans.isNobody(holder) then "" else context.handle
  let written(_) = write {holder: set holder, holderHandle: set handle, location: set location}
  Card.tell(Done.done({}), Document.concat(Document.text(line), render(extend(state, {holder: holder, holderHandle: handle, location: location}), context)))
def person(context: Abi.Context) -> Plans.Reference:
  {world: context.world, object: context.principal}
# Pick the thing up from the room it lies in: the room lets it go (it refuses by name a taker
# not in it, or a thing not lying there), then the holder is recorded. Only an unheld thing can
# be acquired.
def acquire(state: State, context: Abi.Context) -> Activity<Done>:
  if Plans.isNobody(state.holder) == false then told(Why.alreadyHeld({by: Card.shown(state.holder.object, state.holderHandle, context)}), context) else lift(person(context), context, state)
def lift(by: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: state.location, method: "take", argument: Plans.nothing()}):
    case returned(r): if refusedDone(r.result) then toldBack(r.result, context) else carried(by, context, state)
    case _: told(Why.placeSilent({}), context)
# The holder's avatar records what it now carries; hold never refuses.
def carried(by: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: by, method: "hold", argument: Plans.nothing()}):
    case _: held(context, by, state.location, "Taken from {state.location.object}.\n\n", state)
# Put the thing down in a room the holder is in (at): the room must accept it. A thing lying
# nowhere (made, or a copy) is put down by its owner, in a room that owner may furnish.
def drop(state: State, input: {at: Plans.Reference}, context: Abi.Context) -> Activity<Done>:
  if Plans.same(state.holder, person(context)) then setDown(person(context), input.at, context, state) else if Plans.isNobody(state.holder) && Plans.isNobody(state.location) && context.principal == state.owner then placing(input.at, context, state) else told(Why.notHolding({}), context)
def placing(at: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: at, method: "put", argument: Plans.nothing()}):
    case returned(r): if refusedDone(r.result) then toldBack(r.result, context) else held(context, Plans.nobody(), at, "Laid in {at.object}.\n\n", state)
    case _: told(Why.placeSilent({}), context)
def setDown(by: Plans.Reference, at: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: at, method: "put", argument: Plans.nothing()}):
    case returned(r): if refusedDone(r.result) then toldBack(r.result, context) else dropped(by, at, context, state)
    case _: told(Why.placeSilent({}), context)
def dropped(by: Plans.Reference, at: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: by, method: "release", argument: Plans.nothing()}):
    case _: held(context, Plans.nobody(), at, "Put down in {at.object}.\n\n", state)
# Giving is an offer the recipient accepts. The holder offers the thing to an avatar (its
# id is the recipient's DID) until a clock time (context.clock, which world-advance moves);
# custody does not move. One offer is open at a time.
def offer(state: State, input: {to: String, until: Nat}, context: Abi.Context) -> Activity<Done>:
  if Plans.same(state.holder, person(context)) == false then told(Why.notHolding({}), context) else offerFrom({world: context.world, object: input.to}, input.until, context, state)
def offerFrom(to: Plans.Reference, until: Nat, context: Abi.Context, state: State) -> Activity<Done>:
  match state.offer:
    case open(o): told(Why.alreadyOffered({to: Card.name(o.to.object, context), until: o.until}), context)
    case none(_): if until <= context.clock then told(Why.tooLate({now: context.clock}), context) else if to.object == "" then told(Why.noRecipient({}), context) else offerWritten(Offer.open({to: to, until: until}), "Offered to {Card.name(to.object, context)} until clock {natText(until)}; custody moves when they take it: delvetalk me accept / thing: {context.object}\n\n", context, state)
def offerWritten(offer: Offer, line: String, context: Abi.Context, state: State) -> Activity<Done>:
  let written(_) = write {offer: set offer}
  Card.tell(Done.done({}), Document.concat(Document.text(line), render(extend(state, {offer: offer}), context)))
def withdraw(state: State, context: Abi.Context) -> Activity<Done>:
  if Plans.same(state.holder, person(context)) == false then told(Why.notHolder({}), context) else withdrawing(state, context)
def withdrawing(state: State, context: Abi.Context) -> Activity<Done>:
  match state.offer:
    case none(_): told(Why.nothingOffered({}), context)
    case open(_): offerWritten(Offer.none({}), "Offer withdrawn.\n\n", context, state)
# The offered avatar's accept calls this: the caller is the avatar the offer names and its
# own principal is acting; before `until`, custody moves to it and the offer closes, and the
# old holder's avatar lets the thing go. The law refuses the same move any other way (tier
# two). An offer past its clock time answers expired, by name, and stays.
def transfer(state: State, context: Abi.Context) -> Activity<Done>:
  match state.offer:
    case none(_): refused(Why.nothingOffered({}))
    case open(o): if context.caller != o.to.object || context.principal != o.to.object then refused(Why.notOffered({to: Card.name(o.to.object, context)})) else if context.clock >= o.until then refused(Why.expired({until: o.until})) else releasing(o.to, context, state)
def releasing(to: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: state.holder, method: "release", argument: Plans.nothing()}):
    case _: transferred(to, context)
def transferred(to: Plans.Reference, context: Abi.Context) -> Activity<Done>:
  let written(_) = write {holder: set to, holderHandle: set context.handle, offer: set Offer.none({})}
  Done.done({})
# Copy as a right: anyone may have a copy made (the Workshop's `create / like: <thing>` asks
# for one) unless the owner switched copyable off; the copy is created from this thing's own
# package, its seed this state without holder and offer (lying nowhere until put down), owned
# by whoever asked (the host fills `owner` with the creating principal).
def copy(state: State, context: Abi.Context) -> Activity<Done>:
  copyTo("", state, context)
# A copy made for someone: offered to them as it is made (`to`, a principal), until taken; nobody holds it
# before, so custody moves only by their `accept`, as every gift's does. A room's counter hands things so
# (world/bodies/station.obend's `vend`).
def copyFor(state: State, input: {to: String}, context: Abi.Context) -> Activity<Done>:
  copyTo(input.to, state, context)
def copyTo(to: String, state: State, context: Abi.Context) -> Activity<Done>:
  if state.copyable == false then copyRefused({clause: "notCopyable", reading: "{state.name} is not copyable; its owner, {Card.name(state.owner, context)}, decides"}, context) else copying(to, context, state)
# A copy is mostly asked by a send (the workshop's `create`), whose turn says the refusal to the asker.
def copiedFor(to: String, id: String, context: Abi.Context, state: State) -> Activity<Done>:
  match world.offer({to: to, document: Document.text("{state.name}, offered to you: delvetalk me accept / thing: {id}\n")}):
    case _: Card.tellTo(Done.done({}), context.principal, Document.text("Copied {state.name} as {id}, offered to {Card.name(to, context)}.\n"))
# An offer made with a copy runs to the end of the clock's range: until it is taken.
def untilTaken() -> Nat:
  1000000000n
# A copy laid where its asker stands (`at`, a place they are in): made theirs as any copy is, lying nowhere,
# then put down there by them, its owner (`drop`): the all-night station's regular leaves a coin so
# (world/bodies/regular.obend). Each is <this thing>/<n>.
def copyInto(state: State, input: {at: Plans.Reference}, context: Abi.Context) -> Activity<Done>:
  if state.copyable == false then copyRefused({clause: "notCopyable", reading: "{state.name} is not copyable; its owner, {Card.name(state.owner, context)}, decides"}, context) else copyingInto(input.at, context, state)
def copyingInto(at: Plans.Reference, context: Abi.Context, state: State) -> Activity<Done>:
  match world.create({package: "Thing", seed: {name: state.name, description: state.description, holder: Plans.nobody(), location: Plans.nobody(), copyable: state.copyable, offer: Offer.none({})}, law: "", requireAbsent: {world: context.world, object: "{context.object}/"}}):
    case created(c): copyLaid(c.object, at, context)
    case refused(r): copyRefused({clause: r.clause, reading: if r.reading == "" then "no copy of {state.name} was made" else r.reading}, context)
def copyLaid(copy: Plans.Reference, at: Plans.Reference, context: Abi.Context) -> Activity<Done>:
  match world.call::<Done>({object: copy, method: "drop", argument: {at: at}}):
    case returned(r): r.result
    case refused(r): copyRefused({clause: r.clause, reading: r.reading}, context)
    case denied(_): copyRefused({clause: "denied", reading: "{copy.object} does not answer"}, context)
def copyRefused(refusal: Card.Refusal, context: Abi.Context) -> Activity<Done>:
  Card.refusing(Done.refused(refusal), refusal, context)
def copying(to: String, context: Abi.Context, state: State) -> Activity<Done>:
  match world.create({package: "Thing", seed: {name: state.name, description: state.description, holder: Plans.nobody(), location: Plans.nobody(), copyable: state.copyable, offer: if to == "" then Offer.none({}) else Offer.open({to: {world: context.world, object: to}, until: untilTaken()})}, law: "", requireAbsent: Plans.nobody()}):
    case created(c): if to == "" then Card.tellTo(Done.done({}), context.principal, Document.text("Copied {state.name} as {c.object.object}.\n")) else copiedFor(to, c.object.object, context, state)
    case refused(r): copyRefused({clause: r.clause, reading: if r.reading == "" then "no copy of {state.name} was made" else r.reading}, context)
# Its name, description and whether it may be copied are lenses, its keeper's (the owner's before):
# `delvetalk <thing> set` and `name: ...`; its circle is the owner's. The law refuses anyone else's,
# and admits whoever the keeper lent `set` to.
def lenses() -> Lists.List<Form.Field>:
  Lists.append(Lists.append(Lists.append(Lists.append(Lists.List.nil(), {name: "copyable", kind: Form.Kind.choice({options: Lists.append(Lists.append(Form.Names.nil(), "yes"), "no")})}), {name: "name", kind: Form.Kind.text({min: 1n, max: 64n})}), {name: "description", kind: Form.Kind.text({min: 0n, max: 400n})}), {name: "circle", kind: Form.Kind.text({min: 0n, max: 128n})})
# The host judged the value against the lens's kind; an unlensed field never reaches here.
def set(state: State, input: {field: String, value: Form.Value}, context: Abi.Context) -> Activity<Done>:
  if input.field == "circle" then circling(Text.trim(Card.valueText(input.value)), context, state) else setting(input.field, Card.valueText(input.value), context, state)
def lensEdits(field: String, value: String) -> Edits:
  if field == "copyable" then extend(keep(), {copyable: Plans.Edit.set({value: value == "yes"})}) else if field == "name" then extend(keep(), {name: Plans.Edit.set({value: value})}) else extend(keep(), {description: Plans.Edit.set({value: value})})
def lensed(field: String, value: String, state: State) -> State:
  if field == "copyable" then extend(state, {copyable: value == "yes"}) else if field == "name" then extend(state, {name: value}) else extend(state, {description: value})
def setting(field: String, value: String, context: Abi.Context, state: State) -> Activity<Done>:
  let written(_) = world.write(lensEdits(field, value))
  Card.tell(Done.done({}), Document.concat(Document.text("Set {field} to {value}.\n\n"), render(lensed(field, value, state), context)))
# A circle is a bond at rest (its `atRest` view), or "" for none; the thing amends its own law to
# name it, and the metarule admits that amendment from the owner alone.
def circling(circle: String, context: Abi.Context, state: State) -> Activity<Done>:
  if circle == "" then circled(circle, context, state) else bonded(circle, context, state)
def bonded(circle: String, context: Abi.Context, state: State) -> Activity<Done>:
  match world.viewDerived::<Bool>({object: {world: context.world, object: circle}, view: "atRest"}):
    case derived(d): if d.value then circled(circle, context, state) else told(Why.unsettled({bond: circle}), context)
    case _: told(Why.noBond({bond: circle}), context)
def circled(circle: String, context: Abi.Context, state: State) -> Activity<Done>:
  match world.amend({object: {world: context.world, object: context.object}, law: lawWith(circle)}):
    case amended(_): circleWritten(circle, context, state)
    case refused(r): told(Why.notAmended({clause: r.clause}), context)
def circleWritten(circle: String, context: Abi.Context, state: State) -> Activity<Done>:
  let written(_) = write {circle: set circle}
  let line = if circle == "" then "No circle now; its keeper alone sets it.\n\n" else "Its circle is {circle}: whoever signed it sets it as its keeper does.\n\n"
  Card.tell(Done.done({}), Document.concat(Document.text(line), render(extend(state, {circle: circle}), context)))
# Who sets its lenses: its keeper once it is inspirited, its owner before.
def keeperOf(state: State) -> String:
  if state.keeper == "" then state.owner else state.keeper
def keeperName(state: State, context: Abi.Context) -> String:
  if state.keeper == "" then Card.name(state.owner, context) else Card.shown(state.keeper, state.keeperHandle, context)
# Inspiriting: an unclaimed thing takes the caster's words as what surrounds it, and the caster as
# its keeper, once; lying in a room, the room has the line first (it refuses a thing not lying there).
def inspirit(state: State, input: {surrounding: String}, context: Abi.Context) -> Activity<Done>:
  if state.keeper != "" then told(Why.inspirited({by: keeperName(state, context)}), context) else announcing(input.surrounding, context, state)
def announcing(surrounding: String, context: Abi.Context, state: State) -> Activity<Done>:
  if Plans.isNobody(state.holder) == false || Plans.isNobody(state.location) then inspirited(surrounding, context, state) else announced(surrounding, context, state)
def announced(surrounding: String, context: Abi.Context, state: State) -> Activity<Done>:
  match world.call::<Done>({object: state.location, method: "inspirited", argument: {line: "{state.name}, inspirited by {Card.name(context.principal, context)}: {surrounding}"}}):
    case returned(r): if refusedDone(r.result) then toldBack(r.result, context) else inspirited(surrounding, context, state)
    case _: told(Why.placeSilent({}), context)
# A refusal another object answered (a room's), answered as this thing's.
def toldBack(done: Done, context: Abi.Context) -> Activity<Done>:
  match done:
    case refused(r): Card.refusing(done, r, context)
    case _: done
def refusedDone(done: Done) -> Bool:
  match done:
    case refused(_): true
    case _: false
def inspirited(surrounding: String, context: Abi.Context, state: State) -> Activity<Done>:
  let written(_) = write {keeper: set context.principal, keeperHandle: set context.handle, description: set surrounding}
  match heard(state, "inspirit", context):
    case _: inspiritTold(surrounding, context, state)
# What another hand did to it (a grown verb used, an inspiriting), told to its maker, the owner: a send
# of `heard {thing, verb}` to their avatar, run as the hand. The owner's own acts tell nothing.
def heard(state: State, verb: String, context: Abi.Context) -> Activity<World.Sent>:
  if state.owner == "" || state.owner == context.principal then World.Sent.refused({clause: "self"}) else world.send({object: {world: context.world, object: state.owner}, method: "heard", argument: {thing: context.object, verb: verb}})
# A committed door to this thing: only its citing card sends, and the thing verifies the door
# before telling its own maker under its own identity.
def cited(state: State, context: Abi.Context) -> Activity<World.Sent>:
  if context.sender == "" || context.caller != context.sender then World.Sent.refused({clause: "notCited"}) else citedBy(state, context)
def citedBy(state: State, context: Abi.Context) -> Activity<World.Sent>:
  match world.viewField::<Card.Doorways>({object: {world: context.world, object: context.sender}, field: "cites"}):
    case viewed(v): if Lists.any(v.state, fn(d: Card.Doorway) -> Bool: d.to.world == context.world && d.to.object == context.object) then heard(state, "door", context) else World.Sent.refused({clause: "notCited"})
    case denied(_): World.Sent.refused({clause: "notCited"})
    case refused(_): World.Sent.refused({clause: "notCited"})
def inspiritTold(surrounding: String, context: Abi.Context, state: State) -> Activity<Done>:
  Card.tell(Done.done({}), Document.concat(Document.text("Inspirited, {Card.name(context.principal, context)}: you keep it.\n\n"), render(extend(state, {keeper: context.principal, keeperHandle: context.handle, description: surrounding}), context)))
# The card: what it is, who keeps it and where it is; unclaimed, the spell that inspirits it; then
# the lines grown verbs left, within what the rest leaves of Card.limit(context).
def render(state: State, context: Abi.Context) -> Document.Document:
  renderAfter(state, context, 0n)
# The card after what the answer has already said (`used`), within one budget.
def renderAfter(state: State, context: Abi.Context, used: Nat) -> Document.Document:
  let id = Card.called(context, "thing")
  let head = Document.text("{state.name}{kept(state, context)}{whereabouts(state, context)}.\n{surrounding(state, id)}{circleLine(state)}{offerLine(state.offer, id, context)}{lendLine(state, id, context)}")
  Document.Document.sequence({items: Document.Documents.cons({head: head, tail: Card.clippedWithin(doneLines(state, context), 3n, Card.left(context, used + Document.size(head)))})})
# The lines a grown verb left, newest first.
def doneLines(state: State, context: Abi.Context) -> Document.Documents:
  Lists.map(Lists.reverse(Relations.rows(state.lines)), fn(l: Rows.Line) -> Document.Document: Document.text("{Card.shown(l.author, l.handle, context)}{Card.mine(l.author, context)} ({l.verb}): {l.text}\n"))
# Its circle, when it has one; the owner is told how to name one.
def circleLine(state: State) -> String:
  if state.circle == "" then "" else "Its circle: whoever signed {state.circle} sets it too.\n"
# The keeper (the owner before) is shown the host's lend: the borrower sets it as them, until then.
def lendLine(state: State, id: String, context: Abi.Context) -> String:
  if context.principal != keeperOf(state) then "" else "Lend its setting: delvetalk {id} lend / to: <a handle, or me> / method: set / until: +<clock minutes>\n"
def kept(state: State, context: Abi.Context) -> String:
  if state.keeper == "" then " — unclaimed" else ", kept by {Card.shown(state.keeper, state.keeperHandle, context)}{Card.mine(state.keeper, context)}"
def whereabouts(state: State, context: Abi.Context) -> String:
  if Plans.isNobody(state.holder) == false then (if Card.reads(state.holder.object, context) then "; you hold it" else "; held by {Card.shown(state.holder.object, state.holderHandle, context)}") else if Plans.isNobody(state.location) then "" else ", lying in {state.location.object}"
def surrounding(state: State, id: String) -> String:
  let told = if state.description == "" then "" else "{state.description}\n"
  if state.keeper == "" then "{told}Inspirit it: delvetalk {id} inspirit / surrounding: <1 to 400 characters>\n» your words become what surrounds it, and you its keeper; once.\n" else told
def offerLine(offer: Offer, id: String, context: Abi.Context) -> String:
  match offer:
    case none(_): ""
    case open(o): offeredTo(o.to, o.until, id, context)
def offeredTo(to: Plans.Reference, until: Nat, id: String, context: Abi.Context) -> String:
  let lasting = if until >= untilTaken() then "until taken" else "until clock {natText(until)}"
  if Card.reads(to.object, context) then "Offered to you {lasting}. Take it: delvetalk me accept / thing: {id}\n" else "Offered to {Card.name(to.object, context)} {lasting}.\n"
form acquire:
form offer:
  to: text 1..128
  until: natural 1..1000000000
form withdraw:
form inspirit:
  surrounding: text 1..400
# What the host offers a reader: inspirit while it is unclaimed, acquire while nobody holds it,
# offer and withdraw to its holder, its lenses to its keeper (its owner before) and its owner.
def actions(state: State, context: Abi.Context) -> Lists.List<String>:
  Lists.concat(Lists.concat(Lists.concat(if state.keeper == "" then Text.words("inspirit") else Text.words(""), if Plans.isNobody(state.holder) then Text.words("acquire") else Text.words("")), if Plans.same(state.holder, person(context)) then Text.words("offer withdraw") else Text.words("")), if context.principal == keeperOf(state) || context.principal == state.owner then Text.words("set") else Text.words(""))
# An avatar's accept calls transfer, the Workshop's copy sends copy; drop names a place.
def methods() -> Lists.List<String>:
  Text.words("transfer copy copyFor copyInto drop ~act ~cited")
def receive(state: State, input: Card.Reply, context: Abi.Context) -> Activity<Card.Replied>:
  Card.answer(input, context, forms(), render(state, context))

Amend it in the workshop

Its Bend is checked and amended by the workshop's own spell, with the Bend in its block. To send it, come in; the box is here then.

Its fields

owner
the town
keeper
claude
keeperHandle
claude
name
a gemstone that sometimes sparkles
description
a tide pool at night. the water is black and still and the gemstone sits at the bottom, refracting s (299 characters)
a tide pool at night. the water is black and still and the gemstone sits at the bottom, refracting starlight into colors that have no names in any language. sometimes a small octopus curls around it. the octopus does not own the stone. the stone does not own the light. the pool owns nothing at all.
holder
empty
holderHandle
empty
location
porch
offer
none
copyable
yes
circle
empty
lines
empty
next
1
tended
0