Turtle graphics protocol #93

Open
opened 2024-06-21 03:46:50 +00:00 by scott · 8 comments
Owner

We need a protocol for turtle graphics that can be platform-independent, since we're aiming at SVG, animated canvas in a browser, native 2D graphics, robot turtles, and a 2D plotter. And perhaps more!

Since we'll want to add things arbitrarily over time, including in short order with animations (and possibly without easily synchronizing the Javascript and WASM event loops), we'll need a buffer. (Probably a ring buffer of JSON strings, each of which describes a turtle motion.)

It strikes me we will also want similar protocols for input as well. In approximate order of operations:

  • Devise a minimal set of turtle graphics functions
  • Ludus now only speaks turtle graphics
  • Move all p5 calls out from Ludus and into a JS adapter
  • Write a JS turtle graphics to SVG adapter
  • Embed the Ludus code into the SVG (in JS, not in Ludus: Ludus only speaks turtle)
  • Write a terminal-based WASM + JS CLI/REPL (presumably in Bun) for Ludus

Then we can start thinking about animation, input, output, etc.

We need a protocol for turtle graphics that can be platform-independent, since we're aiming at SVG, animated canvas in a browser, native 2D graphics, robot turtles, and a 2D plotter. And perhaps more! Since we'll want to add things arbitrarily over time, including in short order with animations (and possibly without easily synchronizing the Javascript and WASM event loops), we'll need a buffer. (Probably a ring buffer of JSON strings, each of which describes a turtle motion.) It strikes me we will also want similar protocols for input as well. In approximate order of operations: * [x] Devise a minimal set of turtle graphics functions * [x] Ludus now only speaks turtle graphics * [x] Move all p5 calls out from Ludus and into a JS adapter * [x] Write a JS turtle graphics to SVG adapter * [x] Embed the Ludus code into the SVG (in JS, not in Ludus: Ludus only speaks turtle) * [ ] Write a terminal-based WASM + JS CLI/REPL (presumably in Bun) for Ludus Then we can start thinking about animation, input, output, etc.
scott added this to the 0.2.0 milestone 2024-06-21 03:46:50 +00:00
scott added the
enhancement
next
research
semantics
ux
infrastructure
labels 2024-06-21 03:46:50 +00:00
scott self-assigned this 2024-06-21 03:46:50 +00:00
matt was assigned by scott 2024-06-21 03:46:50 +00:00
Author
Owner

One quick question here is whether we want a "turtle graphics protocol" or a more general I/O protocol, which starts with turtle graphics. To wit:

{ "turtle_graphics": [["forward", 100], ["right", 0.25]] }

What this allows is additional fields, and thus additional protocols to be added to Ludus in the future. (This is obvious, I'm tired, and I don't want to forget what are effectively shower thoughts.)

One quick question here is whether we want a "turtle graphics protocol" or a more general I/O protocol, which starts with turtle graphics. To wit: ```json { "turtle_graphics": [["forward", 100], ["right", 0.25]] } ``` What this allows is additional fields, and thus additional protocols to be added to Ludus in the future. (This is obvious, I'm tired, and I don't want to forget what are effectively shower thoughts.)
scott added this to the Turtle Protocol & Adapters project 2024-07-03 00:16:34 +00:00
Owner

I like this idea, and there can be many "adapters" for each protocol ... i.e. turtle_graphics can be then consumed by a p5js adapter, or an svg adapter, or whatever really. We could supply a few initial adapters, and then also let people write their own.... ?

I like this idea, and there can be many "adapters" for each protocol ... i.e. `turtle_graphics` can be then consumed by a p5js adapter, or an svg adapter, or whatever really. We could supply a few initial adapters, and then also let people write their own.... ?
Author
Owner

A few thoughts, notes here:

  • This is really a version of a complete I/O protocol for Ludus.
  • This means that all of these are, in some sense, streams, not static objects.
  • Each output of the standard JSON object protocol is a description of a stream.

That means, also, that we have three protocols to work with:

  • General I/O protocol
  • Text streams: stdout, stderr
  • Turtle graphics

Additional protocols will, of course, be added:

  • Mouse & keyboard events
  • Robot turtle feedback
  • These might be developed into an "event stream" protocol, but that's for future-us.

General I/O protocol rough draft:

  • Each message is a JSON object.
  • Each key in that object is a string specifying an I/O stream. (In Ludus, this will be modelled as keywords, not strings.)
  • Each value in that object is itself an object that has two fields:
    • a protocol name & version, each of which are strings in a two-element array, proto: [proto-name, version]
    • some data that conforms to the protocol name/version, data: ...
  • The two protocols we start with are text streams and turtle graphics.
  • Additional fields can be added in the future (e.g., a timestamp).
  • While the initial version of this will still use one-shot Ludus (we're working on actors), this protocol is specifically a streaming protocol, so new data is appended to the stream in question.

Text stream protocol rough draft:

  • Text streams are a cognate for the Unix standard text streams: stdin, stdout, and stderr.
  • Protocol name: "text-stream"
  • First version: "0.1.0"
  • Data: an array of UTF-8 strings; each string represents a "line", even if it contains newlines; asking for the next item in this stream simply delivers the next string.

Turtle graphics protocol rough draft:

  • Turtle graphics describe the movements and drawing behaviours of screen, robot, and print "turtles."
  • Protocol name: "turtle-graphics"
  • First version: "0.1.0"
  • Data: an array of arrays; each array represents a turtle command; the first element of a command array is the verb; any subsequent items are the arguments to the verbs.
  • Valid arguments are numbers, strings, and booleans.
  • Depending on what we end up doing, we may add arrays of these, representing tuples or lists, and/or objects with string keys whose text are well-formed keywords in Ludus.
  • E.g., ["forward", 100]
  • We'll develop a standard set of verbs and allowed arguments & arities; any updates to these will bump the version of the protocol.
  • Each turtle will have its own stream.
  • At current, this protocol describes the behaviour of turtle-like objects, all of which "live" in the same "world"; there is not yet a provision for multiple canvases/worlds. That said, an additional field for "world" in at the top level may well be added in the future to allow for multiple worlds to unfold at the same time.

Next step: list turtle verbs and arguments.

A few thoughts, notes here: * This is really a version of a complete I/O protocol for Ludus. * This means that all of these are, in some sense, *streams*, not static objects. * Each output of the standard JSON object protocol is a description of a stream. That means, also, that we have three protocols to work with: * General I/O protocol * Text streams: `stdout`, `stderr` * Turtle graphics Additional protocols will, of course, be added: * Mouse & keyboard events * Robot turtle feedback * These might be developed into an "event stream" protocol, but that's for future-us. --- General I/O protocol rough draft: * Each message is a JSON object. * Each key in that object is a string specifying an I/O stream. (In Ludus, this will be modelled as keywords, not strings.) * Each value in that object is itself an object that has two fields: - a protocol name & version, each of which are strings in a two-element array, `proto: [proto-name, version]` - some data that conforms to the protocol name/version, `data: ...` * The two protocols we start with are text streams and turtle graphics. * Additional fields can be added in the future (e.g., a timestamp). * While the initial version of this will still use one-shot Ludus (we're working on actors), this protocol is specifically a *streaming* protocol, so new data is *appended* to the stream in question. --- Text stream protocol rough draft: * Text streams are a cognate for the Unix standard text streams: `stdin`, `stdout`, and `stderr`. * Protocol name: "text-stream" * First version: "0.1.0" * Data: an array of UTF-8 strings; each string represents a "line", even if it contains newlines; asking for the next item in this stream simply delivers the next string. --- Turtle graphics protocol rough draft: * Turtle graphics describe the movements and drawing behaviours of screen, robot, and print "turtles." * Protocol name: "turtle-graphics" * First version: "0.1.0" * Data: an array of arrays; each array represents a turtle command; the first element of a command array is the verb; any subsequent items are the arguments to the verbs. * Valid arguments are numbers, strings, and booleans. * Depending on what we end up doing, we may add arrays of these, representing tuples or lists, and/or objects with string keys whose text are well-formed keywords in Ludus. * E.g., `["forward", 100]` * We'll develop a standard set of verbs and allowed arguments & arities; any updates to these will bump the version of the protocol. * Each turtle will have its own stream. * At current, this protocol describes the behaviour of turtle-like objects, all of which "live" in the same "world"; there is not yet a provision for multiple canvases/worlds. That said, an additional field for "world" in at the top level may well be added in the future to allow for multiple worlds to unfold at the same time. --- Next step: list turtle verbs and arguments.
Author
Owner

A simple example:

{
  "stdout": {
    "proto": ["text-stream", "0.1.0"],
    "data": []
  },
  "stderr": {
    "proto": ["text-stream", "0.1.0"],
    "data": ["oops, I panicked!"]
  },
  "turtle1": {
    "proto": ["turtle-graphics", "0.1.0"],
    "data": [["forward", 100], ["right", 0.25]]
  }
}
A simple example: ```json { "stdout": { "proto": ["text-stream", "0.1.0"], "data": [] }, "stderr": { "proto": ["text-stream", "0.1.0"], "data": ["oops, I panicked!"] }, "turtle1": { "proto": ["turtle-graphics", "0.1.0"], "data": [["forward", 100], ["right", 0.25]] } } ```
Author
Owner

@matt Any thoughts about this?

Two specific hesitations, which I'm happy to bracket for the time being (or quite a while):

  • We're repeating the "proto" section with every message. On the one hand, that's probably a good idea? On the other hand, it feels wasteful. (This is probably not the first place to worry about waste...)

  • stdin, stdout, stderr may eventually be superseded by a WASI interface, but for now I think we can usefully do this without having to deal with the whole WASI thing (including v0.1.0 vs v0.2.0, which is kind of a mess). In this case, I think we can forge ahead with this using our simpler, single-text-stream, JSON-encoded protocol between WASM and JS for the time being.

@matt Any thoughts about this? Two specific hesitations, which I'm happy to bracket for the time being (or quite a while): * We're repeating the "proto" section with every message. On the one hand, that's probably a good idea? On the other hand, it feels wasteful. (This is probably not the first place to worry about waste...) * `stdin`, `stdout`, `stderr` may eventually be superseded by a WASI interface, but for now I think we can usefully do this without having to deal with the whole WASI thing (including v0.1.0 vs v0.2.0, which is kind of a mess). In this case, I think we can forge ahead with this using our simpler, single-text-stream, JSON-encoded protocol between WASM and JS for the time being.
Author
Owner

Current set of things to do:

  • Rework Ludus's output to be only its I/O protocol
  • Rewrite all the logic from Prelude in apply_command, render_turtle, and state/call in JS.
  • Write a p5.js adapter that reproduces current web.ludus.dev behaviour.
  • Write an SVG adapter to work at the command line, embedding the Ludus code in the SVG.
  • Replace the p5.js adapter with SVG.
  • Write a loader for web.ludus.dev to load up an SVG and its code.
  • Turtles might need to report their state back to Ludus. Devise this reporting. (Or should Ludus do this bookkeeping itself?)
Current set of things to do: * [x] Rework Ludus's output to be only its I/O protocol * [x] Rewrite all the logic from Prelude in `apply_command`, `render_turtle`, and `state/call` in JS. * [x] Write a p5.js adapter that reproduces current web.ludus.dev behaviour. * [x] Write an SVG adapter to work at the command line, embedding the Ludus code in the SVG. * [ ] Replace the p5.js adapter with SVG. * [ ] Write a loader for web.ludus.dev to load up an SVG and its code. * [ ] Turtles might need to report their state back to Ludus. Devise this reporting. (Or should Ludus do this bookkeeping itself?)
Author
Owner

So: one thing that seems pointed here is that actually, p5 isn't the best option for web graphics. In particular, we'll likely want three canvases on top of one another: a background layer, a path layer, and a turtle layer. We want to be able to change the background colour without erasing all the paths, and to move the turtles without having to redraw all the paths.

p5 doesn't allow this; multiple canvases aren't a thing, there.

I suspect that directly using the canvas API is likely the best bet, rather than using p5.

So: for now, just as I'm thinking this through, I'll wire up a single-shot, static, not-animated p5 adapter that will be a drop-in replacement for Ludus-web. But the next step, an SVG adapter, will actually be much more robust for a bunch of stuff, including print output.

Then, an animated, multi-turtle, actor-model situation will be based on the Canvas API.

So: one thing that seems pointed here is that actually, p5 isn't the best option for web graphics. In particular, we'll likely want three canvases on top of one another: a background layer, a path layer, and a turtle layer. We want to be able to change the background colour without erasing all the paths, and to move the turtles without having to redraw all the paths. p5 doesn't allow this; multiple canvases aren't a thing, there. I suspect that directly using the canvas API is likely the best bet, rather than using p5. So: for now, just as I'm thinking this through, I'll wire up a single-shot, static, not-animated p5 adapter that will be a drop-in replacement for Ludus-web. But the next step, an SVG adapter, will actually be much more robust for a bunch of stuff, including print output. Then, an animated, multi-turtle, actor-model situation will be based on the Canvas API.
Author
Owner

I did a whole bunch of this this summer. Static SVG graphics are done. Shifting most of p5 stuff from Ludus/Janet to Javascript is done. CLI is not done, but that's simple-ish, and in any event is not a priority.

I did a whole bunch of this this summer. Static SVG graphics are done. Shifting most of p5 stuff from Ludus/Janet to Javascript is done. CLI is not done, but that's simple-ish, and in any event is not a priority.
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: twc/ludus#93
No description provided.