From c8443c6f506add88056952ffc29fa5fd7102be2f Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Mon, 26 Oct 2026 18:30:55 -0400 Subject: [PATCH] Learn the pieces: fifteen scenes and a checkmate, each a small position with a move to make and a word on what came of it Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01CCLa2PaEeCj8njQZSWGqHx --- src/lib/components/Hall.svelte | 2 +- src/lib/components/LessonBoard.svelte | 95 +++++++++++ src/lib/game/index.ts | 2 +- src/lib/game/lessons.test.ts | 63 +++++++ src/lib/game/lessons.ts | 232 ++++++++++++++++++++++++++ src/routes/guide/+page.svelte | 1 + src/routes/learn/+page.svelte | 202 ++++++++++++++++++++++ 7 files changed, 595 insertions(+), 2 deletions(-) create mode 100644 src/lib/components/LessonBoard.svelte create mode 100644 src/lib/game/lessons.test.ts create mode 100644 src/lib/game/lessons.ts create mode 100644 src/routes/learn/+page.svelte diff --git a/src/lib/components/Hall.svelte b/src/lib/components/Hall.svelte index 068b436..26e4dd2 100644 --- a/src/lib/components/Hall.svelte +++ b/src/lib/components/Hall.svelte @@ -208,7 +208,7 @@

Wyrm

Chess on three boards, with a Dragon in the air above your King and a Basilisk in the earth below.

Gary Gygax's Dragonchess, from Dragon Magazine in 1985. Gold and Scarlet each lead 42 pieces across the air, the land and the underworld, and the game ends the way chess does, with a King that cannot escape. Play a drake here, free, or open a table and send a friend the link.

- + diff --git a/src/lib/components/LessonBoard.svelte b/src/lib/components/LessonBoard.svelte new file mode 100644 index 0000000..5cbb815 --- /dev/null +++ b/src/lib/components/LessonBoard.svelte @@ -0,0 +1,95 @@ + + +
+ +
+

{liveText}

+ + diff --git a/src/lib/game/index.ts b/src/lib/game/index.ts index 786cd9c..6ded756 100644 --- a/src/lib/game/index.ts +++ b/src/lib/game/index.ts @@ -9,7 +9,7 @@ import { type Cell, type Kind, type Side, type Setup, NAMES, LETTERS, cellOf, hasLegalMove, inCheck, kindOf, legalMovesFrom, levelOf, movesFrom, opening, other, playOn, sideOf, squareName } from './board'; -export { FILES, RANKS, LEVELS, PER_LEVEL, fileOf, rankOf, levelOf, idx, isLight, kindOf, sideOf, frozen, kingSquare, inCheck, other, square } from './board'; +export { FILES, RANKS, LEVELS, PER_LEVEL, fileOf, rankOf, levelOf, idx, isLight, kindOf, sideOf, frozen, kingSquare, inCheck, other, square, playOn } from './board'; import { chooseMove } from './bot'; import { narrate } from './chronicle'; diff --git a/src/lib/game/lessons.test.ts b/src/lib/game/lessons.test.ts new file mode 100644 index 0000000..adc401d --- /dev/null +++ b/src/lib/game/lessons.test.ts @@ -0,0 +1,63 @@ +import { describe, expect, it } from 'vitest'; +import { SCENES, sceneCells } from './lessons'; +import { frozen, hasLegalMove, inCheck, kindOf, legalMovesFrom, movesFrom, other, playOn, square } from './board'; + +describe('the lessons', () => { + it('every scene’s move is legal for the side to move, and only the asked-for moves count', () => { + for (const scene of SCENES) { + const cells = sceneCells(scene); + for (const [from, to] of scene.moves) { + const legal = legalMovesFrom(cells, square(from), 'printed'); + expect(legal, `${scene.id}: ${from} to ${to}`).toContain(square(to)); + } + // The piece asked for is the player's. + for (const [from] of scene.moves) expect(cells[square(from)][0], scene.id).toBe(scene.side === 'gold' ? 'g' : 's'); + // The scene draws every board its move touches. + for (const [from, to] of scene.moves) { + expect(scene.levels, scene.id).toContain(Number(from[0])); + expect(scene.levels, scene.id).toContain(Number(to[0])); + } + } + }); + + it('the scenes do what their words say', () => { + const at = (id: string) => SCENES.find((s) => s.id === id)!; + const play = (id: string) => { + const s = at(id); + const cells = sceneCells(s); + const [from, to] = s.moves[0]; + return { cells, after: playOn(cells, square(from), square(to)), s }; + }; + // The Warrior's step is blocked and its capture is not. + expect(movesFrom(sceneCells(at('warrior')), square('2c2')).map((i) => i)).toEqual([square('2d3')]); + // The Hero leaps the Warrior and takes the Mage. + expect(play('hero').after.captured).toBe('M'); + // The Mage comes down two boards onto the Basilisk. + expect(play('mage').after.captured).toBe('B'); + // The Paladin vaults over the Dwarf at 1c5. + expect(play('paladin').after.captured).toBe('D'); + // The Sylph's dive and the Dragon's strike take what they say. + expect(play('sylph').after.captured).toBe('O'); + const dragon = play('dragon'); + expect(dragon.after.afar).toBe(true); + expect(dragon.after.captured).toBe('M'); + expect(dragon.after.cells[square('3c4')]).toBe('gR'); + // The Basilisk's arrival freezes the Mage above. + const basilisk = play('basilisk'); + expect(frozen(basilisk.after.cells, square('2e4'))).toBe(true); + expect(movesFrom(basilisk.after.cells, square('2e4'))).toEqual([]); + // The Elemental climbs onto the Thief. + expect(play('elemental').after.captured).toBe('T'); + // The King is in check before it moves, and out of it after either move; up or down leaves it off the land. + const king = sceneCells(at('king')); + expect(inCheck(king, 'gold')).toBe(true); + expect(legalMovesFrom(king, square('2g1'), 'printed').map((i) => i).sort()).toEqual([square('1g1'), square('2f1'), square('2h1'), square('3g1')].sort()); + // The last scene is mate in one, and only that move mates. + const mate = play('mate'); + expect(inCheck(mate.after.cells, 'scarlet')).toBe(true); + expect(hasLegalMove(mate.after.cells, 'scarlet', 'printed')).toBe(false); + expect(kindOf(mate.cells[square('2d4')])).toBe('K'); + expect(frozen(mate.cells, square('2d4'))).toBe(true); + void other; + }); +}); diff --git a/src/lib/game/lessons.ts b/src/lib/game/lessons.ts new file mode 100644 index 0000000..89a03f1 --- /dev/null +++ b/src/lib/game/lessons.ts @@ -0,0 +1,232 @@ +// The lessons: one scene a piece, each a small position with something to +// see and a move to make. The page shows the boards the scene needs, says +// what to look at, takes the move from the player, and tells what came of +// it. Every scene's move is checked legal by a test, and every claim in +// the words is checked against board.ts there too. + +import { type Cell, type Side, CELLS, square } from './board'; + +export interface Scene { + id: string; + title: string; + /** The pieces, by square name. Kings are added at 2l1 and 2a8 where the scene gives none. */ + pieces: Record; + /** Whose move it is: the player's side. */ + side: Side; + /** The boards to draw, top first. */ + levels: number[]; + /** What to look at before moving. */ + before: string; + /** The move to make, in the player's words. */ + task: string; + /** The move itself, from and to; any of these counts. */ + moves: [string, string][]; + /** What came of it. */ + after: string; + /** Said when a legal move is made that is not the one to look at. */ + aside?: string; +} + +export const SCENES: Scene[] = [ + { + id: 'warrior', + title: 'The Warrior', + pieces: { '2c2': 'gW', '2d3': 'sW', '2c3': 'sU' }, + side: 'gold', + levels: [2], + before: 'Twelve of these stand in a wall at the start. A Warrior steps one square straight ahead, never two, and takes one square diagonally ahead, as a pawn does. The Unicorn at 2c3 blocks this one’s step, but the Warrior at 2d3 is on its diagonal.', + task: 'Take the Scarlet Warrior. Tap your Warrior at 2c2, then 2d3.', + moves: [['2c2', '2d3']], + after: 'The Warrior falls, and yours stands on the d file now. A Warrior that reaches the far rank stands up a Hero, with no choice about it, which is a real gain but not a queen. There is no double step and no capture in passing, because Gygax limited the Warrior to the old single step of shatranj, and so every advance is a commitment.', + aside: 'That is a legal move, but the Warrior at 2d3 is the one to take. Tap the board’s title to set the scene again.' + }, + { + id: 'oliphant', + title: 'The Oliphant', + pieces: { '2a1': 'gO', '2a6': 'sT', '2d1': 'gT' }, + side: 'gold', + levels: [2], + before: 'The war elephant is a rook by another name. It runs any distance along a rank or a file while the way is clear, and never leaves the land. The a file is open from your corner to the Thief at 2a6.', + task: 'Take the Thief. Tap the Oliphant at 2a1, then 2a6.', + moves: [['2a1', '2a6']], + after: 'On a board twelve squares wide an open file runs a long way, and the Oliphant is the piece that owns it. Remember what the sky can do, though: an Oliphant standing on the land beneath an enemy Dragon is as good as lost, because it cannot strike back upward.', + aside: 'A legal move, but the Thief at 2a6 is the one to take. Tap the board’s title to set the scene again.' + }, + { + id: 'unicorn', + title: 'The Unicorn', + pieces: { '2b1': 'gU', '2a2': 'gW', '2b2': 'gW', '2c2': 'gW', '2c3': 'sT' }, + side: 'gold', + levels: [2], + before: 'A knight, and the only piece of the land that leaps. Your Warriors wall it in, and the Unicorn does not care. It goes one square along a rank or file and one diagonally outward, over whatever is between.', + task: 'Leap the wall and take the Thief at 2c3. Tap the Unicorn, then 2c3.', + moves: [['2b1', '2c3']], + after: 'The Thief is gone and the wall never moved. Early in a game the Unicorns are the pieces to bring out first, for just this reason. Gygax rates them low, below a Basilisk, because a knight is slow on so wide a board, so trade one gladly for a Hero or a Thief.', + aside: 'A legal move, but the leap to 2c3 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'thief', + title: 'The Thief', + pieces: { '2d1': 'gT', '2h5': 'sO' }, + side: 'gold', + levels: [2], + before: 'The bishop of the land, quick along the diagonals. From 2d1 the diagonal runs e2, f3, g4 and on to the Oliphant at 2h5, with nothing in the way.', + task: 'Take the Oliphant. Tap the Thief, then 2h5.', + moves: [['2d1', '2h5']], + after: 'Five squares in one move, and a five-point piece for a four-point one. A Thief’s work is in the middle ranks, which is where the Dragon hunts from the air, so it is the piece most often lost to a strike from above. Two Thieves cover both colours of square.', + aside: 'A legal move, but the Oliphant at 2h5 is the one to take. Tap the board’s title to set the scene again.' + }, + { + id: 'hero', + title: 'The Hero', + pieces: { '2c1': 'gH', '2d2': 'gW', '2e3': 'sM' }, + side: 'gold', + levels: [2], + before: 'A champion who goes one or two squares along a diagonal and leaps the square between. Your own Warrior stands at 2d2, in the way of nothing. Beyond it, the Scarlet Mage.', + task: 'Leap over the Warrior and take the Mage at 2e3. Tap the Hero, then 2e3.', + moves: [['2c1', '2e3']], + after: 'The Mage, worth eleven, to a Hero worth four and a half. The Hero can also rise to the air or drop to the underworld, onto any of the four squares diagonally beside the square above or below it, and take a piece as it goes. Off the land its only move is back, so it goes up to kill and comes straight home.', + aside: 'A legal move, but the leap to 2e3 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'cleric', + title: 'The Cleric', + pieces: { '2e4': 'gC', '3e4': 'sS' }, + side: 'gold', + levels: [3, 2], + before: 'The one piece at home on every board. It moves one square in any direction wherever it stands, and it can step straight up or down to the board above or below. A Scarlet Sylph hovers directly over it.', + task: 'Step up into the air and take the Sylph. Tap the Cleric, then 3e4 on the upper board.', + moves: [['2e4', '3e4']], + after: 'The Cleric is in the air now and moves there exactly as it did on the land. Gygax says not to underestimate it. Of the five kinds of piece that can visit all three boards, it is the only one that plays the same on each, and he values it at nine, above the Dragon.', + aside: 'A legal move, but the step up to 3e4 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'mage', + title: 'The Mage', + pieces: { '3c4': 'gM', '1c4': 'sB' }, + side: 'gold', + levels: [3, 2, 1], + before: 'On the land the Mage is a queen. Here it is in the air, where it can only step one square along a rank or file, or move straight up or down. Straight down two boards is the underworld, and a Scarlet Basilisk sits there at 1c4. The land square between, 2c4, is empty, and it has to be: the Mage does not vault.', + task: 'Descend two boards and take the Basilisk. Tap the Mage, then 1c4 on the lowest board.', + moves: [['3c4', '1c4']], + after: 'The Basilisk is crushed and the Mage stands in the underworld, where it is a shadow of itself, one step at a time. Gygax warns against bringing the Mage out early, since lesser pieces develop by chasing it. Use its moves between boards to escape, and seldom to visit.', + aside: 'A legal move, but the drop to 1c4 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'paladin', + title: 'The Paladin', + pieces: { '2c4': 'gP', '1c6': 'sD', '1c5': 'sD' }, + side: 'gold', + levels: [2, 1], + before: 'On the land the Paladin has the king’s step and the knight’s leap together. Between boards it leaps the way a knight does, one board up or down and two squares along a rank or file, or two boards and one square, over anything in the way. Two Dwarves wait below.', + task: 'Vault down to the underworld and take the Dwarf at 1c6. Tap the Paladin, then 1c6.', + moves: [['2c4', '1c6']], + after: 'One board down and two squares forward, over the Dwarf at 1c5, which never had a say. In the underworld the Paladin keeps only the king’s step. Worth ten by Gygax’s count, it is the piece that can be on any board from any other in one move, and he counsels keeping it back until the lesser pieces are out.', + aside: 'A legal move, but the vault to 1c6 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'sylph', + title: 'The Sylph', + pieces: { '3e4': 'gS', '2e4': 'sO', '3e5': 'sW' }, + side: 'gold', + levels: [3, 2], + before: 'A pawn turned inside out. In the air the Sylph drifts one square diagonally forward and captures by stepping straight ahead, so the Warrior at 3e5 is in its sights. But look down: a Scarlet Oliphant stands on the land directly beneath it, and a Sylph can strike straight down.', + task: 'Dive and take the Oliphant on the land. Tap the Sylph, then 2e4 on the middle board.', + moves: [['3e4', '2e4']], + after: 'A one-point piece has taken a five-point one. Now the Sylph is grounded. On the land it cannot move at all except to rise again, to the square above it or to any empty square the Sylphs began on, and it takes nothing on the way up. Spend them this way and climb them home.', + aside: 'A legal move, but the dive onto the Oliphant at 2e4 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'griffon', + title: 'The Griffon', + pieces: { '3d4': 'gG', '2e5': 'sT', '3f7': 'sW' }, + side: 'gold', + levels: [3, 2], + before: 'Half eagle and half lion. In the air the Griffon leaps two squares one way and three the other, so the Warrior at 3f7 is one leap away. It can also swoop to the land, onto any of the four squares diagonally beside the square beneath it. The Thief at 2e5 is one of those four.', + task: 'Swoop down and take the Thief. Tap the Griffon, then 2e5 on the middle board.', + moves: [['3d4', '2e5']], + after: 'The Thief is gone, and the Griffon is on the land, where it has lost its wings and creeps one square diagonally until it climbs back. Drop to pick off a defender and climb before the land can gather. In the air it is worth a little more than a Hero, and nothing on the land sees its leap coming.', + aside: 'A legal move, but the swoop onto the Thief at 2e5 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'dragon', + title: 'The Dragon', + pieces: { '3c4': 'gR', '2d4': 'sM', '2c4': 'sW' }, + side: 'gold', + levels: [3, 2], + before: 'The wyrm never leaves the air. It slides the diagonals and steps one square in any direction, and it strikes from afar: without moving, it can take an enemy on the land directly beneath it or on any of the four squares beside that one. Beneath it at 2c4 stands a Warrior, and beside that, at 2d4, the Scarlet Mage.', + task: 'Strike the Mage from afar. Tap the Dragon, then 2d4 on the middle board.', + moves: [['3c4', '2d4']], + after: 'The Mage is lifted from the land and the Dragon has not moved. That strike was its whole move. Gygax set each Dragon directly over its King for this reason: a Dragon at home is a roof over the five squares beneath it, and a Dragon that flies off to hunt leaves its King under the other Dragon’s shadow.', + aside: 'A legal move, but the strike at the Mage on 2d4 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'dwarf', + title: 'The Dwarf', + pieces: { '1d4': 'gD', '2d4': 'sH', '1e5': 'sW' }, + side: 'gold', + levels: [2, 1], + before: 'A miner of the underworld. It walks one square forward or sideways without taking, and takes one square diagonally ahead, so the Warrior at 1e5 is in reach. It can also strike straight up at the land. A Scarlet Hero has stopped at 2d4, directly over it.', + task: 'Burst up and take the Hero. Tap the Dwarf, then 2d4 on the middle board.', + moves: [['1d4', '2d4']], + after: 'A Dwarf is a mine beneath the land, and a piece that settles above one is taken. On the land it keeps the same moves, and it comes back down only onto an empty square beneath it. Gygax says the Dwarves play little part early, and make the best outposts late, if you have not hurried them forward.', + aside: 'A legal move, but the strike up at the Hero on 2d4 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'basilisk', + title: 'The Basilisk', + pieces: { '1e3': 'gB', '2e4': 'sM', '2h7': 'sK' }, + side: 'gold', + levels: [2, 1], + before: 'The serpent whose gaze turns to stone. A Basilisk moves one square forward or diagonally forward, taking what is there, or one square straight back, and never leaves the underworld. Whatever enemy stands on the land directly above it cannot move, take or threaten anything. The Scarlet Mage stands at 2e4. The square beneath it, 1e4, is one step ahead of your Basilisk.', + task: 'Slither under the Mage. Tap the Basilisk, then 1e4.', + moves: [['1e3', '1e4']], + after: 'The Mage is frozen where it stands, and will be until the Basilisk moves or is taken. Gygax says an immobilised piece can be treated as if it did not exist, except that it still blocks its square. His own trick runs the other way too: stand a piece of yours over your own Basilisk, and whatever takes it is frozen on the spot for you to take at your leisure.', + aside: 'A legal move, but 1e4, beneath the Mage, is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'elemental', + title: 'The Elemental', + pieces: { '1d4': 'gE', '2e4': 'sT', '1d6': 'sD' }, + side: 'gold', + levels: [2, 1], + before: 'The one heavy thing in the underworld. It moves one or two squares along a rank or file and takes the same way, so the Dwarf at 1d6 is in reach. It climbs to the land only to capture, one square along a rank or file onto an empty square and then straight up onto an enemy. The square beside it at 1e4 is empty, and above that stands a Thief.', + task: 'Heave up and take the Thief. Tap the Elemental, then 2e4 on the middle board.', + moves: [['1d4', '2e4']], + after: 'The Thief is shattered and the Elemental stands on the land, where it is a rock. Its only move there is back down, straight through an empty square and then one square along a rank or file. Plan its climb: an empty square beside it and an enemy above that square, and nothing else will do.', + aside: 'A legal move, but the climb onto the Thief at 2e4 is the one to see. Tap the board’s title to set the scene again.' + }, + { + id: 'king', + title: 'The King', + pieces: { '2g1': 'gK', '2g8': 'sO', '2f2': 'gW', '2h2': 'gW' }, + side: 'gold', + levels: [3, 2, 1], + before: 'The whole game. The King moves one square in any direction on the land, and one step straight up or down between boards. Here it is in check: the Scarlet Oliphant looks down the open g file. Nothing of yours can take the Oliphant or step into the file, so the King must move. Two squares on the land are safe, and it could also climb into the air or dig into the underworld.', + task: 'Step out of check along the rank. Tap the King, then 2f1 or 2h1.', + moves: [['2g1', '2f1'], ['2g1', '2h1']], + after: 'Safe, and still on the land. The King could have climbed or dug instead, but off the land a King can do nothing except come straight back, and Gygax calls it a sitting duck there. Keep two more things in mind at the table: the square beneath your King, where an enemy Basilisk would freeze it, and your Dragon above it, which is its roof.', + aside: 'That is out of check, but off the land the King can only come back. Set the scene again and stay on the land.' + }, + { + id: 'mate', + title: 'Checkmate', + pieces: { '2d4': 'sK', '1d4': 'gB', '2a1': 'gO', '2g1': 'gK' }, + side: 'gold', + levels: [2, 1], + before: 'Your Basilisk sits beneath the Scarlet King at 2d4, so the King is frozen: it cannot step out of anything. Gygax wrote that a frozen King is checkmated by any attack it cannot capture or block. Your Oliphant stands on the a file with the fourth rank empty between it and the King.', + task: 'Give checkmate. Tap the Oliphant, then 2a4.', + moves: [['2a1', '2a4']], + after: 'Checkmate. The King is attacked along the rank, it cannot move, nothing of Scarlet’s can take the Oliphant, and nothing can step between. That is the Basilisk’s other gift: a well-timed move beneath a King, or beneath the piece that guards it, ends a game.', + aside: 'A legal move, but the Oliphant to 2a4 is the mate. Tap the board’s title to set the scene again.' + } +]; + +/** The scene's position as cells, Kings supplied where the scene gives none. */ +export function sceneCells(scene: Scene): Cell[] { + const cells: Cell[] = new Array(CELLS).fill(''); + for (const [name, cell] of Object.entries(scene.pieces)) cells[square(name)] = cell; + if (!cells.includes('gK')) cells[square('2l1')] = 'gK'; + if (!cells.includes('sK')) cells[square('2a8')] = 'sK'; + return cells; +} diff --git a/src/routes/guide/+page.svelte b/src/routes/guide/+page.svelte index a2d5473..ddf95dc 100644 --- a/src/routes/guide/+page.svelte +++ b/src/routes/guide/+page.svelte @@ -65,6 +65,7 @@

A first game

+

Before that, learn the pieces: fifteen short scenes, one a piece, each a small position with a move for you to make and a word on what came of it.

Play a drake first. It plays a fair game and never minds how long you take. Begin as you would at chess, with Warriors stepping forward and the knights of the land, the Unicorns and Heroes, coming out behind them. Gygax's own advice is to hold the Mage and the Paladin back until the lesser pieces are developed, and to keep your Dragon home. It starts directly above your King for a reason. A Dragon that flies off to raid leaves the King open to the other Dragon, which strikes the land from the air without ever coming down.

Watch the Basilisks. Anything you leave on the land directly above an enemy Basilisk is frozen on the spot, and a frozen piece may as well be off the board. The Cleric is stronger than it looks, since it is the only piece that plays the same on all three boards, and the Dwarves, if you do not hurry them forward, make good guards late in the game.

The full rules, piece by piece, are on the rules page, with Gygax's article beneath them. If a rule here reads wrong to you, or something misbehaves, send word, or use Report in the masthead at the table, which pins what you saw to the move it happened on. The hall's about this game lists the other ways to reach the keeper.

diff --git a/src/routes/learn/+page.svelte b/src/routes/learn/+page.svelte new file mode 100644 index 0000000..aeccf77 --- /dev/null +++ b/src/routes/learn/+page.svelte @@ -0,0 +1,202 @@ + + + + Wyrm: learn the pieces + + +
+
+ {#if room}Back to your game{' · '}{/if}Back to the hall · How to play · The rules +

Learn the pieces

+

Fifteen pieces, one scene each, and a checkmate to finish. Every scene is a small position with something to see and one move to make. Tap any piece to read about it, as at the table.

+
+ + + +
+
+ (inspected = at)} /> +
+
+

Scene {n + 1} of {SCENES.length}

+

{scene.title}

+

{scene.before}

+ {#if outcome} +

{outcome.told}

+

{outcome.text}

+
+ + {#if n < SCENES.length - 1}{:else}Back to the hall{/if} +
+ {:else} +

{scene.task}

+
+ {#if n > 0}{/if} + {#if n < SCENES.length - 1}{/if} +
+ {/if} + {#if inspected !== null && cells[inspected] !== ''} +
+ (inspected = null)} /> +
+ {/if} +
+
+
+ +