Как написать текстовую игру на Ficdown

Ficdown — это набор стандартов на основе языка разметки Markdown, который можно использовать для создания интерактивной литературы в гипертекстовом стиле или на основе выбора (choice-based). Форматирование текста выполняется с использованием обычного Markdown и с сохранением возможности внедрения HTML и CSS для прочего оформления, при этом несколько элементов разметки приобретают дополнительные свойства, определяющие историю. Разработчик Ficdown, Рудис Муизниекс, объясняет концепцию своей системы следующим образом:

«Существует множество систем для создания интерактивной литературы на основе выбора. Многие из этих систем подразумевают изучение нового языка скриптов и требуют использования специализированных сред разработки (онлайн или установленных на вашем компьютере). Большинство из них производят игры, для которых требуется JavaScript и в которые можно играть только в веб-браузере. Я создал Ficdown по трём причинам:

  1. Я хочу писать интерактивную литературу в текстовом редакторе по своему выбору.
  2. Я хочу, чтобы мою интерактивную литературу можно было воспроизводить на таких устройствах, как мой Kindle без Javascript или подключения к Интернету.

  3. Я хочу использовать Markdown вместо изучения нового языка скриптов.

Используя Ficdown, вы можете сосредоточиться на сочинительстве. Ficdown использует только существующий синтаксис Markdown для определения всего в вашей истории, поэтому вы можете писать в любом редакторе, в котором хотите, и вам не нужно изучать новый язык скриптов. И хотя истории Ficdown можно воспроизводить в интерактивном режиме в веб-браузере, их также можно преобразовать в стандартные форматы электронных книг или статический HTML для автономного воспроизведения.»

Если вам близки данные идеи, то из этой статьи вы сможете узнать, как писать собственные интерактивные истории на Ficdown, в том числе с учётом специфики русского языка.

Технологии и инструменты

Существует несколько инструментов для создания игр на Ficdown, среди которых:

  • Ficdown.js — веб-интерпретатор на JavaScript, позволяющий собрать интерактивную версию истории Ficdown.
  • ficdown.exe — консольная утилита для конвертации файлов историй Ficdown в статичные HTML-страницы или электронные книги формата ePub. Работает на системах Windows, macOS и Linux.
  • Online Epub Compiler — веб-приложение, позволяющее выполнить конвертацию файлов историй Ficdown в электронную книгу формата ePub.
  • Playground — веб-приложение, позволяющее прямо в браузере вставить текст истории Ficdown и посмотреть, как она будет работать в Ficdown.js.
  • Ficdown Editor — онлайн-редактор для более удобного написания историй Ficdown, правда с испанским интерфейсом.

В процессе знакомства с Ficdown можно пробовать различные примеры прямо в Playground, а когда вы решите, что эта система вам подходит, перейти на использование более серьёзных инструментов, главным образом, Ficdown.js или ficdown.exe. Впрочем, писать на Ficdown также удобно, сразу собрав шаблон игры на основе Ficdown.js, а потом открыть его параллельно в текстовом редакторе и в браузере, одновременно редактируя текст и проверяя результат.

Скомпилировав интерактивную историю через ficdown.exe, её можно сконвертировать в ещё какой-нибудь формат, если он больше соответствует вашим запросам. Сделать это можно, например, при помощи Calibre.

Написание истории Ficdown

Существует формальное описание синтаксиса Ficdown, в котором подробно описаны все правила обработки Markdown. Однако для первого знакомства лучше всего воспользоваться пошаговым руководством с описанием создания игры Cloak of Darkness («Плащ тьмы»). Именно его мы и разберём, сделав некоторые дополнения.

Определяем историю
Все истории Ficdown начинаются с заголовка первого уровня, содержащего название истории, после чего следует дополнительный вводный текст. Автор может использовать вводный текст для любых целей, но обычно там удобно указывать метаданные истории, такие как имя автора, версию истории, посвящение и т.п. Текст может содержать любое форматирование, кроме заголовков первого и второго уровня.


# Плащ тьмы

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.1*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

Пока это неработоспособный файл истории, так как в нём ещё нет сцен, поэтому при попытке его воспроизведения или конвертации будет возникать ошибка.

Определяем сцены
Сцены определяются заголовками второго уровня. Добавим несколько сцен в нашу историю:


# Плащ тьмы

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.2*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

## Foyer

Вы стоите в просторном холле, пышно убранном в красных и золотых тонах, со сверкающими над головой люстрами. На севере вход с улицы, а также есть двери на юге и западе.

## Cloakroom

На стенах этой небольшой комнаты, очевидно, когда-то было множество крючков, но сейчас остался только один. Единственный выход — это дверь на востоке.

## Bar

Вы входите в буфет, но здесь так темно, что ничего не получается разглядеть. Обратный путь в фойе на севере.

Теперь мы определили три сцены в истории (фойе, гардероб и буфет). Это всё ещё неработоспособная история, так как нет никаких указаний на то, какая сцена является первой. Да и в это невозможно было бы играть в любом случае, поскольку никакие сцены ещё не связаны друг с другом.

Вы также наверняка заметили, что названия сцен написаны по-английски. В следующем разделе будет дано объяснение этой особенности. Ну а позже мы научимся выводить в описании сцены альтернативное название, в котором можно будет использовать любые символы.

Связываем сцены
Технически, единственная обязательная ссылка в файле истории — это ссылка из заглавия истории на её первую сцену. Если вы на этом и остановитесь, ваша история будет довольно короткой: игроку будет представлен титульный лист и вводный текст, он кликнет, чтобы перейти к первой сцене, и игра будет закончена. Мы можем сделать всё немного интереснее, добавив в наши сцены ссылки, которые при клике переводят игрока на другие сцены.

Ссылки на сцены указываются при помощи стандартного синтаксиса якорей (перекрёстных ссылок) Markdown. Меткой цели якоря должно быть имя сцены в нижнем регистре, из которого удалены все символы, кроме цифр и 26 латинских букв, а пробелы заменены на ASCII дефисы, причём, название должно начинаться с буквы. Например, на сцену под названием «Ben's Room» надо ссылаться по метке «bens-room».

Соответственно любые буквы не из набора ASCII, в том числе кириллица или латинская диакритика, при нормализации имён сцен будут удаляться, например, на сцену с названием «Синтаксис Ficdown» надо будет ссылаться по метке «ficdown», так как будет отброшена вся кириллица, а также образовавшийся пробел в одном из концов строки. Именно поэтому, желательно давать сценам названия только на базовой латинице с пробелами между словами, чтобы меньше задумываться над внутренними преобразованиями этих имён при нормализации.


# [Плащ тьмы](/foyer)

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.3*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

## Foyer

Вы стоите в просторном холле, пышно убранном в красных и золотых тонах, со сверкающими над головой люстрами. На севере вход с улицы, а также есть двери на [юге](/bar) и [западе](/cloakroom).

## Cloakroom

На стенах этой небольшой комнаты, очевидно, когда-то было множество крючков, но сейчас остался только один. Единственный выход — это дверь на [востоке](/foyer).

## Bar

Вы входите в буфет, но здесь так темно, что ничего не получается разглядеть. Обратный путь в фойе на [севере](/foyer).

Теперь это работоспособный файл, и его уже можно запустить в средствах воспроизведения игр Ficdown. Впрочем, вы, вероятно, заметите, что это не очень интересная игра, поскольку она позволяет игроку перемещаться между тремя заданными сценами и никогда не заканчивается.

Впервые увиденные описания
Любой текст, помещённый в цитату (строки, перед которыми стоит символ больше «>»), будет отображаться только при первом посещении этой сцены читателем. Это простой способ повторно использовать сцены без необходимости каждый раз воспроизводить один и тот же текст внутри этой сцены.


# [Плащ тьмы](/foyer)

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.4*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

## Foyer

> Вы быстро закрываете за собой дверь и стряхиваете воду с плаща. Это красивый плащ из бархата с атласной отделкой и слегка забрызганный каплями дождя. Его чёрный цвет настолько глубок, что кажется, будто он поглощает свет в комнате.

Вы стоите в просторном холле, пышно убранном в красных и золотых тонах, со сверкающими над головой люстрами. На севере вход с улицы, а также есть двери на [юге](/bar) и [западе](/cloakroom).

## Cloakroom

На стенах этой небольшой комнаты, очевидно, когда-то было множество крючков, но сейчас остался только один. Единственный выход — это дверь на [востоке](/foyer).

## Bar

Вы входите в буфет, но здесь так темно, что ничего не получается разглядеть. Обратный путь в фойе на [севере](/foyer).

Если вы воспроизведёте этот пример, то увидите, что описание плаща отображается только при первом входе в фойе.

Отслеживание состояния
Состояние в игре Ficdown представляет собой список логических (булевых) переменных, каждая из которых изначально имеет значение false. Переменные состояния могут быть переключены на true через специальные ссылки вида [кликните здесь](#my-variable). В этом примере, когда игрок нажимает на ссылку, вызываемая переменная с названием my-variable будет переключена на true. Нет необходимости где-либо объявлять переменные перед их использованием в якорях. Вы можете сделать связь со сценой и переключатель переменной состояния одновременно, указав и цель, и переключатель в одном и том же якоре, например, клик по ссылке [Идти на север](/north#went-north) переместит игрока на сцену north и переключит переменную состояния went-north на true.

Вы можете указать несколько переключателей в одном якоре, разделив их знаком плюс «+», например, [Переключение двух переменных](#variable-one+variable-two). После того, как переменная состояния была переключена на true, она не может быть переключена обратно на false, так что останется включённой на true до конца игры.

Теперь, когда вы знаете, как переключать переменные состояния в своей игре, вы можете изменять описания сцен в зависимости от текущего состояния игрока. Это позволяет вам представлять или разветвлять свою игру по-разному в зависимости от выбора, сделанного игроком в любой предшествовавший момент.

Ну и вероятно вы уже сами догадались, что имена переменных подчиняются тем же правилам, что и метки якорей, то есть должны состоять из 26 строчных латинских букв, цифр и знаков дефиса, а также начинаться с буквы.

Условия указываются в якоре с вопросительным знаком «?», где несколько переменных разделяются знаком амперсанда «&». Например, конструкция [Текст якоря](?state-one&state-two) будет показывать игроку текст якоря, только если переменные state-one и state-two уже были переключены на true в истории ранее. Вы также можете проверить, не была ли ещё изменена переменная состояния, добавив восклицательный знак «!» к её имени. Если вы хотите отобразить текст якоря на экране только тогда, когда state-one равна true, а state-two равна false, то это будет выглядеть как [Текст якоря](?state-one&!state-two). Во всех этих примерах, поскольку целевая сцена или переключатели не указываются в якоре, выводимая конструкция в тексте не будет кликабельной ссылкой — просто обычный текст.

При помощи символа вертикальной черты «|» в тексте якоря можно указать альтернативный текст, который будет отображён, если условие не выполняется. Например, [my-state равна true|my-state равна false](?my-state). Строка текста якоря с любой стороны от вертикальной черты может быть пустой, чтобы полностью удалить якорь, когда условия этому соответствуют. Например, следующие якоря эквивалентны друг другу: [У вас есть ключ](?got-key) и [|У вас есть ключ](?!got-key).

Вы можете комбинировать переключатели и условия в одном и том же якоре, даже используя одну и ту же переменную для обоих. Например, якорь [Снова нажать на кнопку.|Нажать на кнопку.](?pushed-button#pushed-button) покажет игроку ссылку «Нажать на кнопку». Как только он нажмёт на неё, переменная состояния pushed-button будет переключена на true, и сцена перезагрузится, но текст ссылки изменится на «Снова нажать на кнопку». Вы также можете указать целевую сцену для ссылки, если хотите перевести игрока в другое место, вместо того, чтобы просто перезагрузить текущую сцену.

При необходимости, вы можете делать вложенные конструкции, например, [[Активная ссылка](/link)|Простой текст](?active).

Якоря могут иметь не более одной цели, но столько условий и переключателей, сколько вам нужно. Примером особенно сложного якоря будет [Комплексный якорь](/new-scene?state-one&state-two&!state-three#state-three+state-four).

Давайте посмотрим, как переменные состояния и условия могут добавить больше интерактивности в наш пример игры:


# [Плащ тьмы](/foyer)

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.5*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

## Foyer

> Вы быстро закрываете за собой дверь и стряхиваете воду с плаща. Это красивый плащ из бархата с атласной отделкой и слегка забрызганный каплями дождя. Его чёрный цвет настолько глубок, что кажется, будто он поглощает свет в комнате.

Вы стоите в просторном холле, пышно убранном в красных и золотых тонах, со сверкающими над головой люстрами. На севере вход с улицы, а также есть двери на [юге](/bar) и [западе](/cloakroom).

## Cloakroom

На стенах этой небольшой комнаты, очевидно, когда-то было множество крючков, но сейчас остался только один. Единственный выход — это дверь на [востоке](/foyer).

[Здесь на полу ваш плащ.](?dropped-cloak)
[На крючке висит ваш плащ.](?hung-cloak)

- [Осмотреть крючок.](#examined-hook)
- [Повесить ваш плащ на крючок.](?!lost-cloak#lost-cloak+hung-cloak)
- [Бросить ваш плащ на пол.](?!lost-cloak#lost-cloak+dropped-cloak)

## Bar

Вы входите в буфет, но здесь так темно, что ничего не получается разглядеть. Обратный путь в фойе на [севере](/foyer).

Если вы воспроизведёте этот пример, то увидите, что теперь можно либо повесить плащ на крючок, либо бросить его на пол гардероба, и описание сцены будет меняться в зависимости от того, какой выбор вы сделаете. Есть ещё один вариант в гардеробе, чтобы осмотреть крючок, который в настоящее время ничего не делает.

Действия
Порой вам может понадобиться предоставить игроку обратную связь, когда он переключил определённую переменную, и сделать это без создания совершенно новой сцены. Например, мы хотим показать игроку описание крючка в гардеробе, когда он его осматривает. Это, конечно, было бы возможно с дополнительной сценой (в основном, копией текущей сцены гардероба с добавленным описанием крючка), но это означало бы наличие повсюду дублирующих сцен, что представляется не очень изящным решением. Игра с множеством комнат, в которых можно найти осматриваемые предметы, быстро превратилась бы в настоящий кошмар.

Решением этой проблемы в Ficdown являются действия, которые определяются заголовком третьего уровня. Всякий раз, когда переключается переменная, для которой определён соответствующий блок действия, текст действия будет добавлен перед следующей сценой (даже если это та же самая сцена, из которой вы переключили состояние). Мы можем использовать действие, чтобы подключить ссылку «Осмотреть крючок» в нашем примере, например:


# [Плащ тьмы](/foyer)

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.6*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

## Foyer

> Вы быстро закрываете за собой дверь и стряхиваете воду с плаща. Это красивый плащ из бархата с атласной отделкой и слегка забрызганный каплями дождя. Его чёрный цвет настолько глубок, что кажется, будто он поглощает свет в комнате.

Вы стоите в просторном холле, пышно убранном в красных и золотых тонах, со сверкающими над головой люстрами. На севере вход с улицы, а также есть двери на [юге](/bar) и [западе](/cloakroom).

## Cloakroom

На стенах этой небольшой комнаты, очевидно, когда-то было множество крючков, но сейчас остался только один. Единственный выход — это дверь на [востоке](/foyer).

[Здесь на полу ваш плащ.](?dropped-cloak)
[На крючке висит ваш плащ.](?hung-cloak)

- [Осмотреть крючок.](#examined-hook)
- [Повесить ваш плащ на крючок.](?!lost-cloak#lost-cloak+hung-cloak)
- [Бросить ваш плащ на пол.](?!lost-cloak#lost-cloak+dropped-cloak)

### Examined Hook

Это просто маленький латунный крючок[ с висящим на нём плащом|, привинченный к стене](?hung-cloak).

## Bar

Вы входите в буфет, но здесь так темно, что ничего не получается разглядеть. Обратный путь в фойе на [севере](/foyer).

Как видите, в текст действия также можно включить якоря, в том числе условные якоря с переменными состояния, которые вызывают действия. В первый раз, когда игрок переключает переменную состояния, которая вызывает действие, эта переменная всё ещё будет иметь значение false при отображении текста действия. Ну а во все следующие разы она будет иметь значение true. Следующий пример демонстрирует, в каких случаях это может быть полезно:


## Some Scene

Здесь какой-то парень.

[Сказать ему, что он крут!](#cool-guy)

### Cool Guy

[Парень пожимает плечами. «Ты уже говорил», замечает он.|«Гы, спасибо!» — говорит парень.](?cool-guy)

В этом примере, когда игрок впервые выбирает «Сказать ему, что он крут!», парень скажет: «Гы, спасибо!», но будет пожимать плечами всякий следующий раз, как игрок нажмёт на эту ссылку.

Имена действий сами по себе не должны быть якорями. Якоря могут использоваться в описании действия для изменения текста в зависимости от состояния игрока.

Действия сопоставляются с переменными состояния на основе их нормализованного имени, то есть в их названиях, также как и в названиях сцен, желательно использовать только базовые 26 латинских букв, цифры (не в начале) и пробелы, чтобы минимизировать неочевидные преобразования при нормализации.

Условные сцены
Порой вам может захотеться переправлять по ссылке на разные сцены в зависимости от текущего состояния. Вы можете сделать это, создав несколько условных ссылок, но это может быть сложно поддерживать, если вы ссылаетесь на одно и то же место из нескольких сцен. Решение этой проблемы — условные сцены.

Вы можете определить одну и ту же сцену несколько раз и обернуть имя сцены условными якорями, определяющими состояние, которому должен соответствовать игрок, чтобы войти в эту сцену. Возьмём, например, следующие определения сцены:


## Home

Вы подходите к своему дому. Здесь нет ничего необычного.

## [Home](?broken-window)

Вы подходите к своему дому, хмуро смотря на разбитое фасадное окно.

## [Home](?broken-window&fixed-window "Fixed Home")

Вы подходите к своему дому, одобрительно кивая при виде недавно заменённого окна.

Если где-то в истории будут ссылки на сцену по целевой метке home, то, при их нажатии, игрок будет перенаправлен на один из трёх вариантов в зависимости от текущих значений переменных состояния broken-window и fixed-window. Чтобы попасть на определённый вариант условной сцены, игрок должен выполнить все условия в якоре. Если состояние игры соответствует всем условиям для нескольких сцен, приоритет будет отдан сцене с наиболее подходящими условиями. Если состояние игры удовлетворяет условиям на нескольких сценах с одинаковым количеством условий, то игрок будет перенаправлен на ту, которая в файле истории определена раньше. В этом примере, если бы ранее в истории была переключена только переменная broken-window, игрока перенаправили бы на вторую сцену. Если бы обе переменные были переключены, игрок попал бы на третью сцену.

Если для какого-то названия сцены определены только её условные варианты и текущее состояние истории не соответствует ни одному из вариантов, то такая ситуация считается ошибкой в файле истории. Самый эффективный способ избежать подобного — всегда иметь безусловный вариант сцены, на который и будет перемещаться игрок, если ни один из условных вариантов не соответствует текущему состоянию истории. Именно так сделано в первой сцене этого примера.

В третьей сцене также показано, как определить альтернативное отображаемое название. Если вы хотите использовать одно и то же имя сцены для нескольких подобных сцен, но при этом история должна отображать разные названия сцен для игрока, можно определить альтернативное отображаемое название для сцены в двойных кавычках в якоре. Этот же приём наконец-то позволит использовать в отображаемых названиях сцен любой набор символов, в том числе и кириллицу.

Мы можем использовать эти последние соглашения синтаксиса Ficdown для завершения нашей игры-примера «Плащ тьмы»:


# [Плащ тьмы](/foyer)

Простая демонстрационная игра в жанре интерактивной литературы.

*Версия 0.7*

Спеша сквозь промозглую ноябрьскую ночь, вы были рады увидеть яркие огни Оперного театра. Удивительно, что здесь никого больше нет, но, послушайте, а чего вы ожидали от низкопробной демонстрационной игры?..

## [Foyer]("Фойе Оперного театра")

> Вы быстро закрываете за собой дверь и стряхиваете воду с плаща. Это красивый плащ из бархата с атласной отделкой и слегка забрызганный каплями дождя. Его чёрный цвет настолько глубок, что кажется, будто он поглощает свет в комнате.

Вы стоите в просторном холле, пышно убранном в красных и золотых тонах, со сверкающими над головой люстрами. На севере вход с улицы, а также есть двери на [юге](/bar) и [западе](/cloakroom).

## [Cloakroom]("Гардероб")

На стенах этой небольшой комнаты, очевидно, когда-то было множество крючков, но сейчас остался только один. Единственный выход — это дверь на [востоке](/foyer).

[Здесь на полу ваш плащ.](?dropped-cloak)
[На крючке висит ваш плащ.](?hung-cloak)

- [Осмотреть крючок.](#examined-hook)
- [Повесить ваш плащ на крючок.](?!lost-cloak#lost-cloak+hung-cloak)
- [Бросить ваш плащ на пол.](?!lost-cloak#lost-cloak+dropped-cloak)

### Examined Hook

Это просто маленький латунный крючок[ с висящим на нём плащом|, привинченный к стене](?hung-cloak).

## [Bar]("Фойе-бар (в темноте)")

Вы входите в буфет, но здесь так темно, что ничего не получается разглядеть. Обратный путь в фойе на [севере](/foyer).

- [Пошарить вокруг в поисках выключателя.](?!scuffled1#scuffled1+not-in-the-dark)
- [Сесть на барный стул.](?!scuffled2#scuffled2+not-in-the-dark)

### Not in the Dark

В темноте? Вы можете легко что-нибудь испортить!

## [Bar](?lost-cloak "Фойе-бар")

Буфет, намного более невзрачный, чем вы ожидали увидеть после фойе, расположенного на [севере](/foyer), совершенно пуст. Тут, кажется, какая-то надпись, накарябанная в опилках на полу.

- [Осмотреть надпись.](/message)

## [Message]("Фойе-бар")

Надпись, чётко выведенная в опилках, читается как...

**Вы выиграли!**

## [Message](?scuffled1&scuffled2 "Фойе-бар")

Надпись была неосторожно затоптана, что сделало её трудно читаемой. Можно только различить слова...

**Вы проиграли.**

Приведённая выше история Ficdown теперь полностью играбельна с двумя возможными концовками. Если вы поняли все примеры, то у вас имеются достаточные представления о том, на что способен Ficdown и как начать писать на нём свои собственные интерактивные истории. Чуть более затейливую версию «Плаща тьмы» на Ficdown можно посмотреть здесь (исходный текст содержится в коде страницы внутри элемента <textarea>).

Локализация и прочее

Всё это время, если вы пытались запускать вышеприведённые примеры в Playground или же собирать их при помощи Online Epub Compiler, вам наверняка в глаза бросались англоязычные ссылки и сообщения. Дело в том, что Ficdown изначально ориентирован на англоязычные игры, а их локализация является делом самих авторов. К счастью эта процедура совсем несложная, но напрямую доступна лишь для игр, собираемых при помощи Ficdown.js или ficdown.exe, так что в будущем для неанглоязычных историй стоит рассчитывать только на эти инструменты.

При сборке интерактивной версии истории с помощью Ficdown.js, следует обратить внимание на два необязательных свойства (startText и endMarkdown) объекта playerOptions, через которые и можно переопределить оба встроенных англоязычных сообщения интерпретатора:


var player = new Ficdown({
	id: 'game',
	source: document.getElementById('source').value,
	html: true,
	startText: 'Нажмите, чтобы начать...',
	endMarkdown: '## Конец\n\nВы дошли до конца этой истории. [Нажмите здесь](restart()), чтобы начать сначала.',
});
player.play();

За одно, в итоговом HTML-файле, не забудьте указать правильный язык текста в атрибуте lang у элемента <html>, вписать название истории в элементе <title> и для большей доступности добавить атрибут aria-live="polite" элементу с идентификатором из свойства id, в который осуществляется вывод текста игры.

Также не лишним будет поддержать Договор Бабеля и добавить в метаданные истории после заголовка первого уровня IFID, который можно сгенерировать онлайн при помощи IFID Generator. На веб-страницах его следует добавлять в виде следующей конструкции:


<!-- UUID://строка_IFID// -->

Значение true у свойства html как раз включает обработку HTML-вставок в Markdown, так что строка с IFID, обрамлённая HTML-комментарием, будет скрыта.

При сборке истории в виде набора статичных HTML-файлов или электронного документа в формате ePub с помощью ficdown.exe, следует отредактировать стандартный шаблон в поддиректории Render или же при помощи параметра --template собрать историю с своим собственным локализованным шаблоном, где в файле index.html указать желаемое название ссылки на первую сцену:


<p><a href="@FirstScene">Начать читать...</a></p>

***

Вот и всё. Можете переходить от чтения к написанию.

2 комментария

cheshire
Интересный формат, напомнил Harlowe. Спасибо за статью.

P.S. В версии «Плаща» на tseykovets.ru почему-то не гасятся неактивные ссылки. Что-то с CSS?