Bigger moves

Summarize#

Summarize (at the bottom) asks the model to write a summary of the whole game: every important event, who knows what, where things stand and what's still open.

The summary becomes the backstory of a new game right below, called "… (continued)", without any turns yet. It opens so you can check and correct it. Then click Back to game and play on. The original game stays as it was.

This is the way to continue a game that has become too long; see Continue a long game.

Download#

Download (at the bottom, with the little download arrow) saves the current game as a script that reads like a stage play: the world's name and story, the cast and places, then the play itself, in scenes, with stage directions, dialogue under each speaker's name, asides, and entrances and exits.

A new scene begins wherever the place changes: each time you move the scene to another place (see Places), the script starts a new, numbered scene with that place and its description as a stage direction.

The file lands in your Downloads folder. It's a plain text file (Markdown) that opens in any text editor.

Right after it, a second file with the same name but ending in .json is saved: the same game as data, for programs and AI tools. See The play as JSON.

To save a whole world (to keep it, move it or load it again), use Export legacy instead: see Import and export.

The play as JSON#

Download saves, next to the script, a file with the same name ending in .json, for example Harbour - First game.json. It holds the same game as data: every turn, who was on stage, who acted in which order and what each one did, said or said aside, what you said and did, the events, the audience's remarks, the places and scenes, the impulses and the patches. With it, a program — or an AI assistant — can rebuild the play in any form it likes.

Use it to have an AI write things for you, for example:

  • a version of the play typeset with LaTeX, or in a screenplay format;
  • a small program that turns your games into an e-book, subtitles or a website;
  • statistics: who talks most, how often the scene moves, and so on.

How: give the AI the JSON file and the description below. Click Copy at the top right of the box, paste it into your conversation with the AI, attach the JSON file (or paste its contents), and say what you want. The description is written for software engineers and AI models, so you don't need to read it yourself.

ACOPA-PLAY JSON, formatVersion 1  —  specification for software engineers and LLMs

PURPOSE
One game (one playthrough) of an interactive play from the app Acopa (Roller mode), exported as a
single UTF-8 JSON file. A human plays one character ("the user"); a language model plays up to
three other characters on stage at a time; an audience watches from beyond the fourth wall and may
call out. The file contains everything needed to reconstruct the play as written, in any format.
It is written next to a Markdown script of the same game (same base name, ".md").
Read-only export: it is not imported back. Unknown fields may appear in later versions: ignore
them. A change that breaks this description bumps formatVersion.

CONVENTIONS
- Every text field is a string ("" when empty), never null, unless stated "or null".
- Text may contain line breaks ("\n"). Blank lines separate paragraphs.
- Timestamps are ISO 8601 UTC strings, or null when unknown.
- Characters are identified by a letter id "A"…"F". The human's character has id "user", the
  audience "audience". Use "name" for display, the id for logic (names can be changed).
- Places are identified by "p1", "p2" … (list order). A place that was deleted after a turn named
  it gets "gone1", "gone2" … and appears in "places" with "deleted": true.
- Inside "says" (user and characters), text in parentheses is a stage direction about the speaking,
  not spoken words: whom it is addressed to "(to Mara)", how "(quietly)", who can hear it
  "(whispering to Tom)". Only the words outside parentheses are spoken.
- "does" is a visible action, present tense, third person (the user's may start in lower case as
  a predicate: "lights a pipe" = "<user name> lights a pipe").
- "aside" is spoken to the audience only; nobody on stage hears it.

TOP LEVEL
{
  "format": "acopa-play",            constant
  "formatVersion": 1,
  "about": string,                   human-readable pointer to this documentation
  "app": { "id", "name", "version" },  the writing app
  "exportedAt": timestamp,
  "files": { "script": "<base>.md", "json": "<base>.json" },
  "world": { "name", "author", "background" },
        author: by-line of the world's creator ("" if none).
        background: the creator's private notes; never part of the play or sent to the model.
  "story": string,                   the setting, situation, tone and style of the world (Markdown-ish prose)
  "cast": [ CastMember … ],          always 8 entries: A, B, C, D, E, F, user, audience
  "places": [ Place … ],
  "game": Game,
  "prompts": { "protocol": Prompt, "patcher": Prompt },
  "scenes": [ Scene … ],
  "turns": [ Turn … ]                in play order
}

CastMember
{ "id": "A"…"F" | "user" | "audience",
  "role": "character" | "user" | "audience",
  "name": string,                    display name (a default like "Character A" if never renamed)
  "isDefaultName": boolean,
  "description": string,             who they are: background, personality, voice, goals
  "onStageNow": boolean,             characters only: on stage at the time of export
  "inPlay": boolean }                characters only: described, renamed, on stage, or on stage in
                                     any turn. Characters with inPlay false never took part:
                                     usually leave them out of a dramatis personae.

Place
{ "id": "p1" | "gone1" …, "name": string, "description": string or null,
  "activeNow": boolean,              where the next turn would play
  "deleted": true }                  only for places deleted since (description is then null)

Game
{ "name": string,
  "created": timestamp,
  "backstory": string or null,       what went before this game (prepended context; may be a
                                     summary of an earlier game)
  "turnCount": number, "sceneCount": number,
  "unsent": { "says", "does", "events", "audience" } or null }
                                     text the user had typed but not yet sent

Prompt  (the instructions the model played with; shared by all worlds of the user)
{ "text": string, "isDefault": boolean }
        protocol: the system prompt for playing turns. Placeholders like {{STORY}}, {{CAST}},
        {{A.name}} are filled in by the app before sending.
        patcher: the system prompt of the "Patch" function (rewrites a finished turn).

Scene  (a new scene starts at turn 1 and whenever a turn plays at a different place than the
        previous scene; a turn without a place continues the current scene)
{ "n": number (1-based), "place": place id or null, "placeName": string or null,
  "firstTurn": number, "lastTurn": number }   turn numbers "n", inclusive

Turn
{ "n": number,                       1-based position in the game
  "scene": number,                   the Scene it belongs to
  "created": timestamp,
  "place": place id or null, "placeName": string or null,   where this turn plays (null: nowhere
                                     in particular, i.e. unchanged)
  "sceneStart": boolean,             this turn opens a new scene
  "setting": string or null,         on a sceneStart with a place: the place's description (as a
                                     stage direction at the head of the scene)
  "onStage": ["A", …],               the characters present this turn (at most 3); only they act
  "entered": [ids], "exited": [ids], compared with the previous turn ([] on turn 1)
  "user": { "name": string,
            "says": string,          the user's spoken words (see the parenthesis convention)
            "does": string,          the user's visible action
            "passing": boolean,      the user sat this turn out ("stepped into the shade"): unseen,
                                     unheard; says and does are then ""
            "stepsIntoShade": boolean,   first turn of a run of passing turns
            "stepsOutOfShade": boolean },  first turn after such a run
  "events": string,                  something that happens this turn that nobody controls
                                     (a noise, the weather …); after the user's action
  "audience": string,                a remark called out by the audience (unheard on stage)
  "impulses": [ { "who": id, "name": string, "thought": string, "rule": string or null } ],
                                     a sudden urge the app gave a character this turn (it shows in
                                     what they do or say); rule = the name of the rule that fired
  "characters": [ CharacterTurn … ], one per character in onStage, IN ACTING ORDER
  "patched": boolean,                the turn was rewritten by the Patch function
  "beforePatch": [ CharacterTurn … ],  only when patched: the entries before patching
  "patchNotes": object }             only when patched: the patcher's notes (free-form; typically
                                     wants, verdicts, unnoticed, hunches) — display only
  The text is as the user last edited it: any part of a turn may have been corrected by hand.

CharacterTurn
{ "who": id, "name": string,
  "order": number,                   1 = acted first this turn; later ones may react to earlier ones
  "does": string, "says": string, "aside": string,
  "silent": boolean }                true when does, says and aside are all ""

READING ORDER OF A TURN (how the app's own script renders it)
1. If sceneStart: a scene heading (scene n, placeName) and, if present, the setting.
   (On turn 1 this comes first; on later turns it comes after step 4, i.e. the scene moves after
   the user's action and the events.)
2. exited characters leave; entered characters enter (stage directions).
3. stepsIntoShade / stepsOutOfShade as a stage direction; then user.does (action), then
   user.says (dialogue under the user's name).
4. events (a stage direction), then the audience remark.
5. characters in order: for each, does (stage direction), says (dialogue under the name),
   aside (dialogue marked "aside, to the audience"). Skip empty fields; silent characters say
   nothing.

EXAMPLE (abridged)
{"format":"acopa-play","formatVersion":1,"world":{"name":"Harbour","author":"","background":""},
 "story":"A foggy harbour town, 1920s.",
 "cast":[{"id":"A","role":"character","name":"Mara","isDefaultName":false,
          "description":"The harbour master.","onStageNow":true,"inPlay":true}, …],
 "places":[{"id":"p1","name":"The quay","description":"Wet planks, gulls.","activeNow":true}],
 "scenes":[{"n":1,"place":"p1","placeName":"The quay","firstTurn":1,"lastTurn":1}],
 "turns":[{"n":1,"scene":1,"place":"p1","placeName":"The quay","sceneStart":true,
   "setting":"Wet planks, gulls.","onStage":["A","B"],"entered":[],"exited":[],
   "user":{"name":"User","says":"(to Mara) Any ships today?","does":"lights a pipe",
           "passing":false,"stepsIntoShade":false,"stepsOutOfShade":false},
   "events":"A foghorn sounds.","audience":"","impulses":[],
   "characters":[{"who":"B","name":"Character B","order":1,"does":"shrugs","says":"None.",
                  "aside":"He lies.","silent":false},
                 {"who":"A","name":"Mara","order":2,"does":"","says":"Only one.","aside":"",
                  "silent":false}],
   "patched":false}]}