Нововведения в QSP 5.8.0

Алексей Шпак
13 min readJun 11, 2021

--

Что нового?

Пока готовится выход нового плеера версии 5.8.0 (или выше), мы решили рассказать о грядущих нововведениях. Всё (или почти всё), что будет представлено в этой статье, вы уже можете пощупать в плеере “qSpider” от Werewolf`а.

Изменение в работе массивов

Это, пожалуй, самое основное из грядущих изменений, и о нём мы подробно писали в статье “Массивы уже не те”. Здесь же изложим кратко.

Теперь в массиве будет нельзя под одним индексом хранить и текстовое и числовое значение. Если вы запишете в ячейку числовое значение, а потом запишете в ту же ячейку текстовое значение, текстовое значение затрёт числовое.

При этом, если вы попытаетесь получить из ячейки со строковым значением числовое значение, плеер вернёт значение по умолчанию, то есть 0. И наоборот: если попытаться из ячейки с числовым значением получить строковое, плеер вернёт пустую строку.

Примеры:

5.7.0
5.8.0 (qSpider)

Многомерные массивы

Чтобы организовать многомерный массив, в плеерах версии 5.7.0 (и более ранних) приходилось использовать текстовые индексы. Например:

! работает в плеерах любых версий:
$unit_coords["3,1"]="Пехотинец"
$unit_coords["2,7"]="Артиллерист"
$unit_coords["10,0"]="Танк"

Но в новых версиях плеера (начиная с 5.8.0 и выше) можно не использовать текстовые индексы, а указывать несколько нужных значений через запятую:

! версия 5.8.0 и выше
$unit_coords[3,1]="Пехотинец"
$unit_coords[2,7]="Артиллерист"
$unit_coords[10,0]="Танк"

Это намного упрощает работу с многомерными массивами.

Изменения в работе логических операторов и функций

Все мы знаем, что QSP не поддерживает булевы (логические) типы данных, а вместо них в плеерах версии 5.7.0. использовались числа 0 и -1.

Здесь 0 означало Ложь (False), а -1 означало Правду (True). Соответственно и все логические операции возвращали нам эти значения.

Например:

5.7.0

В новых версиях плеера все логические операции будут возвращать 1 в случае Правды (True), и 0 в случае Лжи (False):

5.8.0 (qSpider)

Соответственно и различные функции, возвращавшие “логические” значения, будут возвращать либо 1 (Правда, True), либо 0 (Ложь, False):

5.7.0
5.8.0 (qSpider)

Ещё одно изменение в работе логических операций заключается в том, что теперь они на самом деле будут логическими. Да, оказывается в плеерах версий 5.7.0 и старше операции AND, OR, NO не были логическими — они были побитовыми. Это означает, что данные операции могли выполнять сравнение чисел по отдельным битам и возвращать результат этого сравнения.

Например:

5.7.0

Теперь же, не имеет значения, какое число мы передаём логическому оператору. Если это число отлично от нуля, логический оператор будет воспринимать его как 1, то есть Правду (True).

5.8.0 (qSpider)

И это логично, ведь именно по такому принципу и работали операторы проверки условия if и elseif. Если этим операторам передавалось значение отличное от 0, то это означало, что условие верно (Правда, True).

5.7.0 и 5.8.0 (qSpider)

Аргументы, передаваемые с операторами GOTO и XGOTO

Теперь аргументы (параметры, данные), передаваемые с операторами GOTO и XGOTO, и которые мы можем получить из массива ARGS на локации, однозначно можно будет использовать в действиях, созданных на этой локации.

Раньше это тоже можно было делать, однако в плеере присутствовал досадный баг, который периодически ломал передачу аргументов в действия. Этот баг исправили, и теперь всё прекрасно работает:

# start
goto "proced","текст"
-
# proced
act "Действие":
*pl $args[0]
end
-

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

# start
goto "proced","из аргументов"
-
# proced
act "Действие - 1":
*pl $args[0]
$args[0]="Из действия 1"
end
act "Действие - 2":
*pl $args[0]
$args[0]="Из действия 2"
end
-

https://i.ibb.co/rtpp44q/bandicam-2021-05-31-21-42-18-273-00-00-00-00-00-30.gif

DISABLESUBEX больше нет

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

5.7.0

В плеерах более новых версий это не сработает:

5.8.0

Изменения в работе неявного оператора

Неявный оператор — это оператор, который мы не указываем. В 5.7.0 он делал примерно то же, что делал и оператор *pl. То есть выводил на экран значение, добавляя после этого значения перевод строки:

! работает в плеерах любых версий
*pl 456
*pl "text"
! эквивалентно:456 & ! здесь для вывода используется неявный оператор
"text" & ! и здесь для вывода используется неявный оператор

Если мы вызывали какую-то функцию, но она не возвращала никакого результата, неявный оператор, как и оператор *pl, выводил на экран пустую строку и добавлял к ней перевод строки:

5.7.0

В новых версиях плеера, если неявный оператор не получит никакого значения от функции, он просто ничего не будет делать:

5.8.0 (qSpider)

Неявный вызов пользовательских функций

В плеерах версии 5.7.0 и более ранних вы могли написать собственную функцию и затем вызвать её без возвращения результата, используя оператор GOSUB, или с возвращением результата, используя функцию FUNC. В плеерах версии 5.8.0 и выше эта возможность конечно же сохраняется.

Пример:

Работает во всех версиях плеера

Однако в плеерах версии 5.8.0 и выше вы можете использовать сокращённую запись вызова таких функций:

! только в плеерах 5.8.0 и выше
@proced
@foo.3(23,45)
Работает в плеерах версии 5.8.0 и выше

То есть вместо того, чтобы использовать явное указание оператора GOSUB или функции FUNC, можно писать символ @, а после него без пробелов записывать название локации. Само название вызываемой таким образом локации/функции не должно содержать пробелов, а так же специальных символов, кроме точки ‘.’ и диеза ‘#’.

Если такой функции нужно передать значения, после названия локации ставим скобки и перечисляем нужные аргументы.

Новая функция ARRITEM

Функция ARRITEM возвращает значение указанной ячейки массива. Это новая функция, и введена она по большей части для того, чтобы упразднять подвыражения при использовании DYNAMIC/DYNEVAL.

Примеры:

massive[123]=256! работает в любой версии плеера:
xvar = massive[123]
! работает только в 5.8.0 и выше:
xvar = arritem('massive',123)

Обе команды присваивают переменной xvar значение из ячейки 123 массива massive, однако во втором случае мы указываем название в виде строкового значения. Таким образом мы, не прибегая к помощи DYNAMIC/DYNEVAL можем динамически формировать названия массива при получении значения.

$stringarray[345]='text out'
$mass[0]='string'
$mass[1]='array'
*pl $arritem('$'+$mass[0]+$mass[1],345)
5.8.0 (qSpider)

Так же ARRITEM позволяет получить значение из ячейки с текстовым индексом:

5.8.0 (qSpider)

KILLVAR удаляет по текстовому индексу

В плеерах версии 5.7.0 и ниже оператор KILLVAR умел удалять элементы массивов только по числовому индексу:

Работает в плеерах любой версии

В плеерах версии 5.8.0 и выше KILLVAR умеет удалять элементы массивов не только по числовому, но и по текстовому индексу:

5.8.0 (qSpider)

Операторы ADDQST и KILLQST переименованы

В плеерах версии 5.7.0 (за исключением Quest Navigator) используются операторы ADDQST и KILLQST. В плеерах более новых версий (5.8.0 и выше) данные операторы заменены на INCLIB и FREELIB соответственно.

INCLIB добавляет локации из подключаемого модуля QSP к основной игре.

FREELIB удаляет все локации ранее подключённых модулей QSP из основной игры.

inclib 'module.qsp'
inclib 'drive.qsp'
inclib 'base.qsp'
freelib

Изменение в работе оператора SET

Для явного объявления переменных в QSP используется оператор SET. В плеерах версии 5.7.0 и ниже с помощью этого оператора вы могли объявить лишь одну переменную:

! работает в плеерах любых версий
set mass=45

Если требовалось объявить несколько переменных, приходилось писать несколько команд SET:

! работает в плеерах любых версий
set mass=45 & set daz=65 & set zaz=79
! эквивалентно:
mass=45 & daz=65 & zaz=79

В плеерах версии 5.8.0. и выше вы можете объявить несколько переменных одной командой:

! работает в 5.8.0 и выше:
set mass, daz, zaz = 45, 65, 79

Обратите внимание на форму записи. Здесь лишь один знак `=`. Переменные и их значения перечислены через запятую соответственно слева и справа от знака `=`.

Более того. С помощью оператора SET вы можете не только назначать переменным определённые значения, но и присваивать значения других переменных:

! работает в 5.8.0 и выше:
set a, b, c = x, y, z

В том числе и менять значения переменных местами не прибегая к помощи третьей переменной:

! работает в 5.8.0 и выше:
set j,y=y,j

Как и в плеерах версии 5.7.0, оператор SET указывать не обязательно:

! работает в 5.8.0 и выше:
mass, daz, zaz = 45, 65, 79
a, b, c = x, y, z
j,y=y,j

Новый оператор LOCAL

В плеерах версии 5.8.0 и выше, а так же в Quest Navigator появился новый оператор, который позволяет объявить указанные переменные локальными для отдельного блока кода (локации, действия, код в DYNAMIC/DYNEVAL). После того, как блок кода выполнен, значения переменных восстанавливаются к предыдущим:

5.8.0 (qSpider)

Можно объявить локальную переменную и сразу присвоить ей значение:

local i=45

Можно объявить сразу несколько локальных переменных:

! объявляем локальные переменные
local i, j, k
! объявляем локальные переменные и присваиваем им значения
local f, d, $g = 123, 45, 'string'

Обратите внимание на последнюю форму записи. Сначала мы перечисляем объявляемые переменные через запятую, затем ставим один знак `=`, а после него перечисляем через запятую значения, которые хотим присвоить переменным. Неправильно делать такую запись:

! Данная строчка кода вызовет ошибку "Несоответствие типов данных":
local f=123, d=45, $g='string'

Изменения в работе функций INSTR, ARRCOMP, ARRPOS

Необязательные аргументы функций INSTR, ARRCOMP и ARRPOS в плеерах 5.8.0 и выше, а так же в Quest Navigator переставлены в конец. В плеерах версии 5.7.0. и ниже эти аргументы шли в начале.

Пример для версий плеера 5.7.0 и ниже (кроме Quest Navigator):

5.7.0

Те же самые примеры для плееров версии 5.8.0 и выше и Quest Navigator`а:

5.8.0 (qSpider) и Quest Navigator

Новый оператор цикла LOOP

В плеерах версий 5.7.0 и старше, для организации циклов приходилось использовать метки. Начиная с версии 5.8.0. у нас появляется отдельный оператор циклов LOOP. Вот как он записывается в общем виде:

! многострочная форма:
LOOP [команды 1] WHILE [условие] STEP [команды 2]:
[команды 3]
END
! однострочная форма:
LOOP [команды 1] WHILE [условие] STEP [команды 2]: [команды 3]

Здесь, как вы видите, есть целых три ключевых слова:

* LOOP — это ключевое слово объявляет, что начинается цикл, оно обязательно. После LOOP могут идти некоторые однострочные операторы. Например, здесь мы можем объявить локальные переменные, которые будут считаться локальными только для данного цикла.

* WHILE — после этого ключевого слова должно стоять условие, и пока выполняется это условие, цикл тоже будет выполняться.

* STEP — это ключевое слово не является обязательным, однако оно удобно, чтобы перечислить однострочные операторы, не относящиеся напрямую к телу цикла. Например, здесь можно указать изменение счётчика.

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

Несколько примеров:

5.8.0 (qSpider)
5.8.0 (qSpider)
5.8.0 (qSpider)

Изменения в чтении длинных строк, разбитых на несколько

Для того, чтобы разбивать длинные строки на несколько (для удобства чтения) в QSP используется сочетание символов ‘ _’ (пробел и символ нижнего подчёркивания). В плеерах версии 5.7.0 и ниже (кроме Quest Navigator 0.0.28) при разборе данной конструкции движок оставлял строки, как есть. Для примера возьмём такую конструкцию:

if t _
or _
t:

В плеерах версии 5.7.0 символы преформатирования будут исключены при интерпретации, а строка, разбитая с помощью ‘ _’, будет объединена, как есть, то есть будет равнозначна строке:

if tort:

В плеерах версии 5.8.0 и выше данная строка будет объединена с добавлением пробела вместо каждого сочетания ‘ _’, то есть будет равнозначна строке:

if t or t:

Данное отличие в прочтении строк используется, как костыль, чтобы отличить классический плеер версии 5.7.0 от Quest Navigator версии 0.0.28:

Изменения в работе функции RAND

В плеерах версии 5.7.0 и ниже второй параметр функции RAND по умолчанию был 0. Например, если вы указывали число 100 в качестве аргумента функции RAND, то эта функция возвращала случайное число от 0 до 100. В плеерах версии 5.8.0 и выше, а так же в Quest Navigator, второй параметр по умолчанию равен 1. То есть если вы укажете лишь одно число, например 100, функция RAND вернёт случайное значение от 1 до 100.

RAND(100) & ! в 5.7.0 вернёт значение от 0 до 100
RAND(100) & ! в 5.8.0 вернёт значение от 1 до 100
RAND(10) & ! в 5.7.0 вернёт значение от 0 до 10
RAND(10) & ! в 5.8.0 вернёт значение от 1 до 10
RAND(5) & ! в 5.7.0 вернёт значение от 0 до 5
RAND(5) & ! в 5.8.0 вернёт значение от 1 до 5
RAND(0) & ! в 5.7.0 вернёт значение 0
RAND(0) & ! в 5.8.0 вернёт значение от 0 до 1
RAND(1) & ! в 5.7.0 вернёт значение от 0 до 1
RAND(1) & ! в 5.8.0 вернёт значение 1

https://i.ibb.co/3zgvCVd/Untitled-00-00-00-00-00-30-1.gif

Повышение приоритета функций LOC и OBJ

В плеерах версии 5.7.0 (и ниже) у функций LOC и OBJ приоритет был ниже, чем у операций сравнения. Это могло быть неочевидным для выражений такого рода:

(obj 'Отвёртка'=obj 'Верёвка')

Кажется, что данное выражение должно выполняться так: проверяется наличие предмета “Отвёртка”, проверяется наличие предмета “Верёвка”, и лишь потом значения сравниваются. Однако в 5.7.0 у операции сравнения приоритет выше, чем у OBJ. Поэтому сначала выполняется операция сравнения, и лишь потом функция OBJ. Таким образом в плеерах версии 5.7.0 данное выражение всегда возвращает 0.

5.7.0

В плеерах версии 5.8.0 (и выше) приоритет у функций OBJ и LOC выше, чем у операций сравнения, поэтому данное выражение будет вычисляться именно так, как мы предположили: сначала проверяется наличие обоих предметов и лишь потом сравниваются полученные значения. В плеерах 5.8.0 (и выше) данное выражение будет возвращать 1, если оба предмета или отсутствуют, или присутствуют, и 0, если одни предмет присутствует, а другой отсутствует.

5.8.0 (qSpider)

Больше аргументов для функций

В плеерах версии 5.7.0 (и ниже) максимальное число аргументов, которое вы могли передавать операторам и функциям, было 10. Таким образом, например, функции MAX и MIN могли производить поиск значений лишь среди десяти значений. В плеерах версии 5.8.0 и выше максимальное число аргументов, передаваемых функциям и операторам, — 20.

! работает в плеерах любых версий
max('a','b','c','d','e','f','g','h','i','j')
! работает лишь в плеерах версии 5.8.0 и выше
max('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t')

Старые новости, о которых вы могли не знать

Здесь мы осветим пару изменений, которые появились в плеере версии 5.7.0 (или раньше), но которые прошли не очень заметно.

Игнорирование отрицательных индексов

В плеерах версий ниже 5.6.5 отрицательные индексы приводились к нулю, а в плеерах более новых версий, они просто-напросто игнорируются:

5.3.1
5.7.0

Добавление предмета в определённую позицию

Начиная с версии 5.6.5 вы можете добавлять предмет в указанную позицию в окне предметов. При этом, если на текущей позиции уже находится предмет, он сдвигается вниз (вправо) по списку, и все стоящие за ним предметы так же сдвигаются на одну позицию вниз (вправо).

! версии 5.6.5 и выше
addobj 'Отвёртка','путь к файлу картинки/картинка.png',4

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

! версии 5.6.5 и выше
addobj 'Первый предмет'
addobj 'Второй предмет'
addobj 'Третий предмет'
addobj 'Четвёртый предмет'
addobj 'Пятый предмет','',5 & ! предмет добавится в конец списка
addobj 'Седьмой предмет','',7 & ! предмет не будет добавлен
addobj 'Нулевой предмет','',0 & ! предмет не будет добавлен

Копирование части массива в COPYARR

Начиная с версии 5.7.0 вы можете копировать часть массива в другой массив, используя не обязательные параметры: начальный индекс и количество. В следующем примере в массив mass будут скопированы шесть элементов массива array, начиная с третьего:

! версии 5.7.0 и выше
copyarr 'mass','array',3,6

Передача аргументов в ONNEWLOC

Начиная с версии 5.7.0 аргументы, которые передаются на локацию при переходе на эту локацию с помощью операторов GOTO или XGOTO, передаются так же и на локацию-обработчик перехода на новую локацию (прописанную в переменной $ONNEWLOC). При этом, даже если значения в массиве ARGS будут изменены на локации, на которую был осуществлён переход, на локацию $ONNEWLOC будут переданы исходные значения, переданные с GOTO/XGOTO.

5.7.0

Что будет дальше?

Новая версия классического плеера пока не увидела свет, а значит можно ожидать ещё много изменений в работе, которые мы непременно отразим в новых статьях, а так же в онлайн-справке wiki.qsp.su.

Если у вас возникли вопросы по грядущим изменениям, можете задать их на форуме qsp.su, в нашей группе вконтакте, или в канале #qsp на сервере Interactive Fiction в Дискорде.

Оригинал статьи размещён в vk: https://vk.com/@qsplayer-novovvedeniya-v-qsp-580

--

--

Алексей Шпак
0 Followers

Пишу, пью, программирую