Интерактивные истории, текстовые игры и квесты
Регистрация / Вход
Посетите наш новый сайт AXMAJS.RU
Пишем интерактивную историю вместе. Часть 18-я
Борис Семёнов (Morych), 14.05.13 | Практика ASM
Теперь посмотрим, как же организована внутренняя игра. Код игры занимает два отдельных параграфа: «Игра» и «Бросок». Параграф «Игра» является головным:Игра
<<display 'Заголовок'>>
<<if $игра eq 0>>
<<set $игра_счет1 = 0>>
<<set $игра_счет2 = 0>>
<<set $игра = 1>>
<<endif>>
//<<print $имя>>//{{{<<loop $игра_счет1>> ×<<endloop>>}}}
//Корян//{{{<<loop $игра_счет2>> ×<<endloop>>}}}
----
<<random $шанс = 3>>
<<if $игра eq 1>>
<<if $шанс eq 0>>
-- Ну, чего ждём? -- поторопил Корян.
<<elseif $шанс eq 1>>
-- Ну что, начинай! -- сказал Корян.
<<elseif $шанс eq 2>>
-- Давай-давай, начинай, не томи! -- затараторил Корян.
<<else>>
-- Одну чёрную выкидывай! -- посоветовал Корян, нагло ухмыляясь.
<<endif>>
[[Метнуть зернь|Игра]]
<<elseif $игра eq 2>>
Я хорошенько потряс туесок и метнул зернь.
<<display 'Бросок'>>
<<set $игра_бросок1 = $игра_бросок>>
[[Передать туесок|Игра]]
<<elseif $игра eq 3>>
<<if $шанс eq 0>>
-- Смотри и учись! -- заявил Корян и метнул зернь.
<<elseif $шанс eq 1>>
-- А вот так играют мастера! -- похвастался Корян и бросил зернь.
<<elseif $шанс eq 2>>
-- Буду я играть назло, чтоб ему не повезло, -- прошептал Корян и выметнул зернь.
<<else>>
Корян долго и молча тряс зернь и, наконец, сделал свой бросок.
<<endif>>
<<display 'Бросок'>>
<<set $игра_бросок2 = $игра_бросок>>
<<if $игра_бросок1 gt $игра_бросок2>>
<<set $игра_счет1++>>
В этом круге я победил!
<<elseif $игра_бросок2 gt $игра_бросок1>>
<<set $игра_счет2++>>
В этом круге победил Корян.
<<else>>
Никто не победил, перекидываем.
<<endif>>
<<if $игра_счет1 eq 5>>
И в итоге я первым одержал пять побед!
[[Закончить игру|Разговор с лешим {$диалог_леший = 20}]]
<<elseif $игра_счет2 eq 5>>
И в итоге Корян первым одержал пять побед.
[[Закончить игру|Разговор с лешим {$диалог_леший = 21}]]
<<else>>
[[Продолжить игру|Игра {$игра = 1}]]
<<endif>>
<<endif>>
<<set $игра++>>
В объекте «$игра_счет1» мы будем хранить счёт героя, а в объекте «$игра_счет2» — счёт противника. Объект «$игра» отвечает за этап игры: 0 — инициализация, 1 — перед броском героя, 2 — бросок героя, 3 — бросок противника и обработка результатов раунда. Хоть результат броска и формируется случайным образом, мы предоставляем читателю возможность самому нажать ссылку «Метнуть зернь». Так у читателя формируется ощущение, что именно он влияет на успех игры главного героя.
Как было сказано выше, текущий счёт игры мы показываем крестиками, а не числами. Значит после имени каждого игрока может быть от 0 до 4 символов. Когда нам нужно несколько раз подряд выводить на экран какой-то определённый текст, мы обращаемся к макросу «loop» (от англ. «петля»). Макросы «loop» и «endloop» называются ещё операторами цикла. Казалось бы, если в цикле несколько раз повторяется одно и то же, почему просто не написать этот текст несколько раз подряд? А всё дело в том, что зачастую мы не знаем, сколько именно раз нужно повторить текст. Вот, например, как в нашем случае. Мы никак не можем предсказать, каким будет счёт в каждом раунде игры, и сколько крестиков нам рисовать. К счастью, в макросе «loop» можно указать объект, в котором хранится необходимое число повторений. Если значение объекта меньше либо равно нулю, цикл не сработает ни разу. Таким образом, количество крестиков после имени героя будет соответствовать счёту героя. И аналогично с противником.
Во втором и третьем этапах игры вызываем параграф «Бросок», после отработки которого в объекте «$игра_бросок» будет содержаться результат хода героя или противника. Результаты текущего раунда мы запоминаем в объектах «$игра_бросок1» (для героя) и «$игра_бросок2» (для противника).
В параграфе «Бросок» формируется игровое поле с выпавшими камнями. Размер поля составляет 4 на 4 клетки. На этих 16 клетках мы должны в случайном порядке расположить 5 камней. При этом каждый камень с равной вероятностью может быть белым или чёрным.
Бросок
<<set $игра_клетка = 0>>
<<set $игра_бросок = 0>>
<<set $игра_зернь = 0>>
<<set $игра_поле = ''>>
<<loop 16>><<set $игра_клетка++>><<random $шанс = 99>><<if ($шанс lt 35) or ($игра_клетка gt $игра_зернь + 11)>><<set $игра_зернь++>><<random $шанс = 99>><<if $шанс lt 50>><<set $игра_поле = $игра_поле + ' ○ '>><<else>><<set $игра_бросок++>><<set $игра_поле = $игра_поле + ' ● '>><<endif>><<else>><<set $игра_поле = $игра_поле + ' '>><<endif>><<if $игра_клетка / 4 eq Math.floor($игра_клетка / 4)>><<set $игра_поле = $игра_поле + '<br>'>><<endif>><<if $игра_зернь eq 5>><<break>><<endif>><<endloop>>
===<<print $игра_поле>>===
<<if $игра eq 2>>
<<random $шанс = 3>>
<<else>>
<<set $шанс = 0>>
<<endif>>
<<if $игра_бросок eq 0>>
Вся зернь выпала белая.
<<set $игра_бросок = 5>>
<<if $шанс eq 1>>
-- Все белые -- это больше четырёх чёрных, -- напомнил Корян. -- Надо мне пять выкинуть!
<<elseif $шанс eq 2>>
-- Ишь ты, -- позавидовал мне Корян, -- все белые выметнул.
<<elseif $шанс eq 3>>
-- Да что же мне за невезение такое! -- воскликнул Корян.
<<endif>>
<<elseif $игра_бросок eq 1>>
Выпала одна чёрная.
<<if $шанс eq 1>>
-- Ха! -- обрадовался Корян. -- Теперь я точно выиграю!
<<elseif $шанс eq 2>>
-- Отличный бросок! -- похвалил меня Корян и мерзко захихикал.
<<elseif $шанс eq 3>>
-- Да кто ж так кидает! -- воскликнул Корян. -- Дай, покажу, как надо!
<<endif>>
<<elseif $игра_бросок eq 2>>
Выпало две чёрных.
<<if $шанс eq 1>>
-- Да ну, всего две, -- махнул рукой Корян. -- Считай, круг за мной!
<<elseif $шанс eq 2>>
-- Не везёт тебе сегодня, -- злорадно посочувствовал Корян.
<<elseif $шанс eq 3>>
-- Да-да, две! -- подтвердил Корян и засмеялся.
<<endif>>
<<elseif $игра_бросок eq 3>>
Выпало три чёрных.
<<if $шанс eq 1>>
Корян не нашёл, что сказать и, чтобы не молчать, просто заухал по-совиному.
<<elseif $шанс eq 2>>
-- Три-три -- слюни утри! -- вскричал Корян.
<<elseif $шанс eq 3>>
-- Нет, -- порешил Корян, -- с тремя-то всего ты не победишь.
<<endif>>
<<elseif $игра_бросок eq 4>>
Выпало четыре чёрных.
<<if $шанс eq 1>>
-- Рано радуешься! -- заскрипел зубами Корян.
<<elseif $шанс eq 2>>
-- А я сейчас одну масть выметну! -- посулил мне Корян.
<<elseif $шанс eq 3>>
-- Да случайно тебе повезло, -- мгновенно определил Корян.
<<endif>>
<<else>>
Вся зернь выпала чёрная.
<<set $игра_бросок = 6>>
<<if $шанс eq 1>>
-- Как? -- вскрикнул Корян, не веря своим глазам.
<<elseif $шанс eq 2>>
-- Ты, наверняка, жульничал! -- запротестовал Корян, но я не стал обращать внимания на его протесты.
<<elseif $шанс eq 3>>
-- Не может быть! -- закричал Корян, обдирая бороду-мох.
<<endif>>
<<endif>>
В начале параграфа объявляем четыре служебных объекта: «$игра_клетка» — для запоминания числа обработанных клеток игрового поля, «$игра_бросок» — для результата броска, «$игра_зернь» — для количества выпавших камней, «$игра_поле» — для формирования игрового поля.
Затем используем макрос «loop» для организации цикла из 16 повторений (для каждой клетки поля). Вероятность того, что один из камней упадёт в данную клетку, составляет 35%. Это значение мы выбрали произвольно, его можно регулировать по своему усмотрению. Однако, для определения клетки с камнем одной проверки на вероятность будет не достаточно. Дело в том, что клетки могут закончиться прежде, чем выпадут все камни. Если число оставшихся клеток меньше числа выпавших камней, помещаем камень на данную клетку вне зависимости от значения объекта «$шанс». Вторая часть условия после небольшого преобразования будет выглядеть следующим образом: «$игра_клетка gt $игра_зернь + 11». Обе части условия связываем служебным словом «or» (от англ. «или»). Всё условие в этом случае будет истинным, если хотя бы одна из его частей соответствует истине.
Если наше составное условие срабатывает, мы увеличиваем на 1 значение объекта «$игра_зернь» и снова используем генератор случайных чисел, чтобы определить какой стороной упал камень. Здесь шанс уже строго 50 на 50. При этом если камень упал чёрной стороной вверх, увеличиваем на 1 значение объекта «$игра_бросок».
В объект «$игра_поле» с каждым ходом цикла мы постепенно добавляем соответствующие символы: чёрный или белый кружок в обрамлении пробелов или три неразрывных пробела при пустой клетке. К каждой четвёртой клетке кроме того добавляем html-тег переноса строки <br>. Не делай мы этого, вся зернь была бы расположена в одной строке. Каждую четвёртую клетку мы определим, если число обработанных клеток (объект «$игра_клетка») делится на 4 без остатка. Для этого используем в условии Javascript-функцию «floor()», которая отбрасывает дробную часть числа:
<<if $игра_клетка / 4 eq Math.floor($игра_клетка / 4)>>
Кстати, другие поддерживаемые функции класса «Math» описаны в статье «Расширяем возможности макросов с помощью Javascript. Часть 2-я».
Поскольку камней в туеске всего пять, нам нужно будет прервать выполнение цикла, когда значение объекта «$игра_зернь» станет равным 5. Используем для этого специальный макрос «break» (от англ. «прервать»). Когда ASM встречает такой макрос, происходит досрочный выход из цикла, а выполнение кода продолжается от ближайшего снизу макроса «endloop».
После того, как игровое поле сформировано, показываем его в центре страницы, а ниже выводим один из случайных комментариев противника, который будет зависеть от результата броска.
Продолжение следует...Комментариев нет.
Профиль
Закрыть
Для того, чтобы оставлять комментарии, необходимо зарегистрироваться и подтвердить в профиле указанный
При использовании любых материалов блога обязательно указание ссылки на источник