zturn runs Infocom's Z-machine games behind an HTTP API. Every request plays one turn, every session is a replayable log of what you typed, and any client that can send a line of text can play.
Play in the browserThe Z-machine pauses whenever the game asks for a line of input. That pause is the turn boundary. A request delivers your line, the game runs until it asks again, and the response carries the text and the status line. No process waits between calls.
A session is its seed plus every line you have typed. The server can rebuild the game at any turn by replaying that log, which is how undo, transcripts and recovery after a restart all work without special code.
Everything random in the game, from the thief's wanderings to the fights, is drawn from a generator started with the session's seed. Same seed, same commands, same game. That is what makes a share link work.
# start a session curl -s ORIGIN/sessions \ -H 'content-type: application/json' \ -d '{"gameId":"zork1"}' # play a turn with the token it returned curl -s ORIGIN/sessions/SESSION_ID/turns \ -H 'authorization: Bearer TOKEN' \ -H 'content-type: application/json' \ -d '{"input":"open mailbox","expectedTurn":0}'
{
"turn": 1,
"out": {
"text": "Opening the small mailbox reveals a leaflet.",
"status": { "location": "West of House", "score": 0, "moves": 1 },
"awaiting": "line"
}
}
Pass expectedTurn to be told, with a 409, when someone else has played since you looked. Pass an idempotencyKey so a retried request returns the stored reply instead of playing again. The full reference is in the interactive docs.