Оглавление Сообщение об ошибках Ваше мнение о проекте E-Mail автору

Статья приведена в оригинальном тексте автора

Учимся писать скрипты

Попытаемся разобраться в работе скрипта warehouse.xml «Корабль-склад» версии 2.0 (см. собрание скриптов пилотов). Мы с вам пройдем весь путь: от составления алгоритма до написания скрипта, реализующего выбранный алгоритм. Поехали!

 

Задача: заставить корабль следить за состоянием склада заданного товара станции приписки и поддерживать определенное, заданное пользователем, количество товара на складе, регулируя его за счет своего трюма.

 

Нужно сказать, что четко сформулированная задача – это 20% успеха дела. Необходимо точно представлять, ЧТО вы хотите сделать, чтобы составить нормальный алгоритм программы. Кроме этого, всегда нужно стремиться, чтобы скрипт:

1.        был по-возможности небольшим, а если это по характеру задачи невозможно – то хорошо структурированным, иначе мы начнем в нем теряться;

 

2.        был универсальным, если это требуется;

 

3.        учитывал самые разные возникающие ситуации;

 

4.        содержал некоторую защиту от некорректных действий пользователя;

 

5.        не содержал кода, который мог бы привести к зависанию игры или имел от этого защиту;

 

6.        не загружал игру бесконечными сложными вычислениями.

 

Разумеется, все это сложно совместить, но нужно стараться…

 

Итак, попробуем составить алгоритм, по которому будет действовать наш корабль. Можно было бы воспользоваться стандартной блочной схемой алгоритма из учебника информатики, но мы этого делать не будем. Во-первых, как составляется такая схема, мало кто знает и помнит (в том числе и я), во-вторых, часто она не очень удобна. Вместо этого попробуем человеческим языком расписать порядок действий нашего корабля (включая все необходимые подготовительные действия) с момента получения команды.

 

1.        Очевидно, нам потребуются некоторые начальные условия для корабля, которые задает пользователь. Исходя из условий поставленной задачи, мы должны задать кораблю станцию,  товар на станции, с которым он будет работать, и количество этого товара, которое корабль будет поддерживать. На последнем пункте остановимся и подумаем: каким должно быть это количество? Известно, что разные станции хранят различное количество различного товара. Если мы будем задавать абсолютное количество товара, то мы можем легко ошибиться, т.к. в этом случае мы должны твердо знать, сколько нужного нам товара хранит данная станция. Поэтому лучше задать относительное кол-во товара, например в процентах от максимального объема склада. Это позволит нам не думать о типе товара и фактическом объеме склада. И это будет правильный и универсальный подход к делу.

 

2.        После получения условий начинаем действовать. Но прежде нужно кое-что проверить – вдруг пользователь задал некорректные условия? Ведь это может привести к неправильной работе и даже (не дай бог) к зависанию игры. Прежде всего необходимо проверить, кому принадлежит станция – игроку или другой расе. Если станция наша, то все в порядке, можно продолжать. Если же нет – дальнейшая работа бесполезна и нужно прервать выполнение скрипта.

 

3.        Далее нужно проверить, может ли корабль перевозить/хранить заданный товар. Если да, то все в порядке, можно продолжать. Если же нет – дальнейшая работа также бесполезна и нужно прервать выполнение скрипта.

 

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

 

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

 

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

 

7.        Теперь можно приступать к выполнению главной задачи: следить за количеством товара на станции. Поскольку эта задача постоянна, выполнять мы ее будем циклически, пока кораблю не поступит другая команда. Для этого нужно организовать цикл и внутри цикла производить действия по загрузке/разгрузке.

8.        Что делать внутри цикла? Нужно проверять, сколько товара есть на складе, сравнивать это фактическое кол-во с нашем лимитом, если товара больше, то погружаем излишек в трюм, если недостаток – то выгружаем товар на склад до достижения лимита.

 

Вот и все. Несложно, не правда ли? Попробуем теперь воплотить все это на языке игры.

Arguments

1: home.ware , Перем/Станция и товар , 'Select station and ware'

2: perc , Число , 'Input warehouse percent'

Зададим начальные условия для скрипта в разделе аргументов. Скриптовый движек игры позволяет задать переменную-массив из станции и ее товара. Это удобнее, чем отдельные переменные, потому как в процессе выбора товара запрашиваться будет только товар из списка товаров станции, а не вываливаться полный список всех существующих товаров. Назовем эту переменную-аргумент $home.ware. Процентный лимит будет называться у нас $perc.

Source Text

001 $ship = [THIS]

 

Присвоим переменной $ship указатель на объект (корабль), получивший команду. Это для нашего удобства.

 

002
003 $ware = $home.ware[0]
004 $home = $home.ware[1]

 

Присвоим переменной $ware значение ячейки номер 0 массива $home.ware (это наш товар), а переменной $home значение ячейки номер 1 того же массива (это станция).

 

005
006 $owner = $home -> get owner race

 

Получим в переменную $owner расу владельца станции $home.

 

007 skip if $owner == Player
008 return null

 

Проверим, совпадает ли раса-владелец $owner с расой Player, или, попросту говоря, принадлежит ли она игроку. Если нет, то прерываем скрипт.

 

010 skip if $ship -> can transport ware $ware
011 return null

 

Проверим, может ли корабль $ship перевозить товар $ware. Если нет, то прерываем скрипт.

 

013 $ship -> set homebase to $home

 

Установим для корабля $ship станцию $home в качестве станции приписки.

 

014

015 set script command: COMMAND_TYPE_TRADE_10

 

Эта команда позволит команде «Складировать товар» отображаться в информанционных окнах корабля, и мы будем видеть, ЧТО корабль делает. Это чистой воды сервисная команда. А происходит это потому, что в инициирующем скрипте команда-константа COMMAND_TYPE_TRADE_10 завязана на наш скрипт.

 

016
017 * fly to home if we are not at home

 

Это просто комментарий «летим домой если мы не дома».

 

018 skip if $home == [ENVIRONMENT]
019 @ = $ship -> fly to home base

 

Проверим, совпадает ли окружение [ENVIRONMENT] нашего корабля со станцией $home. В данном случае это наиболее простой способ узнать, пристыкован ли корабль к интересующей нас станции. Если окружение не совпадает, это значит, что корабль находится в космосе, пристыкован к другой станции или кораблю – неважно. Итак, если он не пристыкован, то даем команду кораблю $ship лететь на станцию приписки.

 

020 skip if $home -> exists
021 return null

 

Проверим, существует ли станция $home или нет. Ведь ее могли уничтожить, пока мы летели! Если же мы никуда не летели, то это чистая формальность. Вообщем, если станции нет, прекращаем работу скрипта.

 

022
023 $max = $home -> get max. store amount of ware $ware
024 $max = $max * $perc / 100

 

В переменную $max в строке 023 мы получаем максимальное кол-во товара $ware, которое может храниться на станции $home. В строке 024 мы присваиваем все той же переменной $max абсолютное значение лимита товара, восстанавливая его из указанного игроком процента в переменной $perc. Не будем вдаваться в арифметику второго класса – думаю, механизм всем понятен.

 

025
026 while [TRUE]

 

Организуем «вечный» цикл (для этого в качестве условия оператору while задается постоянное логическое значение «правда»), внутри которого будем заниматься нашим контролем лимита.

 

027 $quantity = $home -> get amount of ware $ware in cargo bay

 

Получаем в переменную $quantity количество товара $ware, которое в данный момент хранится на складе станции $home.

 

028 $quantity = $max - $quantity

 

Присваиваем переменной $quantity разницу нашего лимита $max и того же количества на складе $quantity.

Обратите внимание, как и в строках 023 и 024 мы не заводим лишнюю переменную, а используем уже существующие. Так вполне можно делать, так как это изменяющееся (динамическое) значение и нет нужды его долго хранить. К тому же такой прием экономит память. Итак, после этой строки переменная $quantity вместо текущего количества товара на станции стала хранить количество товара, которым нам нужно обменяться со станцией! Это количество по понятным причинам может быть либо положительным, либо отрицательным. Поняли, почему? Прикиньте возможные ситуации на бумажке и поразмыслите.

 

029 if $quantity > 0
030 = $ship -> unload $quantity units of $ware
031 else
032 $quantity = - $quantity
033 = $ship -> load $quantity units of $ware
034 end

 

Итак, если количество положительное ($quantity > 0), то выполняется строка 030, где корабль $ship пытается выгрузить $quantity единиц товара $ware. В противном случае ($quantity<=0) выполняются строки 032 и 033, где мы сначала инвертируем знак переменной $quantity (из отрицательного числа делаем такое же положительное, 0 останется неизменным), а потом пытаемся загрузить в корабль это количество. Строка 034 – конец оператора условия if. Обратите внимание – мы не занимаемся никакими вычислениями, учитывающими остаток свободного места на корабле! На самом деле за нас это делают команды load и unload. Они сами контролируют корректность процессов и ничего недопустимого не сделают. Кстати, по такому же принципу действуют торговые команды sell и buy, в которых задействованы еще и деньги. Здесь мы придерживаемся святого принципа универсальности: нам совершенно не важно, сколько свободного места на корабле и как оно изменяется.

 

035 @ = wait randomly from 10000 to 15000 ms

036 end

 

В строке 035 мы выдерживаем паузу в 10-15 секунд, а строка 036 – конец цикла.

 

037
038 return null

 

Все, конец скрипта.

  


Оглавление Сообщение об ошибках Ваше мнение о проекте E-Mail автору
Сайт создан в системе uCoz