OTTER - ONLINE TABLE TOP ENVIRONMENT RENDERER
=============================================
-Otter is an online "table simulator" intended to be suitable for board
-games and similar.
+Otter is an online game system.
-It is accessed from a web browser running JavaScript. The server runs
-on a convenationl Unix host. Currently, joining a game requires a
-unix shell account on the server.
+But it is not like most online game systems. It does not know (nor
+does it need to know) the rules of the game you are playing. Instead,
+it lets you and your friends play with common tabletop/boardgame
+elements such as hands of cards, boards, and so on.
-I expect it to be used with a concurrent voice chat.
+So it's something like a "tabletop simulater" (but it does not have
+any 3D, or a physics engine, or anything like that).
-The game server does not currently have a built-in text chat system.
-The game organiser can use the game server to distribute (and update)
-voice chat and info links.
+This means that with Otter:
-Right now Otter is in an alpha state.
+ * Supporting a new game, that Otter doesn't know about yet, would
+ usually not involve writing or modifying any computer programs.
+ * If Otter already has the necessarily game elements (cards, say) all
+ you need to do is write a spec file saying what should be on the
+ table at the start of the game. For example, most Whist variants
+ that start with a standard pack of 52 cards are already playble.
-JOINING A GAME
-==============
+ * You can play games where the rules change as the game goes along,
+ or are made up by the players, or are too complicated to write as a
+ computer program.
-In the simplest case:
-```
- otter join-game unix:<user>::<game-name>
-```
-e.g.
-```
- otter join-game unix:ijackson::test
-```
+ * House rules are no problem, since the computer isn't enforcing the
+ rules - you and your friends are.
-See `otter --help` for further options, including setting your nick.
+ * Everyone can interact with different items on the game table, at
+ any time. (Otter doesn't know about your game's turn-taking, so
+ doesn't know whose turn it might be.)
-Currently when a new player joins a game (with the `otter` command),
-all the other players must reload the page.
+We have played successful and fun online games of both Penultima and
+Mao with Otter.
-CREATING A GAME
-===============
-
-```
-otter reset --reset-table local-users :test demo
- /^^^^^^^^^^^ ^^^\ ^^^^'~ game spec
- `table spec game name
-```
-
-Here `local-users` refers to the file `local-users.table.spec` in the
-Otter specs directory (`/volatile/Otter/specs` on chiark). The table
-spec file handles access control (and some other global properties)
-This particular file says that all local shell account users may join
-the game.
-
-`:test` is the game name. It starts with a colon, which means
-implicitly `unix:<whoami>::test`. Other people have to name the game
-with the full name, with all three colons in it.
-
-`demo` refers to the file `demo.game.spec`. The "game spec" says what
-shape table is and what pieces there are. This is a simple demo game.
-There is also `penultima` which is a work-in-progress set of pieces
-suitable for fairy chess etc.
-
-See `otter --help` for some more options.
-
-Currently, resetting a game (or otherwise adding or removing pieces)
-will mean all the players will get errors until they reload the page.
-
-
-MAKING YOUR OWN GAME
-====================
-
-If you want to use existing piece shapes that Otter already knows
-about, you can do this by providing a `<something>.game.toml` file.
-The format of these files is a TOML document representing a GameSpec
-as found in `src/spec.rs` in the Otter source code.
-
-todo: use rustdoc to provide this somewhere.
-
-
-ADDING SHAPES
-=============
-
-Otter uses SVGs. The sources for the SVGs are all in the otter source
-tree, in the `library/` directory.
-
-Each shape is listed in one of the `library/*.toml` files, in a
-`files` entry. (Most of) the syntax and semantics of this file are
-documented in the Rustdoc documentation for the module
-`otter::shapelib_toml`. If you run `make -j8 shapelib` it will print
-out a `file://` url for these docs.
-
-You can preview the shapes, including any changes you make, without a
-whole game server, by running `make -j8 shapelib`, and looking at
-`templates/shapelib.html`. As above, this make rune will print the
-`file://` url for you. (See BUILDING AND TESTING for information
-about how to install the tools you will need.)
-
-Some of these SVGs were scraped from Wikimedia. The scraper machinery
-can perhaps be adapted to scrape SVGs from elsewhere.
-
-You can also add your own SVGs in the library/edited/ directory.
-If you do that, please make sure to include the actual source code.
-If you copied or adapted an SVG from somewhere, provide details.
-
-Contributions should be via git branch, eg a merge request on Salsa:
-[https://salsa.debian.org/iwj/otter](https://salsa.debian.org/iwj/otter)
-
-NB that shapes must come with a licence compatible with CC-BY-SA 4.0
-or GNU AGPLv3+. See `LICENCE` for more information about copyright status.
-
-
-BUILDING AND TESTING
-====================
-
-You will need at least 6000 megabytes of disk space, or more, and a
-good internet connection. Your computer will be compiling a lot of
-code.
-
-These instructions have been tested on Debian buster.
-
-
-Setup
------
-
-1.
-```
- sudo apt install build-essential cpio git curl \
- pkg-config libssl-dev \
- node-typescript inkscape bubblewrap \
- netpbm imagemagick
-```
-
-2. Install Rust. This is most easily done with [rustup](https://rustup.rs)):
-
-```
- curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-```
-
- and then follow the instructions about your `PATH`. If this rune
- alarms you, see below about Rust privsep.
-
-3. Switch your Rust install to use Rust Nightly and add the WASM
- target:
-
-```
- rustup default nightly
- rustup target add wasm32-unknown-unknown
-```
-
- Unfortunately, it is possible that the Rust nightly you find when
- you run this is missing some pieces. The following is known to
- work (with otter from the time of writing):
-```
- rustup default nightly-2021-01-26
-```
-
-4. Install the `usvg` SVG launderer, which we need for shape libraries
-
-```
- cargo install usvg
-```
-
- This will put it in `~/.cargo/bin`, which you presumably have on
- your `PATH` (or the above `rustup` and `cargo` runes wouldn't work).
-
-
-** If you just want to edit and preview the shape libraries
- (ie the piece shapes) you can stop here **
-
-
-5. Install some more build tools:
-
-```
- cargo install bundle-sources
-```
-
-
-Build
------
-
-```
- git clone https://salsa.debian.org/iwj/otter
- cd otter
- make -j8 all bundled-sources
-```
-
-Or if you just want to edit the piece libraries:
-
-```
- make -j8 shapelib
-```
-And then open `./templates/shapelib.html` in your browser
-
-
-Ad-hoc tests
-------------
-
-In one shell:
-
-```
- target/debug/daemon-otter server-test.toml
-```
-
-The server does not daemonise, and the default config there makes it
-quite verbose. So, in another shell:
-
-```
- target/debug/otter \
- --account server: --config server-test.toml --spec-dir=specs \
- reset --reset-table test server::test demo
-
- target/debug/otter \
- --account server: --config server-test.toml --spec-dir=specs \
- join-game server::test
-```
-
-The URL printed can then be visited in a local browser.
-
-
-Resetting/restoring things after tests, updating server, etc.
--------------------------------------------------------------
-
-After the server is updated, you can just `^C` and restart it. Games
-are constantly saved (although there is an up-to-1s lag on the most
-frequently udpated game state).
-
-If you want to clear out the server state, delete the files `[ag]-*`
-and `accounts`. NB that you should do this with the server not
-running, because the server has most of that information in memory and
-will like to write it out again.
-
-If you update Typescript (JS code) you will need to rerun `make` to
-rebuild the JS output.
-
-Apart from that, if you update JS or WASM code or Tera templates, you
-do not need to restart the server - it will pick up changes
-automatically.
-
-When testing, you do not need to `make bundled-sources` more than
-once, at the beginning. So don't, because it's slow. But you
-definitely should run it for every update if you make a deployment for
-other people to use. Otherwise you might be running a privately
-modified server without offering your users its source code. See
-LICENCE.
-
-If you Do Something to the output from cargo, you should `rm stamp/*`,
-since the `Makefile` won't notice, otherwise, that, the relevant cargo
-rune(s) need to be re-run. Needlessly deleting all the stamp files
-wastes only a handful of seconds (on my stupidly fast laptop).
-
-
-Navigating the otter source code
---------------------------------
-
-* `src/`
-
- The main Rust source code. This is mixture of code used only or
- mainly by the server and code used by the `otter` command line
- utility; these aren't split up in a wholly principled way. In Rust
- terms this is a "library crate".
-
-* `src/bin/*.rs`
-
- Support executables, including in particular the command line
- utility `otter` which is used to set up and join games.
-
-* `daemon/`
-
- The Otter server. This is a simple binary crare. Much
- functionality belonging primarily, or only, to the server, is in
- `src/`, simply because it was easier not to disentangle it.
- Anything that needs Rocket (the web framework) is in `daemon/`.
-
-* `zcoord/`
-
- Code shared by the host and the WebAssembly. Notably, the Z
- coordinate handling, but also a a few other minor functions needed
- by both client and server. To avoid duplicating them are written
- once in Rust and compiled twice - once for the host and once for
- WebAssembly for use in the client. This crate is kept minimal to
- keeep the WebAssembly binary small.
-
-* `wasm/`
-
- WebAssembly/Rust bindings for the items in `zcoord/`. Produces the
- single wasm file for use by the JavaScript, and corresponding
- Typescript annotations etc.
-
-* `templates/script.ts`
-
- The main Typescript (typed Javascript) code. Otter's web
- compatibility target is the earliest browser versions that properly
- support WebAssembly.
-
-* `templates/session.tera`, `macros.tera`, etc.
-
- Tera templates generating the main HTML screen. These templates are
- filled in from structs in the Rust source code. The main files are
- `session.tera` (portrait), `landscape.tera`, and `macros.tera`
- (common), and their rendering uses an instance of
- `SessionRenderContext` from `src/session.rs`.
-
-* `nwtemplates/`
-
- "Non-web templataes". Tera templates for things other than web
- pages. Currently this includes the server's outgoing emails. These
- have to be in a separate directory because Rocket likes to load
- everything applicable it finds in its own `templates/` directory.
- These are used via `src/nwtemplates.rs`.
-
-* `wdriver.rs`, `wdriver/`
-
- WebDriver-based end-to-end tests. Each `wdt-*.rs` is one test
- utility. `wdriver.rs` (in the top level to evade Cargo's
- dur-brained search rules) is the library for these, and contains
- most of the heavy lifting.
-
- These are not standard Rust `#[test]` tests because they need to
- reinvoke themselves via `bwrap` for test isolation reasons, and
- because their dependencies are extensive and not properly capturable
- in Cargo. They are run by `make check`.
-
-* `library/`: The shape libraries.
-
- The program `./media-scraper` (which is not run by the `Makefile`)
- reads `library/*.toml` for instructions and generates `files.make`
- fragments. These fragments arrange to run `./usvg-processor` which
- launders SVGs through `usvg`. `usvg-processor`.
-
- The shape libraries have a different, more relaxed, copyright
- licence.
-
-
-Automatic in-browser tests
+Playing a game with Otter
--------------------------
-* `apt install firefox`
+The Otter game environment is accessed from a web browser running
+JavaScript, using a magic https link obtained from joining the game.
-* `https://github.com/mozilla/geckodriver/releases/tag/v0.28.0`
- download appropriate tarball, put "geckodriver" on PATH
+You will need to be able to talk to your friends about the game, while
+you play. Otter works well when used together with a voice chat - we
+have had success with Jitsi in voice-only mode.
-`make check` runs all the tests; `make wdt` runs only those tests. You can run
-an individual test with a rune like this:
+Most relatively modern desktop browsers should to work with Otter.
+(The most advanced feature needed is support for WebAssembly.)
-```
- OTTER_TEST_LOG=otter_webdriver_tests=trace CARGO_MANIFEST_DIR=~ian/Rustup/Game/server time target/debug/wdt-simple --geckodriver-args=
-```
-(This rune has some example logging options in it, for you to change
-if you like. You can omit the `CARGO_MANIFEST_DIR` for an in-tree
-non-privsep build.) After a test has run, you can find screenshots,
-etc. in `tmp/wdt-simple` or whatever. You can restart the same game
-server setup as the test used, with the state left by the test, with a
-rune like this:
+Predefined games and pieces currently available
+-----------------------------------------------
-```
- target/debug/daemon-otter tmp/wdt-simple/server-config.toml
-```
-and then play with it at this url:
-```
- http://localhost:8000/?kmqAKPwK4TfReFjMor8MJhdRPBcwIBpe
-```
+Otter currently has, in its pieces library:
+ * Ingredients for chess, including fairy chess. So there's a board,
+ pieces, including many fairy chess pieces, and a chess clock.
-Rust, cargo, curl|bash-ware; privsep
-------------------------------------
+ * Ingredients for card games. So, a deck of 52 standard playing
+ cards, plus two kinds of joker. Special "hand" and "deck" pieces
+ for player hands and a pickup deck.
-If you follow the above instructions you will have downloaded and
-executed - and, therefore, trusted:
+Currently there are game definitions for:
- * Various Debian packages - safe
- * Rustup (the Rust downloader/installer) - this is pretty safe
- * Rust itself - again, pretty safe
- * Otter itself - well, I wrote this; up to you.
- * 450 transitive dependencies of otter (from crates.io)
- * 50 transitive dependencies of bundle-sources
- * the transitive dependencies of resvg
- * a geckodriver binary directly from mozilla
+ * Penultima. This can be used directly to play standard chess and
+ some fairy chess variants.
-You will have trusted the integrity of the following:
+ * Mao. This can be used to play any game of roughly that shape.
- * The Debian archive (via its apt keyring) (very good)
- * Rustup's and Rust's TLS keyholders (good, I think)
- * The HTTP TLS cabal (sigh)
- * github (pretty good in practice)
- * whatever mozilla do to make binaries, in particular geckodriver
- * crates.io (extremely poor traceability)
- * the project management of hundreds of random crates.io libraries
+Defining new games using the existing pieces from the library is
+fairly easy. It is also possible to add elements from the library
+ad-hoc, even while a game is in progress.
-If this makes you uncomfortable, as it should, you may wish to
-consider running everything in a separate shell account, or a VM or
-container of some kind.
-(I have a not-properly-released tool called "nailing-cargo" which
-makes it possible to do most things in my main account but run the
-Rust stuff in a separate less-privileged account. There is support
-for this in the Makefile. But if you want to run *everything* in the
-lesser account, you don't need to bother with that.)
+Limitations
+-----------
+Currently, joining a game requires a unix shell account on the server
+host (or help from a shell account user).
-Dependencies - apologia
------------------------
+There is not currently a publicly available server. The server code
+is Free Software and if you have a suitable vm or server you are
+encouraged to build and run it yourself, for you and your friends.
- * Rust Nightly
+Mobile phones are not really suitable for playing on Otter because
+their screens are too small. Tablets and other touchscreen based
+systems could be made to work, but don't work well right now.
- This is needed almost solely because Rocket needs it. Rocket is
- the web framework I am using. The next version of Rocket (0.5.x),
- which is in development, will not need Nightly, but it will also be
- a serious compatibility break. The existing Rocket (0.4.x) will
- almost certainly never be ported to Stable Rust. When Rocket 0.5.x
- is out, porting Otter to it will go on my list - but it won't be
- trivial. Sorry.
+Otter does not currently have even a built-in text chat facility. It
+does have a way to share a URL for a voice chat.
- * The many dependencies of Otter
+Right now Otter is in a beta state. There are significant
+as-yet-unimplemented improvements that would make it work better for
+more people and more games. I don't currently promise savefile
+compatibility, or upgradeability, from one Otter version to the next.
+And there are still bugs.
- These are partly because Rocket is a large piece of software with
- much functionality. But also because I favoured my own programming
- convenience and in some cases was experimenting with different
- approaches. In practice, it seems to me that once I'm using Rocket
- and WASM and resvg and so on, there is not that much to be gained
- by trying to prune the dependencies of the otter package itself.
- * bundle-rust-sources
+Free software, and user freedom
+-------------------------------
- This is mine, but it needs to be properly released.
+Otter is Free Software. I wrote it to liberate game players from the
+need to encode their game rules as computer programs and thus from the
+tyranny of programmers `:-)`.
- * geckodriver (for the automated in-browser tests)
+I would love contributions, particularly to address the limitations I
+mention above, and to improve the user experience.
- This is done with a protocol called "WebDriver" which is a
- cross-browser way to puppet a browser. There is a thing called
- "geckodriver" which converts that to a firefox-specific protocol
- for the same purpose, called "Marionette". (In practice all this
- seems to have lots of bugs and misfeatures.)
+I am also working to make it possible to let you define your own games
+(including your own pieces, cards, boards, and so on) without having
+to install them on the server.
- AFAICT the usual approach for using geckodriver to have it *bind to
- a fixed TCP port accessible to all local programs*. My wrapper
- tooling arranges to run this in an ephemeral $HOME and a private
- network namespace.
-
- AFAICT the only practical way to get geckodriver is to download the
- binary. I got mine here:
- https://github.com/mozilla/geckodriver/releases/tag/v0.28.0 You
- You just dump the binary on your PATH.
-
-
-Final weirdness
----------------
-
- * For running on chiark I build with the Rust target
- `x86_64-unknown-linux-musl` which on my system is configured to
- produce a completely statically linked bionary. I have this in my
- `~/.cargo/config` (in the lesser privsep account):
-
-```
-[target.x86_64-unknown-linux-musl]
-rustflags = ["-C", "target-feature=+crt-static"]
-# ^ from https://stackoverflow.com/questions/31770604/how-to-generate-statically-linked-executables
-```
+The Otter software project is hosted on Debian's GitLab, at
+ https://salsa.debian.org/iwj/otter
+Merge requests (accompanied by a `Signed-off-by` indicating sign-off
+of the Developer Certificate of Origin) would be very welcome.
--- /dev/null
+Making your own game
+====================
+
+If you want to use existing piece shapes that Otter already knows
+about, you can do this by providing a `<something>.game.toml` file.
+The format of these files is a TOML document representing a `GameSpec`
+as found in `src/spec.rs` in the Otter source code.
+
+
+Adding shapes
+=============
+
+Otter uses SVGs. The sources for the SVGs are all in the otter source
+tree, in the `library/` directory.
+
+Each shape is listed in one of the `library/*.toml` files, in a
+`files` entry. (Most of) the syntax and semantics of this file are
+documented in the Rustdoc documentation for the module
+`otter::shapelib_toml`. If you run `make -j8 shapelib` it will print
+out a `file://` url for these docs.
+
+You can preview the shapes, including any changes you make, without a
+whole game server, by running `make -j8 shapelib`, and looking at
+`templates/shapelib.html`. As above, this make rune will print the
+`file://` url for you.
+
+See BUILDING AND TESTING for information about how to install the
+tools you will need.
+
+Some of these SVGs were scraped from Wikimedia. The scraper machinery
+can perhaps be adapted to scrape SVGs from elsewhere.
+
+You can also add your own SVGs in the library/edited/ directory.
+If you do that, please make sure to include the actual source code.
+If you copied or adapted an SVG from somewhere, provide details.
+
+Contributions should be via git branch, eg a merge request on Salsa:
+[https://salsa.debian.org/iwj/otter](https://salsa.debian.org/iwj/otter)
+
+NB that shapes must come with a licence compatible with CC-BY-SA 4.0
+or GNU AGPLv3+. See `LICENCE` for more information about copyright status.
--- /dev/null
+BUILDING AND TESTING OTTER
+==========================
+
+Otter is mostly written in Rust.
+
+The web UI frontend is written in Typescript, with a small amount of
+Rust support code delivered via WebAssembly.
+
+
+You will need at least 6000 megabytes of disk space, or more, and a
+good internet connection. Your computer will be compiling a lot of
+code.
+
+These instructions have been tested on Debian buster.
+
+
+Setup
+-----
+
+1.
+```
+ sudo apt install build-essential cpio git curl \
+ pkg-config libssl-dev \
+ node-typescript inkscape bubblewrap \
+ netpbm imagemagick
+```
+
+2. Install Rust. This is most easily done with [rustup](https://rustup.rs)):
+
+```
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
+
+ and then follow the instructions about your `PATH`. If this rune
+ alarms you, see below about Rust privsep.
+
+3. Switch your Rust install to use Rust Nightly and add the WASM
+ target:
+
+```
+ rustup default nightly
+ rustup target add wasm32-unknown-unknown
+```
+
+ Unfortunately, it is possible that the Rust nightly you find when
+ you run this is missing some pieces. The following is known to
+ work (with otter from the time of writing):
+```
+ rustup default nightly-2021-01-26
+```
+
+4. Install the `usvg` SVG launderer, which we need for shape libraries
+
+```
+ cargo install usvg
+```
+
+ This will put it in `~/.cargo/bin`, which you presumably have on
+ your `PATH` (or the above `rustup` and `cargo` runes wouldn't work).
+
+
+** If you just want to edit and preview the shape libraries
+ (ie the piece shapes) you can stop here **
+
+
+5. Install some more build tools:
+
+```
+ cargo install bundle-sources
+```
+
+
+Build
+-----
+
+```
+ git clone https://salsa.debian.org/iwj/otter
+ cd otter
+ make -j8 all bundled-sources
+```
+
+Or if you just want to edit the piece libraries:
+
+```
+ make -j8 shapelib
+```
+And then open `./templates/shapelib.html` in your browser
+
+
+Ad-hoc tests
+------------
+
+In one shell:
+
+```
+ target/debug/daemon-otter server-test.toml
+```
+
+The server does not daemonise, and the default config there makes it
+quite verbose. So, in another shell:
+
+```
+ target/debug/otter \
+ --account server: --config server-test.toml --spec-dir=specs \
+ reset --reset-table test server::test demo
+
+ target/debug/otter \
+ --account server: --config server-test.toml --spec-dir=specs \
+ join-game server::test
+```
+
+The URL printed can then be visited in a local browser.
+
+
+Resetting/restoring things after tests, updating server, etc.
+-------------------------------------------------------------
+
+After the server is updated, you can just `^C` and restart it. Games
+are constantly saved (although there is an up-to-1s lag on the most
+frequently udpated game state).
+
+If you want to clear out the server state, delete the files `[ag]-*`
+and `accounts`. NB that you should do this with the server not
+running, because the server has most of that information in memory and
+will like to write it out again.
+
+If you update Typescript (JS code) you will need to rerun `make` to
+rebuild the JS output.
+
+Apart from that, if you update JS or WASM code or Tera templates, you
+do not need to restart the server - it will pick up changes
+automatically.
+
+When testing, you do not need to `make bundled-sources` more than
+once, at the beginning. So don't, because it's slow. But you
+definitely should run it for every update if you make a deployment for
+other people to use. Otherwise you might be running a privately
+modified server without offering your users its source code. See
+LICENCE.
+
+If you Do Something to the output from cargo, you should `rm stamp/*`,
+since the `Makefile` won't notice, otherwise, that, the relevant cargo
+rune(s) need to be re-run. Needlessly deleting all the stamp files
+wastes only a handful of seconds (on my stupidly fast laptop).
+Deleting the xtamp files is not needed if you simpl edit Rust source
+files.
+
+
+Navigating the otter source code
+--------------------------------
+
+* `src/`
+
+ The main Rust source code. This is mixture of code used only or
+ mainly by the server and code used by the `otter` command line
+ utility; these aren't split up in a wholly principled way. In Rust
+ terms this is a "library crate".
+
+* `src/bin/*.rs`
+
+ Support executables, including in particular the command line
+ utility `otter` which is used to set up and join games.
+
+* `daemon/`
+
+ The Otter server. This is a simple binary crate. Much
+ functionality belonging primarily, or only, to the server, is in
+ `src/`, simply because it was easier not to disentangle it.
+ Anything that needs Rocket (the web framework) is in `daemon/`.
+
+* `base/`
+
+ Code shared by the host and the WebAssembly. Notably, the Z
+ coordinate handling, but also a a few other minor functions needed
+ by both client and server. To avoid duplicating them are written
+ once in Rust and compiled twice - once for the host and once for
+ WebAssembly for use in the client. This crate is kept fairly small
+ to keeep the WebAssembly binary small (currently, ~100kby).
+
+* `wasm/`
+
+ WebAssembly/Rust bindings for the items in `zcoord/`. Produces the
+ single wasm file for use by the JavaScript, and corresponding
+ Typescript annotations etc.
+
+* `templates/script.ts`
+
+ The main Typescript (typed Javascript) code. Otter's web
+ compatibility target is the earliest browser versions that properly
+ support WebAssembly.
+
+* `templates/session.tera`, `macros.tera`, etc.
+
+ Tera templates generating the main HTML screen. These templates are
+ filled in from structs in the Rust source code. The main files are
+ `session.tera` (portrait), `landscape.tera`, and `macros.tera`
+ (common), and their rendering uses an instance of
+ `SessionRenderContext` from `src/session.rs`.
+
+* `nwtemplates/`
+
+ "Non-web templataes". Tera templates for things other than web
+ pages. Currently this includes the server's outgoing emails. These
+ have to be in a separate directory because Tera (invoked by Rocket)
+ likes to load everything applicable it finds in its own `templates/`
+ directory. These are used via `src/nwtemplates.rs`.
+
+* `apitest/`
+
+ Tests of the server which use its APIs - specifically, the
+ management socket (also used by the `otter` command line tool) and
+ the web API, but which do not use any JavaScript.
+
+ These are not standard Rust `#[test]` tests because they need to
+ reinvoke themselves via `bwrap` for test isolation reasons, and
+ because their dependencies are extensive and not properly capturable
+ in Cargo. They are run by `make check`.
+
+ The file `apitest/apitest.rs` also contains code which is reused by
+ the WebDriver tests.
+
+* `wdriver/`
+
+ WebDriver-based end-to-end tests. Each `wdt-*.rs` is one test
+ utility. `wdriver.rs` is the library for these, and contains most
+ of the heavy lifting.
+
+ The tests produce a single portmanteau binary to reduce compile
+ times. You run it with `target/debug/wdriver --test=wdt-something`.
+
+* `specs/`. The table and game specs, as used directly by `otter`.
+
+* `library/`: The shape libraries.
+
+ The program `./media-scraper` (which is not run by the `Makefile`)
+ reads `library/*.toml` for instructions and generates `files.make`
+ fragments. These fragments arrange to run `./usvg-processor` which
+ launders SVGs through `usvg`. `usvg-processor`.
+
+ The shape libraries have a different, more relaxed, copyright
+ licence.
+
+* `webassembly-types`: A git-subtree of "WebAssembly Types".
+
+
+Automatic in-browser tests (`wdriver`)
+--------------------------------------
+
+* `apt install firefox`
+
+* `https://github.com/mozilla/geckodriver/releases/tag/v0.28.0`
+ download appropriate tarball, put "geckodriver" on PATH
+
+`make check` runs all the tests; `make wdt` runs only those tests. You can run
+an individual test with a rune like this:
+
+```
+ OTTER_TEST_LOG=otter_webdriver_tests=trace CARGO_MANIFEST_DIR=~ian/Rustup/Game/server time target/debug/wdriver --test=wdt-simple --geckodriver-args=
+```
+
+(This rune has some example logging options in it, for you to change
+if you like. You can omit the `CARGO_MANIFEST_DIR` for an in-tree
+non-privsep build.) After a test has run, you can find screenshots,
+etc. in `tmp/wdt-simple` or whatever. You can restart the same game
+server setup as the test used, with the state left by the test, with a
+rune like this:
+
+```
+ target/debug/daemon-otter tmp/wdt-simple/server-config.toml
+```
+and then play with it at this url:
+```
+ http://localhost:8000/?kmqAKPwK4TfReFjMor8MJhdRPBcwIBpe
+```
+
+
+Rust, cargo, curl|bash-ware; privsep
+------------------------------------
+
+If you are not the kind of person to worry about your software supply
+chains you can skp this part.
+
+If you follow the above instructions you will have downloaded and
+executed - and, therefore, trusted:
+
+ * Various Debian packages - safe
+ * Rustup (the Rust downloader/installer) - this is pretty safe
+ * Rust itself - again, pretty safe
+ * Otter itself - well, I wrote this; up to you.
+ * 450 transitive dependencies of otter (from crates.io)
+ * 50 transitive dependencies of bundle-sources
+ * the transitive dependencies of resvg
+ * a geckodriver binary directly from mozilla
+
+You will have trusted the integrity of the following:
+
+ * The Debian archive (via its apt keyring) (very good)
+ * Rustup's and Rust's TLS keyholders (good, I think)
+ * The HTTP TLS cabal (sigh)
+ * github (pretty good in practice)
+ * whatever mozilla do to make binaries, in particular geckodriver
+ * crates.io (extremely poor traceability)
+ * the project management of hundreds of random crates.io libraries
+
+If this makes you uncomfortable, as it should, you may wish to
+consider running everything in a separate shell account, or a VM or
+container of some kind.
+
+(I have a not-properly-released tool called "nailing-cargo" which
+makes it possible to do most things in my main account but run the
+Rust stuff in a separate less-privileged account. There is support
+for this in the Makefile. But if you want to run *everything* in the
+lesser account, you don't need to bother with that.)
+
+
+Dependencies - apologia
+-----------------------
+
+ * Rust Nightly
+
+ This is needed almost solely because Rocket needs it. Rocket is
+ the web framework I am using. The next version of Rocket (0.5.x),
+ which is in development, will not need Nightly, but it will also be
+ a serious compatibility break. The existing Rocket (0.4.x) will
+ almost certainly never be ported to Stable Rust. When Rocket 0.5.x
+ is out, porting Otter to it will go on my list - but it won't be
+ trivial. Sorry.
+
+ * The many dependencies of Otter
+
+ These are partly because Rocket is a large piece of software with
+ much functionality. But also because I favoured my own programming
+ convenience and in some cases was experimenting with different
+ approaches. In practice, it seems to me that once I'm using Rocket
+ and WASM and resvg and so on, there is not that much to be gained
+ by trying to prune the dependencies of the otter package itself.
+
+ * bundle-rust-sources
+
+ This is mine, but it needs to be properly released.
+
+ * geckodriver (for the automated in-browser tests)
+
+ This is done with a protocol called "WebDriver" which is a
+ cross-browser way to puppet a browser. There is a thing called
+ "geckodriver" which converts that to a firefox-specific protocol
+ for the same purpose, called "Marionette". (In practice all this
+ seems to have lots of bugs and misfeatures.)
+
+ AFAICT the usual approach for using geckodriver to have it *bind to
+ a fixed TCP port accessible to all local programs*. My wrapper
+ tooling arranges to run this in an ephemeral $HOME and a private
+ network namespace.
+
+ AFAICT the only practical way to get geckodriver is to download the
+ binary. I got mine here:
+ https://github.com/mozilla/geckodriver/releases/tag/v0.28.0 You
+ You just dump the binary on your PATH.
+
+
+Final weirdness
+---------------
+
+ * The `Makefile` `deploy` target is very specific to my setup.
+
+ * For running on chiark I build with the Rust target
+ `x86_64-unknown-linux-musl` which on my system is configured to
+ produce a completely statically linked bionary. I have this in my
+ `~/.cargo/config` (in the lesser privsep account):
+
+```
+[target.x86_64-unknown-linux-musl]
+rustflags = ["-C", "target-feature=+crt-static"]
+# ^ from https://stackoverflow.com/questions/31770604/how-to-generate-statically-linked-executables
+```
--- /dev/null
+OTTER - USER DOCUMENTATION
+==========================
+
+Basics; joining a game
+----------------------
+
+To join a game, you run a command like this on the server host:
+```
+ otter [--nick <nick>] join-game unix:ijackson::test
+ /^^^^^^^ ^^^^\
+ game owner game name
+```
+
+Tbis will print a URL. You cut and paste that URL into your browser.
+It is not usually necessary to expliitly leave a game, although
+a `leave-game` subcommand is available.
+
+You can have the same URL open in multiple browsers if you wish. The
+browser you use must support JavaScript and WebAssembly. Cookies are
+not used; anyone with your link can see your view of the game.
+
+Game UI
+-------
+
+The main Otter UI is fairly sparse and is dominated by the game table
+area. In that area are various elements such as cards, boards, chess
+pieces, or whatever.
+
+You can pick up and move those pieces about with the mouse. When you
+move an object (henceforth, a "piece"), everyone else will see it move
+too.
+
+Only one player at once may "grasp" a piece. If you and someone else
+both try to manipulate a piece at the same time, only one of your
+manipulations will take effect. For example, if you both try to pick
+up and drag a piece right at the same time, whichever of you got to it
+last will see the piece "jump" out of your grasp.
+
+But in general different players can manipulate separate pieces (eg,
+separate cards) concurrently.
+
+
+Keyboard commands and special functions
+---------------------------------------
+
+Otter makes use of keyboard commands for many functions. The UI will
+display a list of the currently-valid keyboard commands. Note that
+the set of valid command can depend on what you have selected, and
+what state it is in.
+
+
+Hidden information - secrets, card shuffling, etc.
+--------------------------------------------------
+
+Otter supports what is known in gaming terms as "hidden information".
+
+This is achieved by special "pieces" which are capable of hiding, or
+scrambling, other pieces. In Otter this is called "occultation".
+
+For example, a draw pile deck contains cards but maintains them
+shuffled and shows everyone only the backs of the cards. Each time
+anyone draws a card, it is chosen randomly from whatever cards are in
+that draw pile.
+
+There are also occulters which treat different players differently.
+For example, there are "hand repositories". When you have "claimed" a
+hand repository (with the keyboard command), it becomes "your hand".
+Any cards you put in it are identifable only by you. You see the
+fronts of the cards, and their precise positions (and orientations).
+The other players see only a simplified view, showing the backs of
+cards in predetermined locations. Another player can select a card
+from your hand, but their view of even which card is which is
+scrambled, so if they pick a card from your hand they get one selected
+at random.
+
+These special occulting pieces need to be activated before they do
+their thing. This is done by selecting the occulter, and issuing
+keyboard commands.
+
+
+UI features
+-----------
+
+The UI has a number of features intended to ease play of various
+games. It can be worth experimenting with the UI in a test game, to
+see how things work. The information presented by the game interfae
+itself is meant as prompts and hints rather than full documentation.
+
+Notable features you might otherwise overlook include these:
+
+Pressuing "h" repeatedly cycles through various amounts of history
+view (the overliad yellow arrows showing what recently happened).
+
+Typing numbers will get you into a multiple selection mode, which you
+can use (for example) to draw yourself a hand of multiple cards.
+
+Typing a zero will get you into a special selection mode for selecting
+the lowermost piece. This can useful to grasp a hand or pickup deck
+if it is covered in cards so you can't see it.
+
+Hands have an organise function, which lets you neaten the layout of
+the cards, or even sort them. Select the hand and look for the `o`
+and `O` keyboard commands.
+
+There is a Wresting mode for making exceptional changes to the game
+state, such as forcibly grasping a piece out of another player's
+grasp. Don't forget to exit Wresting mode when you're finished with
+it.
+
+
+Bugs and errors
+---------------
+
+Sometimes, bugs can cause things to mess up; in particular, you can
+see error messages on the screen in your browser. They typically
+appear at the top, and they say "reloading may help".
+
+If this happens, do try simply reloading the page in your browser.
+Typically this will improve matters. Hopefully the game state on the
+server side is not too badly affected.
+
+If you can reproduce a bug, please file a bug report;
+ https://salsa.debian.org/iwj/otter/-/issues/new
+
+Of course you might want to reload the Otter game page if you have
+trouble with your network or web browser. The state is all on the
+server, so you can reload when you want to.
+
+
+Game administration
+-------------------
+
+Creating and modifying games is done via the `otter` command line
+utility. See its `--help` message for full details.
+
+The most usual game-creation command looks something like this:
+
+```
+otter reset --reset-table local-users unix:ijackson::test demo
+ /^^^^^^^^^^^ /^^^^
+ `table spec game spec
+```
+
+Here `local-users` refers to the file `local-users.table.spec` in the
+Otter specs directory (`/volatile/Otter/specs` on chiark). The table
+spec file handles access control (and some other global properties)
+This particular file says that all local shell account users may join
+the game.
+
+`demo` refers to the file `demo.game.spec`. The "game spec" says what
+shape table is and what pieces there are. This is a simple demo game.
+
+Currently there are also `penultima` and `mao` game specs.
+
+After a game has finished and you wnat to play again, you can put
+everything back to the starting state (or, even, the starting state
+for a different game) with something like this:
+
+```
+otter reset unix:ijackson::test demo
+ /^^^^^^^^^^^^^^^^^^^ ^^^^\
+ game name game spec
+```
+
+The `otter` command line tool has further subcommands for
+adding/removing players, for ad-hoc addition of pieces from the
+library to an existing game, and so on.