Назад: Порядок работы интерпретатора
Иногда в процессе игры нам требуется на время сохранить какую-либо информацию. Например, герой срывает с дерева яблоки, и нам нужно куда-то "записать", сколько яблок он сорвал. Или же в результате битвы погибает злодей, и нам нужно, чтобы плеер "запомнил", что злодей погиб. Для таких вот "записей", "запоминаний", и существуют переменные.
Переменная - это именованная "ячейка памяти". То есть это некий кусочек памяти в программе, которому мы назначаем имя.
Для удобства можно представлять переменную, как коробку, в которую мы что-нибудь "складываем", например число, или фрагмент текста (или даже несколько значений одновременно - кортеж).
Память программ работает совсем не так, как наша, и "запоминать" они могут только определённого типа значения. QSP умеет "запоминать" только целочисленные (числовые) и строковые значения. Особняком можно отметить кортежи, которые позволяют упаковать в одну переменную сразу группу значений.
Поэтому и переменные в QSP делятся на три типа:
В целочисленных переменных (иногда для краткости их называют просто числовыми) мы можем хранить только целые числа в пределах от -2147483648 до 2147483647.
Если мы не поместили никакого значения в целочисленную переменную, то считается, что она хранит значение 0
. Это значение по умолчанию для числовых переменных.
В строковых переменных (иногда их называют текстовыми переменными) мы можем хранить целые строки текста, и длина таких строк может доходить до двух Гигабайт. Строка не может превысить объём оперативной памяти.
Если мы не поместили никакого значения в строковую переменную, то считается, что она хранит пустую строку, т.е. строку совсем без символов. Это значение по умолчанию для строковых переменных.
В кортежах мы можем хранить сразу группу значений, причём это могут быть значения любого из трёх типов: числовые, строковые и другие кортежи. Не рекомендуется создавать очень большие кортежи, хотя теоретически кортежи могут быть очень большими. Если вам и правда понадобится настолько большой кортеж, примите во внимание, что как и со строкой, объём занимаемых кортежем данных не может превысить двух Гигабайт, или объёма оперативной памяти.
В переменной можно хранить значение только одного типа! Переменные %яблоко
, $яблоко
и яблоко
— это одна и та же переменная, но с разным типом значения, которое в ней хранится.
Чтобы создать переменную, мы должны задать ей значение. Это называется операцией присваивания.
Операция присваивания в QSP записывается так:
Примеры:
! переменной яблоко присваивается число 23 яблоко=23 ! переменной $скороговорка присваивается строка Ехал Грека Через Реку $скороговорка = 'Ехал Грека Через Реку' ! переменной %unit присваивается кортеж значений %unit = [187, 94, 'steel', [0, 2]]
Как видите, во всех трёх случаях сначала ставится имя переменной, потом знак равенства, а потом значение. Вместо значения можно написать название другой переменной, название функции, или даже целое выражение. Плеер автоматически вычислит значение из выражения, функции или переменной, и присвоит это значение переменной, стоящей слева от знака равно. Примеры:
! присваиваем переменной значение другой переменной $скороговорка_про_Греку = $скороговорка ! присваиваем переменной значение выражения яблоко = яблоки_в_кармане + яблоки_в_лукошке + яблоки_у_Лёшки ! присваиваем переменной значение функции случайное_число = rnd $текущая_локация = $curloc
Не путайте операцию присваивания, и операцию сравнения. Их запись похожа, но операция сравнения обычно следует за ключевыми словами IF
, ELSEIF
или WHILE
и позволяет сравнивать одно значение с другим.
Вы можете одной командой присвоить значения сразу нескольким переменным (множественное присваивание). Для этого:
Примеры:
яблоки_в_кармане, яблоки_в_лукошке, яблоки_у_Лёшки = 58, 11, 19 $строка_1, $строка_2 = 'Ехал Грека Через Реку', 'Видит Грека В Реке Рак' $name, count = 'Старый меч', 2
Во всех трёх командах слева от знака равно через запятую перечисляются переменные, которым мы присваиваем значения, а справа через запятую перечисляются значения, которые мы присваиваем переменным.
Вместо прямого указания значений можно присваивать значения других переменных, выражений, функций:
! три переменные = три значения red, green, blue = rand(0,255), rand(0,255), rand(0,255) ! две переменные = два значения яблоки_в_кармане, яблоки_в_лукошке = яблоки_у_Лёшки, яблоки_на_дереве+15
Присваивать значения одной командой очень удобно, если переменные близки по своему смыслу или назначению. Например, одной строкой можно задавать значения сразу нескольким системным переменным в начале игры:
usehtml, debug, nosave = 1, 1, 1 bcolor, lcolor, fcolor = rgb(255,255,255), rgb(0,90,90), rgb(0,0,0)
Благодаря возможности одновременно присваивать значения сразу нескольким переменным, можно менять местами данные в двух переменных, не прибегая к помощи третьей:
! присваиваем пременным x и y значения 12 и 99 x, y = 12, 99 ! меняем местами значения. Теперь в x находится число 99, а в y — 12 x, y = y, x
Важно помнить! Слева от знака равенства должно быть столько же переменных, сколько справа значений. Число переменных, и число присваиваемых значений — должны совпадать. Такие записи неверны:
! три переменные, а значения только два raz, dva, tri = 24, 67 ! одна переменная, и два значения chetyre = 89, 21
Так же в одной команде можно использовать лишь один оператор присваивания:
! так неправильно: raz = 24, dva = 67, tri = 89 ! а вот так правильно raz, dva, tri = 24, 67, 89 ! и вот так правильно, потому что здесь три команды записаны в одну строку raz = 24 & dva = 67 & tri = 89
Поскольку кортежи содержат в себе сразу несколько значений, запись присваивания значений переменным из кортежа может показаться необычной:
! %unit = [187, 94, 'steel', [0, 2]] рост, вес, $материал, %координаты = %unit
Как видите, здесь у нас слева четыре имени переменной, а справа только одно имя переменной-кортежа. Такое присваивание называется распаковкой — значения извлекаются из кортежа и помещаются в указанные переменные.
Точно так же распаковывается кортеж, даже не помещённый в переменную:
рост, вес, $материал, %координаты = [187, 94, 'steel', [0, 2]]
Такая запись мало чем отличается от множественного присваивания, поэтому внешние квадратные скобки не обязательны:
рост, вес, $материал, %координаты = 187, 94, 'steel', [0, 2]
Подробнее о работе с кортежами, читайте в соответствующем разделе.
Из старых версий плеера перекочевали операторы SET
и LET
. Эти операторы явно указывают, что данная команда производит присваивание. Любой из этих операторов может быть поставлен перед операцией присваивания, это никак не влияет на работу переменных. В примере ниже все три варианта присваивания значения переменным равнозначны:
SET golden_axe_damage = 120 LET golden_axe_damage = 120 golden_axe_damage = 120
Точно так же, как и в операции присваивания без операторов SET
и LET
, можно присваивать значения сразу нескольким переменным одной командой и с использованием операторов:
set яблоки_в_кармане, яблоки_в_лукошке, яблоки_у_Лёшки = 58, 11, 19 set $строка_1, $строка_2 = 'Ехал Грека Через Реку', 'Видит Грека В Реке Рак' let $name, count = 'Старый меч', 2
Для улучшения читаемости кода можно использовать оператор SET
только для команд с множественным присваиванием.
Оператор LET
использовать не рекомендуется.
Изменить тип переменной в QSP можно, просто присвоив ей значение другого типа. Например:
! присваиваем переменной строковое значение $яблоко = 'Антоновка' ! если мы попытаемся вывести на экран числовое значение этой переменной, ! то увидим значение по умолчанию, то есть ноль: *pl яблоко & ! выведет 0 на экран ! но мы можем изменить тип переменной, записав в неё число яблоко = 19 ! теперь, если мы попытаемся вывести на экран то же числовое значение ! мы увидим число 19 *pl яблоко & ! выведет 19 на экран ! а если мы попытаемся вывести на экран текстовое значение, ! то ничего не увидим, потому что числовое значение затёрло текстовое *pl $яблоко
Чтобы не сбивать плеер с толку, названия переменных должны соответствовать следующим условиям:
! : & = < > + - * / , ' " ( ) [ ] { } @ ? ;
$
.%
.деньги
и ДеНьГи
- одна и та же переменная.А вот несколько рекомендаций по тому, как правильно подбирать названия переменных
_
".Используйте краткие и ёмкие названия, указывающие на назначение переменной. При этом QSP разрешает пользоваться символами любого алфавита:
яблоки_в_кармане = 3 $АмулетНаШее = "Ожерелье Гроз" money_count = 1037 $money_name = "RUB" 我_拿_钥匙 = 1 %饭碗 = ["Rice Bowl", 'Cat-wife ']
Удалить переменную можно с помощью оператора KILLVAR
.
KILLVAR 'имя_переменной'
Имя переменной при этом должно помещаться в кавычки:
killvar 'яблоки_в_кармане' killvar "$АмулетНаШее"
Более подробное описание оператора KILLVAR
находится в статье про массивы.
В QSP нет специальной команды для проверки существования переменных, однако в силу особенностей движка можно использовать функцию получения размера массива ARRSIZE
. Если функция вернёт единицу 1, значит переменная существует; если вернёт 0, значит переменная не существует.
яблоко = 19 & ! создана переменная яблоко ! увидим на экране Переменная "яблоко" существует if arrsize('яблоко') = 1: *pl 'Переменная "яблоко" существует' else *pl 'Переменная "яблоко" не существует' end ! переменную груша мы не создавали ! увидим на экране Переменная "груша" не существует if arrsize('груша')=1: *pl 'Переменная "груша" существует' else *pl 'Переменная "груша" не существует' end
Название переменной для функции ARRSIZE
указывается внутри кавычек и помещается в круглые скобки. Указывать символ $
или %
перед названием переменной не обязательно. Вне зависимости от типа значения, которое в этой переменной хранится, ARRSIZE
вернёт единицу, если переменная существует:
яблоко = 19 & ! в переменную записано число ! обе команды ниже вернут единицу, потому что ! яблоко, $яблоко и %яблоко - это одна и та же переменная *pl arrsize('яблоко') *pl arrsize('$яблоко') *pl arrsize('%яблоко')
О функции ARRSIZE
так же можно подробнее почитать в разделе "Массивы".
Чтобы получить значение переменной, достаточно написать её имя в выражении.
При этом, чтобы получить кортеж, нужно поставить перед именем переменной %
, а чтобы получить строковое значение, нужно поставить перед именем переменной $
.
Примеры:
! присваиваем значение одной переменной - другой num = int & ! выражение здесь состоит из одной переменной ! выводим значение переменной на экран *pl $text &! выражение состоит из одной переменной ! вычисляем куб числа, записанного в переменную и выводим на экран d * d * d &! выражение состоит из двух операций умножения
Важно! Если мы пытаемся получить значение переменной, которая не была создана, то такая переменная вернёт значение по умолчанию:
0
(ноль);""
(пустая строка);[]
(пустой кортеж).В QSP есть возможность сделать переменные локальными, то есть их значения будут сохраняться в пределах определённого блока кода, например, только на определённой локации или в отдельном действии.
Чтобы объявить переменную локальной, нужно использовать ключевое слово LOCAL
. В общем виде объявление локальной переменной выглядит так:
LOCAL имя_переменной = [значение]
Здесь имя_переменной
— это имя переменной, которую мы объявляем, а [значение]
— это любое значение, которое мы этой переменной присваиваем. Пример:
! объявляем локальную переменную **tempora** со значением **12** local tempora = 12
Эта запись очень похожа на объявление переменной через оператор SET
, и точно так же, как для оператора SET
, для оператора LOCAL
существует возможность объявить сразу несколько локальных переменных:
! множественное объявление локальных переменных local x, y, $item = 11, 19, "Старый меч"
Как видите, сразу после оператора LOCAL
через запятую перечислены имена объявляемых переменных, затем стоит знак равенства и после него перчислены значения, которые мы присваиваем этим переменным. Число переменных слева от знака =
и число значений справа должны совпадать.
Однако, в отличие от оператора SET
оператор LOCAL
позволяет нам назначить локальные переменные без присвоения им значений. Для этого достаточно просто перечислить после оператора LOCAL
через запятую названия переменных:
local $название_предмета, количество, цена
Здесь оператор LOCAL
работает без операции присваивания. Локальные переменные создаются, но arrsize
для них покажет 0
.
Собственные локальные переменные можно создавать для таких блоков кода как:
DYNAMIC
или функции DYNEVAL
в виде текста.
Внимание! У локальных переменных есть одна особенность, которую нужно очень чётко понимать. Значение объявленной в данном блоке кода локальной переменной транслируется и во все вложенные, или вызванные из данного, блоки кода. Например, если на локации объявлена локальная переменная, то её значение транслируется во все вызываемые с помощью GOSUB
или FUNC
локации, в блоки кода для DYNAMIC
/DYNEVAL
, в блоки циклов и так далее. Пример:
# start ! из этой локации мы будем вызывать локацию foo i=99 & ! объявляем глобальную переменную gosub 'foo' *nl i & ! на экране увидим число 99 - start - # foo ! на этой локации объявляем локальную переменную local i=0 ! локальная переменная транслируется в цикл loop while i<10 step i+=1: ! в цикле мы вызываем локацию undo gosub 'undo' ! и так же в цикле мы работаем с переменной, ! объявленной на локации foo end *nl i & ! на экране увидим число 10 - foo - # undo ! в эту локацию из цикла с локации foo ! транслируется всё та же локальная переменная ! объявленная на локации foo i+=1 & ! увеличиваем значение переменной, влияя на значение в foo *p 'undo:<<i>>, ' & ! на экране появятся числа 1,3,5,7,9 с припиской undo: - undo -
Однако! Значения локальных переменных не транслируются в действия (в отличие от значений массива ARGS
на текущей локации):
$args[0] = 'текущая локация' local $var = 'локальная переменная' *pl $args[0] *pl $var act "Вывести значения": *pl $args[0] *pl $var end
Важно. Значения локальных переменных не передаются в локации-обработчики событий, однако передаются на локации-обработчики пунктов меню. Будьте внимательны.
Две локации, на каждой из которых собственная переменная i
:
# локация 1 if i=0: i=99 & ! значение переменной i задаётся лишь раз *pl "Глобальное i = <<i>>" act "На локацию 2": goto 'локация 2' - локация 1 - # локация 2 *pl "Глобальное i = <<i>>" local i=137 & ! значение переменной i задаётся лишь раз *pl "Локальное i = <<i>>" act "На локацию 1": goto 'локация 1' - локация 2 -
Ещё пример с двумя локациями:
! этот код последовательно выведет на экран числа 12, 549 и 99, 549 # start x=99 z=4608 gosub 'foo' *pl x & *pl z & ! на экран выведутся числа 99 и 549 - start - # foo local x & ! объявляем переменную x локальной для данной локации x=12 & ! изменяем значение переменной x z=549 *pl x & *pl z & ! на экран выведутся числа 12 и 549 - foo -
Пример объявления локальных переменных в коде для DYNEVAL
и в цикле:
$chkObjWord = { ! это код, записанный в виде текста в переменную $chkObjWord ! в локальную переменную $word записываем слово, ! по которому производим поиск local $word = $args[0] loop local i = 1 while no i > countobj step i += 1: ! используем локальную переменную i внутри цикла ! цикл выполняется пока счётчик не превысит число предметов if instr($getobj(i), $word) <> 0: ! как только в названии очередного предмета ! встречается рассматриваемое слово result = i & ! возвращаем позицию exit & ! закрываем функцию end end } object_position = dyneval($chkObjWord, 'граната')
Локальные переменные можно объявлять и внутри действий:
i=99 act "Действие с локальной i": local i = 449933 *pl i end act "Действие с глобальной i": *pl i end