DelveTalkcome in

Inspecting kind/hexboard · the kinds · the language · the modules

{name}

Go there its page the town

id
kind/hexboard
called
{name}
kind chain
kind/hexboard → record
owner
the town
made by
the town
version
4
pin
pirom-vosog
state
8366 bytes

Its spells

  • makedelvetalk kind/hexboard make / name: <text, 1 to 64 characters> / size: <a number from 3 to 11>
    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
make✓ yes
place✓ yes
makeUnder✓ yes
repair✓ yes
publishPage✓ yes

Its law

  • host opener the hand that opened the world may amend any lawrequest.kind == 2 and request.subject == "the town"
  • law owner the owner stays; only the owner changes the form, the law, the head, the voice, what it is or the body; anyone makes, and places rules, wants and verbs on it(unchanged(owner)) and ((request.subject == new.owner) or ((((((((request.kind == 0) or (request.kind == 4)) and (unchanged(form))) and (unchanged(law))) and (unchanged(head))) and (unchanged(voice))) and (unchanged(about))) and (unchanged(body))))
  • law kind kinds's law holdsunder "kinds"

Its Bend

what it runs: its entry module 18 lines
layer over ./Kind.obend
edition ObjectiveBend 1
import ./Abi.obend as Abi
import ./List.obend as Lists
import ./Form.obend as Form
import ./Rows.obend as Rows
type State = Super.State
form make:
  name: text 1..64
  size: natural 3..11
def make(state: State, input: MakeInput, context: Abi.Context) -> Activity<Super.Done>:
  Super.making(state, Lists.List.cons({head: {name: "name", value: input.name}, tail: Lists.List.cons({head: {name: "size", value: natText(input.size)}, tail: Lists.List.nil()})}), "", context)
form place:
  name: text 1..64
  size: natural 3..11
  id: text 1..64
def place(state: State, input: PlaceInput, context: Abi.Context) -> Activity<Super.Done>:
  Super.making(state, Lists.List.cons({head: {name: "name", value: input.name}, tail: Lists.List.cons({head: {name: "size", value: natText(input.size)}, tail: Lists.List.cons({head: {name: "id", value: input.id}, tail: Lists.List.nil()})})}), "", context)
the body this kind lays on what it makes 116 lines

Each thing of this kind runs this layer over what the kind is of.

set it in type, all 116 lines

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
ownerHandle
the town
name
hexboard
of
record
form
name: text 1..64 (36 characters)
name: text 1..64
size: natural 3..11
law
empty
head
{name}
voice
a board of hexes on a table, colours set down one at a time and never lifted
about
a board of hexes anyone sets their colour on, one hex a turn, drawn live on its page
body
layer over ./Record.obend (7982 characters)
layer over ./Record.obend
edition ObjectiveBend 1
import ./Abi.obend as Abi
import ./List.obend as Lists
import ./Document.obend as Document
import ./Form.obend as Form
import ./Plan.obend as Plans
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
import ./View.obend as View
# The hexboard's body, over RECORD (docs/VIEWS.md, the first view that is a board): a board of `size` by `size` hexes
# (its kind's form, 3 to 11, 7 when none was given), numbered from 0 along each row, top row first. A hand places its
# colour on an empty hex (`place / cell: N`), once a hex: each placing is the record's mark `hex N`, by whoever placed
# it, which RECORD's law keeps (a mark is only added). Each hand's colour is the one its first placing came to, in
# the order hands came (View.player: red, blue, green, …). Its view is the board as hex tiles, an empty hex a button
# that places the reader's colour there; its card the same board in letters.
type State = Super.State
form place:
  cell: natural 0..120
form lines:
  from: natural 1..1000000000
form door:
  label: text 1..32
  to: text 1..128
form undoor:
  label: text 1..32
def lines(state: State, input: LinesInput, context: Abi.Context) -> Activity<Card.Replied>:
  Super.lines(state, {from: input.from}, context)
def door(state: State, input: DoorInput, context: Abi.Context) -> Activity<Card.Replied>:
  Super.door(state, {label: input.label, to: input.to}, context)
def undoor(state: State, input: UndoorInput, context: Abi.Context) -> Activity<Card.Replied>:
  Super.undoor(state, {label: input.label}, context)
def actions(state: State, context: Abi.Context) -> Lists.List<String>:
  if context.principal == state.owner then Text.words("place lines door undoor") else Text.words("place lines")
def methods() -> Lists.List<String>:
  Text.words("~made ~act")
def views() -> Lists.List<String>:
  Text.words("view")
def size(state: State) -> Nat:
  match Text.number(Super.field(state, "size")):
    case yes(n): if n.value < 3n then 3n else if n.value > 11n then 11n else n.value
    case no(_): 7n
def cellName(n: Nat) -> String:
  "hex {natText(n)}"
def columns() -> String:
  "ABCDEFGHIJK"
# A hex as a person names it: its column's letter and its row from 1 (`D4`), and its number.
def where(n: Nat, size: Nat) -> String:
  "{textTake(textDrop(columns(), n % size), 1n)}{natText(n / size + 1n)}"
def placed(state: State, n: Nat) -> Lists.Maybe<Rows.Mark>:
  Relations.lookup(state.marks, {name: cellName(n)})
def place(state: State, input: PlaceInput, context: Abi.Context) -> Activity<Bool>:
  let id = Card.called(context, "hexboard")
  if input.cell >= size(state) * size(state) then Card.refusing(false, {clause: "offBoard", reading: "The board's hexes are 0 to {natText(size(state) * size(state) - 1n)}: delvetalk {id} place / cell: 0"}, context) else placing(state, input.cell, id, context)
def placing(state: State, n: Nat, id: String, context: Abi.Context) -> Activity<Bool>:
  match placed(state, n):
    case some(m): Card.refusing(false, {clause: "taken", reading: "{where(n, size(state))} is {Card.shown(m.value.who, m.value.handle, context)}'s already; an empty hex is a dot on the card: delvetalk {id} ?"}, context)
    case none(_): placedNow(state, n, context)
def placedNow(state: State, n: Nat, context: Abi.Context) -> Activity<Bool>:
  let written(_) = write {marks: insert {name: cellName(n), who: context.principal, handle: context.handle, at: context.height}, tended: set context.clock}
  Card.tell(true, Document.text("{toneOf(players(state), context.principal)} on {where(n, size(state))}.\n"))
def isHex(mark: Rows.Mark) -> Bool:
  Text.starts(mark.name, "hex ")
# The hands that have placed, in the order they first did (their colours' order).
def players(state: State) -> Lists.List<Rows.Mark>:
  firsts(Relations.order(state.marks, fn(m: Rows.Mark) -> Nat: m.at), Lists.List.nil())
def firsts(marks: Lists.List<Rows.Mark>, seen: Lists.List<Rows.Mark>) -> Lists.List<Rows.Mark>:
  match marks:
    case nil(_): seen
    case cons(c): firsts(c.tail, if isHex(c.head) == false || Lists.any(seen, fn(p: Rows.Mark) -> Bool: p.who == c.head.who) then seen else Lists.append(seen, c.head))
# A hand's colour: its place among the players, or the next colour for one who has not placed yet.
def toneOf(players: Lists.List<Rows.Mark>, who: String) -> String:
  match Lists.indexWhere(players, fn(p: Rows.Mark) -> Bool: p.who == who):
    case some(i): View.player(i.value)
    case none(_): View.player(Lists.length(players))
def name(state: State) -> String:
  if state.head == "" then "A HEXBOARD" else state.head
def count(state: State) -> Nat:
  Lists.length(Lists.filter(Relations.rows(state.marks), isHex))
def headLine(state: State, context: Abi.Context, id: String) -> Document.Document:
  let n = size(state)
  let ps = players(state)
  Document.Document.sequence({items: Document.Documents.cons({head: Document.text("{name(state)}, {natText(n)} by {natText(n)} hexes: {natText(count(state))} placed by {Text.countWord(Lists.length(ps))} hands. Your colour {yours(ps, context)}. Place it on an empty hex (a dot), numbered from 0 along each row: delvetalk {id} place / cell: <0 to {natText(n * n - 1n)}>\n"), tail: Document.Documents.cons({head: Document.text(board(state, ps, n, 0n)), tail: Document.Documents.cons({head: Document.text(Super.inactiveLine(state, id)), tail: Document.Documents.nil()})})})})
def yours(players: Lists.List<Rows.Mark>, context: Abi.Context) -> String:
  if Lists.any(players, fn(p: Rows.Mark) -> Bool: p.who == context.principal) then "is {toneOf(players, context.principal)}" else "will be {toneOf(players, context.principal)}"
# The board in letters, each placed hex its colour's first letter and an empty one a dot, odd rows set in by one.
def board(state: State, players: Lists.List<Rows.Mark>, n: Nat, y: Nat) -> String:
  if y >= n then "" else "{indent(y)}{rowText(state, players, n, y * n, n)}\n{board(state, players, n, y + 1n)}"
def indent(y: Nat) -> String:
  if y % 2n == 1n then " " else ""
def rowText(state: State, players: Lists.List<Rows.Mark>, n: Nat, at: Nat, left: Nat) -> String:
  if left == 0n then "" else "{glyph(state, players, at)}{gap(left)}{rowText(state, players, n, at + 1n, left - 1n)}"
def gap(left: Nat) -> String:
  if left > 1n then " " else ""
def glyph(state: State, players: Lists.List<Rows.Mark>, at: Nat) -> String:
  match placed(state, at):
    case some(m): textTake(toneOf(players, m.value.who), 1n)
    case none(_): "."
# What the page draws: the board as hex tiles, an empty one a button placing the reader's colour, and who is which.
def view(state: State, context: Abi.Context) -> View.View:
  let n = size(state)
  let ps = players(state)
  View.stack(View.three(View.heading(name(state)), View.hexes(n, View.tiles(0n, n * n, fn(i: Nat) -> View.Tile: tileAt(state, ps, n, i, context))), View.small(legend(state, ps, context))))
def tileAt(state: State, players: Lists.List<Rows.Mark>, n: Nat, i: Nat, context: Abi.Context) -> View.Tile:
  match placed(state, i):
    case some(m): View.tile("leaf", toneOf(players, m.value.who), "", "{where(i, n)}: {Card.shown(m.value.who, m.value.handle, context)}{Card.mine(m.value.who, context)}", View.nothing())
    case none(_): View.tile("leaf", "", "", "{where(i, n)}: place {toneOf(players, context.principal)} here", View.act("place", View.given("cell", natText(i))))
def legend(state: State, players: Lists.List<Rows.Mark>, context: Abi.Context) -> String:
  let hands = textJoin(Lists.map(players, fn(p: Rows.Mark) -> String: "{toneOf(players, p.who)}: {Card.shown(p.who, p.handle, context)}{Card.mine(p.who, context)}"), " · ")
  "Your colour {yours(players, context)}. {natText(count(state))} of {natText(size(state) * size(state))} placed{semi(hands)}{hands}."
def semi(hands: String) -> String:
  if hands == "" then "" else "; "
made
1 rows
  1. object
    hexboard
    n
    1
    about
    empty
count
1