From 45fc5f45b51e7e03ed57ad35879bf38d76b285e6 Mon Sep 17 00:00:00 2001 From: Aleksey <75123881+AleksVersus@users.noreply.github.com> Date: Sun, 15 Dec 2024 11:05:10 +0500 Subject: [PATCH] Update keywords chapters for 5.9.0 syntax. Close #29 (#30) * docs(language/keywords): add scanstr, sortarr, curobjs to pointer * docs(language/keywords): update math-operation by operation with tuples * docs(language/keywords): add sortarr, scanstr; update operators descs to 5.9.0 * fix(syntax): comment after colon; add scanstr, sortarr * docs(language/keywords): split if-heading on parts, fix grammar-errors * fix(syntax): add curobjs to keywords list * docs(language/keywords): add 'curobjs' keyword, update funcs descs to 5.9.0. * docs(language/keywords): update sys-vars descs to 5.9.0 * docs(language/keywords): update syntaxemes to 5.9.0 * blog: add and write 2024-11-16-update-keywords-to-590 * docs(language/keywords): update to 5.9.1 the oprts, funcs arrpack, unpackarr, setvar, arrtype; extend: rand, replace * docs(lang/kwrds/operacion): fix inaccuracy; add tip. * docs(lang/kwrds/oprcn): fix tuples comparison (upd to 5.9.2). --- blog/2024-11-16-update-keywords-to-590.md | 27 + docs/language/qsp-keywords/index.md | 27 +- .../qsp-keywords/qsp-keyword-functions.md | 172 ++++- .../qsp-keywords/qsp-keyword-operacion.md | 543 +++++++++++++-- .../qsp-keywords/qsp-keyword-operators.md | 655 +++++++++++++----- .../qsp-keywords/qsp-keyword-syntaxems.md | 59 +- .../qsp-keywords/qsp-keyword-sys-var.md | 59 +- src/theme/qsp-syntax/prism-qsp.js | 10 +- 8 files changed, 1266 insertions(+), 286 deletions(-) create mode 100644 blog/2024-11-16-update-keywords-to-590.md diff --git a/blog/2024-11-16-update-keywords-to-590.md b/blog/2024-11-16-update-keywords-to-590.md new file mode 100644 index 0000000..fc8e0e7 --- /dev/null +++ b/blog/2024-11-16-update-keywords-to-590.md @@ -0,0 +1,27 @@ +--- +authors: + - alex +tags: + - документация + - syntax + - синтаксис + - язык QSP +--- + +# Обновление документации по ключевым словам до 5.9.0 + +У меня сложилось стойкое ощущение, что я обновляю документацию намного медленнее, чем Byte обновляет движок. Впрочем, это не только ощущение, так в самом деле и есть. + +Тут, конечно, играет роль моя привычка полностью перевычитывать весь текст, что отнимает время. И не спасает от ошибок. + +Что я успел сделать за три месяца: + +- обновил информацию на вики; +- обновил информацию в разделе ключевых слов здесь; +- перевёл подсветку синтаксиса для обсидиан на Prism (теперь по сути синтаксис для обсидиан и синтаксис для докузаурус работают на одном механизме, с небольшими отличиями, что позволяет мне на лету исправлять ошибки и обновлять синтаксис, пока я пользуюсь обсидианом, или пишу для докузаурус, и сразу закидывать обновлённый синтаксис в любой другой источник). + +Ну, и чего я не успел: + +- овердофига всего. + +Но придётся продолжать в том же темпе. diff --git a/docs/language/qsp-keywords/index.md b/docs/language/qsp-keywords/index.md index a553147..45ec8ce 100644 --- a/docs/language/qsp-keywords/index.md +++ b/docs/language/qsp-keywords/index.md @@ -20,9 +20,9 @@ sidebar_position: 6 - [`{}` (Фигурные скобки)](qsp-keyword-syntaxems.md#фигурные-скобки-) - [`()` (круглые скобки)](qsp-keyword-syntaxems.md#круглые-скобки-) - [`[]` (квадратные скобки)](qsp-keyword-syntaxems.md#квадратные-скобки-) -- [`@` (коммерческое "эт")](qsp-keyword-syntaxems#%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D1%80%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%8D%D1%82-) +- [`@` (коммерческое "эт")](qsp-keyword-syntaxems#%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D1%80%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%8D%D1%82-) - 5.8.0 - [`$` (знак доллара)](qsp-keyword-syntaxems#%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB-%D0%B7%D0%BD%D0%B0%D0%BA-%D0%B4%D0%BE%D0%BB%D0%BB%D0%B0%D1%80%D0%B0-) -- [`%` (знак процента)](qsp-keyword-syntaxems#%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB-%D0%B7%D0%BD%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D0%BD%D1%82%D0%B0-) +- [`%` (знак процента)](qsp-keyword-syntaxems#%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB-%D0%B7%D0%BD%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D0%BD%D1%82%D0%B0-) - 5.9.0 - [`*`](qsp-keyword-operacion.md#-умножение) - [`*=`](qsp-keyword-operacion.md#-умножение-присвоение) - [`+`](qsp-keyword-operacion.md#-сложение) @@ -49,8 +49,10 @@ sidebar_position: 6 - [`AND`](qsp-keyword-operacion.md#and) - [`ARGS`](qsp-keyword-sys-var.md#args) - [`ARRCOMP`](qsp-keyword-functions.md#arrcomp) -- [`ARRITEM`](qsp-keyword-functions.md#arritem) +- [`ARRITEM`](qsp-keyword-functions.md#arritem) - 5.8.0 +- [`ARRPACK`](qsp-keyword-functions.md#arrpack) - 5.9.1 - [`ARRPOS`](qsp-keyword-functions.md#arrpos) +- [`ARRTYPE`](qsp-keyword-functions.md#arrtype) - 5.9.1 - [`ARRSIZE`](qsp-keyword-functions.md#arrsize) - [`$BACKIMAGE`](qsp-keyword-sys-var.md#backimage) - [`BCOLOR`](qsp-keyword-sys-var.md#bcolor) @@ -69,6 +71,7 @@ sidebar_position: 6 - [`COUNTOBJ`](qsp-keyword-functions.md#countobj) - [`$CURACTS`](qsp-keyword-functions.md#curacts) - [`$CURLOC`](qsp-keyword-functions.md#curloc) +- [`$CUROBJS`](qsp-keyword-functions.md#curobjs) - 5.9.0 - [`DEBUG`](qsp-keyword-sys-var.md#debug) - [`DELACT`](qsp-keyword-operators.md#delact) - ~~[`DELLIB`](qsp-keyword-operators.md#freelib)~~ @@ -78,13 +81,13 @@ sidebar_position: 6 - ~~[`DISABLESUBEX`](qsp-keyword-sys-var.md#disablesubex)~~ - [`DYNAMIC`](qsp-keyword-operators.md#dynamic) - [`DYNEVAL`](qsp-keyword-functions.md#dyneval) -- [`ELSE`](qsp-keyword-operators.md#if-else-elseif) -- [`ELSEIF`](qsp-keyword-operators.md#if-else-elseif) +- [`ELSE`](qsp-keyword-operators.md#else) +- [`ELSEIF`](qsp-keyword-operators.md#elseif) - [`END`](qsp-keyword-syntaxems.md#end) - [`EXIT`](qsp-keyword-operators.md#exit) - [`FCOLOR`](qsp-keyword-sys-var.md#fcolor) - [`$FNAME`](qsp-keyword-sys-var.md#fname) -- [`FREELIB`](qsp-keyword-operators.md#freelib) +- [`FREELIB`](qsp-keyword-operators.md#freelib) - 5.8.0 - [`FSIZE`](qsp-keyword-sys-var.md#fsize) - [`FUNC`](qsp-keyword-functions.md#func) - [`$GETOBJ`](qsp-keyword-functions.md#getobj) @@ -92,9 +95,9 @@ sidebar_position: 6 - [`GOTO`](qsp-keyword-operators.md#goto) - [`GS`](qsp-keyword-operators.md#gosub) - [`GT`](qsp-keyword-operators.md#goto) -- [`IF`](qsp-keyword-operators.md#if-else-elseif) +- [`IF`](qsp-keyword-operators.md#if) - [`IIF`](qsp-keyword-functions.md#iif) -- [`INCLIB`](qsp-keyword-operators.md#inclib) +- [`INCLIB`](qsp-keyword-operators.md#inclib) - 5.8.0 - [`$INPUT`](qsp-keyword-functions.md#input) - [`INSTR`](qsp-keyword-functions.md#instr) - [`ISNUM`](qsp-keyword-functions.md#isnum) @@ -109,8 +112,8 @@ sidebar_position: 6 - [`LEN`](qsp-keyword-functions.md#len) - [`LET`](qsp-keyword-operators.md#let) - [`LOC`](qsp-keyword-operacion.md#loc) -- [`LOCAL`](qsp-keyword-operators.md#local) -- [`LOOP`](qsp-keyword-operators.md#loop) +- [`LOCAL`](qsp-keyword-operators.md#local) - 5.8.0 +- [`LOOP`](qsp-keyword-operators.md#loop) - 5.8.0 - [`$MAINTXT`](qsp-keyword-functions.md#maintxt) - [`MAX`](qsp-keyword-functions.md#max) - [`MENU`](qsp-keyword-operators.md#menu) @@ -147,14 +150,17 @@ sidebar_position: 6 - [`RGB`](qsp-keyword-functions.md#rgb) - [`RND`](qsp-keyword-functions.md#rnd) - [`SAVEGAME`](qsp-keyword-operators.md#savegame) +- [`SCANSTR`](qsp-keyword-operators.md#scanstr) - 5.9.0 - [`$SELACT`](qsp-keyword-functions.md#selact) - [`$SELOBJ`](qsp-keyword-functions.md#selobj) - [`SET`](qsp-keyword-operators.md#set) - [`SETTIMER`](qsp-keyword-operators.md#settimer) +- [`SETVAR`](qsp-keyword-operators.md#setvar) - 5.9.1 - [`SHOWACTS`](qsp-keyword-operators.md#showacts) - [`SHOWINPUT`](qsp-keyword-operators.md#showinput) - [`SHOWOBJS`](qsp-keyword-operators.md#showobjs) - [`SHOWSTAT`](qsp-keyword-operators.md#showstat) +- [`SORTARR`](qsp-keyword-operators.md#sortarr) - 5.9.0 - [`$STATTXT`](qsp-keyword-functions.md#stattxt) - [`$STR`](qsp-keyword-functions.md#str) - [`STRCOMP`](qsp-keyword-functions.md#strcomp) @@ -162,6 +168,7 @@ sidebar_position: 6 - [`STRPOS`](qsp-keyword-functions.md#strpos) - [`$TRIM`](qsp-keyword-functions.md#trim) - [`$UCASE`](qsp-keyword-functions.md#ucase) +- [`UNPACKARR`](qsp-keyword-operators.md#unpackarr) - 5.9.1 - [`UNSEL`](qsp-keyword-operators.md#unselect) - [`UNSELECT`](qsp-keyword-operators.md#unselect) - [`USEHTML`](qsp-keyword-sys-var.md#usehtml) diff --git a/docs/language/qsp-keywords/qsp-keyword-functions.md b/docs/language/qsp-keywords/qsp-keyword-functions.md index 9fa9168..c5f96b1 100644 --- a/docs/language/qsp-keywords/qsp-keyword-functions.md +++ b/docs/language/qsp-keywords/qsp-keyword-functions.md @@ -38,6 +38,22 @@ act "Перезайти на текущую локацию": end ``` +## `$CUROBJS` + +`$CUROBJS` - данная функция возвращает список выведенных на экран предметов в виде QSP-кода. +Предметы сохраняются в виде набора операторов `ADDOBJ` с ответствующими параметрами и операциями. + +Записав возвращённое функцией значение в переменную, можно восстановить предметы с помощью оператора `DYNAMIC`. Пример: + +```qsp +! сохраняем список предметов как код QSP: +$old_objects = $CUROBJS +! удаляем все предметы из окна предметов: +KILLOBJ +! восстанавливаем все предметы в окне предметов: +DYNAMIC $old_objects +``` + ## `$DESC` `$DESC` — возвращает текст базового описания локации с заданным названием. Общая запись: @@ -86,9 +102,10 @@ dyneval('result = 3 + 4') проход = dyneval("result = ($args[0] <> 'текст')", 'строка') ``` +- Чтобы `DYNEVAL` вернула несколько значений, результат должен быть записан в `%RESULT`. - Чтобы `DYNEVAL` вернула строковое значение, результат должен быть записан в `$RESULT`. - Чтобы `DYNEVAL` вернула числовое значение, результат должен быть записан в `RESULT`. -- `$RESULT` и `RESULT` — это одна и та же переменная, но с разными типами данных. Следует помнить, что новая запись значения затирает предыдущее, какого бы типа данных не было это значение. +- `%RESULT`, `$RESULT` и `RESULT` — это одна и та же переменная, но с разными типами данных. Следует помнить, что новая запись значения затирает предыдущее, какого бы типа данных не было это значение. Если при выполнении `dyneval` она не возвращает значения (`result` не инициализируется), и является единственным элементом выражения, передаваемого неявному оператору, плеер ничего не выведет на экран. Т.е. `dyneval` будет работать, как `DYNAMIC`. Пример: @@ -117,27 +134,33 @@ $FUNC([$локация], [аргумент 0], [аргумент 1], ... , [ар , где `[$локация]` — это название локации, код которой мы хотим выполнить без непосредственного перехода на неё. Аргументы `[аргумент 0]`, `[аргумент 1]` и т.д. могут использоваться на этой локации, их значения автоматически помещаются в переменные `args[0]`, `args[1]`, и т.д. соответственно. -Чтобы `FUNC` вернула строковый результат, на указанной локации нужно присвоить этот результат переменной `$RESULT`. Для возвращения числового результата, он должен быть присвоен переменной `RESULT`. Следует помнить, что `$RESULT` и `RESULT` — это одна и та же переменная, но разных типов, поэтому если вы определили на локации и `$RESULT` и `RESULT`, функция вернёт то значение, которое было записано в эту переменную последним. +Чтобы `FUNC` вернула: + +- несколько значений или кортеж, на указанной локации нужно присвоить результат переменной `%RESULT`; +- строковый результат, на указанной локации нужно присвоить этот результат переменной `$RESULT`; +- для возвращения числового результата, он должен быть присвоен переменной `RESULT`. -Если переменной `RESULT` не было присвоено ни строковое, ни числовое значение, функция ничего не вернёт. И тут есть два варианта поведения плеера. +Следует помнить, что `%RESULT`, `$RESULT` и `RESULT` — это одна и та же переменная, но разных типов, поэтому если вы определили на локации и `%RESULT`, и `$RESULT`, и `RESULT`, функция вернёт то значение, которое было записано в эту переменную последним. -- Если функция `FUNC` стоит в каком либо выражении, вместо функции будет подставлено значение по умолчанию (пустая строка или ноль в зависимости от типа самого выражения). +Если переменной `RESULT` не было присвоено значение, функция ничего не вернёт. И тут есть два варианта поведения плеера. + +- Если функция `FUNC` стоит в каком либо выражении, вместо функции будет подставлено значение по умолчанию (пустой кортеж, пустая строка или ноль в зависимости от типа самого выражения). - Если функция `FUNC` стоит сразу после неявного оператора, такой оператор будет проигнорирован, и на экран ничего выводиться не будет. Пример: - ```qsp title="локация_Н" - N = 23 * 13 - ! ни одно значение не присваивается переменной result - ``` +```qsp title="локация_Н" +N = 23 * 13 +! ни одно значение не присваивается переменной result +``` - ```qsp title="Другая локация" - 'строка 1' - func('локация_Н') &! ничего не выведется на экран - 'строка 2' - 56 + func('локация_Н') &! функция стоит в выражении. Её значение = 0 - ``` +```qsp title="Другая локация" +'строка 1' +func('локация_Н') &! ничего не выведется на экран +'строка 2' +56 + func('локация_Н') &! функция стоит в выражении. Её значение = 0 +``` -:::note -Не обязательно, но рекомендуется, записывать ключевое слово `FUNC` с символом `$`, если функция должна вернуть текстовое значение, и без символа `$`, если функция должна вернуть числовое значение: +:::note[Рекомендация:] +Не обязательно, но рекомендуется, использовать префикс типа (`$` или `%`) с ключевым словом `FUNC`, если функция должна вернуть строковое значение или кортеж, и — без префикса типа, если функция должна вернуть числовое значение: ```qsp $func('срез_строки', 'Мы вышли из дома, когда во всех окнах погасли огни.', 3, 7) @@ -146,6 +169,8 @@ func('возвести_в_степень', 3, 3) ::: +**Порядок работы.** + При вызове указанной локации с помощью `FUNC` происходит следующее: - Плеер прерывает выполнение текущего кода (например, кода текущей локации), и обращается к указанной локации. @@ -186,6 +211,8 @@ $name_loc = "summ" *pl func($name_loc, 23) & ! выведет на экран 276 ``` +Также см. ["Неявный вызов функции `FUNC`"](qsp-keyword-syntaxems.md#%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB-%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D1%80%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5-%D1%8D%D1%82-). + ## `$GETOBJ` `$GETOBJ` — возвращает название предмета в *Окне предметов*, расположенного в заданной позиции. Общая запись: @@ -287,6 +314,7 @@ if instr($answer, 'красный') or instr($answer, 'желтый') or instr($ ! Введя красный или зеленый ил желтый произойдет переход на локацию 'win' ``` +:::warning[Будьте внимательны!] Допустимо, но не одобряется, использовать функцию для возвращения числовых значений: ```qsp @@ -299,7 +327,9 @@ INPUT([$приглашение]) age = input('Сколько вам лет?') ``` -Если игрок введёт вместо числа строку "24 года", плеер выдаст ошибку **101** "Несоответствие типов данных". Подобные ситуации должен предусматривать автор игры, а значит правильно будет озаботиться проверкой введённого значения уже после того, как функция `$input` будет выполнена. +Если игрок введёт вместо числа строку "24 года", плеер выдаст ошибку **101** "Несоответствие типов данных". + +Подобные ситуации должен предусматривать автор игры, а значит правильно будет озаботиться проверкой введённого значения уже после того, как функция `$input` будет выполнена. ```qsp loop local $text while 1: @@ -320,6 +350,8 @@ end :break ``` +::: + ## `$LCASE` `$LCASE` — возвращает строку маленьких букв, полученную изменением регистра букв исходной строки. Общая запись: @@ -480,21 +512,30 @@ end $qspver('platform') ``` +:::note[5.7.0] + +В старых версиях плееров функция возвращала только версию интерпретатора (библиотеки libqsp). + +::: + ## `$REPLACE` `$REPLACE` — общая запись: ```qsp -$REPLACE([$строка], [$поиск], [$замена]) +$REPLACE([$строка], [$поиск], [$замена], [#число_замен]) ``` -Данная функция заменяет в строке `[$строка]` все вхождения строки `[$поиск]` строкой `[$замена]` и возвращает результат. Если `[$замена]` отсутствует или указана пустая строка, то удаляет в исходной строке все вхождения искомой строки. Примеры: +Данная функция заменяет в строке `[$строка]` несколько вхождений строки `[$поиск]` строкой `[$замена]` и возвращает результат. Замена производится слева-направо и только для непересекающихся вхождений. Параметр `[#число_замен]` показывает, сколько вхождений должно быть заменено. Если параметр не указан, производится замена всех вхождений. Если `[$замена]` отсутствует или указана пустая строка, то удаляет в исходной строке все вхождения искомой строки. Примеры: ```qsp $replace('test', '12', '4') & ! выведет на экран 'test' $replace('test', 'e', 's') & ! выведет на экран 'tsst' $replace('test', 't', '34') & ! выведет на экран '34es34' $replace('test', 't') & ! выведет на экран 'es' + +$replace('test', 't', 'qu', 1) &! 'quest' +$replace('test my test', 't', 'q', 3) &! 'qesq my qest' ``` ```qsp @@ -771,7 +812,7 @@ ARRITEM([$имя_массива], [индекс_элемента]) ! выводим значение элемента с текстовым индексом *pl $arritem('$mass', 'Петя') ! выводим значение элемента с многомерным индексом -*pl $arritem('$mass', (-2, 9, 0)) +*pl $arritem('$mass', [-2, 9, 0]) ``` Эта функция может быть полезна для извлечения значений, если имя массива заранее не известно. Пример: @@ -791,9 +832,37 @@ loop local j = 0 while j < arrsize('$array_name') step j += 1: end ``` +## ARRPACK + +`ARRPACK` — возвращает кортеж, в который упакованы значения из указанного массива. + +Общая запись: + +```qsp +ARRPACK([$имя_массива], [#начальный_индекс], [#количество]) +``` + +, где `[#начальный_индекс]` - это номер элемента массива `[$имя_массива]`, с которого нужно начать отбор элементов для упаковки; `[#количество]` — это число элементов, которое будет упаковано в кортеж. + +Данная функция позволяет сократить команду извлечения аргументов из `args`: + +```qsp +! вместо: +local type, name = args[0], args[1] +! можно написать так: +local type, name = arrpack('args') +``` + +Ещё она может быть удобна, если нужно быстро просмотреть содержимое массива или его части: + +```qsp +! просматриваем значения в массиве без использования цикла: +*pl arrpack('massive', 11, 10) & ! увидим на экране десять элементов, начиная с 11-го, в виде кортежа +``` + ## ARRPOS -`ARRPOS` — возвращает индекс элемента массива, равного указанному значению. Поиск начинается с элемента с заданным номером; индексация элементов массива ведётся с нуля. Если указанное значение не найдено, функция возвращает -1. +`ARRPOS` — возвращает индекс элемента массива, равного указанному значению. Поиск начинается с элемента с заданным номером; индексация элементов массива ведётся с нуля. Если указанное значение не найдено, функция возвращает -1. Общая запись: @@ -855,6 +924,38 @@ ARRPOS([#начало], [$имя_массива], [$шаблон]) ::: +## ARRTYPE + +`ARRTYPE` — возвращает тип значения, хранящегося в переменной, или указанной ячейке массива. Тип возвращается в виде одного из следующих значений: +- `''` (пустая строка) — значение не определено (например, для неинициализированных переменных); +- `'#'` — переменная содержит число; +- `'$'` — переменная содержит строку; +- `'%'` — переменная содержит кортеж. + +Общая запись: + +```qsp +ARRTYPE([$имя_массива], [индекс]) +``` + +, где `[$имя_массива]` — название массива (префикс типа роли не играет, лучше не указывать); `[индекс]` — индекс ячейки, тип значения которой мы хотим получить. + +Примеры: + +```qsp +$ddd = 'text' +arrtype('ddd') & ! '$' + +$g = 'text' & g = 13 +arrtype('g') & ! '#' + +%tuple['index'] = [12, 'string'] +arrtype('tuple', 'index') & ! '%' + +! $empty not exist +arrtype('$empty') & ! '' +``` + ## ARRSIZE `ARRSIZE` — функция возвращает число элементов массива. Общая запись: @@ -873,6 +974,12 @@ n = ARRSIZE('$a') ! Результат будет одинаковый ``` +:::[warning] Внимание! + +Если массив был объявлен с помощью оператора `LOCAL`, но ни одному элементу массива не было присвоено значение, `ARRSIZE` такого массива вернёт `0`. + +::: + ## COUNTOBJ `COUNTOBJ` — возвращает количество предметов в инвентаре. @@ -1009,10 +1116,14 @@ pl "Скорость работы нового цикла: " + $str(new_time - o `RAND` — возвращает случайное число между двумя указанными числами. Общая запись: ```qsp -RAND([#выражение 1], [#выражение 2]) +RAND([#выражение 1], [#выражение 2], [#мода]) ``` -, где `[#выражение 1]` и `[#выражение 2]` — два любых числа или числовых выражения. Параметр `[#выражение 2]` может отсутствовать, при этом он принимается равным `1`. +, где `[#выражение 1]` и `[#выражение 2]` — два любых числа или числовых выражения. + +Параметр `[#мода]` позволяет указать число, которое должно выпадать более часто, чем остальные. При этом распределение частоты выпадения будет плавно изменяться для всех остальных чисел, уменьшаясь от моды к пределам выбранного интервала. Если 3й параметр не указан, то функция возвращает случайное число в заданном диапазоне с равномерным/равновероятным распределением чисел. + +Параметр `[#выражение 2]` может отсутствовать, при этом он принимается равным `1`. :::note[5.7.0] В более старых версиях плеера, данный параметр по умолчанию равен нулю. @@ -1025,6 +1136,13 @@ rand(1, 4) &! вернёт случайное значение от 1 до 4 rand(4, 1) &! вернёт случайное значение от 1 до 4 rand(1000) &! вернёт случайное значение от 1 до 1000 rand 1000 &! вернёт случайное значение от 1 до 1000 + +x = RAND(1, 1000, 500) & ! чаще будет выпадать 500 +x = RAND(1, 1000, 1) & ! чаще будет выпадать 1 +x = RAND(1, 1000, 1000) & ! чаще будет выпадать 1000 +x = RAND(-1000, 0, -500) & ! чаще будет выпадать -500 +x = RAND(1, 1000, 5000) & ! чаще будет выпадать 1000 +x = RAND(-1000, -100, -5000) & ! чаще будет выпадать -1000 ``` ## RGB @@ -1054,6 +1172,12 @@ fcolor = rgb(100, 255, 100) lcolor = rgb(0, 255, 255, 128) ``` +:::note[Примечание.] + +Не стоит полагаться на параметр `[#альфа]` так как многие плееры его не поддерживают. + +::: + ## RND `RND` - возвращает случайное значение от `1` до `1000`. Аналогично команде: @@ -1072,7 +1196,7 @@ STRCOMP([$строка], [$шаблон]) , где `[$строка]` — любое текстовое значение, `[$шаблон]` — регулярное выражение, с которым производится сравнение. -Например, нам нужно проверить, состоит ли указанная строка из трёх слов. Каждое слово, в грубом виде, это набор непробельных символов, значит мы можем воспользоваться метасимволом `\S` и квантификатором `+`. Слова обычно разделены пробельными символами, для чего мы используем метасимвол `\s`. Получается вот такое регулярное выражение: +Например, нам нужно проверить, состоит ли указанная строка из трёх слов. Каждое слово, в грубом виде, это набор непробельных символов, значит мы можем воспользоваться метасимволом `\S` с квантификатором `+`. Слова обычно разделены пробельными символами, для чего мы используем метасимвол `\s`. Получается вот такое регулярное выражение: ```regex \s?\S+\s+\S+\s+\S+\s? diff --git a/docs/language/qsp-keywords/qsp-keyword-operacion.md b/docs/language/qsp-keywords/qsp-keyword-operacion.md index 43d8b91..cad7517 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operacion.md +++ b/docs/language/qsp-keywords/qsp-keyword-operacion.md @@ -24,7 +24,7 @@ sidebar_position: 1 Вычисление значений функций имеет приоритет перед всеми операциями. -Верным считается числовое выражение, значение которого отлично от `0`. При значении `0` выражение считается ложным. Для значения "верно" настоятельно рекомендуется использовать `1`, т.к. только в этом случае будут адекватно работать побитовые операторы в роли логических. +Верным считается числовое выражение, значение которого отлично от `0`. При значении `0` выражение считается ложным. Для значения "верно" настоятельно рекомендуется использовать `1` для совместимости с логическими операциями и функциями, возвращающими логические значения. :::note[5.7.0] В более старых версиях плееров порядок приоритета был иной. @@ -41,6 +41,83 @@ sidebar_position: 1 ::: +**Некоторые особенности операций сравнения:** + +- Операции сравнения возвращают `1` (верно) или `0` (неверно) в зависимости от результата сравнения. +- При сравнении чисел всё просто: + - из двух положительных чисел положительное число большее по модулю будет считаться большим; + - отрицательное число всегда меньше не отрицательного (положительное и нуль); + - положительное число всегда больше не положительного (отрицательное и нуль); + - из двух отрицательных чисел отрицательное число большее по модулю будет считаться меньшим. +- При сравнении строк происходит посимвольное сравнение слева направо: + - большим считается символ, который в таблице символов стоит позже. Можно опираться на алфавитную последовательность символов, чтобы понять, какая строка окажется большей. Тогда символ '`z`' будет больше символа '`a`'. Примеры: + + ```qsp + 'z' > 'a' & ! вернёт 1 + 'z' > 'az' & ! вернёт 1 + 'akz' > 'akk' & ! вернёт 1 + ``` + + - при сравнении любой непустой строки с пустой строкой пустая строка будет считаться меньшей: + + ```qsp + ' ' > '' & ! вернёт 1 + 'a' > '' & ! вернёт 1 + 'z' > '' & ! вернёт 1 + 'akzakz' > 'akzak' & ! вернёт 1 + ``` + + :::tip[Можно считать,] + что отсутствующие символы в строке — это пустые символы (пустые строки), которые при сравнении с любым другим символом оказываются меньшим. + ::: + + - при сравнении строки с числом, плеер попытается преобразовать оба значения к числу. Если это удастся, будут сравниваться числа. Если не удастся — число будет преобразовано в строку, и будут сравниваться строки. + + ```qsp + 'zzz' > 123 & ! вернёт 1 + '123' > 92 & ! вернёт 1 + '123' > '92' & ! вернёт 0 + ``` + +- При сравнении кортежей происходит поэлементное сравнение слева направо: + - большим будет считаться тот кортеж, элемент которого оказался большим: + + ```qsp + [1, 2, 3] > [1, 2, 2] & ! вернёт 1 + [2, 2, 3] > [1, 2, 3] & ! вернёт 1 + ``` + + - при сравнении любого непустого кортежа с пустым кортежем, пустой кортеж будет считаться меньшим: + + ```qsp + [1] > [] & ! вернёт 1 + [''] > [] & ! вернёт 1 + [0] > [] & ! вернёт 1 + [1, 2] > [1] & ! вернёт 1 + [1, 2] < [9] & ! вернёт 1 + ``` + + :::tip[Можно считать,] + что отсутствующие элементы в кортеже — это пустые элементы, которые при сравнении с любым другим элементом оказываются меньшим. + ::: + + - при сравнении кортежей с числами или строками, число или строка будут сравниваться, как кортеж из одного элемента. Для упрощения понимания можно считать, что число или строка при сравнении преобразуются в кортеж: + + ```qsp + [8] < 9 & ! вернёт 1 + [9, 8] > 9 & ! вернёт 1 + [0, 0] > 9 & ! вернёт 0 + + [8, 9] > '8,9' & ! вернёт 0 + ['a', 'z'] < 'az' & ! вернёт 1 + ['a', 'z'] > 'a' & ! вернёт 1 + (['az'] = "az") & ! вернёт 1 + ``` + +:::warning[Рекомендуем:] +Не проводить сравнения значений разных типов, чтобы это не приводило к путанице. +::: + ## `*` (умножение) `*` — арифметическая операция "УМНОЖЕНИЕ". Перемножает два числа. Общая запись: @@ -60,6 +137,32 @@ sidebar_position: 1 37 * 100 & ! вернёт 3700 ``` +Можно использовать с кортежами, значениями которых являются числа и/или другие кортежи, содержащие числа. Общая запись: + +```qsp +[%кортеж] * [#число] +``` + +В данном случае каждый элемент кортежа будет умножен на указанное число. Примеры: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple * 2 +! %a будет равно [8, 20, 32] + +[4, 10] * 'b' & ! ошибка о несоответствии типов данных +``` + +Обратите внимание на последний пример. Ошибка о несоответствии типов данных возникает из-за того, что невозможно применить операцию умножения к строковому значению. Такая же ошибка возникнет, если кортеж будет содержать строковые значения. Однако перемножать между собой кортежи, содержащие только числовые значения можно: + +```qsp +*pl [2, 3] * [4, 5] +! [2 * [4,5], 3 * [4,5]] +! [[8,10],[12,15]] +``` + +В этом случае каждый элемент первого кортежа умножается на второй кортеж. Это и даёт нам в результате новый кортеж из двух кортежей. + ## `*=` (умножение-присвоение) `*=` — операция "УМНОЖЕНИЕ-ПРИСВОЕНИЕ". Сочетает в себе операции присвоения и умножения. Умножает значение указанной переменной на определённое число и возвращает результат той же переменной. Общая запись: @@ -85,6 +188,34 @@ warrior = warrior * 2 warrior *= 2 ``` +Если значением переменной `ИМЯ_МАССИВА` является кортеж, каждый элемент кортежа будет умножен на указанное число, а полученный таким образом кортеж присвоится переменной. Пример: + +```qsp +%tuple = [4, 10, 16] +%tuple *= 2 +! %tuple будет равно [8, 20, 32] +``` + +Нельзя умножать на значение строкового типа, это приведёт к ошибке о несоответствии типов данных. Так же и значения кортежа (и всех вложенных кортежей) при выполнении данной операции не должны содержать строковых значений. Однако можно выполнить умножение-присвоение с другим кортежем: + +```qsp +%tuple = [2, 3] +%tuple *= [4, 5] +! %tuple будет равно [[8,10],[12,15]] +``` + +:::warning[Обратите внимание.] +Умножение-присвоение с кортежем вызовет ошибку несоответствия типов данных, если тип переменной не является кортежем: + +```qsp +number = 4 +number *= [4,5] & ! ошибка о несоответствии типов данных +! так ошибки не будет, но в переменной окажется пустой кортеж: +%number *= [4,5] +``` + +::: + ## `+` (сложение) `+` — арифметическая операция "СЛОЖЕНИЕ". Суммирует два числа. Общая запись: @@ -104,13 +235,29 @@ warrior *= 2 37+100 & ! вернёт 137 ``` -Можно "суммировать" и текстовые значения. В этом случае операция работает как [конкатенация](qsp-keyword-operacion.md#-конкатенация): +При "суммировании" строковых значений производится [конкатенация](qsp-keyword-operacion.md#-конкатенация), то есть "склеивание" строк: ```qsp ! на экран будет выведена строка "2627" "26"+"27" ``` +Если значения "прибавляются" к кортежу, происходит суммирование каждого элемента кортежа с указанным значением: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple + 2 +! %a будет равно [6, 12, 18] +``` + +Если складываются два кортежа, к значениям каждого элемента первого кортежа прибавляется второй кортеж: + +```qsp +[4, 10] + ['b', 'x'] +! [4 + ['b', 'x'], 10 + ['b', 'x']] +! [['4b','4x'], ['10b','10x']] +``` + ## `+=` (сложение-присвоение) `+=`, `(инкремент)` — операция "ИНКРЕМЕНТ", сочетающая в себе операции присвоения и сложения. Прибавляет к текущему значению переменной указанное значение. Общая запись: @@ -142,7 +289,35 @@ warrior += 15 $text += " (может быть тут что-то написано)" ``` -:::note +Если значением переменной `ИМЯ_МАССИВА` является кортеж, каждый элемент кортежа будет суммирован с указанным значением, а полученный таким образом кортеж присвоится переменной. Пример: + +```qsp +%tuple = [4, 10, 16] +%tuple += 2 +! %tuple будет равно [6, 12, 18] +``` + +Можно выполнить сложение-присвоение с другим кортежем: + +```qsp +%tuple = [2, 3] +%tuple += [4, 5] +! %tuple будет равно [[6,7],[7,8]] +``` + +:::warning Обратите внимание. +Сложение-присвоение с кортежем вызовет ошибку несоответствия типов данных, если тип переменной не является кортежем: + +```qsp +number = 4 +number += [4,5] & ! ошибка о несоответствии типов данных +! так ошибки не будет, но в переменной окажется пустой кортеж: +%number += [4,5] +``` + +::: + +:::tip[Примечание] Инкремент — во многих языках программирования это операция, которая выполняет увеличение переменной. Чаще всего под инкрементом подразумевается увеличение переменной на `1`. ::: @@ -151,10 +326,10 @@ $text += " (может быть тут что-то написано)" `-` — арифметическая операция "ВЫЧИТАНИЕ". Вычитает одно число из другого. Общая запись: ```qsp -[выражение 1] - [выражение 2] +[#выражение 1] - [#выражение 2] ``` -, где `[выражение 1]` и `[выражение 2]` — два любых значения, или выражения. Результатом работы операции является разность двух значений. +, где `[#выражение 1]` и `[#выражение 2]` — два числовых значения, или выражения. Результатом работы операции является разность двух значений. Примеры: @@ -165,6 +340,34 @@ $text += " (может быть тут что-то написано)" 37 - 100 & ! вернёт -63 ``` +Можно использовать с кортежами, значениями которых являются числа и/или другие кортежи, содержащие числа. Общая запись: + +```qsp +[%кортеж] - [#число] +``` + +В данном случае из каждого элемента кортежа будет вычтено указанное число. Примеры: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple - 2 +! %a будет равно [2, 8, 14] + +[4, 10] - 'b' & ! ошибка о несоответствии типов данных +``` + +Обратите внимание на последний пример. Ошибка о несоответствии типов данных возникает из-за того, что невозможно применить операцию вычитания к строковому значению. Такая же ошибка возникнет, если кортеж будет содержать строковые значения. Однако из одного кортежа другой кортеж можно, если оба кортежа содержат только числовые значения: + +```qsp +*pl [2, 3] - [4, 5] +! [2 - [4,5], 3 - [4,5]] +! [2 + ([4,5] * -1), 3 + ([4,5] * -1)] +! [[-4, -5] + 2, [-4,-5] + 3] +! [[-2,-3],[-1,-2]] +``` + +В этом случае из каждого элемента первого кортежа вычитается второй кортеж. Если последовательно раскрыть скобки и произвести все необходимые математические операции, получится новый кортеж, содержащий другие кортежи с результатами. + ## `-=` (вычитание-присвоение) **`-=`, `(декремент)`** — операция "ДЕКРЕМЕНТ", сочетающая в себе операции присвоения и вычитания. Вычитает из текущего значения переменной указанное значение. Общая запись: @@ -190,7 +393,35 @@ warrior = warrior - 15 warrior -= 15 ``` -:::note +Если значением переменной `ИМЯ_МАССИВА` является кортеж, из каждого элемента кортежа будет вычитаться указанное число, а полученный таким образом кортеж присвоится переменной. Пример: + +```qsp +%tuple = [4, 10, 16] +%tuple -= 2 +! %tuple будет равно [2, 8, 14] +``` + +Нельзя вычитать значение строкового типа, это приведёт к ошибке о несоответствии типов данных. Так же и значения кортежа (и всех вложенных кортежей) при выполнении данной операции не должны содержать строковых значений. Однако можно выполнить вычитание-присвоение с другим кортежем: + +```qsp +%tuple = [2, 3] +%tuple -= [4, 5] +! %tuple будет равно [[-2,-3],[-1,-2]] +``` + +:::warning[Обратите внимание.] +Вычитание-присвоение с кортежем вызовет ошибку несоответствия типов данных, если тип переменной не является кортежем: + +```qsp +number = 4 +number -= [4,5] & ! ошибка о несоответствии типов данных +! так ошибки не будет, но в переменной окажется пустой кортеж: +%number -= [4,5] +``` + +::: + +:::tip[Примечание] Декремент — во многих языках программирования это операция, которая выполняет уменьшение переменной. Чаще всего под декрементом подразумевается уменьшение переменной на `1`. ::: @@ -212,6 +443,13 @@ warrior -= 15 -(-27) & ! вернёт 27 ``` +Унарный минус можно использовать перед кортежем, содержащим только числовые значения. Это выражение вернёт новый кортеж, в котором знак каждого элемента будет изменён на противоположный: + +```qsp +- [2, 3, -1, -17, 5] +! [-2, -3, 1, 17, -5] +``` + :::note[5.7.0] В более ранних версиях плеера существовала операция "унарный плюс": @@ -244,6 +482,32 @@ warrior -= 15 37 / 100 & ! вернёт 0 ``` +Можно использовать с кортежами, значениями которых являются числа и/или другие кортежи, содержащие числа. Общая запись: + +```qsp +[%кортеж] / [#число] +``` + +В данном случае каждый элемент кортежа будет разделён на указанное число. Примеры: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple / 2 +! %a будет равно [2, 5, 8] + +[4, 10] / 'b' & ! ошибка о несоответствии типов данных +``` + +Обратите внимание на последний пример. Ошибка о несоответствии типов данных возникает из-за того, что невозможно применить операцию деления к строковому значению. Такая же ошибка возникнет, если кортеж будет содержать строковые значения. Однако делить друг на друга кортежи, содержащие только числа можно: + +```qsp +*pl [30, 60] / [2, 6] +! [30 / [2,6], 60 / [2,6]] +! [[15,5],[30,10]] +``` + +В этом случае каждый элемент первого кортежа "делится" на второй кортеж. Это даёт нам в результате новый кортеж из двух кортежей. + ## `/=` (деление-присвоение) `/=` — операция "ДЕЛЕНИЕ-ПРИСВОЕНИЕ". Сочетает в себе операции присвоения и деления. Делит значение указанной переменной на определённое число и возвращает результат той же переменной. Общая запись: @@ -269,6 +533,34 @@ warrior = warrior / 2 warrior /= 2 ``` +Если значением переменной `ИМЯ_МАССИВА` является кортеж, каждый элемент кортежа будет разделён на указанное число, а полученный таким образом кортеж присвоится переменной. Пример: + +```qsp +%tuple = [4, 10, 16] +%tuple /= 2 +! %tuple будет равно [2, 5, 8] +``` + +Нельзя делить на значение строкового типа, это приведёт к ошибке о несоответствии типов данных. Так же и значения кортежа (и всех вложенных кортежей) при выполнении данной операции не должны содержать строковых значений. Однако можно выполнить деление-присвоение с другим кортежем: + +```qsp +%tuple = [10, 30] +%tuple /= [5, 2] +! %tuple будет равно [[2,5],[6,15]] +``` + +:::warning[Обратите внимание.] +Деление-присвоение с кортежем вызовет ошибку несоответствия типов данных, если тип переменной не является кортежем: + +```qsp +number = 4 +number /= [4,5] & ! ошибка о несоответствии типов данных +! так ошибки не будет, но в переменной окажется пустой кортеж: +%number /= [4,5] +``` + +::: + ## `<` (меньше) `<` — операция сравнения "МЕНЬШЕ". Общая запись: @@ -290,14 +582,22 @@ warrior /= 2 7 < 3 ``` -Сравнивать можно и текстовые значения, при этом символы сравниваются поочерёдно, и большим считается символ, стоящий ближе к концу алфавита. +Сравнивать можно текстовые значения: ```qsp -"a" < "z" & ! верно +"a" < "z" & ! верно "z" < "zz" & ! верно "aaaaaa" < "z" & ! верно ``` +И можно сравнивать кортежи: + +```qsp +[1, 2, 3] < [1, 2, 9] & ! верно +[1, 2, 3] < [2, 2, 3] & ! верно +[1, 2] < [1, 2, 3] & ! верно +``` + ## `<=` (меньше либо равно) `<=` — операция сравнения "МЕНЬШЕ ЛИБО РАВНО". Общая запись: @@ -327,7 +627,7 @@ warrior /= 2 no [выражение_1] > [выражение_2] ``` -Сравнивать можно и текстовые значения, при этом символы сравниваются поочерёдно, и большим считается символ, стоящий ближе к концу алфавита. +Сравнивать можно и текстовые значения: ```qsp "a" <= "z" & ! верно @@ -336,6 +636,15 @@ no [выражение_1] > [выражение_2] "z" <= "z" & ! верно ``` +И кортежи: + +```qsp +[1, 2, 3] <= [1, 2, 9] & ! верно +[1, 2, 3] <= [2, 2, 3] & ! верно +[1, 2] <= [1, 2, 3] & ! верно +[1, 2, 3] <= [1, 2, 3] & ! верно +``` + ## `<>` (не равно) `<>` — операция сравнения "НЕ РАВНО". Общая запись: @@ -368,6 +677,13 @@ no [выражение_1] = [выражение_2] "abc" <> "abc" & ! вернёт 0 ``` +Можно сравнивать кортежи: + +```qsp +[1, 2, 3] <> [4, 6, 7] & ! вернёт 1 +[1, 2, 3] <> [1, 2, 3] & ! вернёт 0 +``` + ## `=` (равно) `=` — операция сравнения "РАВНО". Общая запись: @@ -389,7 +705,7 @@ no [выражение_1] <> [выражение_2] ```qsp ! 2 не равно 4 — вернёт 0 (2 = 4) -! 5 равно 5 — вернёт -1 +! 5 равно 5 — вернёт 1 (5 = 5) ``` @@ -397,7 +713,14 @@ no [выражение_1] <> [выражение_2] ```qsp ("abc" = "def") & ! вернёт 0 -("abc" = "abc") & ! вернёт -1 +("abc" = "abc") & ! вернёт 1 +``` + +Можно сравнивать кортежи: + +```qsp +([1, 2, 3] = [4, 6, 7]) & ! вернёт 0 +([1, 2, 3] = [1, 2, 3]) & ! вернёт 1 ``` :::warning[Внимание!] @@ -423,10 +746,14 @@ BOX = 13 $text = "Строка текста" ! нулевой ячейке массива day присваивается значение 365 day[0] = 365 +! переменной tuple присваивается кортеж [1, 'unit', 3]: +%tuple = [1, 'unit', 3] ``` Имена строковых переменных/массивов должны начинаться с символа `$`. +Имена переменных/массивов, содержащих кортежи должны начинаться с символа `%`. + :::warning[Внимание!] Операцию присвоения не следует путать с операцией сравнения "РАВНО", хотя они очень похожи: @@ -445,16 +772,111 @@ alukard = 1000 синтаксически ошибочна. Плеер выдаст ошибку: недопустимое название переменной/массива. Так как в этом случае он не понимает, что это операция сравнения. -Если перед операцией сравнения стоит оператор, скобки можно не писать: +Если перед операцией сравнения явно стоит оператор, скобки можно не писать: ```qsp if alukard = 150: *pl "Не хватает сил" +*pl "abc" = "abc" ``` ::: +### Множественное присвоение + +Множественное присвоение позволяет одной командой `=` присвоить значения сразу нескольким переменным или ячейкам массива. Общая запись: + +```qsp +ИМЯ_МАССИВА_1, ИМЯ_МАССИВА_2, ... , ИМЯ_МАССИВА_N = [ЗНАЧЕНИЕ_1], [ЗНАЧЕНИЕ_2], ... , [ЗНАЧЕНИЕ_N] +``` + +, где слева от знака `=` пишутся имена переменных (или имена массивов с указанием индекса ячейки в квадратных скобках), а справа от знака `=` перечисляются значения, которые нужно присвоить переменным или ячейкам массивов. + +:::warning[Важно помнить!] +Слева от знака равенства должно быть столько же переменных, сколько справа значений. Число переменных, и число присваиваемых значений — должны совпадать. + +При распаковке кортежей это правило не соблюдается. +::: + +Примеры: + +```qsp +яблоки_в_кармане, яблоки_в_лукошке, яблоки_у_Лёшки = 58, 11, 19 +$строка_1, $строка_2 = 'Ехал Грека Через Реку', 'Видит Грека В Реке Рак' +$name, count = 'Старый меч', 2 +``` + +Вместо прямого указания значений можно присваивать значения других переменных, выражений, функций: + +```qsp +! три переменные = три значения +red, green, blue = rand(0,255), rand(0,255), rand(0,255) +! две переменные = два значения +яблоки_в_кармане, яблоки_в_лукошке = яблоки_у_Лёшки, яблоки_на_дереве+15 +``` + +Благодаря возможности одновременно присваивать значения сразу нескольким переменным, можно менять местами данные в двух переменных, не прибегая к помощи третьей: + +```qsp +! присваиваем пременным x и y значения 12 и 99 +x, y = 12, 99 +! меняем местами значения. Теперь в x находится число 99, а в y — 12 +x, y = y, x +``` + +### Распаковка кортежей + +Поскольку кортежи содержат в себе сразу несколько значений, запись присвоения значений переменным из кортежа может отличаться от привычной: + +```qsp +! %unit = [187, 94, 'steel', [0, 2]] +рост, вес, $материал, %координаты = %unit +``` + +Как видите, здесь у нас слева четыре имени переменной, а справа только одно имя переменной-кортежа. Такое присвоение называется распаковкой — значения извлекаются из кортежа и помещаются в указанные переменные. + +Точно так же распаковывается кортеж, даже не помещённый в переменную: + +```qsp +рост, вес, $материал, %координаты = [187, 94, 'steel', [0, 2]] +``` + +Такая запись мало чем отличается от множественного присвоения, поэтому внешние квадратные скобки не обязательны: + +```qsp +рост, вес, $материал, %координаты = 187, 94, 'steel', [0, 2] +``` + +Cледует подчеркнуть, что **множественное присвоение — это по сути распаковка кортежей**. + +Поскольку, если переменных слева от знака равенства будет больше, чем значений в кортеже, в "лишние" переменные запишутся значения по умолчанию для этих переменных, то и при множественном присвоении произойдёт то же самое. + +```qsp +r, g, b, a = [255, 188, 19] +! r = 255, g = 188, b = 19, a = 0 +raz, dva, tri, chetyre = 137, 61 +! raz = 137, dva = 61, tri = 0, chetyre = 0 +``` + +В то же время, если при множественном присвоении переменных слева от знака равенства будет меньше, чем значений справа, это вызовет ошибку о несоответствии типов данных: + +```qsp title="Несоответствие типов данных" +coords = 23, 34 +age, weight, material = 27, 94, 'steel', 'biorobot' +``` + +Если тип последней из перечисленных переменных будет кортеж, такое присвоение ошибку не вызовет: + +```qsp +age, weight, %type = 27, 94, 'steel', 'biorobot' +! age = 27, weight = 94, %type = ['steel', 'biorobot'] +``` + ## `=<` (равно либо меньше) +:::warning[Внимание!] +Данная запись, хотя и допустима в QSP, к использованию не рекомендуется. Используйте "`<=` (меньше либо равно)" вместо этого. +::: + `=<` — операция сравнения "РАВНО ЛИБО МЕНЬШЕ". Общая запись: ```qsp @@ -482,23 +904,14 @@ if alukard = 150: *pl "Не хватает сил" no [выражение_1] > [выражение_2] ``` -Сравнивать можно и текстовые значения, при этом символы сравниваются поочерёдно, и большим считается символ, стоящий ближе к концу алфавита. +## `=>` (равно или больше) -```qsp -"a" =< "z" & ! верно -"z" =< "zz" & ! верно -"aaaaaa" =< "z" & ! верно -"z" =< "z" & ! верно -``` +`=>` — операция сравнения "РАВНО ИЛИ БОЛЬШЕ". Общая запись: :::warning[Внимание!] -Данная запись, хотя и допустима в QSP, к использованию не рекомендуется. Используйте "`<=` (меньше либо равно)" вместо этого. +Данная запись, хотя и допустима в QSP, к использованию не рекомендуется. Используйте "`>=` (больше либо равно)" вместо этого. ::: -## `=>` (равно или больше) - -`=>` — операция сравнения "РАВНО ИЛИ БОЛЬШЕ". Общая запись: - ```qsp [выражение_1] => [выражение_2] ``` @@ -523,19 +936,6 @@ no [выражение_1] > [выражение_2] no [выражение_1] < [выражение_2] ``` -Сравнивать можно и текстовые значения, при этом символы сравниваются поочерёдно, и большим считается символ, стоящий ближе к концу алфавита. - -```qsp -"z" => "a" & ! верно -"zz" => "z" & ! верно -"z" => "aaaaaa" & ! верно -"z" => "z" & ! верно -``` - -:::warning[Внимание!] -Данная запись, хотя и допустима в QSP, к использованию не рекомендуется. Используйте "`>=` (больше либо равно)" вместо этого. -::: - ## `>` (больше) `>` — операция сравнения "БОЛЬШЕ". Общая запись: @@ -565,6 +965,14 @@ no [выражение_1] < [выражение_2] "z" > "aaaaaa" & ! верно ``` +И можно сравнивать кортежи: + +```qsp +[1, 2, 9] > [1, 2, 3] & ! верно +[1, 2, 3] > [2, 2, 3] & ! неверно +[1, 2, 3] > [1, 2] & ! верно +``` + ## `>=` (больше либо равно) `>=` — операция сравнения "БОЛЬШЕ ЛИБО РАВНО". Общая запись: @@ -602,8 +1010,23 @@ no [выражение_1] < [выражение_2] "z" >= "z" & ! верно ``` +И кортежи: + +```qsp +[1, 2, 9] >= [1, 2, 3] & ! верно +[1, 2, 3] >= [2, 2, 3] & ! не верно +[1, 2] >= [1, 2, 3] & ! не верно +[1, 2, 3] >= [1, 2, 3] & ! верно +``` + ## `!` (не равно) +:::warning[Внимание!] +Не путайте с оператором комментария. + +Для улучшения читаемости кода рекомендуем использовать `<>`. +::: + `!` — операция сравнения "НЕ РАВНО". Общая запись: ```qsp @@ -627,29 +1050,43 @@ no [выражение_1] = [выражение_2] 5 ! 5 ``` -:::warning[Внимание!] -Не путайте с оператором комментария. +## `&` (конкатенация) -Для улучшения читаемости кода используйте `<>`. +`&` — конкатенация, операция объединения строковых выражений или кортежей. Общая запись: + +```qsp +([$выражение 1] & [$выражение 2]) +([%выражение 1] & [%выражение 2]) +``` + +:::warning[внимание!] +Конкатенацию всегда нужно заключать в скобки! ::: -## `&` (конкатенация) +Если попытаться объединить числовые значения, они будут преобразованы к строкам, а затем строки будут объединены. -`&` — конкатенация, операция объединения строковых выражений. Общая запись: +Примеры: ```qsp -[$выражение 1] & [$выражение 2] +*pl ('привет, ' & 'Мир!') +! на экране увидим строку 'привет, Мир!' +*pl ([1, 2, 3] & [4, 5, 6]) +! на экране увидим кортеж [1, 2, 3, 4, 5, 6] ``` +:::warning[внимание!] Не путайте с символом перечисления команд: ```qsp -! в данном случае на экран будут последовательно выведены строки "26" и "27" +! в данном случае на экран будут +! последовательно выведены строки "26" и "27" "26" & "27" -! в данном случае на экран будет выведена строка "2627" +! а здесь на экран будет выведена строка "2627" ("26" & "27") ``` +::: + :::tip Не рекомендуется использовать данную операцию для объединения строк, поскольку строки можно объединять через [`+`](qsp-keyword-operacion.md#-сложение): @@ -658,7 +1095,15 @@ no [выражение_1] = [выражение_2] "26"+"27" ``` -Такая запись создаёт меньше путаницы и работает аналогичным образом. +Такая запись создаёт меньше путаницы при чтении кода и работает аналогичным образом. + +Склеить два кортежа в один при помощи операции `+` не получится: + +```qsp +[2, 5] + [3, 7] +! на экране будет кортеж: [[5,9],[8,12]] +``` + ::: ## AND @@ -729,9 +1174,7 @@ end 13 mod 10 & ! возвращает 3 ``` -:::note Остаток от деления отрицательного числа будет отрицательным числом. -::: ## NO @@ -747,11 +1190,11 @@ NO [#выражение] ```qsp ! 4 равно 4 это верно, значит всё выражение неверно -no 4 = 4 & ! вернёт 0 (ложь) +no (4 = 4) & ! вернёт 0 (ложь) ! можно читать как вопрос: четыре не равно четырём? Нет — ложь. ! то, что 5 равно 3, — неверно, значит всё выражение верно -no 5 = 3 & ! вернёт 1 (правда) +no (5 = 3) & ! вернёт 1 (правда) ! можно читать как вопрос: пять не равно трём? Да — правда. ``` diff --git a/docs/language/qsp-keywords/qsp-keyword-operators.md b/docs/language/qsp-keywords/qsp-keyword-operators.md index 782ac95..cf022b3 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operators.md +++ b/docs/language/qsp-keywords/qsp-keyword-operators.md @@ -6,7 +6,7 @@ sidebar_position: 2 ## Неявный оператор -Неявный оператор — это оператор, который не прописывается в коде QSP, но производит вывод значений на экран. Неявный оператор подразумевается везде, где в команде присутствует выражение без оператора. Неявный оператор выводит в **Окно основного описания** значения таким же образом, как если бы вы использовали явное указание оператора `*pl`, то есть выводит значение и совершает переход на новую строку. Примеры: +Неявный оператор — это оператор, который не прописывается в коде QSP, но производит вывод значений на экран. Он подразумевается везде, где в команде присутствует выражение без оператора. Неявный оператор выводит в **Окно основного описания** значения таким же образом, как если бы вы использовали явное указание оператора `*pl`, то есть выводит значение и совершает переход на новую строку. Примеры: ```qsp $AAA + '989' @@ -68,6 +68,17 @@ local i=0 *pl "строка текста" & ! тоже однострочный комментарий ``` +:::tip[Исключение] +Единственным исключением из этого правила является запись комментария после двоеточия в многострочных операторах: + +```qsp +act "Многострочное действие": ! комментарий + *pl "Текст на экране" +end +``` + +::: + Комментарии могут быть многострочными. Для этого после оператора комментария нужно записать кавычки, апострофы, или фигурные скобки. Например так: ```qsp @@ -225,8 +236,7 @@ ADDOBJ [$название], [$путь к файлу изображения], [# , где `[$название]` — это название предмета, `[$путь к файлу изображения]` — это путь к файлу изображения предмета (отображается рядом с названием предмета), а `[#позиция]` — на какое место в инвентаре добавляется предмет. Параметр `[#позиция]` может отсутствовать. По умолчанию предметы добавляются в конец списка. Нумерация предметов в инвентаре ведётся с `1`. Параметр `[$путь к файлу изображения]` может отсутствовать, значение по умолчанию - `''`, при этом предмет добавляется без изображения. -:::note -Допустима, но не рекомендуется, запись: +:::note[Допустима, но не рекомендуется, устаревшая форма записи:] ```qsp ADD OBJ [$название],[$путь к файлу изображения],[#индекс] @@ -237,7 +247,7 @@ ADD OBJ [$название],[$путь к файлу изображения],[# Можно добавлять предметы с одинаковым названием, однако если вы планируете добавлять много одинаковых предметов, то лучше использовать дополнительную переменную для подсчёта этих предметов, а в окно предметов добавить один предмет, чтобы не загромождать инвентарь списком из 137 предметов Рубль / Патрон: ```qsp -if obj 'Патроны': +if obj('Патроны'): ! если предмет "Патроны" уже добавлен, просто увеличиваем их число патроны += 10 else @@ -347,8 +357,7 @@ delact 'Идти вперед' delact $selact ``` -:::note -Допустима, но не рекомендуется, устаревшая форма записи: +:::note[Допустима, но не рекомендуется, устаревшая форма записи:] ```qsp DEL ACT [$название] @@ -377,8 +386,7 @@ delobj "Отвёртка" delobj $selobj ``` -:::note -Допустима, но не рекомендуется, устаревшая форма записи: +:::note[Допустима, но не рекомендуется, устаревшая форма записи:] ```qsp DEL OBJ [$название] @@ -410,7 +418,7 @@ dynamic " Нижеследующая информация справедлива и для функции [`dyneval`](qsp-keyword-functions.md#dyneval). -Важно! Если код задан с помощью апострофов (`''`) или кавычек (`""`), в тексте вычисляются подвыражения: +**Важно!** Если код задан с помощью апострофов (`''`) или кавычек (`""`), в тексте вычисляются подвыражения: ```qsp $args[0] = 'qwerty' @@ -464,6 +472,14 @@ end Тело цикла так же считается отдельным блоком кода, однако оператор `exit` прерывает не только сам цикл, но и блок кода, в котором находится цикл. ::: +## FREELIB + +`FREELIB` — удаляет все локации, добавленные с помощью оператора `inclib`. + +:::note[5.7.0] +В старых версиях плеера команда называлась `dellib` и `killqst`. +::: + ## GOSUB `GOSUB` — выполнение кода указанной локации без непосредственного перехода на неё. @@ -484,7 +500,7 @@ GOSUB [$локация],[аргумент 0],[аргумент 1], ... ,[арг !обработка локации "ход". Массив args[] пуст. gosub 'ход' -!обработка локации с названием из переменной $loc +!обработка локации с названием из переменной $location !Передаётся один параметр - args[0] равен 1. gosub $location,1 @@ -547,21 +563,36 @@ goto 'улица',1,'данные' GT [$локация],[аргумент 0],[аргумент 1], ... ,[аргумент 8] ``` -## IF (ELSE, ELSEIF) +## IF -`IF` — оператор условия. Собственно для того и нужен, чтобы проверять выполнение какого-либо условия. Имеет несколько форм записи. +`IF` — основной оператор для записи конструкций условий. Конструкции, записываемые с помощью этого оператора (назовём их "простыми условиями"), имеют две формы: однострочную и многострочную, — и в общем виде выглядят так: -Простая однострочная форма записи: +Общая форма записи: ```qsp -IF [#выражение]: [команда 1] & [команда 2] & ... +! однострочная форма записи +IF [#выражение]: {команда 1} & {команда 2} & ... + +! многострочная форма записи +IF [#выражение]: + {команда 1} + {команда 2} + ... +END ``` -Как видите, за ключевым словом `if` следует выражение `[#выражение]`, и если это выражение верно, тогда выполняется набор команд `[команда 1]`, `[команда 2]`, и т.д., которые записаны после двоеточия в той же строке. При этом команды перечисляются через амперсанд (`&`). +В данном случае, если верно условие `[#выражение]`, выполняются команды `{команда 1}`, `{команда 2}` и т.д. -Именно по наличию команд сразу в той же строке после двоеточия плеер определяет, что это однострочная форма, и считает конец этой строки концом конструкции условия. +- Для **однострочной формы** записи это будут только те команды, которые идут в той же строке, что и оператор `IF` до конца строки; +- а для **многострочной формы** записи это будут те команды, которые идут в последующих строках после двоеточия и до специального ключевого слова `END`. -Примеры: +В качестве условия могут выступать операции сравнения, логические операции и иные выражения, возвращающие числовые значения. + +Ключевое слово `END` при многострочной форме записи должно стоять отдельной строкой. + +Если условие `[#выражение]` не верно, команды выполнены не будут. + +Примеры однострочной формы записи условий: ```qsp ! если сумма a и b равна двум, @@ -573,198 +604,280 @@ if no obj("Апельсин"): pl "У Вас нет апельсина." if ((a+b)/c)=45+54 or (b<5 or c>45) and no obj 'лопата' and $f=$vvv+'RRRRR': p 'OK' & goto 'Next' ``` -Сложная однострочная форма записи: +Примеры многострочной формы записи условий: ```qsp -IF [#выражение]: [команда д1] & [команда д2] & ... ELSE [команда н1] & [команда н2] & ... +if библиотека = 0: + узнал_о_тусовке = 0 + библиотека_вернулся = 1 + gt 'библиотека' +end +if a+b=2: + c=30 +end ``` -Здесь снова за ключевым словом `if` следует `[#выражение]`, истинность которого требуется проверить. Если выражение верно, выполняется набор команд `[команда д1]`, `[команда д2]` и т.д., от двоеточия до ключевого слова else. В противном случае, если выражение `[#выражение]` неверно, выполняется набор команд `[команда н1]`, `[команда н2]` и т.д., от `else` и до конца строки. Точно так же, как и для простой однострочной формы, концом конструкции условия считается конец строки. +:::warning[Обратите внимание!!!] -Примеры сложной однострочной формы: +При многострочной форме записи после двоеточия в той же строке, в какой находится оператор IF, не должны идти никакие команды, иначе плеер посчитает такой оператор условия однострочным, и команды в последующих строках будут выполняться в любом случае, независимо от того, верным окажется условие или нет. Пример такой ошибочной записи: ```qsp -! если сумма a и b равна двум, переменной c присваивается значение 30 -! в противном случае (то есть если сумма a и b не равна двум) -! переменной c присваивается значение 10 -if a+b=2: c=30 else c=10 -! в зависимости от того есть ли в инвентаре апельсин -! выводится соответствующий текст -if obj "Апельсин": pl "У Вас есть апельсин." else pl "У Вас нет апельсина." +if библиотека = 0: узнал_о_тусовке = 0 + библиотека_вернулся = 1 &! эта строчка будет выполняться в независимости от верности условия + gt 'библиотека' &! и эта +end &! ключевое слово end - просто игнорируется ``` -Простая многострочная форма записи в общем виде выглядит вот так: +Исключением является оператор комментария записанный после двоеточия: ```qsp -IF [#выражение]: - [команда 1] - [команда 2] - ... -END +if библиотека = 0: ! если не посещал библиотеку + узнал_о_тусовке = 0 + библиотека_вернулся = 1 + gt 'библиотека' +end +``` + +Но в случае, если комментарий отделён амперсандом, условие будет считаться однострочным: + +```qsp +if библиотека = 0: & ! такой комментарий делает условие однострочным! + узнал_о_тусовке = 0 & ! эта строчка будет выполняться в независимости от верности условия + библиотека_вернулся = 1 & ! и эта + gt 'библиотека' &! и эта тоже +end &! ключевое слово end - просто игнорируется ``` -Как видите, она отличается от простой однострочной формы записи тем, что команды `[команда 1]`, `[команда 2]` и т.д. записаны не сразу после двоеточия, а только в следующей строке. Именно так плеер понимает, что имеет дело с многострочной формой записи. Наличие или отсутствие пробелов или символов табуляции перед командами роли не играет, однако, чтобы плеер понял, где заканчивается конструкция условия, в конце на отдельной строке необходимо прописывать ключевое слово `end`, или `end if`. +::: + +Для многострочных форм записи допускается вложенность неограниченной глубины. Каждый уровень вложения должен заканчиваться своей строкой `end`. Примеры: ```qsp -if библиотека = 0: - узнал_о_тусовке = 0 - библиотека_вернулся = 1 - gt 'библиотека' +if a+b<3 or y=8: + p 'A+B<3 или Y=8' + nl + if j=88: nl & p 'NEXT' + if $h='ooo': + p 'loo' & jump 'lll' + end end +``` -if a+b=2: - c=30 +```qsp +if a=0: + 'abc1234' + if b=0: '0' else '1' + if j=88: nl & p 'NEXT' + if $h='ooo': + p 'loo' & jump 'lll' + else + p 'sample text' + v=8 + end + 1234 +else + '01234' + g=78 end ``` -Сложная многострочная форма в общей записи выглядит вот так: +Несколько примеров неверной записи: + +```qsp {4} +! в этом случае, если условие не будет выполнено, +! плеер проигнорирует только команду `k1=34` +! поскольку посчитает, что это однострочное условие +if abcd=3: k1=34 + k2=35 & ! эта команда будет выполняться всегда + k3=36 & ! эта комнада будет выполняться всегда +end & ! этот end будет проигнорирован +``` + +```qsp {3,9} +! данная строка выведет ошибку неизвестное действие +! так как однострочные формы записи не должны оканчиваться end`ом +if abcd=3: k1=34 else k1=25 end +``` + +## ELSE + +`ELSE` — ключевое слово, использующееся совместно с оператором `IF`, и которое служит для предоставления альтернативы, если условие не выполнено. Ключевое слово `ELSE` так же имеет две формы записи: однострочную и многострочную. + +- Многострочную форму записи `ELSE` можно использовать только в многострочной конструкции оператора `IF`, +- однострочную форму записи можно использовать как в однострочной, так и в многострочной, конструкции оператора `IF`. Общая форма записи: ```qsp +! однострочная форма записи +IF [#выражение]: {команда д1} & {команда д2} & ... ELSE {команда н1} & {команда н2} & ... + +! в многострочном IF: + +! многострочная форма ELSE IF [#выражение]: - [команда д1] - [команда д2] + {команда д1} + {команда д2} ... ELSE - [команда н1] - [команда н2] + {команда н1} + {команда н2} ... END + +! однострочная форма ELSE +IF [#выражение]: + {команда д1} + {команда д2} + ... +ELSE {команда н1} & {команда н2} & ... + ! команды в следующих строках + ! до END игнорируются +END ``` -Здесь так же команды `[команда д1]`, `[команда д2]` и т.д. записываются не сразу после двоеточия, а только в следующей строке. Ключевое слово else так же записывается в отдельной строке, и команды `[команда н1]`, `[команда н2]` и т.д. идут в последующих строках после `else`. Завершается конструкция условия ключевым словом `end` (или `end if`), которое снова идёт отдельной строкой. +Здесь, если условие`[#выражение]` верно, выполняются команды от двоеточия до ключевого слова `ELSE`, а если условие `[#выражение]` не верно, выполняются команды от ключевого слова `ELSE` и до конца конструкции условия. -При верности выражения `[#выражение]` выполняется набор команд между двоеточием и `else`, а если `[#выражение]` неверно, выполняется набор команд между `else` и `end`. +После `ELSE` можно ставить, а можно не ставить двоеточие. -Примеры: +**При однострочной форме записи:** + +- и команды и ключевое слово `ELSE` должны быть записаны в одной строке +- окончанием альтернативного списка команд является конец строки. +- если однострочная форма записи `ELSE` используется в многострочной форме записи `IF`, все команды, которые идут в последующих строках после `ELSE` до `END` игнорируются. + +Примеры однострочной записи: + +```qsp +! если сумма a и b равна двум, переменной c присваивается значение 30 +! в противном случае (то есть если сумма a и b не равна двум) +! переменной c присваивается значение 10 +if a+b=2: c=30 else c=10 + +! в зависимости от того есть ли в инвентаре апельсин +! выводится соответствующий текст +if obj("Апельсин"): pl "У Вас есть апельсин." else pl "У Вас нет апельсина." + +! однострочная форма else внутри многострочной if +if $левая_рука = 'Великий меч': + gosub 'atack', 300 + gosub 'health.prove' + gosub 'win.prove' +else gosub 'atack', atack_power +end +``` + +**При многострочной форме записи:** + +- все команды должны идти в последующих строках после `ELSE`; + +Примеры многострочной записи: ```qsp if a+b=2: - c=30 + c=30 else - c=10 + c=10 end if obj("Апельсин"): - pl "У Вас есть апельсин." + pl "У Вас есть апельсин." else - pl "У Вас нет апельсина." + pl "У Вас нет апельсина." end if len($curtoken) > 0: - $tokens[curtoken] = $curtoken - tokens = curtoken + 1 + $tokens[curtoken_num] = $curtoken tokens_count = curtoken_num + 1 else - tokens = curtoken + tokens_count = curtoken_num end ``` -Ещё одна форма записи работает только в многострочном варианте (обещали исправить в новых версиях). Это расширенная форма. Она позволяет размещать на одном уровне вложенности последовательно-исключающие условия. Общая форма записи такая: +## ELSEIF + +`ELSEIF` — ключевое слово, которое используется совместно с оператором `IF` и позволяет определять на одном уровне вложенности последовательно-исключающие условия. Имеет однострочную и многострочную формы записи. + +- Многострочную форму записи можно использовать только в многострочных конструкциях с оператором `IF`, +- однострочную — как в многострочных, так и в однострочных конструкциях с оператором `IF`. + +Общие формы записи: ```qsp +! однострочная в однострочном условии +IF [#выражение 1]: {набор команд 1} ELSEIF [#выражение 2]: {набор команд 2} ELSE {последний набор команд} + +! многострочная в многострочном условии IF [#выражение 1]: - [набор команд 1] - ... + {набор команд 1} + ... ELSEIF [#выражение 2]: - [набор команд 2] - ... + {набор команд 2} + ... ELSEIF ... : - ... + ... ELSE - [последний набор команд] - ... + {последний набор команд} + ... +END + +! однострочная в многострочном условии +IF [#выражение 1]: + {набор команд 1} + ... +ELSEIF [#выражение 2]: {набор команд 2} +ELSEIF ... : ... +ELSE {последний набор команд} END ``` -Правила записи такие же, как и для других видов многострочных условий. После двоеточия в той же строке, где находится оператор `if` или `elseif` не должно идти никаких команд, только со следующей строки. Вся конструкция должна заканчиваться оператором `end` (или `end if`), стоящим в отдельной строке. В конструкции может как присутствовать, так и отсуствовать часть с `else`. +Работает это следующим образом. Если `[#выражение 1]` верно, выполняются команды `{набор команд 1}`. Если `[#выражение 1]` неверно, но верно `[#выражение 2]`, выполняются команды `{набор команд 2}`, и т.д. И только если неверны все выражения в текущей конструкции условия, выполнятся команды после `ELSE`. Верность выражения `[#выражение 1]` не исключает верности выражения `[#выражение 2]`, однако верность выражения `[#выражение 2]` исключает верность выражения `[#выражение 1]`. -Работает это следующим образом. Если `[#выражение 1]` верно, выполняются команды `[набор команд 1]`. Если `[#выражение 1]` неверно, но верно `[#выражение 2]`, выполняются команды `[набор команд 2]`, и т.д. И только если неверны все выражения в текущей конструкции условия, выполнятся команды после `else`. +Особенности записи `ELSEIF`: -Как вы понимаете, верность выражения `[#выражение 1]` не исключает верности выражения `[#выражение 2]`, однако верность выражения `[#выражение 2]` исключает верность выражения `[#выражение 1]`. Поэтому я и назвал эту конструкцию конструкцией последовательно-исключающих условий. +- Может использоваться вариант написания `ELSE IF`. Работает точно так же. +- Если в многострочной конструкции `IF` после `ELSEIF` операторы идут в той же самой строке (однострочная форма), то все последующие строки игнорируются до следующего `ELSEIF`, либо до `ELSE` или `END`. +- В конструкции `IF` c `ELSEIF` может как присутствовать, так и отсутствовать часть с `ELSE`. Примеры: ```qsp +if obj('Зелье здоровья'): health += 100 esleif obj('Яблоко'): health += 15 else *pl 'Нечем пополнить силы!' + IF ОЧКИ>124: - GOTO 'КОН3' + GOTO 'КОН3' ELSEIF ОЧКИ>99: - GOTO 'КОН4' + GOTO 'КОН4' ELSE - GOTO 'КОН5' + GOTO 'КОН5' END -``` - -```qsp + if money mod 10=1 and money mod 100<>11: - *pl "У вас <> монета." + *pl "У вас <> монета." elseif money mod 10>1 and money mod 10<5 and (money mod 100<5 or money mod 100>20): - *pl "У вас <> монеты." + *pl "У вас <> монеты." elseif money mod 10=0 or money mod 10>4 or (money mod 100>10 and money mod 100<21): - *pl "У вас <> монет." + *pl "У вас <> монет." end ``` -Обратите внимание. Ключевым словом `end` заканчивается не каждый отдельный `elseif`, а вся конструкция условия. - -Для многострочных форм записи допускается вложенность неограниченной глубины. Каждый уровень вложения должен заканчиваться своей строкой `end`. - -Примеры: - -```qsp -if a+b<3 or y=8: - p 'A+B<3 или Y=8' - nl - if j=88: nl & p 'NEXT' - if $h='ooo': - p 'loo' & jump 'lll' - end -end -``` +Пример записи `ELSEIF` с операторами в той же строке: ```qsp -if a=0: - 'abc1234' - if b=0: '0' else '1' - if j=88: nl & p 'NEXT' - if $h='ooo': - p 'loo' & jump 'lll' - else - p 'sample text' - v=8 - end - 1234 -else - '01234' - g=78 +! реализация switch/case на QSP +if r = 0: + 'Вариант 0' + elseif r = 1: 'Вариант 1' + elseif r = 2: 'Вариант 2' + elseif r = 3: 'Вариант 3' + else: 'Без вариантов' end ``` -Несколько примеров неверной записи: +:::tip[На заметку:] -```qsp {4} -! в этом случае, если условие не будет выполнено, -! плеер проигнорирует только команду `k1=34` -! поскольку посчитает, что это однострочное условие -if abcd=3: k1=34 - k2=35 & ! эта команда будет выполняться всегда - k3=36 & ! эта комнада будет выполняться всегда -end & ! этот end будет проигнорирован -``` +Для улучшения читаемости кода рекомендуется использовать конструкции с `elseif` только в многострочной форме оператора `if`. -```qsp {3,9} -! данная строка выведет ошибку неизвестное действие -! так как однострочные формы записи не должны оканчиваться end`ом -if abcd=3: k1=34 else k1=25 end - -! данная запись приведёт к ошибке: -! "Неверная запись однострочного оператора" -if absd=3: - k=34 -else if absd=6: - k1=25 -end -``` +::: ## INCLIB @@ -784,7 +897,7 @@ inclib "res/base.qsp" inclib "res/intro.qsp" ``` -:::note +:::note[5.7.0] В более старых версиях плееров команда называлась `addqst` и `addlib`. ::: @@ -802,10 +915,10 @@ JUMP [$метка] Отдельными блоками кода в QSP являются: -* код "Выполнить при посещении" конкретной локации (каждая локация - отдельный блок кода), -* код действия даже если действие добавлено программно, -* код в гиперссылке, -* код `DYNAMIC`/`DYNEVAL` +- код "Выполнить при посещении" конкретной локации (каждая локация - отдельный блок кода), +- код действия даже если действие добавлено программно, +- код в гиперссылке, +- код `DYNAMIC`/`DYNEVAL` Пример: @@ -890,14 +1003,6 @@ killobj countobj killobj ``` -## FREELIB - -`FREELIB` — удаляет все локации, добавленные с помощью оператора `inclib`. - -:::note[5.7.0] -В старых версиях плеера команда называлась `dellib` и `killqst`. -::: - ## KILLVAR `KILLVAR` — удаление указанного элемента массива. Общая запись: @@ -946,9 +1051,9 @@ LET [название переменной] = [выражение] , где `[название переменной]` — это допустимое имя переменной, `[выражение]` — это допустимое для данной переменной значение. -* Названия числовых переменных записываются без символов `$` и `%` в начале. -* Названия текстовых переменных записываются с символом `$` в начале. -* Названия переменных, содержащих кортежи, записываются с символом `%` в начале. +- Названия числовых переменных записываются без символов `$` и `%` в начале. +- Названия текстовых переменных записываются с символом `$` в начале. +- Названия переменных, содержащих кортежи, записываются с символом `%` в начале. Примеры: @@ -958,14 +1063,14 @@ let $text = "text string" ! задаём числовую переменную let abs = 123 ! задаём кортеж -let %tuple = (123, "text string") +let %tuple = [123, "text string"] ``` :::tip Данный оператор считается устаревшим. Используйте вместо него оператор `set`, и только в тех случаях, когда это улучшит читаемость кода. ```qsp -! присвоение можно проводить без оператора set или let: +! присвоение можно проводить без операторов set или let: $text = "text string" ``` @@ -993,7 +1098,7 @@ local tempora = 12 local x, y, $item = 11, 19, "Старый меч" ! объявляение с распаковкой local i, j = %map_cell -local z, $a = (13, '37') +local z, $a = [13, '37'] ``` В отличие от операторов `set` и `let` переменную можно объявить, но значение ей не присваивать. @@ -1012,11 +1117,11 @@ local arr Собственные локальные переменные можно создавать в следующих блоках кода: -* Локации сами со себе. -* Код, передаваемый оператору `DYNAMIC`, или функции `DYNEVAL`, в виде текста. -* Код, выполняемый при нажатии на гиперссылку. -* Код каждого отдельного Действия ([ACT](qsp-keyword-operators.md#act)). -* Код каждого отдельного Цикла ([LOOP](qsp-keyword-operators.md#loop)) +- Локации сами по себе. +- Код, передаваемый оператору `DYNAMIC`, или функции `DYNEVAL`, в виде текста. +- Код, выполняемый при нажатии на гиперссылку. +- Код каждого отдельного Действия ([ACT](qsp-keyword-operators.md#act)). +- Код каждого отдельного Цикла ([LOOP](qsp-keyword-operators.md#loop)) :::warning[**Внимание!**] У локальных переменных есть одна особенность, которую нужно очень чётко понимать. Значение объявленной в данном блоке кода локальной переменной транслируется и во все вложенные, или вызванные из данного, блоки кода. Например, если на локации объявлена локальная переменная, то её значение транслируется во все вызываемые с помощью `GOSUB` или `FUNC` локации, в блоки кода для `DYNAMIC`/`DYNEVAL`, в блоки циклов и так далее. Пример: @@ -1149,10 +1254,10 @@ END , где: -* `{команды до начала цикла}` — это команды, выполняемые до того, как цикл будет запущен. Данные команды относятся к блоку цикла, но не попадают в итерации (проходы), т.е. выполняются только один раз. Здесь можно, например, объявить счётчик цикла. И здесь можно писать множество команд, перечисляя их через разделитель `&` (амперсанд). -* `[условие]` — это выражение, по значению которого проверяется условие. Здесь могут использоваться операции сравнения и логические операции в любых связках. В случае, если значение выражения `[условие]` равно нулю, цикл прерывается. -* `{команды в конце итеррации}` — это команды, выполняемые в конце каждого прохода цикла. Сюда можно помещать команды, которые не относятся напрямую к телу цикла, но тем не менее должны быть выполнены на каждой итерации. Здесь можно, например, изменять значение счётчика цикла. И здесь можно писать на самом деле множество команд, перечисляя их через разделитель `&` (амперсанд). -* `{операторы тела цикла}` — это команды, которые необходимо выполнять на каждом проходе, и являющиеся основными для цикла. То есть мы делаем цикл именно ради этих команд. +- `{команды до начала цикла}` — это команды, выполняемые до того, как цикл будет запущен. Данные команды относятся к блоку цикла, но не попадают в итерации (проходы), т.е. выполняются только один раз. Здесь можно, например, объявить счётчик цикла. И здесь можно писать множество команд, перечисляя их через разделитель `&` (амперсанд). +- `[условие]` — это выражение, по значению которого проверяется условие. Здесь могут использоваться операции сравнения и логические операции в любых связках. В случае, если значение выражения `[условие]` равно нулю, цикл прерывается. +- `{команды в конце итеррации}` — это команды, выполняемые в конце каждого прохода цикла. Сюда можно помещать команды, которые не относятся напрямую к телу цикла, но тем не менее должны быть выполнены на каждой итерации. Здесь можно, например, изменять значение счётчика цикла. И здесь можно писать на самом деле множество команд, перечисляя их через разделитель `&` (амперсанд). +- `{операторы тела цикла}` — это команды, которые необходимо выполнять на каждом проходе, и являющиеся основными для цикла. То есть мы делаем цикл именно ради этих команд. Цикл в QSP является отдельным блоком кода, и это значит, что внутри этого блока кода мы можем объявить локальные переменные. Это очень удобно, потому что мы можем объявить локальную переменную для счётчика, и это не повлияет на остальные переменные на локации: @@ -1184,29 +1289,116 @@ end MENU [$название массива] ``` -Прежде, чем использовать данный оператор, необходимо заполнить массив, на основе содержимого которого будут формироваться пункты меню. Пункты меню — это строковые начения массива с особым форматом записи: +Прежде, чем использовать данный оператор, необходимо заполнить массив, на основе содержимого которого будут формироваться пункты меню. Пункты меню — это кортежи из трёх значений, последовательно помещаемые в подряд идущие ячейки массива, начиная с нулевой. Содержимое каждого кортежа должно быть примерно таким: ```qsp -"название пункта меню:название локации:путь к файлу иконки" +["название пункта меню", "название локации", "путь к файлу иконки"] ``` Название пункта меню — это то, что мы увидим на экране, когда меню будет выведено; название локации — это название локации, код которой будет выполняться при щелчке на соответствующем пункте меню; путь к файлу иконки — это путь к файлу изображения, которое будет выведено рядом с названием пункта меню. -Таким образом мы можем заполнить массив для того, чтоб создать наши пункты меню: +Зная это, мы можем заполнить массив для того, чтоб создать наши пункты меню: ```qsp -$stone[0] = 'Взять камень:takestone' -$stone[1] = 'Кинуть камень:throwstone' -$stone[2] = 'Осмотреть камень:lookstone' +%stone[0] = ['Взять камень', 'takestone'] +%stone[1] = ['Кинуть камень', 'throwstone'] +%stone[2] = ['Осмотреть камень', 'lookstone'] ``` +Здесь название массива (`%stone`) - это название меню, а кортежи - действия, для которых указаны названия пунктов и названия локаций-обработчиков выбора пунктов меню. При выборе пункта "Взять камень" произойдёт вызов локации с названием "takestone". Аналогично будет происходить с другими пунктами. + +Чтобы вывести меню на экран, нужно воспользоваться оператором `MENU`: + +```qsp +menu '%stone' +``` + +Пример создания меню с иконками: + +```qsp +! нет иконки +%usr_menu[0] = ['Взять предмет', 'take_item'] +! иконка задана gif-файлом +%usr_menu[1] = ['Положить предмет', 'put_item', 'images/put_item.gif'] +! иконка задана значением $icon_file +%usr_menu[2] = ['Уничтожить предмет','del_item', $icon_file] +! пункт меню задан 3-мя переменными +%usr_menu[3] = [$name, $location, $icon_file] + +menu 'usr_menu' &! покажет меню из 4-х пунктов +``` + +Меню заканчивается на элементе массива со пустым кортежем, либо с кортежем, в котором отсутствует значение для названия пункта меню или локации-обработчика пункта меню. + +Примеры, когда два последних пункта меню не будут созданы: + +```qsp +%usr_menu[0]=['Взять предмет','take_item'] & ! этот пункт мы увидим на экране +$usr_menu[1]=['Осмотреть предмет','look_item'] & ! и этот пункт мы увидим на экране +$usr_menu[2]=[] & ! пустой кортеж, плеер посчитает, что меню кончилось +$usr_menu[3]=['Положить предмет','put_item'] & ! этот пункт мы не увидим +``` + +```qsp +%usr_menu[0]=['Взять предмет','take_item'] & ! этот пункт мы увидим на экране +$usr_menu[1]=['Осмотреть предмет','look_item'] & ! и этот пункт мы увидим на экране +$usr_menu[2]=['уничтожить предмет', ''] & ! не указана локация-обработчик, пункт не увидим +$usr_menu[3]=['Положить предмет','put_item'] & ! и этот пункт мы не увидим +``` + +```qsp +%usr_menu[0]=['Взять предмет','take_item'] & ! этот пункт мы увидим на экране +$usr_menu[1]=['Осмотреть предмет','look_item'] & ! и этот пункт мы увидим на экране +$usr_menu[2]=['', 'del_item'] & ! не указано название, пункт не увидим +$usr_menu[3]=['Положить предмет','put_item'] & ! и этот пункт мы не увидим +``` + +Чтобы вставить разделитель в меню, используйте кортеж со значениями -. Т.е. если нужно поставить разделитель вместо 3-го элемента: + +```qsp +%usr_menu[0]=['Взять предмет','take_item'] +$usr_menu[1]=['Осмотреть предмет','look_item'] +$usr_menu[2]=['-', '-'] & ! разделитель вместо пункта меню +$usr_menu[3]=['Положить предмет','put_item'] +``` + +В локацию-обработчик выбора пункта меню передаётся аргумент (`args[0]`) - позиция выбранного пункта. Позиции элементов меню нумеруются с 1. + +:::note[Устаревший вариант заполнения массива меню. Строки] + +Этот вариант можно использовать, как в плеерах версии 5.9.0, так и в более ранних версиях. + +Здесь пункты меню — это строковые значения массива с особым форматом записи: + +```qsp +"название пункта меню:название локации:путь к файлу иконки" +``` + +- Название пункта меню — это то, что мы увидим на экране, когда меню будет выведено; +- название локации — это название локации-обработчика пункта меню, код которой будет выполняться при щелчке на соответствующем пункте меню; +- путь к файлу иконки — это путь к файлу изображения, которое будет выведено рядом с названием пункта меню. Если путь к файлу иконки не указан или указанный файл недоступен, то пункт меню отобразится без иконки. + Поиск символов ":" начинается с конца строки, то есть название пункта меню может содержать двоеточия, однако тогда обязательно после названия локации должно стоять двоеточие, даже если вы не используете иконки для пунктов меню. +```qsp +$stone[0]='Камень: взять:takestone:' +$stone[1]='Камень: кинуть:throwstone:' +$stone[2]='Камень: осмотреть:lookstone:' +``` + Если путь к файлу иконки не указан или указанный файл недоступен, то пункт меню отобразится без иконки. +Таким образом мы должны заполнить массив для того, чтоб создать наши пункты меню: + +```qsp +$stone[0]='Взять камень:takestone' +$stone[1]='Кинуть камень:throwstone' +$stone[2]='Осмотреть камень:lookstone' +``` + Здесь название массива (`$stone`) - это название меню, а текстовые значения массива - действия, для которых указаны названия и названия локаций-обработчиков выбора пунктов меню. При выборе пункта "Взять камень" произойдёт обработка локации с названием "takestone". Аналогично будет происходить с другими пунктами. -Чтобы вызвать меню на экран нужно воспользоваться оператором menu: +Чтобы вызвать меню на экран нужно воспользоваться оператором `menu`: ```qsp menu '$stone' @@ -1218,8 +1410,6 @@ menu '$stone' 'Камень' ``` -В локацию-обработчик выбора пункта меню передаётся аргумент (`args[0]`) - позиция выбранного пункта. Позиции элементов меню нумеруются с 1. - Пример создания меню с иконками: ```qsp @@ -1235,7 +1425,7 @@ $usr_menu[3] = '<<$name>>:<<$location>>:<<$file>>' menu 'usr_menu' &! покажет меню из 4-х пунктов ``` -Меню заканчивается на элементе массива со значением `''` (пустая строка). Т.е. если массив меню состоит из элементов 'Взять', 'Осмотреть', 'Бросить', то 2 последних пункта меню не будут созданы: +Меню заканчивается на элементе массива со значением `''` (пустая строка). Т.е. если массив меню состоит из элементов 'Взять', 'Осмотреть', '', 'Бросить', то 2 последних пункта меню не будут созданы: ```qsp $usr_menu[0] = 'Взять предмет:take_item' & ! этот пункт мы увидим на экране @@ -1253,6 +1443,8 @@ $usr_menu[2] = '-:-' $usr_menu[3] = 'Положить предмет:put_item' ``` +::: + ## MSG `MSG` — вывод указанного сообщения в диалоговом окне. Общая запись: @@ -1261,7 +1453,7 @@ $usr_menu[3] = 'Положить предмет:put_item' MSG [сообщение] ``` -, где `[сообщение]` — любая строка текста. число, выражение любого типа. Примеры: +, где `[сообщение]` — любая строка текста, число, выражение любого типа. Примеры: Примеры: @@ -1289,7 +1481,7 @@ end ## NL -`NL` — переход на новую строку, затем вывод текста в окне основногодополнительного описания. Общая запись: +`NL` — переход на новую строку, затем вывод текста в окне дополнительного описания. Общая запись: ```qsp NL [$текст] @@ -1346,7 +1538,7 @@ killall & cls & close all ## P -`P` — вывод текста в окно основного описания без перехода на новую строку. Вывод текста любым другим оператором сразу после p добавит новый текст сразу после текущего. Общая запись: +`P` — вывод текста в окно дополнительного описания без перехода на новую строку. Вывод текста любым другим оператором сразу после p добавит новый текст сразу после текущего. Общая запись: ```qsp P [$текст] @@ -1363,7 +1555,7 @@ p "Текст без перехода на новую строку." ## PL -`PL` — вывод текста в окно основного описания, затем переход на новую строку. Общая запись: +`PL` — вывод текста в окно дополнительного описания, затем переход на новую строку. Общая запись: ```qsp PL [$текст] @@ -1438,9 +1630,38 @@ savegame См. также [локацию-обработчик события сохранения состояния игры ($ongsave)](qsp-keyword-sys-var.md#ongsave). +## SCANSTR + +`SCANSTR` — поиск в строке непересекающихся вхождений, соответствующих шаблону, и помещение этих вхождений в массив. Общая запись: + +```qsp +SCANSTR [$имя_массива], [$текст_для_разбора], [$регэксп], [#номер_группы] +``` + +, где `[$имя_массива]` — массив, в который помещаются строки, соответствующие регулярному выражению `[$регэксп]`. поиск производится по строке `[$текст_для_разбора]`. Если указан параметр `[#номер_группы]`, в массив будет помещаться не вся строка, соответствующая регулярному выражению, а лишь часть, соответствующая указанной группе в этом регулярном выражении. + +Примеры: + +```qsp +! вытаскиваем из строки все слова: +$text = 'Шла Саша по шоссе, а Грека через реку.' +scanstr '$words', $text, '\b\w+\b' +!В массиве $words окажутся значения: 'Шла', 'Саша', 'по', 'шоссе', 'а', 'Грека', 'через', 'реку' + +! разбиваем строку по разделителю: +$text = 'утро|день|вечер|ночь' +scanstr '$words', $text, '[^|]+' +!В массиве $words окажутся значения: 'утро', 'день', 'вечер', 'ночь' + +! вытаскиваем из строки все слова, помещённые в квадратные скобки, но без квадратных скобок: +$text = '[first] ignoredtext [second][third] also ignored' +scanstr '$words', $text, '\[(.*?)\]', 1 +!В массиве $words окажутся значения: 'first', 'second', 'third' +``` + ## SET -`SET` — устаревший оператор для установки значения переменной. Общая запись: +`SET` — оператор для установки значения переменной. Общая запись: ```qsp SET [название переменной] = [выражение] @@ -1455,10 +1676,11 @@ SET [название переменной] = [выражение] set $text = "text string" ! задаём числовую переменную set abs = 123 - +! задаём кортеж +set %tuple = [27, 184, 'steel'] ``` -:::note +:::note[Рекомендация:] Поскольку присваивание можно делать без оператора `set`, рекомендуем использовать данный оператор лишь для тех случаев, когда это улучшит читаемость кода. Например, при множественном присваивании: ```qsp @@ -1512,6 +1734,34 @@ settimer 1 Однако на практике минимальное значение ограничено мощностью вашего компьютера, и оно, как правило, выше 1 миллисекунды. +## SETVAR + +`SETVAR` — присваивает значение переменной или ячейке массива. + +Данная функция позволит избегать использования `dynamic` в тех случаях, когда нужно присвоить значение переменной, имя которой заранее неизвестно. + +Общая запись: + +```qsp +SETVAR [$имя_массива], [значение], [индекс] +``` + +, где `[$имя_массива]` — название массива или переменной, которой нужно присвоить значение; `[значение]` — значение любого типа: строка, число, кортеж, — однако тип значения, которое будет помещено в переменную определяется по префиксу типа перед именем переменной; `[индекс]` — если значение присваивается ячейке массива, необходимо указать индекс ячейки данным параметром (может быть любого типа). + +Примеры: + +```qsp +SETVAR 'A', 65 +SETVAR '$X', 'name', 4 +SETVAR '$X', 'name', 'string index' +SETVAR '%Q', ['пример', 'кортежа'], 3 +SETVAR '%Q', ['пример', 'кортежа'], [x, y] + +$arr_pref = '%' +$arr_name = 'tuple' +SETVAR $arr_pref+$arr_name, ['кортеж', 1], 3 +``` + ## SHOWACTS `SHOWACTS` — управляет отображением окна действий на экране. Общая запись: @@ -1608,6 +1858,63 @@ showstat on & ! показывает окно дополнительного о showstat off & ! скрывает окно дополнительного описания ``` +## SORTARR + +`SORTARR` — сортировка указанного массива. Общая запись: + +```qsp +SORTARR [$имя_массива], [#порядок] +``` + + Здесь `[$имя_массива]` — название массива, который нужно отсортировать. Параметр `[#порядок]` можно не указывать. Если не указан или равен `0`, то сортирует массив по возрастанию (от меньшего к большему). Если равен `1`, то сортирует массив по убыванию (от большего к меньшему). + +Может сортировать массивы любых типов (числа, строки, кортежи), но не допускается смешивать значения разных типов в одном массиве. + +Для указания типа сортируемых значений нужно указать префикс типа как часть имени массива (`$`, `%`). + +Пример сортировки текстового массива: + +```qsp +$a[] = 'nn' +$a[] = 'zz' +$a[] = 'aa' +sortarr '$a' + +!проверяем результат сортировки: +loop local i=0 while iКрасный текст." ``` +:::note[qSpider] +В **qSpider** распознавание включено всегда и не отключается изменением значения переменной `usehtml`. +::: + ## Примечания для любопытных 1. Есть возможность определить любую системную переменную локальной для отдельного блока кода, и тогда эту системную переменную можно использовать как обычную локальную переменную, т.е. она не повлияет на работу плеера. Однако, **строго** не рекомендуется так делать, чтобы не допускать возможных ошибок. diff --git a/src/theme/qsp-syntax/prism-qsp.js b/src/theme/qsp-syntax/prism-qsp.js index 142f9bb..104915c 100644 --- a/src/theme/qsp-syntax/prism-qsp.js +++ b/src/theme/qsp-syntax/prism-qsp.js @@ -1,9 +1,9 @@ -let kw_operators = '\\b(inclib|freelib|addqst|killqst|openqst|opengame|savegame|addobj|delobj|killobj|unsel|unselect|cls|cla|delact|cmdclr|cmdclear|play|close|all|jump|dynamic|goto|gt|xgoto|xgt|gosub|gs|menu|exit|showobjs|showstat|showacts|showinput|refint|copyarr|killvar|killall|view|msg|settimer|wait|exec)\\b' +let kw_operators = '\\b(act|addobj|cla|close|all|cls|cmdclear|copyarr|delact|delobj|dynamic|exit|gosub|goto|if|else|elseif|inclib|jump|killall|killobj|freelib|killvar|let|local|loop|menu|msg|opengame|openqst|play|refint|savegame|scanstr|set|settimer|showacts|showinput|showobjs|showstat|sortarr|unselect|view|wait|xgoto|addqst|killqst|unsel|cmdclr|gt|xgt|gs|exec)\\b' let kw_controls = '\\b(act|if|elseif|else|loop|while|step|end)\\b' let kw_text_operators = '\\*?\\b(pl?|nl|clr|clear)\\b' -let functions_string = '\\$(desc|user_text|usrtxt|maintxt|stattxt|curloc|selobj|selact|mid|(u|l)case|trim|replace|str|strfind|input|qspver|curacts|getobj|iif|dyneval|func|max|min|arritem)\\b' +let functions_string = '\\$(desc|user_text|usrtxt|maintxt|stattxt|curloc|selobj|selact|mid|(u|l)case|trim|replace|str|strfind|input|qspver|curacts|curobjs|getobj|iif|dyneval|func|max|min|arritem)\\b' let functions_num = '\\b(loc|obj|isnum|isplay|len|val|instr|strcomp|strpos|arrsize|arrpos|arrcomp|msecscount|rgb|countobj|ra?nd|iif|dyneval|func|max|min|arritem)\\b' let system_vars_string = '\\$(counter|ongload|ongsave|onnewloc|onactsel|onobjsel|onobjadd|onobjdel|usercom|fname|backimage|args|result)\\b' @@ -11,18 +11,18 @@ let system_vars_num = '\\b(nosave|disablescroll|disablesubex|debug|usehtml|(b|f| Prism.languages.qsp = { 'comment': { - pattern: /((^\s*?)|(\&\s*?))(![^\n{'"]*$)/m, + pattern: /((^\s*?)|(\&\s*?)|(\:\s*?))(![^\n{'"]*$)/m, lookbehind: true, greedy: true, }, 'braced-comment': { - pattern: /((^\s*?)|(\&\s*?))(![^\n{'"]*\{[^\}]*\}.*?$)/m, + pattern: /((^\s*?)|(\&\s*?)|(\:\s*?))(![^\n{'"]*\{[^\}]*\}.*?$)/m, alias: 'comment', lookbehind: true, greedy: true, }, 'quoted-comment': { - pattern: /((^\s*?)|(\&\s*?))((![^\n{'"]*"[^"]*".*?$)|(![^'\n\r]*'[^']*?'.*?$))/m, + pattern: /((^\s*?)|(\&\s*?)|(\:\s*?))((![^\n{'"]*"[^"]*".*?$)|(![^'\n\r]*'[^']*?'.*?$))/m, alias: 'comment', lookbehind: true, greedy: true,