Интерактивные истории, текстовые игры и квесты
Регистрация / Вход
Посетите наш новый сайт AXMAJS.RU
Пишем интерактивную историю вместе. Часть 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 09:46
Согласен! Массивы бы помогли справиться с этой проблемой, но официально они пока не поддерживаются. Конечно, с большей вероятностью программа зациклится на 25 описаниях, никогда не показав какие-то 3-4, но рандом такой рандом. Хотя это касается только одного читателя. Энный читатель (или тот же самый, запустивший игру энный раз) наверняка увидит скрытые до поры описания.
16.04.13 21:32
В таком случае игра продлит свою жизнь т.к. читатель будет запускать ее раз за разом в надежде найти новый фрагмент.
Для того, чтобы оставлять комментарии, необходимо зарегистрироваться и подтвердить в профиле указанный
При использовании любых материалов блога обязательно указание ссылки на источник
В случае с количеством случайных описаний больше двух есть момент.Да, мы избавились от проблемы повторения одного и того же описания по-нескольку раз, но программа может зациклиться на выводе двух, трёх, четырёх описаний и ни разу не вывести остальные двадцать пять.Я, например, для решения такой проблемы использую массивы, но они официально не документированы.