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

Введение в скриптописание Х2

 

v    Переменные. Типы переменных

 

Использование переменных является простым способом хранения временных данных в вашем НС и передачи их в нужном виде ScE Х2. Переменные  могут являться указателями на объект, хранить в себе данные его типе ($station = [HOMEBASE]), а также результаты математических, логических или операций сравнения ($res = 2+2), принимать значения ЛОЖЬ или ИСТИНА ($res= [FALSE]), содержать текст ($text=Hello world !!!).  Имя переменной задается пользователем и отображается после знака $<имя> . Имя должно состоять из одного слова, может содержать цифры, строчные и прописные буквы латинского алфавита (но начинаться должно с буквы). При создании переменной желательно давать ей максимально информативное имя, т.к. в сложных скриптах используется не один десяток переменных и чтобы избежать путаницы имена должны быть понятны и сообщать о содержимом переменной. Например, переменная содержащая информацию о свободном месте в трюме корабля может иметь имя $ShipFreeAmount. Такое имя сообщает пользователю о том какие данные содержит переменная.

В ScE присутствуют следующие типы переменных:

Приватные переменные – переменные относящиеся непосредственно к скрипту в котором они созданы. Над этим типом переменных можно производить любые  операции, математические, логические, сравнения. Приватные переменные недоступны другим скриптам. Формат записи $<имя>.

002            $test = 5

003            $total = $test+10

004            if $total < 10

 

Локальные переменные – переменные этого типа относятся к определенному объекту, но доступны другим скриптам. Все операции с локальными переменными осуществляются по принципу Считал-Изменил-Записал. Для выполнения каких либо действий над локальной переменной, нужно получить ее значение при помощи команды get local variable в приватную переменную. Произвести над приватной переменной нужные операции и командой set local variable записать полученный результат обратно в локальную переменную.

...

005            $test = [THIS] get local variable: name= localVar

006            $test = $test + 1

007            [THIS] set local variable: name= localVar value=$test

 

Глобальные переменные – этот тип переменных не привязан ни к одному объекту, это делает их доступными для любого скрипта просто по имени этой переменной. В связи с этим, объявляя глобальную переменную следует позаботиться о том, чтобы ее имя было оригинальным и информативным. Принцип выполнения операций на глобальными переменными тот же, что и у локальных. Команды для работы с глобальными переменными get global variable и set global variable.

008            $test = get global variable: name=globVar

009            $test = $test + 1

010            set global variable: name=globVar value=$test


            Теперь мы разобрались какие бывают типы переменных и для чего они нужны. Осталось разобраться как они устроены.

 

      В ScE любая переменная состоит из двух частей. Первая, это тип данных. Вторая часть сами данные. Тип данных сообщает ScE как работать с содержащимися в переменной данными. Сделано это для того, что бы работая с переменными мы могли не задумываясь помещать в них как информацию о какой либо точке в пространстве сектора, так и просто какое ни будь числовое значение не выполняя никаких дополнительных манипуляций, кроме как указать тип данных который будет хранится в создаваемой переменной. Всего в ScE "X2 The Threat" имеется 22 типа данных:

 

DATATYP_NULL

Переменная имеет нулевую величину

DATATYP_UNKNOWN

Это тип данных устанавливается ScE если он не может определить тип данных переменной.

DATATYP_VAR

Этот тип является внутренним типом переменной ScE. Этот тип является внутренним типом переменной и значение  задается непосредственно ScE

DATATYP_CONST

Переменная-константа описанная в ScE. Этот тип является внутренним типом переменной и значение  задается непосредственно ScE

DATATYP_INT

Численная переменная в диапазоне

 [-2147483648,2147483647] или

 [-0x80000000,0x7FFFFFFF]

DATATYP_STRING

Переменная содержащая данные в виде текста. Пример:  $str= Hello World!!!

DATATYP_SHIP

Указатель на корабль. Переменная ссылается на объект Корабль

DATATYP_STATION

Указатель на станцию. Переменная ссылается на объект Станция

DATATYP_SECTOR

Указатель на сектор. Переменная ссылается на объект Сектор

DATATYP_WARE

Переменная Товар в "X2 The Threat" это, все что можно купить или продать (кроме кораблей станций)

DATATYP_RACE

Переменная-указатель  на расу объекта (Аргон, Борон, Сплит, Игрок и т.д.).

DATATYP_STATIONSERIAL

Порядковый номере объекта Станции и соответствующая ему буква в греческом алфавите. (альфа, бета, гама, и т.д.)

DATATYP_OBJCLASS

 

DATATYP_TRANSPORTCLASS

Переменная константа принимающая значение класса транспорта (ST, XL, L, etc.)

 

DATATYP_RELATION

Отношение  Друг (Friendly)– Нейтральный (Neutral)– Враг (Enemy)

DATATYP_OP

Тип данных Оператор. Этот тип является внутренним типом переменной и используется непосредственно самим ScE

DATATYP_EXPR

Выражение. Этот тип является внутренним типом переменной и используется непосредственно самим ScE

DATATYP_OBJECT

Указатель на объект. Переменная ссылается на объект не являющийся кораблем, станцией или сектором, а только солнцем, туманностью или астероидом.

DATATYP_OBJCOMMAND

Переменная содержит мнемосхему команды

DATATYP_FLRET

Переменная содержит код возврата команды fly to (описание далее)

DATATYP_DATATYP

Переменная содержит тип данных. Используется в инструкциях типа get datatype

 

DATATYP_ARRAY

Переменная является массивом

 

Большинство используемых НС инструкций возвращают результат который может быть помещен в переменную для дальнейших действий. А непосредственно над переменной, вы сможете выполнять арифметические, логические и т.п. операции как было описано в начале главы.

Для объявления переменной используется инструкция из раздела «Основные команды» “<RetVar/IF><Expression>”. Выбрав данную инструкцию в списке редактор предложит ввести имя переменной. После ввода нажимайте «Enter». Редактор вернется к листингу скрипта и вы увидите следующие выражение:

 

001            $MainVar = «?»

 

«?» красным цветом, говорит о том что редактор ожидает дальнейшего ввода данных. Нажимайте «Enter» выберете тип данных из открывшегося списка, а затем и сами данные. Например: выбираем тип данных станция, далее редактор предлагает  выбрать сектор и станцию при помощи открывающихся интерфейсов. Выбираем сектор Аргон Прайм станцию Арогонская торговая станция.

 

001            $MainVar = Аргонская торговая станция [Аргон Прайм]

 

Теперь объявленная нами переменная $MainVar указывает на Аргонскую торговую станцию находящуюся в секторе Аргон Прайм.

 

 

v    Массивы.

 

      Продолжая рассматривать наш пример предположим, что у нас возникает потребность в том, чтобы наша переменная содержала в себе указатель не на одну станцию, а на целый список. Мы могли бы это решить объявив для каждой станции из списка свою собственную переменную, но если в нашем списке несколько десятков или даже сотен станций, то время и силы потраченные на эту работу начисто отбили бы интерес к скриптописанию. Здесь на помощь нам приходит особая переменная, которая умеет хранить в себе огромное количество однотипных данных, название  этой переменной МАССИВ. В массиве данные расположены как в таблице с пронумерованными строками. Номера строк называются индексом массива, общее количество строк размером массива, а данные элементами массива. То есть, для того чтобы использовать данные из массива нам необходимо установить указатель индекса на нужный элемент и получить его значение в переменную. Синтаксис такой операции с массивом в ScE выглядит так:

 

006      $MainVar = $array [2]

 

В данном примере элемент массива $array с индексом [2] будет помещен в переменную $MainVar.

      Следует обратить внимание на то, что индексация массивов начинается с 0, а не с 1. То есть, в массиве размерностью в десять элементов, первый элемент будет иметь индекс 0, а последний 9.

Теперь давайте рассмотрим как в ScE организован сам массив.

Прежде всего запомните, что переменная типа <Var/Array> в ScE Х2 сама по себе не является массивом, а только указателем на область памяти где он храниться. То есть когда вы используете инструкцию <RetVar>=array alloc: size=<Var/Number> для того чтобы создать новый массив, вы даете ScE указание распределить память под указанное в инструкции количество элементов и вернуть в переменную указатель на эту область. Этот указатель называется – пойнтер. Именно из-за этого, в ScE для выполнения копирования массивов предусмотрены специальные инструкции, т.к. скопировать массив в другую переменную при помощи инструкции $array2=$array1 на удастся. После того как ScE выполнит эту команду, мы будем иметь две переменные указывающие на один и тот же массив.

 

соответственно если произвести работу с каким либо элементом массива $array1, значения изменяться и для псевдо массива $array2:

005     $array2=$array1

006     $array1 [2] = 5

007     $var = $array2 [2]

значение переменной $var = 5, так как пойнтеры $array1 и $array2 указывают на одну и ту же область памяти.

            Для того, чтобы получить копию массива, нам следует использовать команду <RetVar>=clone array <Var/Array>: index <Var/Number>  <Var/Number>. Если в нашем примере заменить строку 005 на :

005     $array2=clone array $array1: index 0 … 2

            Теперь мы имеем два независимых массива, а переменная $array2 содержит пойнтер на новую область памяти в которой расположена копия трех элементов из массива $array1.

Не забывайте учитывать данную особенность работы ScE с массивами при написании своих скриптов.

      При создании массива, также надо учитывать тип данных хранящийся в нем. Например если массив содержит данные о точке в секторе Var/Sector Position, то данные будут располагаться следующим образом: координата x[0], y[1], z[2], sector[3]. Соответственно если в массиве информация о трех точках, то размерность массива составит 12 элементов с 0 по 11, первая точка индексы [0-3], вторая [4-7], третья [8-11].

 

v    Константы

Константы – это величины имеющие постоянное значение. В ScE Х2 используется несколько типов констант: первый тип Глобальные константы, это константы которые может использовать практически любая команда, и приватные константы, это константы зарезервированные для каких либо команд и используются только ими.

 

В таблице указанны все используемые константы имеющиеся в Х2:

 

Глобальные константы

THIS

указатель на объект, который только что получил команду и занялся ее выполнением. Например, вы запустили на корабле команду "Покупать товар". Этот корабль и будет THIS.

PLAYERSHIP

Указывает на корабль в котором сидит игрок

HOMEBASE

Указывает на базу приписки текущего объекта

ENVIRONMENT

возвращает объект-окружение для другого объекта. Например, если корабль в космосе, то его окружение объект "сектор", а если пристыкован к базе - "база" и т.п.

SECTOR

возвращает объект-сектор, в котором находится текущий объект.

OWNER

Константа указатель на владельца текущего объекта

NEAREST

Константа указывающая на ближайший объект, по отношению к текущему объекту.

FALSE

Константа ЛОЖЬ

TRUE

Константа ИСТИНА

DOCKEDAT

Константа указывает на станцию или носитель в доке которого находится текущий корабль. Если корабль не в доке, то принимает значение FALSE

 

Приватные константы:

 

Formation.Delta

Константы указывающие на тип построения для команды set formation подробно рассмотрены в описании команды.

Formation.Line

Formation.X

Formation.XDelta

Formation.BigShipEscort

Formation.Pyramid

Formation.Random

Find.Random

Константы Find являются флагами при организации поиска, каждая константа имеет числовое значение, допускается использовать эти константы в виде комбинаций составленных через побитовое ИЛИ «|».

Find.Nearest

Find.ExactJumps

Find.Enemy

Find.Neutral

Find.Friend

Find.Multiple

Find.TypeAsWareCategorie

Find.IllegalWare

Find.ForceUsePos

CmdConCheck.Available

Константы используемые командой set script command upgradescript, как флаги возвращаемые проверочным скриптом. Флаги используются для активации или деактивации строки в командном меню. (См. описание команды)

CmdConCheck.Disabled

CmdConCheck.OneTime

CmdConCheck.Infinite

CmdConCheck.NeedHomeStation

CmdConCheck.NeedHomeBase

IncomingTransmission.SOS

Набор констант для аудиокоманды play sample: incoming transmission, (подробное описание этих констант в описании команды)

IncomingTransmission.Message

IncomingTransmission.Greeting

IncomingTransmission.Scanned

Comm.DLG_C_START_FIGHTING

Используется аудиокомандой send audio message, (см. описание команды)

Comm.DLG_POL_ILLEGAL_GOODS

Comm.DLG_POL_LAST_WARNING

Comm.DLG_POL_LEGAL_GOODS

 

Если вы просматривали список констант который предлагает редактор, то наверняка заметили, что в этот список не вошли несколько групп констант. Это специальные внутренние константы  ScE (SSTYPE, ACTION, GalaxyFlight) и нам для использования они недоступны (то есть выбрать мы их можем, но они не имеют никакого информативного содержания).

 

 

v    Операции

 

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

В ScE Х2 операндами могут являться константы, числа, переменные, строковое выражение, указатели на объект. Какие именно действия нужно произвести над операндами, ScE сообщает знак операции (+,-,*,/ и т.п.).

Все операции производимые в ScE, можно разделить на несколько групп:

·        Арифметические;

·        Сравнения;

·        Логические

·        Побитовые (формальная логика)

·        Отрицания и дополнения

 

Давайте подробнее рассмотрим каждую группу:

 

Арифметические операции.

 

Арифметические операции выполняют общий набор математических действий (сложение, вычитание, умножение, деление  и т.п.). Обратите внимание, что в ScE все операции цельно-численные, то есть не допускается использования дробных чисел, все числовые операнды должны являться целыми числами. Последовательность выполнения вычислений математическая, то есть слева на право, умножение имеет более высокий приоритет чем сложение. В выражениях можно изменять последовательность вычислений используя скобки (угловые скобки), допускается многоуровневое построение выражений используя вложенность скобок, например математическое выражение ((3+2)*5)+10, в ScE будет выглядеть так: [[3+2]*5]+10.

 

 

 

+

сложение

-

вычитание

*

умножение

/

Деление

mod

Получение остатка от деления

[

Математические скобки

]

 

Сложение:

001      $MainVal = 3                          *Присвоить переменной $MainVal значение 3

002      $Total = $MainVal + 8            *Прибавить к $MainVal число 8, $Total = 11

003      $Total = $Total - $MainVal     *Операция вычитания  $Total = 8

004      $Total = 5 * 6                          *Умножение $Total = 30

005      $Total = [2+3]*5                     *Использование скобок $Total = 25

006      $Total = 7+[-2]                       *Использование отрицательных чисел $Total = 5

007      $Total = 49 / 10                      *Деление $Total = 4 (результат цельно-численный)

008      $Total = 49 / [-10]                   *$Total = -4

009      $Total = 49 mod 10                *Остаток от деления $Total = 9 (10*4=40+9=49)

010      $Total = 49 mod [-10]             *$Total = 9

011      $Total = -49 mod [-10]           *$Total = -9

 

Диапазон используемых чисел ограничен от  -2 147 483 648 до 2 147 483 647  или в шестнадцатеричном исчислении от -0x80000000 до 0x7FFFFFFF.

      Следует заметить о еще одной особенности оператора «+», это возможность работать со строковыми переменными. При помощи этого знака можно сложить две переменные содержащие текстовые строки.

 

Пример:

001      $str1 = ‘Наша Маша’

002      $str2 = ‘ громко плачет.’

003      $str1 = $str1 + $str2

 

Теперь переменная, $str1 содержит строку «Наша Маша громко плачет.» Для того, чтобы соединяемые фразы были разделены пробелом, не забывайте добавлять его в конце первой или начале второй.

 

Операции сравнения.

 

Операции сравнения, формируют значение [FALSE] (0 Ложь) или [TRUE] (1 Истина) в зависимости от результата обработки операндов. Возвращаемое операцией значение используется для обработки такими операторами как IF, IF NOT, SKIP IF. SKIP IF NOT, WHILE и т.п. Операции сравнения выполняются слева на право.

 

==

проверка условия «равно»

!=

проверка условия «не равно»

>

проверка условия «больше»

<

проверка условия «меньше»

>=

проверка условия «больше или равно»

<=

проверка условия «меньше или равно»

 

Примеры использования:

 

001      $variable = 10                         *присвоить переменной $variable значение 10

002      if $variable == 10                   *сравнить равно ли значение $variable, 10 [TRUE]

003      skip $variable > 5                   *сравнить $variable больше 5 [TRUE]

004      skip not $variable < 5             *сравнить $variable меньше 5 [FALSE]

005      while $variable >= 20             *сравнить $variable больше или равно 20 [FALSE]

006      while not $variable != 20        *сравнить значение $variable не равно 20 [TRUE]

 

Логические операции.

 

К логическим операциям относиться операция логического «И» (оператор AND) и логического «ИЛИ» (оператор OR). Логические операции не вызывают ни каких арифметических преобразований. Они оценивают каждый операнд с точки зрения его эквивалентности нулю. Результатом логической операции является  [FALSE] (0 Ложь) или [TRUE] (1 Истина). Операции выполняются слева на право.

 

Операция логического И (оператор AND) вырабатывает значение 1, если оба операнда имеют значение 1. Если один из операндов равен 0, то результат будет равен 0.

Примеры:

001      $variable = 10

002      if $variable == 10 AND 5+5==10       *результат 1 [TRUE]

003      if $variable == 10 AND 5+5==11       *результат 0 [FALSE]

 

Операция логического ИЛИ (оператор OR) выполняет над операндами операцию включающего ИЛИ. Она вырабатывает значение 0, если оба операнда имеют значение 0, если какой-либо из операндов имеет ненулевое значение, то результат операции равен 1.

Примеры:

001      $variable = 10

002      if $variable == 10 OR 5+5==10         *результат 1 [TRUE]

003      if $variable == 10 OR 5+5==11         *результат 1 [TRUE]

004      if $variable == 11 OR 5+5==11         *результат 0 [FALSE]

 

Побитовые операции (формальная логика).

 

К поразрядным операциям относятся: операция поразрядного логического "И" (&), операция поразрядного логического "ИЛИ" ( | ), операция поразрядного "исключающего ИЛИ" (^).

 

Операция поразрядного логического И (&) сравнивает каждый бит первого операнда с соответствующим битом второго операнда. Если оба сравниваемых бита единицы, то соответствующий бит результата устанавливается в 1, в противном случае в 0.

 

Операция поразрядного логического ИЛИ (|) сравнивает каждый бит первого операнда с соответствующим битом второго операнда. Если любой (или оба) из сравниваемых битов равен 1, то соответствующий бит результата устанавливается в 1, в противном случае результирующий бит равен 0.

 

Операция поразрядного исключающего ИЛИ (^) сравнивает каждый бит первого операнда с соответствующими битами второго операнда. Если один из сравниваемых битов равен 0, а второй бит равен 1, то соответствующий бит результата устанавливается в 1, в противном случае, т.е. когда оба бита равны 1 или 0, бит результата устанавливается в 0.

 

Пример.

001      $int = 17919               *0100 0101 1111 1111

002      $int2=255                   *0000 0000 1111 1111

 

003      $res = $int ^ $int2       *0100 0101 0000 0000

004      $res = $int | $int2        *0100 0101 1111 1111

005      $res = $int & $int2      *0000 0000 1111 1111

 

 

Операции отрицания.

 

Операция арифметического отрицания (-) вырабатывает отрицание своего операнда. Операнд должен быть целой величиной. При выполнении осуществляются обычные арифметические преобразования.

 

Пример:

001      $int = 5

002      $int= - $int                  *Значение $int = -5

 

Операция логического отрицания "НЕ" (!) вырабатывает значение 0, если операнд есть истина (не нуль), и значение 1, если операнд равен нулю (0).

 

Пример:

001      $int = 5

002      $int= ! $int                  *Значение 0 [FALSE] т.к. $int Истина

 

Операция двоичного отрицания (~) вырабатывает двоичное отрицание своего операнда. Операнд должен быть целого типа. Осуществляется обычное арифметическое преобразование, все биты операнда инвертируются.

 

Пример:

001      $int = 17919               *0100 0101 1111 1111

002      $int=~$int                   *1011 1010 0000 0000

 

 

 

v    Операторы условного перехода

 

Операторы условного перехода используются для того, чтобы изменить последовательность выполнения команд в скрипте в зависимости от определенного условия. Простейшим примером оператора условного перехода может служить оператор «if» применяющийся в паре с оператором «end». Логика его работы следующая:

 

if (выражение принимающее значение «Истина» или «Ложь»)

операторы, исполняющиеся в случае, если выражение принимает значение «Истина»

end

 

 

 

Пример:

 

210      if [HOMEBASE]

220          @ = [THIS] -> fly to homebase

230      end

 

В строке 210 проверяется, задана ли база для данного корабля. Если она установлена (функция [HOMEBASE] вернула значение, которое может быть интерпретировано как «Истина»), то управление переходит в строку 220, где корабль получает команду возвращаться на неё. Поскольку нам может быть необходимо, чтобы при выполнении определенного условия исполнялся не один, а целая группа операторов, мы должны указать, где именно заканчивается эта группа. Для этой цели и служит оператор «end». Оператор «if» может принимать и более сложные формы:

 

if (выражение, принимающее значение «Истина» или «Ложь»)

операторы, исполняющиеся в случае, если выражение принимает значение «Истина»

else

операторы, исполняющиеся в случае, если выражение принимает значение «Ложь»

end

 

 

if not (выражение, принимающее значение «Истина» или «Ложь»)

операторы исполняющиеся в случае если выражение принимает значение «Ложь»

else

операторы исполняющиеся в случае если выражение принимает значение «Истина»

end

 

if (выражение1, принимающее значение «Истина» или «Ложь»)

операторы исполняющиеся в случае, если выражение1 принимает значение «Истина»

else if (выражение2, принимающее значение «Истина» или «Ложь»)

операторы исполняющиеся в случае, если выражение1 принимает значение «Ложь», а выражение2 принимает значение «Истина»

else

операторы исполняющиеся в случае, если выражение1 принимает значение «Ложь» и выражение2 принимает значение «Ложь»

end

 

 

if not (выражение1, принимающее значение «Истина» или «Ложь»)

операторы исполняющиеся в случае, если выражение1 принимает значение «Ложь»

else if not (выражение2, принимающее значение «Истина» или «Ложь»)

операторы, исполняющиеся в случае, если выражение1 принимает значение «Истина» а выражение2 принимает значение «Ложь»

else

операторы, исполняющиеся в случае, если выражение1 принимает значение «Истина» и выражение2 принимает значение «Истина»

end

 

 

 

skip if (выражение, принимающее значение «Истина» или «Ложь»)

оператор, исполняющийся в случае, если выражение принимает значение «Ложь»

 

В данной форме записи оператора «if» оператор «end» не требуется, поскольку в случае если выражение принимает значение «Истина» пропускается (не выполняется) только один оператор (не группа операторов), следующий в строке сразу за «skip if»

 

 

 

skip if not (выражение принимающее значение «Истина» или «Ложь»)

оператор, исполняющийся в случае, если выражение принимает значение «Истина»

 

 

 

 

 

v    Операторы безусловного перехода

 

К операторам безусловного перехода относится оператор «goto label», который используется для перехода к определенной строке скрипта. Прежде чем использовать «goto label» необходимо объявить метку для строки, в которую мы хотим осуществить переход. Делается это при помощи оператора «define label» из раздела «Общие команды=>Команды исполнения».

 

Пример:

 

100 StartCalculation:

110 $Total = $Price * $Amount

120 …

430 goto label StartCalculation

 

 

Само ключевое слово «define label» в тексте скрипта не указывается, вместо него указывается имя метки со знаком «:» – двоеточие после него. Будьте особенно внимательны используя конструкцию  «define  label»  «goto label» так как с её помощью очень легко получить «вечный» цикл, т.е. закольцованный кусок программы, выход из которого не предусмотрен, а при отсутствии в сегменте кода между меткой и оператором goto команд wait и команд со знаком @ произойдет зависание игры.

Х2 help Dimaxx & Pegasus script MAD_Kuzia

v    Циклы

 

Принципы использование циклов

 

Циклы используются для повторения  действия (или последовательности действий) нужное нам кол-во раз. Сколько в цикле будет витков (проходов цикла), определяется условием цикла. В развитых языках программирования существуют циклы 3-х типов: с проверкой условия в начале, с проверкой условия в конце и итерационные (с явно заданным кол-вом витков). В принципе, все они являются взаимозаменяемыми, однако выделены в разные типы для нашего удобства. Скриптовый движок Х2 использует только один тип цикла – с проверкой условия в начале.

Бывает 2-х видов:

 

while <условие>

  …

end

 

Этот цикл выполняется, пока условие имеет значение “Истина” (TRUE).

 

while not <условие>

  …

end

 

Этот цикл выполняется, пока условие имеет значение “Ложь” (FALSE).

 

В качестве условия могут быть использованы числа, переменные, логические выражения, сложные логические выражения использующие логические операторы AND, OR, сложные вычисляемые выражения, возвращаемые значения инструкций. Оператор цикла While интерпретирует любое значение как логическое значение Истина или Ложь. Истиной является любое значение большее 0, ложью считается значение 0 или null.

 

Итерационный цикл

 

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

 

001      $count = 0

002      while $count < 20

  …

  …

007      inc $count =

008      end

 

Здесь у нас счетчик – переменная $count, которой перед началом цикла мы присваиваем начальное значение 0. Далее мы организуем цикл, который будет продолжаться, пока наш счетчик будет меньше 20. Перед каждым последующим витком цикла мы увеличиваем значение счетчика на 1. Как видите, процесс неложный.

 

Бесконечный цикл

 

Это цикл, который выполняется бесконечное число раз, если мы не прервем его специально. Такие циклы широко используются в скриптах для различных команд корабля: торговли, патрулирования и т.п. Например, команда «Продавать товар по лучшей цене» выполняется постоянно, пока мы не прервем ее другой командой. Такие бесконечные циклы организуются просто: достаточно оператору цикла задать в качестве условия заведомо неизменное значение. Например:

 

while [TRUE]

  …

end

 

или

 

while 1

 …

end

 

Бесконечные циклы нужно использовать очень аккуратно, внутри них обязательно надо предусматривать временные задержки (команды wait), иначе можно легко «подвесить» игру. Это связано с тем, что все запущенные скрипты выполняются в игре по-очереди, т.к. движок игры основан на принципе «Не вытесняющей многозадачности» (будет рассмотрено в следующей главе). Задержки внутри скриптов позволяют  приостановить текущий скрипт и дать в это время возможность выполняться другим скриптам. Если внутри бесконечного цикла не будет задержки (или вызова команды, которая имеет свои задержки, команды перед которыми стоит значок @), то этот скрипт захватит все процессорное время и подвесит игру.

Бесконечный цикл можно получить ненарочно, задав некорректное условие оператору цикла. Например:

 

while $a !=1 OR $a = 1

end

 

Здесь цикл будет выполняться при любом значении $а, что приведет к бесконечному “зацикливанию”. Зацикливание можно получить в итерационном цикле (см. пример выше), забыв изменить значение счетчика (оператор inc). Ошибочных вариантов много, всех не перечислишь, поэтому всегда будьте внимательны с циклами, условными и бесконечными, тщательно все продумывайте, чтобы не получилось неприятностей. И возьмите за правило, добавлять в тело любого цикла команду wait с небольшой задержкой, это убережет игру от зависания в случае некорректного условия и сохранит возможность принудительной остановки некорректно работающего скрипта.

 

Дополнительное управление циклами

 

Скриптовый язык Х2 имеет, подобно прочим языкам, команды break и continue. Эти команды служат для дополнительного гибкого контроля над циклами. Команда break позволяет в любой (нужный нам) момент прервать текущий цикл, а команда continue – прервать текущий виток и сразу перейти на следующий.

 

Пример для команды break:

 

while $i < 40

  … последовательность действий 1

 skip if  $i != 20

    break

  … последовательность действий 2

end

 

Здесь цикл будет выполняться, пока $i меньше 40, и принудительно прервется, если $i станет равным 20. При этом успеет выполнится последовательность действий 1, а до последовательности действий 2 дело не дойдет.

 

Пример для команды continue:

 

while $i < 40

  … последовательность действий 1

 skip if  $i != 20

    continue

  … последовательность действий 2

end

 

Здесь цикл будет выполняться, пока $i меньше 40, и принудительно начнется новый его виток, если $i станет равным 20. При этом успеет выполнится последовательность действий 1, а последовательность действий 2 – нет.

 

Также можно прервать текущий цикл, используя операторы безусловного перехода. Например:

 

while $i < 40

  … последовательность действий 1

 skip if  $i != 20

    goto label metka

  … последовательность действий 2

end

… последовательность действий 3

metka:

… последовательность действий 4

 

Здесь цикл будет выполняться, пока $i меньше 40, и принудительно прервется, если $i станет равным 20. При этом успеет выполнится только последовательность действий 1, после чего мы сразу перейдем к последовательности действий 4, минуя последовательность 2, принадлежащую циклу, и последовательность 3, которая наступила бы при нормальном завершении цикла. Как видите, оператор безусловного перехода goto label можно использовать даже более гибко, чем команду break.

 

Далее давайте рассмотри несколько примеров использования циклов в навигационных скриптах:

И так, циклы используются, когда вам необходимо повторять определенную последовательность команд, пока не будет достигнуто некоторое условие. Конечно, получить зацикленный кусок кода можно и используя операторы безусловного перехода, однако подобный подход не рекомендуется, поскольку он ухудшает читаемость кода, к тому же использовать команды цикла гораздо удобнее и проще. Вот пример простейшего цикла:

 

010 while [ENVIRONMENT] != [HOMEBASE]

011 @=wait randomly from 5000 to 10000 ms

012 @=[THIS] ->fly to home base

013 end

 

 

В строке 010, заголовке цикла («while»), задано условие цикла (пока корабль не пристыкован к своей базе), пока оно истинно, т.е. принимает значение «истина», цикл выполняется, т.е. выполняются строки с номерами 011 и 012 (ждать 5-10 сек, возвращаться на базу). Как только выполнение скрипта доходит до строки 013, управление передается в строку 010, проверяется условие и если оно выполняется (принимает значение «истина»), то снова выполняются строки 011 и 012, и так до тех пор, пока условие не примет значение «ложь». Как только условие становится ложно, управление переходит в строку, следующую за «end». Если срока с ключевым словом «end» последняя в скрипте, выполнение скрипта завершается. Однако нам может понадобится выйти из цикла до того как условие цикла примет значение «ложь» (например, базу уничтожили, в этом случае корабль никогда не сядет на свою базу, и цикл окажется «вечным»). Для этих целей служит команда «break». Она передает управление в строку, следующую за «end». С учетом проверки на существование базы наш цикл можно записать следующим образом:

 

010 while [ENVIRONMENT] != [HOMEBASE]

011 if not [HOMEBASE]

012 break

013 end

014 @ =wait randomly from 5000 to 10000 ms

015 @ =[THIS] ->fly to home base

016 end

 

Ключевое слово «end» стоящее в строке 013 относится к оператору «if» стоящему в строке 011, «end» всегда относится к ближайшему «if» или «while». Оператор «while» можно записать и как «while not», в этом случае значение выражения, задающего условие цикла, инвертируется. Вот так будет выглядеть предыдущий пример в форме «while not»:

 

010 while not [ENVIRONMENT] == [HOMEBASE]

011 if not [HOMEBASE]

012 break

013 end

014 @ =wait randomly from 5000 to 10000 ms

015 @ =[THIS] ->fly to home base

016 end

 

 

 


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