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

Логин (e-mail)

Пароль

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

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

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

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

Продолжаем рассматривать пример использования одномерных массивов. Загадку игроку мы загадали, теперь наша задача — предоставить игроку возможность эту загадку решить. Конечно же, герой должен видеть содержимое каждого сундука, а ещё нужно научить героя вытаскивать из сундука верхний предмет и помещать его в любой другой сундук. А чтобы решение загадки не было совсем уж простым, мы ограничим вместимость каждого из сундуков.

Рисунок 15 — Решаем загадку.

Полный код нового параграфа «Сундуки» будет выглядеть следующим образом:

Сундуки

<<display 'Новая сцена'>>
<<if $сундук eq -1>>
    <<set $сцена = "Новый дом">>
    <<set $место = 0>>
<<elseif $сундук eq $сундук_1>>
    <<set $сцена = "Первый сундук">>
    <<set $место = 11>>
<<elseif $сундук eq $сундук_2>>
    <<set $сцена = "Второй сундук">>
    <<set $место = 9>>
<<else>>
    <<set $сцена = "Третий сундук">>
    <<set $место = 7>>
<<endif>>
<<display 'Заголовок'>>
<<if $место gt 0>>
    <<set $текст = "">>
    <<set $число = $сундук.length + $действие>>
    <<loop $число>>
        <<set $текст = $текст + "■">>
    <<endloop>>
    <<set $место = Math.max(0, $место - $число)>>
    <<loop $место>>
        <<set $текст = $текст + "□">>
    <<endloop>>
    ===<<print $текст>>===
<<endif>>
<<if $действие eq 0>>
    <<set $предмет_сундука = "">>
    <<if $сундук eq -1>>
        Я посмотрел на каждый из трёх сундуков, решая, в который бы из них заглянуть. Первый сундук был самым большим и старым, его доски давно прокоптились и потемнели, но стягивающие их железные полосы делали сундук одновременно и самым крепким. Второй сундук был немного поменьше и гораздо новее, его стенки и крышка светились белизной. А третий сундук был сделан совсем недавно и приятно пахнул свежим деревом, крышку его покрывала искусная и замысловатая резьба.
        Мне подумалось, что первый сундук лучше всего подойдёт для добра главы семейства, второй можно использовать для хранения кухонной утвари, а третий сундук -- словно бы нарочно создан для приданного невесты.
    <<else>>
        <<set $текст = "">>
        <<if $сундук.length gt 0>>
            <<set $предмет_сундука = $сундук[$сундук.length - 1]>>
            <<if $сундук.length gt 1>>
                <<set $текст = "увидел там ">>
                <<set $номер = 0>>
                <<loop $сундук.length - 1>>
                    <<set $текст = $текст + $сундук[$номер].substr(2)>>
                    <<if $номер lt $сундук.length - 2>>
                        <<set $текст = $текст + ", ">>
                    <<endif>>
                    <<set $номер++>>
                <<endloop>>
                <<set $текст = $текст + " и ">>
            <<else>>
                <<set $текст = "увидел там только ">>
            <<endif>>
            <<set $текст = $текст + $предмет_сундука.substr(2)>>
        <<endif>>
        <<if $в_руках.length gt 2>>Держа в руках <<print $в_руках.substr(2)>>, я<<else>>Я<<endif>> заглянул <<if $сундук eq $сундук_1>>в первый<<elseif $сундук eq $сундук_2>>во второй<<else>>в третий<<endif>> сундук <<if $предмет_сундука eq "">> -- там было пусто<<else>> и <<print $текст>><<endif>>.        
        <<if $место eq 0>>
            Похоже, больше ничего в этот сундук и не влезет.
        <<endif>>
    <<endif>>
<<elseif $действие eq -1>>
    Я вытащил <<print $предмет_сундука.substr(2)>> из <<if $сундук eq $сундук_1>>первого<<elseif $сундук eq $сундук_2>>второго<<else>>третьего<<endif>> сундука.
    <<set $в_руках = $сундук.pop()>>
    <<set $предмет_сундука = "">>
    <<set $сундук = -1>>
<<elseif $действие eq 1>>
    Я положил <<print $в_руках.substr(2)>> <<if $сундук eq $сундук_1>>в первый<<elseif $сундук eq $сундук_2>>во второй<<else>>в третий<<endif>> сундук.
    <<if $показать_подсказки>>
        <<if (($сундук eq $сундук_1) and ($в_руках.indexOf("1") gt -1)) or (($сундук eq $сундук_2) and ($в_руках.indexOf("2") gt -1)) or (($сундук eq $сундук_3) and ($в_руках.indexOf("3") gt -1))>>
            Ведь именно в этом сундуке и следует хранить <<print $в_руках.substr(2)>>.
        <<else>>
            Конечно, всякому ясно, что <<print $в_руках.substr(2)>> в этом сундуке хранить нельзя.
        <<endif>>
    <<endif>>
    <<set $сундук.push($в_руках)>>
    <<set $в_руках = "">>
    <<set $сундук = -1>>
<<endif>>
<<set $действие = 0>>
----
<<if ($предмет_сундука neq "") and ($в_руках eq "") and ($сундук neq -1)>>
    [[''Вытащить''|Сундуки {$действие = -1}]] ''<<print $предмет_сундука.substr(2)>>''
<<endif>>
<<if ($в_руках neq "") and ($сундук neq -1) and ($место gt 0)>>
    <<if $сундук.length eq 0>>
        [[''Положить внутрь''|Сундуки {$действие = 1}]] ''<<print $в_руках.substr(2)>>''
    <<else>>
        [[''Положить сверху''|Сундуки {$действие = 1}]] ''<<print $в_руках.substr(2)>>''
    <<endif>>
<<endif>>
<<if $сундук neq $сундук_1>>
    [[''Заглянуть в первый сундук''|Сундуки {$сундук = $сундук_1}]]
<<endif>>
<<if $сундук neq $сундук_2>>
    [[''Заглянуть во второй сундук''|Сундуки {$сундук = $сундук_2}]]
<<endif>>
<<if $сундук neq $сундук_3>>
    [[''Заглянуть в третий сундук''|Сундуки {$сундук = $сундук_3}]]
<<endif>>
<<if $в_руках eq "">>
    [[''Закончить перебирать добро''|Новый дом]]
<<endif>>

Итак, объект «$сундук» изначально равен -1, это означает, что ни один из сундуков не выбран. Если герой выбирает какой-либо сундук, объекту «$сундук» будет присвоена ссылка на соответствующий список. До вызова параграфа «Заголовок» в зависимости от значения объекта «$сундук» зададим название сцены, чтобы игроку было понятнее, с которым сундуком взаимодействует герой. Здесь же установим максимальную вместимость выбранного сундука (объект «$место»). Каждый предмет будет занимать одну условную единицу места.

Под названием сцены показываем уровень заполнения сундука. Для формирования полосы в объект «$текст» используем циклы — макросы «loop» и «endloop». Сначала в строку «$текст» собираем чёрные символы, их количество — это число элементов списка «$сундук» (которое возвращает свойство length) плюс значение объекта «$действие». Объект «$действие» равен -1, если герой достаёт предмет из сундука, и 1, когда герой кладёт предмет в сундук. Если герой просто изучает содержимое сундука, объект «$действие» равен 0. После чёрных добираем в строку «$текст» белые символы, которые показывают свободное место. Обратите внимание, что в объекте «$место» теперь содержится не общая вместимость сундука, а именно оставшееся свободное место.

Для перечисления содержимого выбранного сундука нам снова понадобятся макросы цикла и объект «$текст». При этом, если в сундуке содержится более одного предмета, перед последним предметом мы добавим союз «и». Остальные предметы будем отделять запятыми. Вот почему число повторений цикла равно $сундук.length - 1. В объекте «$номер» содержится индекс очередного предмета, название которого мы добавим к строке «$текст». А перед этим используем метод «substr(2)», чтобы получить только название и не добавлять вместе с названием ещё и номер типа предмета:

<<set $текст = $текст + $сундук[$номер].substr(2)>>

Кроме того, используем «substr(2)» во всех других случаях, когда нужно вывести на экран название предмета. Этот метод вырезает часть строки, начиная с указанного символа. Почему в скобках именно 2? Индексация символов строки начинается с 0. Нулевой символ названия —это номер типа, первый символ — пробел, а собственно название предмета начинается как раз со второго символа.

В объекте «$предмет_сундука» будем хранить тип и название последнего (верхнего) предмета сундука. Именно этот предмет герой и может вытащить. Когда игрок выбирает действие «Вытащить предмет», мы при помощи метода «pop» извлекаем из соответствующего списка последний элемент и помещаем его в объект «$в_руках»:

<<set $в_руках = $сундук.pop()>>

При этом последний элемент исчезает из списка, а длина списка уменьшается на 1. Когда же герой кладёт предмет в сундук, мы используем метод «push», который добавляет указанный объект в конец списка:

<<set $сундук.push($в_руках)>>

Одновременно с этим, если игрок не отключил подсказки, сообщаем, в правильный ли сундук помещён предмет. Так же, как и в параграфе «Новый дом», в условии используем метод строковых объектов «indexOf» для поиска номера типа в названии предмета.

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

Комментариев нет.

Профиль


Закрыть

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

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