Авторизация
×

Логин (e-mail)

Пароль

Интерактивные истории, текстовые игры, квесты и визуальные новеллы
Гиперкнига

Библиотека    Блог

Пишем интерактивную историю вместе. Часть 9-я

Борис Семёнов (Morych), 01.04.13 | Практика ASM

Случайные значения при описании сцен

Мы договорились пока придумывать по два описания на сцену. Но если вы вдруг придумали, например, сразу N описаний, мы можем выводить их в случайном порядке, чтобы не зацикливать, как в параграфе «Старое селение». Число N при этом должно быть больше 3. Наш гипотетический параграф (а точнее его часть с описанием) будет выглядеть следующим образом:

<<if $пред_описание gt 0>>
    <<random $номер_описания = N-2>>
    <<set $номер_описания = $номер_описания + 2>>
    <<if $номер_описания eq $пред_описание>>
        <<set $номер_описания = $номер_описания + 1>>
    <<endif>>
    <<if $номер_описания gt N>>
        <<set $номер_описания = 2>>
    <<endif>>
<<endif>>
<<if $номер_описания eq 1>>
    Первое описание, показывается только один раз.
<<elseif $номер_описания eq 2>>
    Второе описание.
<<elseif $номер_описания eq 3>>
    Третье описание.
...
<<elseif $номер_описания eq N-1>>
    Предпоследнее описание.
<<else>>
    Последнее описание.
<<endif>>
<<set $пред_описание = $номер_описания>>

Нам понадобится привычный уже объект «$номер_описания», а также объект «$пред_описание», который будет хранить номер предыдущего описания. Первоначальное значение объекта «$номер_описания» должно быть равно 1, а значение «$пред_описание» — 0. Каждый раз в конце параграфа значение объекта «$пред_описание» будет обновляться. Для чего же мы запоминаем номер предыдущего описания сцены? Дело в том, что вполне может возникнуть ситуация, когда «random» сгенерирует несколько раз подряд одно и то же число. Кстати, чем меньше общее число описаний N, тем больше вероятность такого события. Чтобы читателю не приходилось несколько раз подряд любоваться одним и тем же описанием, мы сравниваем сгенерированное значение с предыдущим и в случае совпадения увеличиваем новое значение на 1. Если при этом номер описания станет больше общего числа описаний, установим значение объекта «$номер_описания» в 2. Теперь каждый раз описание сцены будет непредсказуемым.

Этот алгоритм можно использовать и для вывода произвольных реплик второстепенных персонажей. Пожалуй, так мы и поступим, когда наш герой доберётся до следующего второстепенного персонажа. А сейчас посмотрим, как организовать какое-нибудь случайное событие на одной из сцен. Пусть на сцене «Старое селение» герой с вероятность 35% может услышать чей-то смех за спиной (напустим немного таинственности) и пусть это событие случается только один раз. Добавляем в параграфе «Старое селение» несколько строк перед ссылками.

Старое селение

...
<<random $шанс = 99>>
<<if $шанс lt 35 and !$слышал_смех>>
    Как вдруг за спиной мне помстился чей-то издевательский смешок. Я резко крутанулся на месте, намереваясь проучить обидчика, но увидал лишь пыльную дорогу. Ничего не оставалось мне, как в недоумении пожать плечами и отправиться дальше.
    <<set $слышал_смех = true>>
<<endif>>

[[Идти к дому старейшины|Дом старейшины]]
[[Вернуться на пепелище|Сгоревший дом]]
<<if $диалог_дед gt 12>>
    [[Выйти за околицу|Лес]]
<<endif>>

В первой строке объекту «$шанс» присваивается случайное значение от 0 до 99. Теперь это значение нужно сравнить с вероятностью нашего события (35%). При проверке мы используем служебное слово «lt» (от англ. «less than» — «меньше чем»). Вы, наверняка, заметили, что условие в макросе «if» состоит из двух частей, которые связаны служебным словом «and» (от англ. «и»). Такая связка означает, что всё условие будет истинным, только если обе его части соответствуют истине. В первой части мы проверяем выпадение необходимого значения объекта «$шанс», а во второй — признак того, что событие ещё не происходило. За это у нас отвечает объект «$слышал_смех».

Кстати, объект-признак «$слышал_смех» может иметь только два значения: «true» (от англ. «истина») или «false» (от англ. «ложь»). Это значения логического или булева типа. Объекты с логическим типом значений удобно использовать в условиях, поскольку нам не понадобятся служебные слова вроде «eq», и запись условия становится короче и нагляднее. Достаточно написать лишь «if $объект» для проверки на «true» и «if !$объект» для проверки на «false». Восклицательный знак здесь означает логическое отрицание («не»). Первоначально значение объекта «$слышал_смех» будет установлено в «false», поэтому в нашем условии мы используем восклицательный знак перед именем объекта.

Говоря человеческим языком, наше условие звучит так: «Если выпавшее случайное значение меньше 35, и герой не слышал смех прежде». Конечно, вероятность события не обязательно должна быть 35%. В приведённом примере она может иметь любое значение от 1 до 99. Конкретное значение вероятности того или иного события определяется методом подбора.

Запустим историю на тестирование и погуляем немного по главной улице старого селения. Рано или поздно значение объекта «$шанс» выпадет меньше 35, и мы увидим текст с описанием события. Ну а чтобы не бродить вслепую и знать текущее значение объекта «$шанс», давайте нажмём в режиме тестирования кнопку «Консоль» (кнопка в виде лампочки).

Рисунок 6 — Консоль.

Сверху отобразится панель с перечислением всех объектов и их значений. Объекты, значения которых изменились в данном параграфе, выделяются красным цветом. Убедимся, что сообщение о событии появляется при соответствующем значении объекта «$шанс» и только один раз. Попробуйте несколько раз начать историю заново, вы увидите, что наше событие каждый раз происходит неожиданно.

Продолжение следует...

Комментарии: 3.

Профиль


Закрыть
Вячеслав Добранов
01.04.13 08:00

В случае с количеством случайных описаний больше двух есть момент.

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

Я, например, для решения такой проблемы использую массивы, но они официально не документированы.
Morych
01.04.13 09:46

Согласен! Массивы бы помогли справиться с этой проблемой, но официально они пока не поддерживаются. Конечно, с большей вероятностью программа зациклится на 25 описаниях, никогда не показав какие-то 3-4, но рандом такой рандом. Хотя это касается только одного читателя. Энный читатель (или тот же самый, запустивший игру энный раз) наверняка увидит скрытые до поры описания.
Кельта
16.04.13 21:32

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

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

При использовании любых материалов блога обязательно указание ссылки на источник