From 5a2b356c1945bed89b46320cb85bd2e5ef67975e Mon Sep 17 00:00:00 2001 From: Awesome158 Date: Fri, 8 Aug 2025 10:19:10 +0200 Subject: [PATCH 1/4] feat(lang): Add English translation #23 --- ...08-15-docs-add-chapters-of-keywords-etc.md | 2 +- docs/all-together.md | 5 + docs/co-development/index.md | 5 + docs/intro.md | 4 +- docs/language/index.md | 2 + docs/language/qsp-keywords/index.md | 2 + .../qsp-keywords/qsp-keyword-functions.md | 2 + .../qsp-keywords/qsp-keyword-operacion.md | 12 +- .../qsp-keywords/qsp-keyword-operators.md | 38 +- .../qsp-keywords/qsp-keyword-syntaxems.md | 8 +- .../qsp-keywords/qsp-keyword-sys-var.md | 2 + docs/parsers/index.md | 5 + docs/parsers/qsp-fsharp-parser.md | 5 + docs/parsers/qsplib-parser.md | 5 + docs/syntax-highlighting.md | 5 + docusaurus.config.ts | 22 +- .../current/all-together.md | 143 ++ .../current/co-development/branches.png | Bin 0 -> 10754 bytes .../co-development/create-pull-request.png | Bin 0 -> 14923 bytes .../current/co-development/index.md | 166 ++ .../pull-request-creation-form.png | Bin 0 -> 22346 bytes .../select-and-pull-request.png | Bin 0 -> 21496 bytes .../current/intro.md | 9 + .../current/language/index.md | 8 + .../current/language/qsp-keywords/index.md | 184 ++ .../qsp-keywords/qsp-keyword-functions.md | 1542 ++++++++++++++++ .../qsp-keywords/qsp-keyword-operacion.md | 1263 +++++++++++++ .../qsp-keywords/qsp-keyword-operators.md | 1573 +++++++++++++++++ .../qsp-keywords/qsp-keyword-syntaxems.md | 646 +++++++ .../qsp-keywords/qsp-keyword-sys-var.md | 519 ++++++ .../current/parsers/index.md | 8 + .../current/parsers/qsp-fsharp-parser.md | 24 + .../current/parsers/qsplib-parser.md | 14 + .../current/syntax-highlighting.md | 41 + 34 files changed, 6233 insertions(+), 31 deletions(-) create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/all-together.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/co-development/branches.png create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/co-development/create-pull-request.png create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/co-development/pull-request-creation-form.png create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/co-development/select-and-pull-request.png create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/intro.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/index.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md create mode 100644 i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md diff --git a/blog/2024-08-15-docs-add-chapters-of-keywords-etc.md b/blog/2024-08-15-docs-add-chapters-of-keywords-etc.md index 9649fc3..bc29fed 100644 --- a/blog/2024-08-15-docs-add-chapters-of-keywords-etc.md +++ b/blog/2024-08-15-docs-add-chapters-of-keywords-etc.md @@ -11,7 +11,7 @@ tags: Поскольку этот раздел был практически полностью написан мной в другом проекте, я решил слегка его отредактировать и перенести сюда. -[Это раздел](../../../../docs/language/qsp-keywords/), в котором собраны все операторы, функции, системные переменные, а так же спецсимволы и синтаксемы языка QSP. +[Это раздел](/docs/language/qsp-keywords/), в котором собраны все операторы, функции, системные переменные, а так же спецсимволы и синтаксемы языка QSP. :::warning[Важно помнить:] Раздел охватывает полностью ключевые слова и т.д. для версий плееров 5.8.0, и частично затрагивает плееры версии 5.9.0. А значит, в будущем требует дополнения. diff --git a/docs/all-together.md b/docs/all-together.md index 841ce58..6b23539 100644 --- a/docs/all-together.md +++ b/docs/all-together.md @@ -1,3 +1,8 @@ +--- +id: all-together +title: Всё вместе +--- + # Всё вместе Здесь вкратце расписаны всевозможные тернистые пути от начала разработки игры на QSP (с использованием различных средств и инструментов) до ее реализации и запуска игры у конечного игрока. diff --git a/docs/co-development/index.md b/docs/co-development/index.md index 91ea2f5..5d61b0f 100644 --- a/docs/co-development/index.md +++ b/docs/co-development/index.md @@ -1,3 +1,8 @@ +--- +id: co-development +title: Совместная разработка +--- + # Совместная разработка Главный смысл совместной разработки заключается в том, чтобы не наступить друг другу на ноги. Для этого нужно придерживаться некоторых правил: diff --git a/docs/intro.md b/docs/intro.md index 67c0b82..cc63abd 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -1,4 +1,6 @@ ---- +--- +id: intro +title: QSP Foundation sidebar_position: 1 --- diff --git a/docs/language/index.md b/docs/language/index.md index 9867dc3..5daf6de 100644 --- a/docs/language/index.md +++ b/docs/language/index.md @@ -1,4 +1,6 @@ --- +id: language +title: Язык QSP sidebar_position: 1 --- diff --git a/docs/language/qsp-keywords/index.md b/docs/language/qsp-keywords/index.md index 45ec8ce..d30ee24 100644 --- a/docs/language/qsp-keywords/index.md +++ b/docs/language/qsp-keywords/index.md @@ -1,4 +1,6 @@ --- +id: qsp-keywords +title: Зарезервированные слова, системные переменные, спецсимволы sidebar_position: 6 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-functions.md b/docs/language/qsp-keywords/qsp-keyword-functions.md index d56feb0..dd42f3c 100644 --- a/docs/language/qsp-keywords/qsp-keyword-functions.md +++ b/docs/language/qsp-keywords/qsp-keyword-functions.md @@ -1,4 +1,6 @@ --- +id: qsp-keyword-functions +title: Функции sidebar_position: 3 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-operacion.md b/docs/language/qsp-keywords/qsp-keyword-operacion.md index cad7517..498990b 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operacion.md +++ b/docs/language/qsp-keywords/qsp-keyword-operacion.md @@ -1,4 +1,6 @@ --- +id: qsp-keyword-operacion +title: Операции sidebar_position: 1 --- @@ -149,7 +151,7 @@ sidebar_position: 1 %tuple = [4, 10, 16] %a = %tuple * 2 ! %a будет равно [8, 20, 32] - + [4, 10] * 'b' & ! ошибка о несоответствии типов данных ``` @@ -352,7 +354,7 @@ number += [4,5] & ! ошибка о несоответствии типов да %tuple = [4, 10, 16] %a = %tuple - 2 ! %a будет равно [2, 8, 14] - + [4, 10] - 'b' & ! ошибка о несоответствии типов данных ``` @@ -494,7 +496,7 @@ number -= [4,5] & ! ошибка о несоответствии типов да %tuple = [4, 10, 16] %a = %tuple / 2 ! %a будет равно [2, 5, 8] - + [4, 10] / 'b' & ! ошибка о несоответствии типов данных ``` @@ -1231,7 +1233,7 @@ elseif obj("Пустой кувшин") = 1: addobj "Полный кувшин" delobj "Пустой квушин" goto $curloc - end + end end ``` @@ -1253,7 +1255,7 @@ end ! одна часть выражения верна, значит всё выражение верно (2 <> 2) or (3 <> 2) & ! выражение вернёт 1 (правда) ! обе части выражения не верны, значит и всё выражение не верно -(2 <> 2) or (3 = 2) & ! выражение вернёт 0 (ложь) +(2 <> 2) or (3 = 2) & ! выражение вернёт 0 (ложь) ``` :::note[5.7.0] diff --git a/docs/language/qsp-keywords/qsp-keyword-operators.md b/docs/language/qsp-keywords/qsp-keyword-operators.md index cf022b3..c69d5d7 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operators.md +++ b/docs/language/qsp-keywords/qsp-keyword-operators.md @@ -1,4 +1,6 @@ --- +id: qsp-keyword-operators +title: Операторы sidebar_position: 2 --- @@ -93,7 +95,7 @@ end ```qsp ! строка до кавычек " текст внутри кавычек может переходить на другие строки " а так же { -можно использовать другие группы символов, чтобы +можно использовать другие группы символов, чтобы продолжать многострочный комментарий } и комментарий не кончится, пока не кончится строка ``` @@ -426,7 +428,7 @@ $code = ' *pl "<<$args[0]>>" *pl $args[0] ' - + dynamic $code, 'asdfg' ``` @@ -504,8 +506,8 @@ gosub 'ход' !Передаётся один параметр - args[0] равен 1. gosub $location,1 -!обработка локации "ход" с передачей 3-х параметров. -! $args[0] = $var (значению), args[1] = 2, +!обработка локации "ход" с передачей 3-х параметров. +! $args[0] = $var (значению), args[1] = 2, ! $args[2] = "данные". Обратите внимание на символы '$'. gosub 'ход',$var,2,'данные' ``` @@ -657,8 +659,8 @@ end &! ключевое слово end - просто игнорируется ```qsp if a+b<3 or y=8: p 'A+B<3 или Y=8' - nl - if j=88: nl & p 'NEXT' + nl + if j=88: nl & p 'NEXT' if $h='ooo': p 'loo' & jump 'lll' end @@ -711,7 +713,7 @@ if abcd=3: k1=34 else k1=25 end ```qsp ! однострочная форма записи IF [#выражение]: {команда д1} & {команда д2} & ... ELSE {команда н1} & {команда н2} & ... - + ! в многострочном IF: ! многострочная форма ELSE @@ -819,8 +821,8 @@ ELSE {последний набор команд} ... END - -! однострочная в многострочном условии + +! однострочная в многострочном условии IF [#выражение 1]: {набор команд 1} ... @@ -835,7 +837,7 @@ END Особенности записи `ELSEIF`: - Может использоваться вариант написания `ELSE IF`. Работает точно так же. -- Если в многострочной конструкции `IF` после `ELSEIF` операторы идут в той же самой строке (однострочная форма), то все последующие строки игнорируются до следующего `ELSEIF`, либо до `ELSE` или `END`. +- Если в многострочной конструкции `IF` после `ELSEIF` операторы идут в той же самой строке (однострочная форма), то все последующие строки игнорируются до следующего `ELSEIF`, либо до `ELSE` или `END`. - В конструкции `IF` c `ELSEIF` может как присутствовать, так и отсутствовать часть с `ELSE`. Примеры: @@ -850,7 +852,7 @@ ELSEIF ОЧКИ>99: ELSE GOTO 'КОН5' END - + if money mod 10=1 and money mod 100<>11: *pl "У вас <> монета." elseif money mod 10>1 and money mod 10<5 and (money mod 100<5 or money mod 100>20): @@ -1133,7 +1135,7 @@ i = 99 & ! объявляем глобальную переменную gosub 'foo' *nl i & ! на экране увидим число 99 --- start --- - + # foo ! на этой локации объявляем локальную переменную local i = 0 @@ -1146,7 +1148,7 @@ loop while i < 10 step i += 1: end *nl i & ! на экране увидим число 10 --- foo --- - + # undo ! в эту локацию из цикла с локации foo ! транслируется всё та же локальная переменная @@ -1179,7 +1181,7 @@ if i = 0: i = 99 & ! значение переменной i задаётся л *pl "Глобальное i = <>" act "На локацию 2": goto 'локация 2' --- локация 1 --- - + # локация 2 *pl "Глобальное i = <>" local i = 137 & ! значение переменной i задаётся лишь раз @@ -1324,7 +1326,7 @@ menu '%stone' %usr_menu[2] = ['Уничтожить предмет','del_item', $icon_file] ! пункт меню задан 3-мя переменными %usr_menu[3] = [$name, $location, $icon_file] - + menu 'usr_menu' &! покажет меню из 4-х пунктов ``` @@ -1421,7 +1423,7 @@ $usr_menu[1] = 'Положить предмет:put_item:images/put_item.gif' $usr_menu[2] = 'Осмотреть предмет:look_item:<<$icon_file>>' ! пункт меню задан 3-мя переменными $usr_menu[3] = '<<$name>>:<<$location>>:<<$file>>' - + menu 'usr_menu' &! покажет меню из 4-х пунктов ``` @@ -1647,12 +1649,12 @@ SCANSTR [$имя_массива], [$текст_для_разбора], [$рег $text = 'Шла Саша по шоссе, а Грека через реку.' scanstr '$words', $text, '\b\w+\b' !В массиве $words окажутся значения: 'Шла', 'Саша', 'по', 'шоссе', 'а', 'Грека', 'через', 'реку' - + ! разбиваем строку по разделителю: $text = 'утро|день|вечер|ночь' scanstr '$words', $text, '[^|]+' !В массиве $words окажутся значения: 'утро', 'день', 'вечер', 'ночь' - + ! вытаскиваем из строки все слова, помещённые в квадратные скобки, но без квадратных скобок: $text = '[first] ignoredtext [second][third] also ignored' scanstr '$words', $text, '\[(.*?)\]', 1 diff --git a/docs/language/qsp-keywords/qsp-keyword-syntaxems.md b/docs/language/qsp-keywords/qsp-keyword-syntaxems.md index 58bbaa4..f15c8f2 100644 --- a/docs/language/qsp-keywords/qsp-keyword-syntaxems.md +++ b/docs/language/qsp-keywords/qsp-keyword-syntaxems.md @@ -1,4 +1,6 @@ --- +id: qsp-keyword-syntaxems +title: Синтаксемы и спецсимволы sidebar_position: 5 --- @@ -417,9 +419,9 @@ health = 150 ```qsp !обработка локации "ход". Массив args[] пуст. @ход() - -!обработка локации "ход" с передачей 3-х параметров. -! $args[0] = $var (значению), args[1] = 2, + +!обработка локации "ход" с передачей 3-х параметров. +! $args[0] = $var (значению), args[1] = 2, ! $args[2] = "данные". Обратите внимание на символы '$'. @ход($var, 2, 'данные') ``` diff --git a/docs/language/qsp-keywords/qsp-keyword-sys-var.md b/docs/language/qsp-keywords/qsp-keyword-sys-var.md index a097748..e206c49 100644 --- a/docs/language/qsp-keywords/qsp-keyword-sys-var.md +++ b/docs/language/qsp-keywords/qsp-keyword-sys-var.md @@ -1,4 +1,6 @@ --- +id: qsp-keyword-sys-var +title: Системные переменные sidebar_position: 4 --- diff --git a/docs/parsers/index.md b/docs/parsers/index.md index 4e36e2b..b8433c5 100644 --- a/docs/parsers/index.md +++ b/docs/parsers/index.md @@ -1,3 +1,8 @@ +--- +id: parsers +title: Парсеры +--- + # Парсеры Задача синтаксического анализатора (то есть парсера) заключается в том, чтобы взять исходник, написанный на [языке QSP](../language/), и преобразовать его в такую форму, с которой можно в дальнейшем удобно работать (интерпретировать, компилировать, использовать для анализа и т.д.) diff --git a/docs/parsers/qsp-fsharp-parser.md b/docs/parsers/qsp-fsharp-parser.md index 0c5f760..90d783a 100644 --- a/docs/parsers/qsp-fsharp-parser.md +++ b/docs/parsers/qsp-fsharp-parser.md @@ -1,3 +1,8 @@ +--- +id: qsp-fsharp-parser +title: Qsp Fsharp Parser +--- + # Qsp.FSharp.Parser [Qsp.FSharp.Parser](https://github.com/QSPFoundation/Qsp.FSharp/tree/master/src/Qsp.FSharp.Core) разрабатывается для сред разработки, которые поддерживают LSP (к примеру, VS Code, для [расширения](https://github.com/QSPFoundation/Qsp.FSharp.VsCode) которого всё это и затевалось). diff --git a/docs/parsers/qsplib-parser.md b/docs/parsers/qsplib-parser.md index 15a62c4..2371249 100644 --- a/docs/parsers/qsplib-parser.md +++ b/docs/parsers/qsplib-parser.md @@ -1,3 +1,8 @@ +--- +id: qsplib-parser +title: QSPlib Parser +--- + # QSPLib Parser [QSPLib](https://github.com/QSPFoundation/qsp/tree/master/qsp) парсил исходники ещё задолго до того, как это стало модным, и продолжает этим заниматься и по сей день. diff --git a/docs/syntax-highlighting.md b/docs/syntax-highlighting.md index ac862f1..90acf53 100644 --- a/docs/syntax-highlighting.md +++ b/docs/syntax-highlighting.md @@ -1,3 +1,8 @@ +--- +id: syntax-highlighting +title: Подсветка синтаксиса +--- + # Подсветка синтаксиса Подсветка синтаксиса в редакторах и в прочих окружениях достигается довольно специфическими средствами, для которых, к сожалению, нет общего решения. А раз нет общего решения, то появляются трудности с сопровождением кода для каждого отдельного решения. diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 172e7f0..0ade03b 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -26,8 +26,20 @@ const config: Config = { // useful metadata like html lang. For example, if your site is Chinese, you // may want to replace "en" with "zh-Hans". i18n: { - defaultLocale: 'en', - locales: ['en'], + defaultLocale: 'ru', + locales: ['ru', 'en'], + localeConfigs: { + ru: { + label: 'Русский', + direction: 'ltr', + htmlLang: 'ru-RU', + }, + en: { + label: 'English', + direction: 'ltr', + htmlLang: 'en-US', + }, + }, }, presets: [ @@ -82,7 +94,11 @@ const config: Config = { position: 'left', label: 'Docs', }, - {to: '/blog', label: 'Blog', position: 'left'}, + { to: '/blog', label: 'Blog', position: 'left' }, + { + type: 'localeDropdown', + position: 'right', + }, { href: 'https://github.com/QSPFoundation/qspfoundation.github.io', label: 'GitHub', diff --git a/i18n/en/docusaurus-plugin-content-docs/current/all-together.md b/i18n/en/docusaurus-plugin-content-docs/current/all-together.md new file mode 100644 index 0000000..203002e --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/all-together.md @@ -0,0 +1,143 @@ +--- +id: all-together +title: All Together +--- + +# All Together + +This section briefly outlines various thorny paths from starting QSP game development (using various tools and instruments) to implementing and launching the game for the end player. + +## Writing Games + +```mermaid +graph TD + GameDev[Game Developer] --> |writes game in| Editor + + Editor --> |can be| QGen[QGen] + QGen --> |compiles| BinaryFile[Binary game file .qsp] + + Editor --> |can be| VSCode[VS Code] + VSCode --> |edits and checks code| Qsp.FSharp.VsCode[Qsp.FSharp.VsCode] + + VSCode --> |generates| RawSource + + Editor --> |can be| AnyTextEditor[Any text editor] + AnyTextEditor --> |generates| RawSource[Raw source files .qsps .qsrc] + + Editor --> |can be| Sublime[Sublime Text] + Sublime --> |generates| RawSource + Sublime --> |edits and checks code| JAD_for_QSP[JAD_for_QSP] + + RawSource --> QSP_CLI[qsp-cli] + QSP_CLI --> |compiles| BinaryFile + RawSource --> TXT2GAM[TXT2GAM] + TXT2GAM --> |compiles| BinaryFile + + RawSource --> QSPGame[QSP Game] + BinaryFile --> QSPGame +``` + +QSP game developers write games in: + +* QGen +* Editors + * Sublime Text + * VS Code + * Any text editor + +If using Sublime Text, the JAD_for_QSP extension is used for code checking. + +If using VS Code, the Qsp.FSharp.VsCode extension is used when writing code. + +QGen converts source code into a binary game file. + +Raw source files written in editors are either left as-is or converted to binary using one of the utilities: + +* QSP CLI +* TXT2GAM + +Some utilities allow converting binary game files back to text format. + +## Playing Games + +```mermaid +flowchart TD + QSPGame --> RawSource + RawSource --> |played in| Player + QSPGame --> BinaryFile + BinaryFile --> |played in| Player + + Player --> |can be| Classic[Classic] + Classic --> |interprets game code in| QSPLib[QSPLib] + + Player --> |can be| Navigator[Navigator] + Navigator --> |interprets game code in| QSPLib + + Player --> |can be| QSpider[QSpider] + QSpider --> |uses| qsp-wasm-engine + qsp-wasm-engine --> |interprets game code in| QSPLib +``` + +Raw source files or binaries are played in players: + +* Classic +* Navigator +* QSpider + +Classic and Navigator use the QSPLib interpreter. + +QSpider uses qsp-wasm-engine, which is a wrapper around the QSPLib interpreter. + +## Game Distribution + +```mermaid +flowchart TD + QSPGame --> QSPCatalog[Catalog on https://qsp.org/] + QSPGame --> |wrapped in| QSpiderStandalone[QSpider Standalone] + QSpiderStandalone --> |published on| GitHubPages + QSpiderStandalone --> |published on| ItchIo[itch.io] +``` + +Later, the game developer publishes game resources to: + +* QSP catalog +* GitHub Pages using QSpider Standalone + +Now the player can: + +* Download the game from the [QSP catalog](https://qsp.org/index.php?option=com_sobi2&Itemid=55) and play it in players +* Launch the game with [QSpider](https://dev.qsp.org/qspider) + + There you can either: + + * Open a .qsp file from your device + * Add a game from the library and run it + * Run a game via direct link + + * Game from catalog + + If you know the game ID (for example, 285 — "Ballad of the Hero"), you can run it like this: + + ```text + https://qspfoundation.github.io/qspider/?catalogId=285 + ``` + + * From a separate source + + For example, there's a game "Ballad of the Hero" located at the following link: + + ```text + https://aleksversus.github.io/QSP-storage/game/heroballad/heroballad.qsp + ``` + + This link can be loaded into QSpider: + + ```text + https://qspfoundation.github.io/qspider/?config=https://aleksversus.github.io/QSP-storage/game/heroballad/heroballad.qsp + ``` + + And [go to it](https://qspfoundation.github.io/qspider/?config=https://aleksversus.github.io/QSP-storage/game/heroballad/heroballad.qsp) + +* Go to a link on GitHub, itch.io, etc., and just start playing + +The best option to make life easier for both the game developer and player is to upload the game to a website and give the player a direct link to the game. This way you can avoid +100500 problems. \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/branches.png b/i18n/en/docusaurus-plugin-content-docs/current/co-development/branches.png new file mode 100644 index 0000000000000000000000000000000000000000..6e8fd12994b549d8448e8ae6e5cf3883c400bf95 GIT binary patch literal 10754 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 NG*op}s)4UU{|}U9HZTAH literal 0 HcmV?d00001 diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/create-pull-request.png b/i18n/en/docusaurus-plugin-content-docs/current/co-development/create-pull-request.png new file mode 100644 index 0000000000000000000000000000000000000000..555a204118b9ebfcd2056cd4b816f44848d3b425 GIT binary patch literal 14923 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 literal 0 HcmV?d00001 diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md b/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md new file mode 100644 index 0000000..342b1a9 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md @@ -0,0 +1,166 @@ +--- +id: co-development +title: Collaborative Development +--- + +# Collaborative Development + +The main purpose of collaborative development is to avoid stepping on each other's toes. To achieve this, we need to follow some rules: + +* We coordinate in [#qsp_platform_dev](https://discord.com/channels/373163463842725891/749965798038306866) ([IF Discord invitation](https://discord.gg/bbbdxhE9M2)) about what we're going to write +* We don't touch the `main` branch at all +* We create and use our own branches +* We merge all branches through pull requests +* We delete our branches when they're no longer needed + +## Example + +For instance, someone decided to write about syntax highlighting. To do this, they need to: + +* Set up the development environment: + * Clone the repository: + + ```bash + git clone https://github.com/QSPFoundation/qspfoundation.github.io.git + ``` + + * Go to the repository folder and install packages: + + ```bash + cd qspfoundation.github.io + npm install + ``` + + * Start the live server: + + ```bash + npm run start + ``` + + * Open the link in a browser + + Now the documentation page in the browser will automatically update with every change made. + +* Create a `syntax-highlight` branch + + ```bash + git checkout -b syntax-highlight + ``` + + You can do this through your editor tools — doesn't matter. + +* Create a file `docs/syntax-highlighting.md` and start writing the article in it +* Add the file to git and commit: + + ```bash + git add docs/syntax-highlighting.md + git commit -m "wip: I was too lazy to give it a proper name" + ``` + + You can give a meaningful message, but it doesn't always work out that way, so this is fine too. More about meaningfulness below. + +* Push the branch to GitHub: + + ```bash + git push -u origin syntax-highlight + ``` + + That's it, now the branch is there. We don't touch other people's branches, or we'll get confused. + +* Continue writing the article in `docs/syntax-highlighting.md` +* Add the file changes to git and commit: + + ```bash + git add . + git commit -m "wip: finally finished writing the article!" + ``` + +* Push: + + ```bash + git push + ``` + +* Create a pull request from this branch through GitHub: + + * Go to the creation page using one of two methods: + * Through the main repository page: + + ![create-pull-request](./create-pull-request.png) + + * Through branches + * Click on [branches](https://github.com/QSPFoundation/qspfoundation.github.io/branches) + + ![branches](./branches.png) + * Select the branch you're interested in, click on `...` and in the dropdown menu select "New Pull Request" + + ![select-and-pull-request.png](./select-and-pull-request.png) + + * Give the pull request a meaningful name in the "Add a title" field + + By meaningful name, we mean something like: + + ```bash + docs: write the syntax highlighting article + ``` + + The repository uses a [common commit naming convention](https://www.conventionalcommits.org/en/v1.0.0/). + +* As soon as the pull request is created, tests will run (they are defined in `.github/workflows/test-deploy.yml`). They will check if everything is in order with your changes + +* Let people know in the IF Discord, so someone can approve your Pull Request, and wait + +Once your Pull Request is approved, your branch will merge with the `main` branch, deployment will automatically start (this is configured in `.github/workflows/deploy.yml`), and after some time you'll be able to see the changes on the documentation site. + +After the branch is merged, it becomes unnecessary and should be deleted so it doesn't get in the way: + +* Delete the branch from GitHub: + + ```bash + git push -d origin syntax-highlighting + ``` + +* Delete the branch on your computer: + + ```bash + git branch -d syntax-highlighting + ``` + +* Delete all local branches that no longer exist on GitHub: + + ```bash + git fetch -p && git branch -vv | awk '/: \w+]/{print $1}' | xargs git branch -d --force + ``` + +## Pull Request Approval + +If you have the rights, you can approve a Pull Request in three ways: + +* `squash` — all commits from your branch are combined into one commit (*if you're not sure, use this method*) + + This is needed to turn this stream of consciousness: + + ```text + wip: I was too lazy to give it a proper name + wip: finally finished writing the article! + ``` + + Into one meaningful commit: + + ```bash + docs: write syntax highlighting article + ``` + +* `rebase` — this merges new commits into `main` + + Can be used if you have meaningful commits, like: + + ```text + docs(syntax-highlighting): start writing an article + docs(syntax-highlighting): write short description of what syntax highlighting is + ... + ``` + + Then it's not embarrassing to put all this directly into `main` in this form. + +* something else that merges the branch through a commit. I forgot what it's called \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/pull-request-creation-form.png b/i18n/en/docusaurus-plugin-content-docs/current/co-development/pull-request-creation-form.png new file mode 100644 index 0000000000000000000000000000000000000000..1724a86560488f19d83c3e86aa533fb888ae4d38 GIT binary patch literal 22346 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 CXeapq literal 0 HcmV?d00001 diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/select-and-pull-request.png b/i18n/en/docusaurus-plugin-content-docs/current/co-development/select-and-pull-request.png new file mode 100644 index 0000000000000000000000000000000000000000..4cef3a1df9ef9de149b5c7839eaf0d5a33a565b6 GIT binary patch literal 21496 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 literal 0 HcmV?d00001 diff --git a/i18n/en/docusaurus-plugin-content-docs/current/intro.md b/i18n/en/docusaurus-plugin-content-docs/current/intro.md new file mode 100644 index 0000000..453cc79 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/intro.md @@ -0,0 +1,9 @@ +--- +id: intro +title: QSP Foundation +sidebar_position: 1 +--- + +# QSP Foundation + +QSP Foundation is the QSP ecosystem, that is, everything we know about the [language](./language/), its [parsers](./parsers/index.md), interpreters and compilers, players, development environments, and useful tools. \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/index.md b/i18n/en/docusaurus-plugin-content-docs/current/language/index.md new file mode 100644 index 0000000..c54730c --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/index.md @@ -0,0 +1,8 @@ +--- +id: language +title: Language +sidebar_position: 1 +--- + + +# QSP Language diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md new file mode 100644 index 0000000..9e3936c --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md @@ -0,0 +1,184 @@ +--- +id: qsp-keywords +title: Reserved Words, System Variables, Special Symbols +sidebar_position: 6 +--- + +# Index + +:::warning[Attention!] +Crossed-out commands do not work in players version 5.8.0 and higher. +::: + +- [Implicit operator](qsp-keyword-operators#implicit-operator) +- [`!` (comment)](qsp-keyword-operators.md#-comment) +- [`!` (not equal)](qsp-keyword-operacion.md#-not-equal-1) +- [`&` (concatenation)](qsp-keyword-operacion.md#-concatenation) +- [`&` (command enumeration)](qsp-keyword-syntaxems.md#ampersand-) +- [`:` (labels)](qsp-keyword-syntaxems.md#labels-) +- [`,` (argument separator)](qsp-keyword-syntaxems.md#comma-) +- [`""` (quotes)](qsp-keyword-syntaxems.md#quote-) +- [`''` (apostrophes)](qsp-keyword-syntaxems.md#apostrophe-) +- [`{}` (Curly brackets)](qsp-keyword-syntaxems.md#curly-brackets-) +- [`()` (round brackets)](qsp-keyword-syntaxems.md#round-brackets-) +- [`[]` (square brackets)](qsp-keyword-syntaxems.md#square-brackets-) +- [`@` (commercial "at")](qsp-keyword-syntaxems#at-symbol-) - 5.8.0 +- [`$` (dollar sign)](qsp-keyword-syntaxems#dollar-sign-) +- [`%` (percent sign)](qsp-keyword-syntaxems#percent-sign-) - 5.9.0 +- [`*`](qsp-keyword-operacion.md#-multiplication) +- [`*=`](qsp-keyword-operacion.md#-multiplication-assignment) +- [`+`](qsp-keyword-operacion.md#-addition) +- [`+=`](qsp-keyword-operacion.md#-addition-assignment) +- ~~[`+` (unary)](qsp-keyword-operacion.md#--unary-minus)~~ +- [`-`](qsp-keyword-operacion.md#--subtraction) +- [`-=`](qsp-keyword-operacion.md#--subtraction-assignment) +- [`-` (unary)](qsp-keyword-operacion.md#--unary-minus) +- [`/`](qsp-keyword-operacion.md#-division) +- [`/=`](qsp-keyword-operacion.md#-division-assignment) +- [`<`](qsp-keyword-operacion.md#-less-than) +- [`<=`](qsp-keyword-operacion.md#-less-than-or-equal) +- [`<>`](qsp-keyword-operacion.md#-not-equal) +- [`=` (equal)](qsp-keyword-operacion.md#-equal) +- [`=` (assignment)](qsp-keyword-operacion.md#-assignment) +- [`=<`](qsp-keyword-operacion.md#-equal-or-less) +- [`=>`](qsp-keyword-operacion.md#-equal-or-greater) +- [`>`](qsp-keyword-operacion.md#-greater-than) +- [`>=`](qsp-keyword-operacion.md#-greater-than-or-equal) +- [`ACT`](qsp-keyword-operators.md#act) +- ~~[`ADDLIB`](qsp-keyword-operators.md#inclib)~~ +- [`ADDOBJ`](qsp-keyword-operators.md#addobj) +- ~~[`ADDQST`](qsp-keyword-operators.md#inclib)~~ +- [`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) - 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) +- [`CLA`](qsp-keyword-operators.md#cla) +- [`CLEAR`](qsp-keyword-operators.md#clear-1) +- [`*CLEAR`](qsp-keyword-operators.md#clear) +- [`CLOSE`](qsp-keyword-operators.md#close) +- [`CLOSE ALL`](qsp-keyword-operators.md#close-all) +- [`CLR`](qsp-keyword-operators.md#clear-1) +- [`*CLR`](qsp-keyword-operators.md#clear) +- [`CLS`](qsp-keyword-operators.md#cls) +- [`CMDCLEAR`](qsp-keyword-operators.md#cmdclear) +- [`CMDCLR`](qsp-keyword-operators.md#cmdclear) +- [`COPYARR`](qsp-keyword-operators.md#copyarr) +- [`$COUNTER`](qsp-keyword-sys-var.md#counter) +- [`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)~~ +- [`DELOBJ`](qsp-keyword-operators.md#delobj) +- [`$DESC`](qsp-keyword-functions.md#desc) +- [`DISABLESCROLL`](qsp-keyword-sys-var.md#disablescroll) +- ~~[`DISABLESUBEX`](qsp-keyword-sys-var.md#disablesubex)~~ +- [`DYNAMIC`](qsp-keyword-operators.md#dynamic) +- [`DYNEVAL`](qsp-keyword-functions.md#dyneval) +- [`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) - 5.8.0 +- [`FSIZE`](qsp-keyword-sys-var.md#fsize) +- [`FUNC`](qsp-keyword-functions.md#func) +- [`$GETOBJ`](qsp-keyword-functions.md#getobj) +- [`GOSUB`](qsp-keyword-operators.md#gosub) +- [`GOTO`](qsp-keyword-operators.md#goto) +- [`GS`](qsp-keyword-operators.md#gosub) +- [`GT`](qsp-keyword-operators.md#goto) +- [`IF`](qsp-keyword-operators.md#if) +- [`IIF`](qsp-keyword-functions.md#iif) +- [`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) +- [`ISPLAY`](qsp-keyword-functions.md#isplay) +- [`JUMP`](qsp-keyword-operators.md#jump) +- [`KILLALL`](qsp-keyword-operators.md#killall) +- [`KILLOBJ`](qsp-keyword-operators.md#killobj) +- ~~[`KILLQST`](qsp-keyword-operators.md#freelib)~~ +- [`KILLVAR`](qsp-keyword-operators.md#killvar) +- [`$LCASE`](qsp-keyword-functions.md#lcase) +- [`LCOLOR`](qsp-keyword-sys-var.md#lcolor) +- [`LEN`](qsp-keyword-functions.md#len) +- [`LET`](qsp-keyword-operators.md#let) +- [`LOC`](qsp-keyword-operacion.md#loc) +- [`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) +- [`$MID`](qsp-keyword-functions.md#mid) +- [`MIN`](qsp-keyword-functions.md#min) +- [`MOD`](qsp-keyword-operacion.md#mod) +- [`MSECSCOUNT`](qsp-keyword-functions.md#msecscount) +- [`MSG`](qsp-keyword-operators.md#msg) +- [`NL`](qsp-keyword-operators.md#nl-1) +- [`*NL`](qsp-keyword-operators.md#nl) +- [`NO`](qsp-keyword-operacion.md#no) +- [`NOSAVE`](qsp-keyword-sys-var.md#nosave) +- [`OBJ`](qsp-keyword-operacion.md#obj) +- [`$ONACTSEL`](qsp-keyword-sys-var.md#onactsel) +- [`$ONGLOAD`](qsp-keyword-sys-var.md#ongload) +- [`$ONGSAVE`](qsp-keyword-sys-var.md#ongsave) +- [`$ONNEWLOC`](qsp-keyword-sys-var.md#onnewloc) +- [`$ONOBJADD`](qsp-keyword-sys-var.md#onobjadd) +- [`$ONOBJDEL`](qsp-keyword-sys-var.md#onobjdel) +- [`$ONOBJSEL`](qsp-keyword-sys-var.md#onobjsel) +- [`OPENGAME`](qsp-keyword-operators.md#opengame) +- [`OPENQST`](qsp-keyword-operators.md#openqst) +- [`OR`](qsp-keyword-operacion.md#or) +- [`P`](qsp-keyword-operators.md#p-1) +- [`*P`](qsp-keyword-operators.md#p) +- [`PL`](qsp-keyword-operators.md#pl-1) +- [`*PL`](qsp-keyword-operators.md#pl) +- [`PLAY`](qsp-keyword-operators.md#play) +- [`$QSPVER`](qsp-keyword-functions.md#qspver) +- [`RAND`](qsp-keyword-functions.md#rand) +- [`REFINT`](qsp-keyword-operators.md#refint) +- [`$REPLACE`](qsp-keyword-functions.md#replace) +- [`RESULT`](qsp-keyword-sys-var.md#result) +- [`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) +- [`$STRFIND`](qsp-keyword-functions.md#strfind) +- [`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) +- [`$USERCOM`](qsp-keyword-sys-var.md#usercom) +- [`$USER_TEXT`](qsp-keyword-functions.md#user_text) +- [`$USRTXT`](qsp-keyword-functions.md#user_text) +- [`VAL`](qsp-keyword-functions.md#val) +- [`VIEW`](qsp-keyword-operators.md#view) +- [`WAIT`](qsp-keyword-operators.md#wait) +- [`XGOTO`](qsp-keyword-operators.md#xgoto) +- [`XGT`](qsp-keyword-operators.md#xgoto) \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md new file mode 100644 index 0000000..86a77e7 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md @@ -0,0 +1,1542 @@ +--- +id: qsp-keyword-functions +title: Functions +sidebar_position: 3 +--- + +# Functions + +## `$CURACTS` + +`$CURACTS` — this function returns actions displayed on screen as QSP code, as a text value. + +Actions are saved as a set of `act` operators with corresponding parameters and operations. + +By writing the value returned by the function to a variable, actions can be restored using the `dynamic` operator. Example: + +```qsp +! write current actions to variable +$actlist = $curacts +! restore actions from variable +dynamic $actlist +``` + +## `$CURLOC` + +`$CURLOC` — function returns the name of the current location, i.e., the location where the player "is". + +Technically, this should be understood as follows. When the game starts, the player begins executing code of the very first location in the game, and when the code is executed, the player "stops" and waits for player participation. The player can press various buttons in the game, links and select menu items, which leads to execution of other code blocks (for example, actions) and transitions to new locations via `goto` or `xgoto`. During such transitions, the player again executes code of other locations and, when code is executed, "stops". + +So, when a direct transition to a location is made (i.e., via `goto` or `xgoto`, or it's the very first location in the game), `$curloc` begins returning the name of this location, — throughout the time while code is executing and when the player "stops". If no transition via `goto`/`xgoto` occurs after stopping, the value returned by `$curloc` doesn't change. + +Usage example: + +```qsp +*pl $curloc & ! output current location name to Main Description Window +*pl "Times re-entered: <>" +act "Re-enter current location": + re_entered += 1 + goto $curloc +end +``` + +## `$CUROBJS` + +`$CUROBJS` - this function returns the list of objects displayed on screen as QSP code. +Objects are saved as a set of `ADDOBJ` operators with corresponding parameters and operations. + +By writing the value returned by the function to a variable, objects can be restored using the `DYNAMIC` operator. Example: + +```qsp +! save object list as QSP code: +$old_objects = $CUROBJS +! remove all objects from objects window: +KILLOBJ +! restore all objects in objects window: +DYNAMIC $old_objects +``` + +## `$DESC` + +`$DESC` — returns the base description text of a location with the specified name. General syntax: + +```qsp +$DESC([$location]) +``` + +, where `[$location]` — the name of the location we're interested in. For example: + +```qsp +! return base description of location "cupboard_under_stairs" +$desc('cupboard_under_stairs') +!return base description of current location +$desc($curloc) +``` + +If sub-expressions are present in the base description, the function automatically expands them. + +:::warning[Pay attention!] +The function returns text written only in the "Description" field (**Base description**) of the **Quest Generator** editor. When working in a text editor, this field is unavailable to you and the function will always return an empty string. +::: + +## `$DYNEVAL` + +`DYNEVAL` — executes code passed as a text string and returns the result if it exists. General syntax: + +```qsp +$DYNEVAL([$code], [argument 0], [argument 1], ... , [argument 18]) +DYNEVAL([$code], [argument 0], [argument 1], ... , [argument 18]) +``` + +, where `[$code]` — regular QSP code written as text. Executing such code is analogous to executing `FUNC` function code. Arguments `[argument 0]`, `[argument 1]`, etc. can be used inside `[$code]`, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. + +Inside the code executed by `dyneval`, its own `ARGS` array is used, its values don't intersect with `ARGS` values at the location from which `dyneval` was called. + +After executing the code passed to the `dyneval` function, calculation of the expression in which `dyneval` is located continues. + +For `dyneval` to return a result, you need to assign this result to the `result` variable inside `[$code]`. + +Examples: + +```qsp +dyneval('result = 3 + 4') +*pl $dyneval('$result = mid("abcd", 2, 1) + "qwerty"') +pass = dyneval("result = ($args[0] <> 'text')", 'string') +``` + +- For `DYNEVAL` to return multiple values, the result must be written to `%RESULT`. +- For `DYNEVAL` to return a string value, the result must be written to `$RESULT`. +- For `DYNEVAL` to return a numeric value, the result must be written to `RESULT`. +- `%RESULT`, `$RESULT` and `RESULT` are the same variable but with different data types. Remember that a new value assignment overwrites the previous one, regardless of the data type of that value. + +If `dyneval` doesn't return values during execution (`result` is not initialized), and is the only element of an expression passed to the implicit operator, the player will output nothing to screen. I.e., `dyneval` will work like `DYNAMIC`. Example: + +```qsp +! implicit operator will output 123 to screen: +123 +! code in dyneval will execute, but we won't see +! anything on screen: +dyneval("code = 123 + 890") +! implicit operator will output 1013 to screen: +code +``` + +See also [operator `DYNAMIC`](qsp-keyword-operators.md#dynamic). + +## `$FUNC` + +`FUNC` — executes code of the specified location without direct transition to it with value return. + +General syntax: + +```qsp +FUNC([$location], [argument 0], [argument 1], ... , [argument 18]) +$FUNC([$location], [argument 0], [argument 1], ... , [argument 18]) +``` + +, where `[$location]` — the name of the location whose code we want to execute without direct transition to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. + +For `FUNC` to return: + +- multiple values or a tuple, at the specified location you need to assign the result to variable `%RESULT`; +- a string result, at this location you need to assign this result to variable `$RESULT`; +- for returning a numeric result, it must be assigned to variable `RESULT`. + +Remember that `%RESULT`, `$RESULT` and `RESULT` are the same variable but of different types, so if you defined both `%RESULT`, `$RESULT`, and `RESULT` at the location, the function will return the value that was written to this variable last. + +If no value was assigned to the `RESULT` variable, the function returns nothing. And here there are two player behavior variants. + +- If the `FUNC` function is in some expression, the default value will be substituted instead of the function (empty tuple, empty string, or zero depending on the expression type). +- If the `FUNC` function stands right after the implicit operator, such operator will be ignored, and nothing will be output to screen. Example: + +```qsp title="location_N" +N = 23 * 13 +! no value is assigned to result variable +``` + +```qsp title="Other location" +'string 1' +func('location_N') &! nothing will be output to screen +'string 2' +56 + func('location_N') &! function is in expression. Its value = 0 +``` + +:::note[Recommendation:] +It's not mandatory, but recommended, to use the type prefix (`$` or `%`) with the `FUNC` keyword if the function should return a string value or tuple, and — without type prefix if the function should return a numeric value: + +```qsp +$func('string_slice', 'We left the house when lights went out in all windows.', 3, 7) +func('raise_to_power', 3, 3) +``` + +::: + +**Order of operation.** + +When calling the specified location using `FUNC`, the following happens: + +- The player interrupts execution of current code (for example, current location code) and calls the specified location. +- Base description and action list of the specified location are added to the description and actions of the current location. +- Code from the **Execute on visit** field is executed +- Then the player returns to executing the code it interrupted. I.e., to calculating the expression in which this function stands. + +Separate unique `ARGS` and `RESULT` arrays are automatically created at each location, so values in these arrays will be separate for each location. After executing the location code called by `FUNC`, the `ARGS` and `RESULT` arrays of this location are destroyed. + +Other examples: + +```qsp +!Processing location "function" as function. +!ARGS array is empty. +apples = FUNC('function') + +!processing location with name in variable $name as function. ARGS[0] equals 1. +pl func($name, 1) * 78 + +!processing location with name in $name as function. +!$ARGS[0] contains string "string", ARGS[1] equals 2. +msg "text" + func($name, "string", 2) +``` + +```qsp +! location code for function getting sum of series of numbers from one to specified value +# summ +! args[0] will contain the number we specify as [argument 0] +loop while args[0]>0 step args[0] -= 1: + result += args[0] +end +---summ--- + +! example of calling location "summ" as function +*pl func("summ", 19) & ! will output 190 to screen +! example of call with location name written to variable +$name_loc = "summ" +*pl func($name_loc, 23) & ! will output 276 to screen +``` + +Also see ["Implicit `FUNC` function call"](qsp-keyword-syntaxems.md#at-symbol-). + +## `$GETOBJ` + +`$GETOBJ` — returns the name of an item in the *Objects Window* located at the specified position. General syntax: + +```qsp +$GETOBJ([#item_number]) +``` + +Indexing (numbering) of items in the *Objects Window* starts from 1. If an item with index `[#item_number]` doesn't exist, an empty string (`''`) is returned. + +Examples: + +```qsp +$getobj(1) & ! returns name of first item in backpack + +$getobj(countobj) & ! returns name of last added item +``` + +Code counting the number of items with identical names in the `OBJECTS` array: + +```qsp +loop local i = 1 while i <= countobj step i += 1: + objects[$getobj(i)] += 1 +end +``` + +## `$QSPVER` + +`$QSPVER` - returns the interpreter version in the format "X.Y.Z Player". For example, classic player version 5.8.0 returns the value "5.8.0 (classic)", and qSpider simply "5.8.0". Usage example: + +```qsp +if $qspver < "5.8.0": + *pl "Your player version is not suitable for this game." + *pl "Install player version 5.8.0 or higher." +end +``` + +This function can also return the platform on which the game is running if you specify "platform" as an argument: + +```qsp +$qspver('platform') +``` + +:::note[5.7.0] + +In older player versions, the function returned only the interpreter version (libqsp library). + +::: + +## `$SELACT` + +`$SELACT` — returns the name of the selected action anywhere in the game. + +Remember that action selection occurs when hovering the mouse pointer over it, not when directly clicking. + +Most often this function is used to remove the current action: + +```qsp +act "Eat apple": + *pl "It was a very tasty apple. Too bad it was wormy." + health += 100 + delact $selact +end +``` + +Also see usage examples in the [`$onactsel`](qsp-keyword-sys-var.md#onactsel) section + +## `$SELOBJ` + +`$SELOBJ` — returns the name of the selected object anywhere in the game. Object selection occurs when clicking (mouse click on object) and is not removed until the `unselect` command is applied. + +Usage examples can be found in the [`$onobjsel`](qsp-keyword-sys-var.md#onobjsel) section + +## `$STATTXT` + +`$STATTXT` — returns text output to the additional description window. Can be useful for replacing part of text in the additional description window. + +Example: + +```qsp +p 'The Ship Carried Caramel' +nl 'The Ship Hit a Shoal' +$string = $stattxt +``` + +## `$USER_TEXT` + +`$USER_TEXT` — anywhere in the game returns text that is in the input line (input field). Has the short form `$usrtxt`. + +Example of an action that will output text entered in the input line to the additional description window when clicked: + +```qsp +act "What did I write?": pl 'I wrote: "<<$user_text>>".' +``` + +A more common example is presented in the [`$usercom`](qsp-keyword-sys-var.md#usercom) section. + +## COUNTOBJ + +`COUNTOBJ` — returns the number of items in inventory. + +The number of the last item in the list numerically matches the number of items, so you can always get the name of the last item like this: + +```qsp +$getobj(countobj) +``` + +## MSECSCOUNT + +`MSECSCOUNT` — returns the number of milliseconds elapsed since the game started. This function, when used at the counter location, allows organizing various events occurring in real time. Also, with this function you can measure performance of various code sections in your game: + +```qsp +i = 0 +old_time = msecscount +:for +if i < 100000: + d[i] = i + i += 1 + jump 'for' +end +new_time = msecscount +pl "Old loop performance: " + $str(new_time - old_time) + +old_time = msecscount +loop i = 0 while i < 100000 step i += 1: + b[i] = i +end +new_time = msecscount +pl "New loop performance: " + $str(new_time - old_time) +``` + +:::note +The maximum number this function can return is `2147483647`. It's not hard to calculate that this is enough for more than **550** hours of gameplay. +::: + +## RND + +`RND` - returns a random value from `1` to `1000`. Analogous to the command: + +```qsp +rand(1, 1000) +``` + +## `$IIF` + +`IIF` — returns a value depending on expression truth. + +General syntax: + +```qsp +IIF([#expression], [#expression_yes], [#expression_no]) +$IIF([#expression], [$expression_yes], [$expression_no]) +``` + +If `[#expression]` is true, returns the value of expression `[expression_yes]`, otherwise returns the value of expression `[expression_no]`. + +Only one of the expressions `[expression_yes]` and `[expression_no]` will be calculated, depending on whether the condition is met. + +Examples: + +```qsp +!Absolute value of number +abs_x = iif(x>0, x, -x) + +!And the following construct will NOT cause division by zero error: +x = 0 +y = iif(x = 0, 0, 1/x) + +! typical solution for outputting time so as not to lose zero on hours: +$iif(hour>9, $str(hour), "0"+$str(hour)) + ":"+$iif(minute>9, $str(minute), "0"+$str(minute)) +``` + +Equivalence of conditional constructs with `IF` operator and `IIF` function: + +```qsp +if number mod 2 = 0: + *pl "Number is even" +else + *pl "Number is odd" +end +! equivalent to +*pl $iif(number mod 2 = 0,"Number is even","Number is odd") +``` + +## `$INPUT` + +`$INPUT` — returns to the interpreter the text entered by the player, or `''` (empty string) if the "Cancel" button was pressed. General syntax: + +```qsp +$INPUT([$text]) +``` + +, where `[$text]` — the prompt in the dialog box that the player sees. For example: + +```qsp +$name = $input('What is your name, hero?') +``` + +When this command is executed, a dialog box with the text "What is your name, hero?" will appear on screen, and execution of the rest of the code will pause until the player interacts with the dialog box. + +The player can enter or not enter text, and press the "OK" or "Cancel" button. If the player entered text and pressed the "OK" button, the `$input` function will return the text entered by the player to the `$text` variable. In all other cases, after closing the dialog box, the function will return an empty string (`''`). + +Other examples: + +```qsp +! Question with one correct answer. +if $input('What comes after darkness?') = 'light': + msg 'Correct.' +else + msg 'Wrong answer.' +end + +! Example implementation of question with multiple answer variants where any will be correct. +$answer = $trim($lcase($input('Answer'))) +if instr($answer, 'red') or instr($answer, 'yellow') or instr($answer, 'green'): gt 'win' +! Entering red or green or yellow will transition to 'win' location +``` + +:::warning[Be careful!] +It's acceptable but not approved to use the function for returning numeric values: + +```qsp +INPUT([$prompt]) +``` + +This can lead to various game errors if the player enters not only digits in the dialog box. For example: + +```qsp +age = input('How old are you?') +``` + +If the player enters the string "24 years old" instead of a number, the player will give error **101** "Data type mismatch". + +Such situations should be anticipated by the game author, which means it's correct to check the entered value after the `$input` function is executed. + +```qsp +loop local $text while 1: + ! ask player to answer question + ! and assign entered text to variable + $text = $input('How old are you?') + ! if entered text contains not only digits + ! or player didn't enter answer + if isnum($text) and $text <> "": + ! player entered number + age = val($text) & ! set age + jump 'break' & ! break loop + else + ! player entered nothing or incorrect value + ! loop continues + end +end +:break +``` + +::: + +## `$LCASE` + +`$LCASE` — returns a lowercase string obtained by changing the case of letters in the original string. General syntax: + +```qsp +$LCASE([$text]) +``` + +, where `[$text]` — any text string. + +Examples: + +```qsp +$lcase('TExT#') & ! returns 'text#' +$lcase('Hello, Alice!') & ! returns 'hello, alice!' +$lcase('I DON\'T WANT TO SHOUT AT YOU.') & ! returns 'i don\'t want to shout at you.' +``` + +## `$MAINTXT` + +`$MAINTXT` — returns text output to the main description window. + +This function can be useful for replacing part of text in the main description window, or other text processing. Example: + +```qsp +! initially we output a string +*pl "We output a string to screen and in this string there's a piece we want to remove." + +! get text from main description window +$text = $maintxt +! cut out extra piece +$text_new = $replace($text, " and in this string there's a piece we want to remove") +! clear main description window +*clr +! output new text +*p $text_new +``` + +## `$MID` + +`$MID` — allows cutting a part from a string. General syntax: + +```qsp +$MID([$string], [#start], [#length]) +``` + +, where `[$string]` — text string from which the function cuts a part, starting from character number `[#start]`, and with length of `[#length]` characters. Character numbering starts from 1. + +- If the `[#length]` parameter is absent, the part is cut to the end of the string. +- The `[#start]` parameter is mandatory and can take any values. +- If the `[#start]` value exceeds the string length, an empty string is returned. + +```qsp +$mid('abcdef', 1, 2) & ! 'ab' +$mid('abcdef', 2, 3) & ! 'bcd' +$mid('abcdef', 2) & ! 'bcdef' +$mid('abcdef') & ! 'error [120] — incorrect number of operator/function arguments' +$mid('abcdef', 0) & ! 'abcdef' +$mid('abcdef', 8) & ! '' +``` + +## `$REPLACE` + +`$REPLACE` — general syntax: + +```qsp +$REPLACE([$string], [$search], [$replacement], [#num_replacements]) +``` + +This function replaces several occurrences of string `[$search]` with string `[$replacement]` in string `[$string]` and returns the result. Replacement is performed left-to-right and only for non-overlapping occurrences. The `[#num_replacements]` parameter shows how many occurrences should be replaced. If the parameter is not specified, all occurrences are replaced. If `[$replacement]` is absent or an empty string is specified, then all occurrences of the searched string are removed from the original string. Examples: + +```qsp +$replace('test', '12', '4') & ! will output 'test' to screen +$replace('test', 'e', 's') & ! will output 'tsst' to screen +$replace('test', 't', '34') & ! will output '34es34' to screen +$replace('test', 't') & ! will output 'es' to screen + +$replace('test', 't', 'qu', 1) &! 'quest' +$replace('test my test', 't', 'q', 3) &! 'qesq my qest' +``` + +```qsp +! you can assign value to variable +$text = "Text string with different letters." +! and write new value to another variable +$text_new = $replace($text, "st", "st") +*pl $text +*pl $text_new +``` + +## `$STR` + +`$STR` — returns a text string obtained by converting a number to string. General syntax: + +```qsp +$STR([#number]) +``` + +Example: + +```qsp +$str(56) & ! converts number 56 to string "56" and outputs to screen +``` + +## `$STRFIND` + +`$STRFIND` — returns a substring matching a regular expression from the specified string. General syntax: + +```qsp +$STRFIND([$string], [$pattern], [#number]) +``` + +, where `[$string]` — source string in which we search for an occurrence matching regular expression `[$pattern]`, or group number `[#number]` in the regular expression. If substring with specified number is absent, an empty string is returned. Group numbering starts from 1. If parameter `[#number]` is absent or equals 0, the substring matching the entire regular expression `[$pattern]` is returned. + +For example, let's take the regular expression: + +```regex +^(\S+)\s(\S+)\s(\S+)$ +``` + +The `\S` metacharacter means any non-whitespace character, and the `+` quantifier indicates that non-whitespace characters must be present one or more times. Thus the notation `\S+` can be conditionally matched to a word. Each word is enclosed in separate groups using parentheses `()`, and whitespace characters `\s` are present between groups. The `^` and `## `$IIF` + +`IIF` — returns a value depending on expression truth. + +General syntax: + +```qsp +IIF([#expression], [#expression_yes], [#expression_no]) +$IIF([#expression], [$expression_yes], [$expression_no]) +``` + +If `[#expression]` is true, returns the value of expression `[expression_yes]`, otherwise returns the value of expression `[expression_no]`. + +Only one of the expressions `[expression_yes]` and `[expression_no]` will be calculated, depending on whether the condition is met. + +Examples: + +```qsp +!Absolute value of number +abs_x = iif(x>0, x, -x) + +!And the following construct will NOT cause division by zero error: +x = 0 +y = iif(x = 0, 0, 1/x) + +! typical solution for outputting time so as not to lose zero on hours: +$iif(hour>9, $str(hour), "0"+$str(hour)) + ":"+$iif(minute>9, $str(minute), "0"+$str(minute)) +``` + +Equivalence of conditional constructs with `IF` operator and `IIF` function: + +```qsp +if number mod 2 = 0: + *pl "Number is even" +else + *pl "Number is odd" +end +! equivalent to +*pl $iif(number mod 2 = 0,"Number is even","Number is odd") +``` + + metacharacters mean the beginning and end of string respectively. Thus our regular expression matches any string of three words separated by spaces. + +Then: + +```qsp +! in this case the string doesn't match the regular expression +! because according to the regular expression the string should start +! with a group of non-whitespace characters. The command will return empty string '' +$strfind(' go to cave','^(\S+)\s(\S+)\s(\S+)) +``` + +```qsp +! in this case the string fully matches the regular expression +! so the command will return the string entirely 'go to cave' +$strfind('go to cave','^(\S+)\s(\S+)\s(\S+)) = '' +``` + +```qsp +! in the next three examples the string matches the regular expression +! but the third argument specifies which group from this +! regular expression we want to get, so each command will return +! the first, second and third words from the string respectively +$strfind('go to cave','^(\S+)\s(\S+)\s(\S+), 1) & ! returns 'go' +$strfind('go to cave','^(\S+)\s(\S+)\s(\S+), 2) & ! returns 'to' +$strfind('go to cave','^(\S+)\s(\S+)\s(\S+), 3) & ! returns 'cave' +``` + +```qsp +! here the last group of non-whitespace characters is combined into one +! group with the last whitespace character. The "?" quantifier indicates +! that this group may or may not be present in the string: +$strfind('go to cave', '^(\S+)\s(\S+)(\s(\S+))?, 4) & ! returns 'cave' +$strfind('go to cave', '^(\S+)\s(\S+)(\s(\S+))?, 3) & ! returns ' cave' +! this regular expression also matches this string +$strfind('search key', '^(\S+)\s(\S+)(\s(\S+))?, 1) & ! returns 'search' +! but this string no longer matches the regular expression +$strfind('search', '^(\S+)\s(\S+)(\s(\S+))?, 1) & ! returns '' +``` + +The following examples show how `$strfind` returns part of string matching the regular expression: + +```qsp +$strfind('go to house', 'to\s(\S+)') & ! returns 'to house' +$strfind('go to house', 'to\s(\S+)', 1) & ! returns 'house' +$strfind('go to my house', 'to\s(\S+)', 1) & ! returns 'my' +``` + +Other examples: + +```qsp title="four-letter word" +$strfind('go to cave', '\b\w{4}\b') &! we'll see 'cave' on screen +``` + +```qsp title="Selection with nested groups" +$strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 1) &! we'll see '671' on screen +$strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 2) &! we'll see '-190-23-999' on screen +$strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 3) &! we'll see '-999' on screen +``` + +```qsp title="searching for numbers in string without numbers" +$strfind('Eight green apples in basket','\d+') &! empty string will be on screen +``` + +## `$TRIM` + +`$TRIM` — returns the specified string without adjacent tab and space characters. General syntax: + +```qsp +$TRIM([$expression]) +``` + +For example: + +```qsp +$trim(' trim test ') & ! returns 'trim test' +``` + +## `$UCASE` + +`$UCASE` — returns an uppercase string obtained by changing the case of letters in the original string. General syntax: + +```qsp +$UCASE([$text]) +``` + +, where `[$text]` — any text string. + +Examples: + +```qsp +$ucase('TExT#') & ! returns 'TEXT#' +$ucase('Hello, Alice!') & ! returns 'HELLO, ALICE!' +$ucase('I want to shout at you.') & ! returns 'I WANT TO SHOUT AT YOU.' +``` + +## INSTR + +`INSTR` — returns the character number from which the substring occurrence begins in the string. General syntax: + +```qsp +INSTR([$string], [$substring], [#start]) +``` + +, where `[#start]` — the character number from which to start the search, `[$string]` — text value (string) in which to search, and `[$substring]` — value we're looking for in the specified string. Character numbering starts from `1`. The `[#start]` parameter can be absent, in which case it's taken as 1. + +Examples: + +```qsp +instr('abcdefabcdef', 'bc', 3) & ! returns number 8 +instr('abcdefghijklm', 'abc') & ! returns number 1 +``` + +If no occurrence of the specified substring is found in the string, `instr` returns `0`. + +Example: + +```qsp +instr('Vasya left the house.', 'go') & ! returns 0 +``` + +:::note[5.7.0] +In older player versions, the `[#start]` parameter was specified first: + +```qsp +INSTR([#start], [$string], [$substring]) +``` + +::: + +## ISNUM + +`ISNUM` — function returns `1` (true) if the passed string is a number, and `0` if the string is not a number. General syntax: + +```qsp +ISNUM([$string]) +``` + +, where `[$string]` — any text string. + +The check takes into account the `-` sign at the beginning, adjacent spaces and tab characters, but if at least one character turns out not to be a digit, the function will return `0` (false). + +Examples: + +```qsp +isnum(' 9999 ') & ! returns 1 +isnum(' -888') & ! returns 1 +isnum('777a6') & ! returns 0 +isnum('') & ! returns 0, since empty string contains no number +``` + +## ISPLAY + +`ISPLAY` — function checks if a file with the specified name is currently playing, and if it is, returns `1`. Otherwise the function returns `0`. General syntax: + +```qsp +ISPLAY([$file_path]) +``` + +, where `[$file_path]` — path to sound file relative to game file. + +Example: + +```qsp +if isplay('music/mountsound.mp3'): + *pl 'Music is playing.' +else + *pl 'Music is not playing.' +end +``` + +## LEN + +`LEN` — returns the length of the specified text string (number of characters). General syntax: + +```qsp +LEN([$text]) +``` + +, where `[$text]` — any text value. + +Examples: + +```qsp +len("abc") & ! returns value 3 +len("thousand-nine-hundred-eighty-nine-millimeter") & ! returns value 46 +len("") & ! returns value 0 +``` + +## STRCOMP + +`STRCOMP` — compares a string with a regular expression and, if the string matches the regular expression, returns `1` (true), and if it doesn't match — `0` (false). General syntax: + +```qsp +STRCOMP([$string], [$pattern]) +``` + +, where `[$string]` — any text value, `[$pattern]` — regular expression to compare with. + +For example, we need to check if the specified string consists of three words. Each word, roughly speaking, is a set of non-whitespace characters, so we can use the `\S` metacharacter with the `+` quantifier. Words are usually separated by whitespace characters, for which we use the `\s` metacharacter. We get this regular expression: + +```regex +\s?\S+\s+\S+\s+\S+\s? +``` + +Now we can check which strings match this regular expression: + +```qsp +strcomp('go along road', '\s?\S+\s+\S+\s+\S+\s?') & ! returns 1 +strcomp(' go home', '\s?\S+\s+\S+\s+\S+\s?') & ! returns 0 +strcomp(' go to forest ', '\s?\S+\s+\S+\s+\S+\s?') & ! returns 1 +strcomp('oneword', '\s?\S+\s+\S+\s+\S+\s?') & ! returns 0 +``` + +## STRPOS + +`STRPOS` — returns the position of the character from which the substring occurrence matching the regular expression begins in the specified string. General syntax: + +```qsp +STRPOS([$string], [$pattern], [#number]) +``` + +, where `[$string]` — source string in which we search for an occurrence matching regular expression `[$pattern]`, or group number `[#number]` in the regular expression. Group numbering in regular expression starts from 1. If substring with specified number is absent, `0` is returned. + +If parameter `[#number]` is absent or equals `0`, the position of the character from which the substring occurrence matching the entire regular expression begins is returned. + +For example, we need to find out in which part of the text the phrase "green apple" occurs, but the case of this adjective shouldn't matter. + +To write a regular expression for this task, we need to account for all cases: + +```plain +green apple +green apple +green apple +green apple +green apple +green apple +``` + +As we can see, only word endings change in all forms. Therefore we can compose this regular expression: + +```regex +green(oe|ogo|omu|ym|om)\s+apple(o|a|u|om|e) +``` + +Possible ending variants are listed through a vertical bar in parentheses. And now let's find out from which character in the string the possible phrase "green apple" begins: + +```qsp +! for convenience we put the regular expression in a variable +$regexp = "green(oe|ogo|omu|ym|om)\s+apple(o|a|u|om|e)" +strpos("I have a green apple", $regexp) & ! returns 13 +strpos("You threw a green apple at him!", $regexp) & ! returns 19 +strpos("full box of green apples", $regexp) & ! returns 0, because we didn't account for this form +``` + +If we don't just want to know from which character the phrase occurrence begins in the string, but specifically where the word "apple" from this phrase begins, we need to put the word "apple" with ending variants in a separate group and use the `[#number]` parameter: + +```qsp +$regexp = "green(oe|ogo|omu|ym|om)\s+(apple(o|a|u|om|e))" +strpos("I have a green apple", $regexp, 2) & ! returns 21 +strpos("You threw a green apple at him!", $regexp, 2) & ! returns 27 +strpos("full box of green apples", $regexp, 2) & ! returns 0, because we didn't account for the form +``` + +Other examples: + +```qsp title="Working with groups" +!------'----5--8------15--' +STRPOS('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)',1) &! we'll see 5 on screen +STRPOS('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)',2) &! we'll see 8 on screen +STRPOS('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)',3) &! we'll see 15 on screen +``` + +```qsp title="Searching for number in string without number" +STRPOS('Eight green apples in basket','\d+') &! 0 will be on screen +``` + +```qsp +STRPOS('go to cave', '^(\S+)\s(\S+)\s(\S+), 0) &! 1 +STRPOS(' go to cave', '^(\S+)\s(\S+)\s(\S+), 0) &! 0 +STRPOS('go to cave', '^(\S+)\s(\S+)\s(\S+), 1) &! 1 +STRPOS('go to cave', '^(\S+)\s(\S+)\s(\S+), 2) &! 6 +STRPOS('go to cave', '^(\S+)\s(\S+)\s(\S+), 3) &! 8 +STRPOS('go to cave', '^(\S+)\s(\S+)(\s(\S+))?, 4) &! 8 +STRPOS('go to house', 'to\s(\S+)', 0) &! 6 +STRPOS('go to house', 'to\s(\S+)') &! 6 +STRPOS('go to house', 'to\s(\S+)', 1) &! 8 +STRPOS('go to my house', 'to\s(\S+)', 1) &! 8 +``` + +## VAL + +`VAL` — converts the specified digit string to corresponding number. General syntax: + +```qsp +VAL([$expression]) +``` + +, where `[$expression]` — any text string. + +The check takes into account the `-` sign at the beginning, adjacent spaces and tab characters, but if at least one character turns out not to be a digit, the function will return `0`. Also if `[$expression]` equals `''` (empty string), `0` is returned. + +Examples: + +```qsp +apples = val($apples) + +val('123') & ! we'll see 123 +val('') & ! we'll see 0 +val('sand') & ! we'll see 0 +``` + +## `$MAX` + +`MAX` — returns the maximum of expression-argument values. You can pass from one to twenty values/arguments. If one argument is passed, it's considered that an array name is specified. General syntax: + +```qsp +MAX([#expression 1], [#expression 2], ... , [#expression 20]) +$MAX([$expression 1], [$expression 2], ... , [$expression 20]) + +MAX([$array_name]) +$MAX([$array_name]) +``` + +Note, when passing one argument, the search for maximum element occurs among string (if array name is specified with `$` sign) or among numeric values of array elements. For example: + +```qsp +max('a') & ! returns maximum of numeric values of "a" array elements +$max('$b') & ! returns maximum of string values of "b" array elements +``` + +You can't write like this and expect search among array `a` values: + +```qsp +max(a) +``` + +You can do this: + +```qsp +$b = 'a' +max($b) & ! search for maximum value among elements of "a" array will occur +``` + +Other examples: + +```qsp +max(1, 2, 5, 2, 0) &! returns 5 +max(a, b, c) &! returns maximum of variable values a,b,c +$max('aa', 'ab', 'zz') &! returns 'zz' +``` + +## `$MIN` + +`MIN` — returns the minimum of expression-argument values. You can pass from one to twenty values/arguments. If one argument is passed, it's considered that an array name is specified. General syntax: + +```qsp +MIN([#expression 1], [#expression 2], ... , [#expression 20]) +$MIN([$expression 1], [$expression 2], ... , [$expression 20]) +``` + +```qsp +MIN([$array_name]) +$MIN([$array_name]) +``` + +Note, when passing one argument, the search for minimum element occurs among string (if array name is specified with `$` sign) or among numeric values of array elements. For example: + +```qsp +min('a') & ! returns minimum of numeric values of "a" array elements +$min('$b') & ! returns minimum of string values of "b" array elements +``` + +You can't write like this: + +```qsp +min(a) +``` + +You can do this: + +```qsp +$b = 'a' +min($b) & ! search for maximum value among elements of "a" array will occur +``` + +Other examples: + +```qsp +min(1, 2, 5, 2, 0) & ! returns 0 +min(a, b, c) & ! returns minimum of variable values a,b,c +$min('aa', 'ab', 'zz') & ! returns 'aa' +``` + +## RAND + +`RAND` — returns a random number between two specified numbers. General syntax: + +```qsp +RAND([#expression 1], [#expression 2], [#mode]) +``` + +, where `[#expression 1]` and `[#expression 2]` — any two numbers or numeric expressions. + +The `[#mode]` parameter allows specifying a number that should occur more frequently than others. The frequency distribution will smoothly change for all other numbers, decreasing from mode to the limits of the selected interval. If the 3rd parameter is not specified, the function returns a random number in the specified range with uniform/equiprobable number distribution. + +The `[#expression 2]` parameter can be absent, in which case it's taken as `1`. + +:::note[5.7.0] +In older player versions, this parameter defaults to zero. +::: + +Examples: + +```qsp +rand(1, 4) &! returns random value from 1 to 4 +rand(4, 1) &! returns random value from 1 to 4 +rand(1000) &! returns random value from 1 to 1000 +rand 1000 &! returns random value from 1 to 1000 + +x = RAND(1, 1000, 500) & ! 500 will occur more often +x = RAND(1, 1000, 1) & ! 1 will occur more often +x = RAND(1, 1000, 1000) & ! 1000 will occur more often +x = RAND(-1000, 0, -500) & ! -500 will occur more often +x = RAND(1, 1000, 5000) & ! 1000 will occur more often +x = RAND(-1000, -100, -5000) & ! -1000 will occur more often +``` + +## RGB + +`RGB` — returns the numeric color code based on three numeric arguments, each corresponding to a component of the required color. General syntax: + +```qsp +RGB([#red], [#green], [#blue], [#alpha]) +``` + +, where `[#red]`, `[#green]` and `[#blue]` — numeric expression of three color components respectively red, green and blue; `[#alpha]` — transparency component; should take values from 0 to 255. + +This function is usually used together with system variables `bcolor`, `fcolor`, `lcolor`. Example: + +```qsp +! light yellow hyperlinks +lcolor = rgb(255, 255, 100) +! dark gray background +bcolor = rgb(25, 25, 25) +! light green text +fcolor = rgb(100, 255, 100) +``` + +Example of semi-transparent link color: + +```qsp +lcolor = rgb(0, 255, 255, 128) +``` + +:::note[Note.] + +Don't rely on the `[#alpha]` parameter as many players don't support it. + +::: + +## ARRCOMP + +`ARRCOMP` — returns the index of array element matching a regular expression. Search starts from element with specified number; array element indexing starts from zero. If the specified value is not found, the function returns -1. General syntax: + +```qsp +ARRCOMP([$array_name], [$pattern], [#start]) +``` + +, where `[#start]` — array element number from which to start search, `[$array_name]` — array name to search in, `[$pattern]` — regular expression to compare the searched element with. + +- The `[#start]` parameter can be absent, in which case its value is taken as 0. +- Search works only on text arrays (the `$` symbol in array name can be omitted). + +For example, let's take this array: + +```qsp +$mass[0] = "stomp forward" +$mass[1] = " go to cave" +$mass[2] = "don't go to cave" +$mass[3] = "stomp to house" +``` + +We need to find an element whose value consists of three words. Roughly speaking, a word is a set of one or more non-whitespace characters `\S+`, which can be surrounded by whitespace characters `\s`, so we can compose this regular expression: + +```regex +\s?\S+\s\S+\s\S+\s? +``` + +Now we just need to find out which array element matches the pattern: + +```qsp +arrcomp('$mass', '\s?\S+\s\S+\s\S+\s?') & ! the first element matches this expression +``` + +If we want to ignore the first element and start search from the second: + +```qsp +arrcomp('$mass', '\s?\S+\s\S+\s\S+\s?', 2) & ! the third element matches this expression +``` + +And this is how we can output all element values containing the word "go": + +```qsp +loop local pos, index = 0, 0 while 1: + index = arrcomp('$mass', '(.*\s|^)go(\s.*|$)', pos) + if index <> -1: + $mass[index] + pos = index + 1 + else: + jump 'break' + end +end +:break +``` + +Other examples: + +```qsp +! Search for string 'This' among elements of array "$A" +arrcomp('$A', 'This', 0) +! Search for string matching regular expression "abc\d+" +! (first two array elements are ignored) +arrcomp('$A', 'abc\d+', 2) +! similar to previous example, +! but search is performed on all array elements +arrcomp('$A', '.*string.*', 0) + +arrcomp('$A', 'This') & ! equivalent to 1st variant +``` + +:::warning[Attention!] +The function returns only the numeric index of the element. String or multi-dimensional index cannot be obtained with this function. +::: + +## ARRITEM + +`ARRITEM` — returns the value of array element at specified index. General syntax: + +```qsp +ARRITEM([$array_name], [element_index]) +``` + +, where `[$array_name]` — the name of the array whose element we want to get, and `[element_index]` — numeric, text, or multi-dimensional index. + +In other words, the function extracts a value from the specified array cell. Examples: + +```qsp +! output value of element with index 3 +*pl $arritem('$mass', 3) +! output value of element with text index +*pl $arritem('$mass', 'Pete') +! output value of element with multi-dimensional index +*pl $arritem('$mass', [-2, 9, 0]) +``` + +This function can be useful for extracting values when the array name is not known in advance. Example: + +```qsp title="Output contents of several arrays without using DYNAMIC" +$array_name[] = 'mass_1' +$array_name[] = 'mass_2' +$array_name[] = 'mass_3' +$array_name[] = 'mass_4' +$array_name[] = 'mass_5' +! outer loop iterates through array names +loop local j = 0 while j < arrsize('$array_name') step j += 1: + ! inner loop outputs array contents + loop local i = 0 while i < arrsize($array_name[j]) step i += 1: + *pl arritem($array_name[j], i) + end +end +``` + +## %ARRPACK + +`ARRPACK` — returns a tuple into which values from the specified array are packed. + +General syntax: + +```qsp +%ARRPACK([$array_name], [#start_index], [#count]) +``` + +, where `[#start_index]` - the number of array element `[$array_name]` from which to start selecting elements for packing; `[#count]` — the number of elements to be packed into the tuple. + +This function allows shortening the command for extracting arguments from `args`: + +```qsp +! instead of: +local type, name = args[0], args[1] +! you can write like this: +local type, name = arrpack('args') +``` + +It can also be convenient if you need to quickly view array contents or part of it: + +```qsp +! view values in array without using loop: +*pl %arrpack('massive', 11, 10) & ! we'll see ten elements starting from 11th, as a tuple on screen +``` + +## ARRPOS + +`ARRPOS` — returns the index of array element equal to specified value. Search starts from element with specified number; array element indexing starts from zero. If the specified value is not found, the function returns -1. + +General syntax: + +```qsp +ARRPOS([$array_name], [value], [#start]) +``` + +, where `[#start]` — array element number from which to start search, `[$array_name]` — array name to search in, `[value]` — number or string (depending on array type) to find in the array. + +For example, let's take this array: + +```qsp +$color[0] = 'red' +$color[1] = 'yellow' +$color[2] = 'green' +$color[3] = 'blue' +$color[4] = 'yellow' +``` + +We need to find element with value "yellow": + +```qsp +arrpos('$color', 'yellow') & ! returns value 1 +``` + +If we want to ignore the first two elements: + +```qsp +arrpos('$color', 'yellow', 2) & ! returns value 4 +``` + +If we want to find element with value that doesn't exist in the array: + +```qsp +arrpos('$color','light blue') & ! returns value -1 +``` + +Other examples: + +```qsp +! search for string 'this' in text array "$a" +arrpos('$a', 'this', 0) +! search for number 65 in array "a" (two array elements are ignored) +arrpos('a', 65, 2) +! search for string 'test' among values of array "$b" +arrpos('$b', 'test') +``` + +:::warning[Attention!] +The function returns only the numeric index of the element. String or multi-dimensional index cannot be obtained with this function. +::: + +:::note[5.7.0] +In older player versions, the `[#start]` parameter was specified first: + +```qsp +ARRPOS([#start], [$array_name], [$pattern]) +``` + +::: + +## ARRTYPE + +`ARRTYPE` — returns the type of value stored in a variable or specified array cell. The type is returned as one of the following values: +- `''` (empty string) — value not defined (for example, for uninitialized variables); +- `'#'` — variable contains number; +- `'` — variable contains string; +- `'%'` — variable contains tuple. + +General syntax: + +```qsp +ARRTYPE([$array_name], [index]) +``` + +, where `[$array_name]` — array name (type prefix doesn't matter, better not to specify); `[index]` — cell index whose value type we want to get. + +Examples: + +```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` — function returns the number of array elements. General syntax: + +```qsp +ARRSIZE([$array_name]) +``` + +, where `[$array_name]` — the name of the array whose size we want to get. + +It doesn't matter whether you specify **`## `$MAX` + +`MAX` — returns the maximum of expression-argument values. You can pass from one to twenty values/arguments. If one argument is passed, it's considered that an array name is specified. General syntax: + +```qsp +MAX([#expression 1], [#expression 2], ... , [#expression 20]) +$MAX([$expression 1], [$expression 2], ... , [$expression 20]) + +MAX([$array_name]) +$MAX([$array_name]) +``` + +Note, when passing one argument, the search for maximum element occurs among string (if array name is specified with `$` sign) or among numeric values of array elements. For example: + +```qsp +max('a') & ! returns maximum of numeric values of "a" array elements +$max('$b') & ! returns maximum of string values of "b" array elements +``` + +You can't write like this and expect search among array `a` values: + +```qsp +max(a) +``` + +You can do this: + +```qsp +$b = 'a' +max($b) & ! search for maximum value among elements of "a" array will occur +``` + +Other examples: + +```qsp +max(1, 2, 5, 2, 0) &! returns 5 +max(a, b, c) &! returns maximum of variable values a,b,c +$max('aa', 'ab', 'zz') &! returns 'zz' +``` + +## `$MIN` + +`MIN` — returns the minimum of expression-argument values. You can pass from one to twenty values/arguments. If one argument is passed, it's considered that an array name is specified. General syntax: + +```qsp +MIN([#expression 1], [#expression 2], ... , [#expression 20]) +$MIN([$expression 1], [$expression 2], ... , [$expression 20]) +``` + +```qsp +MIN([$array_name]) +$MIN([$array_name]) +``` + +Note, when passing one argument, the search for minimum element occurs among string (if array name is specified with `$` sign) or among numeric values of array elements. For example: + +```qsp +min('a') & ! returns minimum of numeric values of "a" array elements +$min('$b') & ! returns minimum of string values of "b" array elements +``` + +You can't write like this: + +```qsp +min(a) +``` + +You can do this: + +```qsp +$b = 'a' +min($b) & ! search for maximum value among elements of "a" array will occur +``` + +Other examples: + +```qsp +min(1, 2, 5, 2, 0) & ! returns 0 +min(a, b, c) & ! returns minimum of variable values a,b,c +$min('aa', 'ab', 'zz') & ! returns 'aa' +``` + +## RAND + +`RAND` — returns a random number between two specified numbers. General syntax: + +```qsp +RAND([#expression 1], [#expression 2], [#mode]) +``` + +, where `[#expression 1]` and `[#expression 2]` — any two numbers or numeric expressions. + +The `[#mode]` parameter allows specifying a number that should occur more frequently than others. The frequency distribution will smoothly change for all other numbers, decreasing from mode to the limits of the selected interval. If the 3rd parameter is not specified, the function returns a random number in the specified range with uniform/equiprobable number distribution. + +The `[#expression 2]` parameter can be absent, in which case it's taken as `1`. + +:::note[5.7.0] +In older player versions, this parameter defaults to zero. +::: + +Examples: + +```qsp +rand(1, 4) &! returns random value from 1 to 4 +rand(4, 1) &! returns random value from 1 to 4 +rand(1000) &! returns random value from 1 to 1000 +rand 1000 &! returns random value from 1 to 1000 + +x = RAND(1, 1000, 500) & ! 500 will occur more often +x = RAND(1, 1000, 1) & ! 1 will occur more often +x = RAND(1, 1000, 1000) & ! 1000 will occur more often +x = RAND(-1000, 0, -500) & ! -500 will occur more often +x = RAND(1, 1000, 5000) & ! 1000 will occur more often +x = RAND(-1000, -100, -5000) & ! -1000 will occur more often +``` + +## RGB + +`RGB` — returns the numeric color code based on three numeric arguments, each corresponding to a component of the required color. General syntax: + +```qsp +RGB([#red], [#green], [#blue], [#alpha]) +``` + +, where `[#red]`, `[#green]` and `[#blue]` — numeric expression of three color components respectively red, green and blue; `[#alpha]` — transparency component; should take values from 0 to 255. + +This function is usually used together with system variables `bcolor`, `fcolor`, `lcolor`. Example: + +```qsp +! light yellow hyperlinks +lcolor = rgb(255, 255, 100) +! dark gray background +bcolor = rgb(25, 25, 25) +! light green text +fcolor = rgb(100, 255, 100) +``` + +Example of semi-transparent link color: + +```qsp +lcolor = rgb(0, 255, 255, 128) +``` + +:::note[Note.] + +Don't rely on the `[#alpha]` parameter as many players don't support it. + +::: + +## ARRCOMP + +`ARRCOMP` — returns the index of array element matching a regular expression. Search starts from element with specified number; array element indexing starts from zero. If the specified value is not found, the function returns -1. General syntax: + +```qsp +ARRCOMP([$array_name], [$pattern], [#start]) +``` + +, where `[#start]` — array element number from which to start search, `[$array_name]` — array name to search in, `[$pattern]` — regular expression to compare the searched element with. + +- The `[#start]` parameter can be absent, in which case its value is taken as 0. +- Search works only on text arrays (the `$` symbol in array name can be omitted). + +For example, let's take this array: + +```qsp +$mass[0] = "stomp forward" +$mass[1] = " go to cave" +$mass[2] = "don't go to cave" +$mass[3] = "stomp to house" +``` + +We need to find an element whose value consists of three words. Roughly speaking, a word is a set of one or more non-whitespace characters `\S+`, which can be surrounded by whitespace characters `\s`, so we can compose this regular expression: + +```regex +\s?\S+\s\S+\s\S+\s? +``` + +Now we just need to find out which array element matches the pattern: + +```qsp +arrcomp('$mass', '\s?\S+\s\S+\s\S+\s?') & ! the first element matches this expression +``` + +If we want to ignore the first element and start search from the second: + +```qsp +arrcomp('$mass', '\s?\S+\s\S+\s\S+\s?', 2) & ! the third element matches this expression +``` + +** before the array name or not. The total number of cells with both string and numeric values is counted. For example: + +```qsp +n = ARRSIZE('a') +n = ARRSIZE('$a') +! The result will be the same +``` + +:::warning[Attention!] + +If an array was declared using the `LOCAL` operator, but no value was assigned to any array element, `ARRSIZE` of such array will return `0`. + +::: \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md new file mode 100644 index 0000000..0d94414 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md @@ -0,0 +1,1263 @@ +--- +id: qsp-keyword-operacion +title: Operations +sidebar_position: 1 +--- + +# Operations + +List of operations for player version 5.8.0 in ascending order of priority: + +- `OR` +- `AND` +- `NO` +- `=`, `<`, `>`, `!`, `<>`, `<=`, `>=`, `=<`, `=>` (comparison operations) +- `OBJ`, `LOC` +- `&` (concatenation) +- `+`, `-` (addition, subtraction) +- `MOD` +- `*`, `/` (multiplication, division) +- `-` (unary minus) +- `([expr])` - expressions in brackets + +Operations written on one line have equal priority and are executed in order from left to right if present at the same level in an expression. + +Operations in brackets have priority over other operations. + +Function value calculation has priority over all operations. + +A numeric expression whose value is not `0` is considered true. When the value is `0`, the expression is considered false. For the "true" value, it's strongly recommended to use `1` for compatibility with logical operations and functions returning logical values. + +:::note[5.7.0] +In older player versions, the priority order was different. + +- `&` +- `OR` +- `AND` +- `OBJ`, `LOC`, `NO` +- `=`, `<`, `>`, `!`, `<>`, `<=`, `>=`, `=<`, `=>` +- `+`, `-` +- `MOD` +- `*`, `/` +- `+`, `-` (unary) + +::: + +**Some features of comparison operations:** + +- Comparison operations return `1` (true) or `0` (false) depending on the comparison result. +- When comparing numbers, everything is simple: + - of two positive numbers, the positive number with greater magnitude will be considered greater; + - a negative number is always less than a non-negative (positive and zero); + - a positive number is always greater than a non-positive (negative and zero); + - of two negative numbers, the negative number with greater magnitude will be considered smaller. +- When comparing strings, character-by-character comparison occurs from left to right: + - the character that comes later in the character table is considered greater. You can rely on alphabetical sequence of characters to understand which string will be greater. Then character '`z`' will be greater than character '`a`'. Examples: + + ```qsp + 'z' > 'a' & ! returns 1 + 'z' > 'az' & ! returns 1 + 'akz' > 'akk' & ! returns 1 + ``` + + - when comparing any non-empty string with an empty string, the empty string will be considered smaller: + + ```qsp + ' ' > '' & ! returns 1 + 'a' > '' & ! returns 1 + 'z' > '' & ! returns 1 + 'akzakz' > 'akzak' & ! returns 1 + ``` + + :::tip[You can consider] + that missing characters in a string are empty characters (empty strings), which when compared with any other character turn out to be smaller. + ::: + + - when comparing a string with a number, the player will try to convert both values to numbers. If successful, numbers will be compared. If unsuccessful — the number will be converted to a string, and strings will be compared. + + ```qsp + 'zzz' > 123 & ! returns 1 + '123' > 92 & ! returns 1 + '123' > '92' & ! returns 0 + ``` + +- When comparing tuples, element-by-element comparison occurs from left to right: + - the tuple whose element turned out to be greater will be considered greater: + + ```qsp + [1, 2, 3] > [1, 2, 2] & ! returns 1 + [2, 2, 3] > [1, 2, 3] & ! returns 1 + ``` + + - when comparing any non-empty tuple with an empty tuple, the empty tuple will be considered smaller: + + ```qsp + [1] > [] & ! returns 1 + [''] > [] & ! returns 1 + [0] > [] & ! returns 1 + [1, 2] > [1] & ! returns 1 + [1, 2] < [9] & ! returns 1 + ``` + + :::tip[You can consider] + that missing elements in a tuple are empty elements, which when compared with any other element turn out to be smaller. + ::: + + - when comparing tuples with numbers or strings, the number or string will be compared as a tuple of one element. For easier understanding, you can consider that the number or string is converted to a tuple when compared: + + ```qsp + [8] < 9 & ! returns 1 + [9, 8] > 9 & ! returns 1 + [0, 0] > 9 & ! returns 0 + + [8, 9] > '8,9' & ! returns 0 + ['a', 'z'] < 'az' & ! returns 1 + ['a', 'z'] > 'a' & ! returns 1 + (['az'] = "az") & ! returns 1 + ``` + +:::warning[We recommend:] +Not to compare values of different types to avoid confusion. +::: + +## `*` (multiplication) + +`*` — arithmetic operation "MULTIPLICATION". Multiplies two numbers. General syntax: + +```qsp +[#expression 1] * [#expression 2] +``` + +, where `[#expression 1]` and `[#expression 2]` — any two numeric values or expressions. The operation result is the product of two numbers. + +Examples: + +```qsp +2 * 2 & ! returns 4 +4 * 2 & ! returns 8 +17 * 5 & ! returns 85 +37 * 100 & ! returns 3700 +``` + +Can be used with tuples whose values are numbers and/or other tuples containing numbers. General syntax: + +```qsp +[%tuple] * [#number] +``` + +In this case, each tuple element will be multiplied by the specified number. Examples: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple * 2 +! %a will equal [8, 20, 32] + +[4, 10] * 'b' & ! data type mismatch error +``` + +Note the last example. A data type mismatch error occurs because it's impossible to apply multiplication to a string value. The same error will occur if the tuple contains string values. However, you can multiply tuples containing only numeric values: + +```qsp +*pl [2, 3] * [4, 5] +! [2 * [4,5], 3 * [4,5]] +! [[8,10],[12,15]] +``` + +In this case, each element of the first tuple is multiplied by the second tuple. This gives us a new tuple of two tuples as a result. + +## `*=` (multiplication-assignment) + +`*=` — "MULTIPLICATION-ASSIGNMENT" operation. Combines assignment and multiplication operations. Multiplies the specified variable value by a certain number and returns the result to the same variable. General syntax: + +```qsp +ARRAY_NAME *= [#expression 1] +``` + +, where `ARRAY_NAME` — variable name (without quotes) or array name with cell specification, and `[#expression 1]` — any numeric value or expression. + +Analogous to: + +```qsp +ARRAY_NAME = ARRAY_NAME*[#expression 1] +``` + +Example: + +```qsp +! we replace two operations: assignment and multiplication +warrior = warrior * 2 +! with multiplication-assignment (identical action) +warrior *= 2 +``` + +If the `ARRAY_NAME` variable value is a tuple, each tuple element will be multiplied by the specified number, and the resulting tuple will be assigned to the variable. Example: + +```qsp +%tuple = [4, 10, 16] +%tuple *= 2 +! %tuple will equal [8, 20, 32] +``` + +You cannot multiply by a string type value; this will lead to a data type mismatch error. Also, tuple values (and all nested tuples) should not contain string values when performing this operation. However, you can perform multiplication-assignment with another tuple: + +```qsp +%tuple = [2, 3] +%tuple *= [4, 5] +! %tuple will equal [[8,10],[12,15]] +``` + +:::warning[Note] +Multiplication-assignment with a tuple will cause a data type mismatch error if the variable type is not a tuple: + +```qsp +number = 4 +number *= [4,5] & ! data type mismatch error +! this way there will be no error, but the variable will contain an empty tuple: +%number *= [4,5] +``` + +::: + +## `+` (addition) + +`+` — arithmetic operation "ADDITION". Adds two numbers. General syntax: + +```qsp +[expression 1]+[expression 2] +``` + +, where `[expression 1]` and `[expression 2]` — any two values or expressions. The operation result is the sum of two values. + +Examples: + +```qsp +2+2 & ! returns 4 +4+2 & ! returns 6 +17+5 & ! returns 22 +37+100 & ! returns 137 +``` + +When "adding" string values, [concatenation](qsp-keyword-operacion.md#-concatenation) is performed, i.e., "gluing" strings together: + +```qsp +! the string "2627" will be output to screen +"26"+"27" +``` + +If values are "added" to a tuple, each tuple element is summed with the specified value: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple + 2 +! %a will equal [6, 12, 18] +``` + +If two tuples are added, the second tuple is added to the values of each element of the first tuple: + +```qsp +[4, 10] + ['b', 'x'] +! [4 + ['b', 'x'], 10 + ['b', 'x']] +! [['4b','4x'], ['10b','10x']] +``` + +## `+=` (addition-assignment) + +`+=`, `(increment)` — "INCREMENT" operation, combining assignment and addition operations. Adds the specified value to the current variable value. General syntax: + +```qsp +ARRAY_NAME += [expression 1] +``` + +, where `ARRAY_NAME` — variable name (without quotes) or array name with cell specification, and `[expression 1]` — any value or expression. + +Analogous to: + +```qsp +ARRAY_NAME = ARRAY_NAME + [expression 1] +``` + +Example: + +```qsp +! we replace two operations: assignment and addition +warrior = warrior + 15 +! with increment (identical action) +warrior += 15 +``` + +It's also possible to perform increment with string values, works like [concatenation](qsp-keyword-operacion.md#-concatenation): + +```qsp +$text += " (maybe something is written here)" +``` + +If the `ARRAY_NAME` variable value is a tuple, each tuple element will be summed with the specified value, and the resulting tuple will be assigned to the variable. Example: + +```qsp +%tuple = [4, 10, 16] +%tuple += 2 +! %tuple will equal [6, 12, 18] +``` + +You can perform addition-assignment with another tuple: + +```qsp +%tuple = [2, 3] +%tuple += [4, 5] +! %tuple will equal [[6,7],[7,8]] +``` + +:::warning[Note] +Addition-assignment with a tuple will cause a data type mismatch error if the variable type is not a tuple: + +```qsp +number = 4 +number += [4,5] & ! data type mismatch error +! this way there will be no error, but the variable will contain an empty tuple: +%number += [4,5] +``` + +::: + +:::tip[Note] +Increment — in many programming languages this is an operation that performs variable increase. Most often, increment means increasing a variable by `1`. +::: + +## `-` (subtraction) + +`-` — arithmetic operation "SUBTRACTION". Subtracts one number from another. General syntax: + +```qsp +[#expression 1] - [#expression 2] +``` + +, where `[#expression 1]` and `[#expression 2]` — two numeric values or expressions. The operation result is the difference of two values. + +Examples: + +```qsp +2 - 2 & ! returns 0 +4 - 2 & ! returns 2 +17 - 5 & ! returns 12 +37 - 100 & ! returns -63 +``` + +Can be used with tuples whose values are numbers and/or other tuples containing numbers. General syntax: + +```qsp +[%tuple] - [#number] +``` + +In this case, the specified number will be subtracted from each tuple element. Examples: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple - 2 +! %a will equal [2, 8, 14] + +[4, 10] - 'b' & ! data type mismatch error +``` + +Note the last example. A data type mismatch error occurs because it's impossible to apply subtraction to a string value. The same error will occur if the tuple contains string values. However, you can subtract one tuple from another if both tuples contain only numeric values: + +```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]] +``` + +In this case, the second tuple is subtracted from each element of the first tuple. If you sequentially expand brackets and perform all necessary mathematical operations, you get a new tuple containing other tuples with results. + +## `-=` (subtraction-assignment) + +**`-=`, `(decrement)`** — "DECREMENT" operation, combining assignment and subtraction operations. Subtracts the specified value from the current variable value. General syntax: + +```qsp +ARRAY_NAME -= [#expression 1] +``` + +, where `ARRAY_NAME` — variable name (without quotes) or array name with cell specification, and `[#expression 1]` — any numeric value or expression. + +Analogous to: + +```qsp +ARRAY_NAME = ARRAY_NAME - [#expression 1] +``` + +Example: + +```qsp +! we replace two operations: assignment and subtraction +warrior = warrior - 15 +! with decrement (identical action) +warrior -= 15 +``` + +If the `ARRAY_NAME` variable value is a tuple, the specified number will be subtracted from each tuple element, and the resulting tuple will be assigned to the variable. Example: + +```qsp +%tuple = [4, 10, 16] +%tuple -= 2 +! %tuple will equal [2, 8, 14] +``` + +You cannot subtract a string type value; this will lead to a data type mismatch error. Also, tuple values (and all nested tuples) should not contain string values when performing this operation. However, you can perform subtraction-assignment with another tuple: + +```qsp +%tuple = [2, 3] +%tuple -= [4, 5] +! %tuple will equal [[-2,-3],[-1,-2]] +``` + +:::warning[Note] +Subtraction-assignment with a tuple will cause a data type mismatch error if the variable type is not a tuple: + +```qsp +number = 4 +number -= [4,5] & ! data type mismatch error +! this way there will be no error, but the variable will contain an empty tuple: +%number -= [4,5] +``` + +::: + +:::tip[Note] +Decrement — in many programming languages this is an operation that performs variable decrease. Most often, decrement means decreasing a variable by `1`. +::: + +## `-` (unary minus) + +**unary `-`** — unary operation. General syntax: + +```qsp +-[#expression] +``` + +, where `[#expression]` — any numeric value or expression. The result of this operation is the same value but with opposite sign. + +Examples: + +```qsp +-2 & ! returns -2 +-(3+6) & ! returns -9 +-(-27) & ! returns 27 +``` + +Unary minus can be used before a tuple containing only numeric values. This expression will return a new tuple where the sign of each element is changed to opposite: + +```qsp +- [2, 3, -1, -17, 5] +! [-2, -3, 1, 17, -5] +``` + +:::note[5.7.0] + +In earlier player versions, there was a "unary plus" operation: + +```qsp ++(6+7) +``` + +Essentially, it did nothing, so it was decided to abandon it. +::: + +## `/` (division) + +`/` — arithmetic operation "DIVISION". General syntax: + +```qsp +[#expression 1] / [#expression 2] +``` + +, where `[#expression 1]` and `[#expression 2]` — any two numeric values or expressions. The value `[#expression 2]` must not equal zero. The operation result is the quotient of dividing two numbers. + +Since QSP supports only integer values, division is also performed as integer division, without rounding, with truncation of the fractional part. + +Examples: + +```qsp +2 / 2 & ! returns 1 +4 / 2 & ! returns 2 +17 / 5 & ! returns 3 +37 / 100 & ! returns 0 +``` + +Can be used with tuples whose values are numbers and/or other tuples containing numbers. General syntax: + +```qsp +[%tuple] / [#number] +``` + +In this case, each tuple element will be divided by the specified number. Examples: + +```qsp +%tuple = [4, 10, 16] +%a = %tuple / 2 +! %a will equal [2, 5, 8] + +[4, 10] / 'b' & ! data type mismatch error +``` + +Note the last example. A data type mismatch error occurs because it's impossible to apply division to a string value. The same error will occur if the tuple contains string values. However, you can divide tuples containing only numbers: + +```qsp +*pl [30, 60] / [2, 6] +! [30 / [2,6], 60 / [2,6]] +! [[15,5],[30,10]] +``` + +In this case, each element of the first tuple is "divided" by the second tuple. This gives us a new tuple of two tuples as a result. + +## `/=` (division-assignment) + +`/=` — "DIVISION-ASSIGNMENT" operation. Combines assignment and division operations. Divides the specified variable value by a certain number and returns the result to the same variable. General syntax: + +```qsp +ARRAY_NAME /= [#expression 1] +``` + +, where `ARRAY_NAME` — variable name (without quotes) or array name with cell specification, and `[#expression 1]` — any numeric value or expression. + +Analogous to: + +```qsp +ARRAY_NAME = ARRAY_NAME / [#expression 1] +``` + +Example: + +```qsp +! we replace two operations: assignment and division +warrior = warrior / 2 +! with division-assignment (identical action) +warrior /= 2 +``` + +If the `ARRAY_NAME` variable value is a tuple, each tuple element will be divided by the specified number, and the resulting tuple will be assigned to the variable. Example: + +```qsp +%tuple = [4, 10, 16] +%tuple /= 2 +! %tuple will equal [2, 5, 8] +``` + +You cannot divide by a string type value; this will lead to a data type mismatch error. Also, tuple values (and all nested tuples) should not contain string values when performing this operation. However, you can perform division-assignment with another tuple: + +```qsp +%tuple = [10, 30] +%tuple /= [5, 2] +! %tuple will equal [[2,5],[6,15]] +``` + +:::warning[Note] +Division-assignment with a tuple will cause a data type mismatch error if the variable type is not a tuple: + +```qsp +number = 4 +number /= [4,5] & ! data type mismatch error +! this way there will be no error, but the variable will contain an empty tuple: +%number /= [4,5] +``` + +::: + +## MOD + +`MOD` — operation calculates the remainder from dividing two numbers. General syntax: + +```qsp +[#expression 1] MOD [#expression 2] +``` + +, where `[#expression 1]` — dividend, `[#expression 2]` — divisor. + +Examples: + +```qsp +! 4 divides by 2 evenly +4 mod 2 & ! returns 0 +! 5 doesn't divide by 2 evenly +5 mod 2 & ! returns 1 +! 13 doesn't divide by 10 evenly +13 mod 10 & ! returns 3 +``` + +The remainder from dividing a negative number will be a negative number. + +## `<` (less than) + +`<` — comparison operation "LESS THAN". General syntax: + +```qsp +[expression_1] < [expression_2] +``` + +If the value of expression `[expression_1]` is less than the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns `0`. In other words: true if the first is less than the second. + +Examples: + +```qsp +! 2 is less than 4 — returns 1 +2 < 4 +! 5 is not less than 5 — returns 0 +5 < 5 +! 7 is not less than 3 — returns 0 +7 < 3 +``` + +You can compare text values: + +```qsp +"a" < "z" & ! true +"z" < "zz" & ! true +"aaaaaa" < "z" & ! true +``` + +And you can compare tuples: + +```qsp +[1, 2, 3] < [1, 2, 9] & ! true +[1, 2, 3] < [2, 2, 3] & ! true +[1, 2] < [1, 2, 3] & ! true +``` + +## `<=` (less than or equal) + +`<=` — comparison operation "LESS THAN OR EQUAL". General syntax: + +```qsp +[expression_1] <= [expression_2] +``` + +If the value of expression `[expression_1]` is less than or equal to the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns `0`. In other words: true if the first is less than the second, or equal to it. + +Examples: + +```qsp +! 2 is less than 4 — returns 1 +2 <= 4 +! 5 equals 5 — returns 1 +5 <= 5 +! 7 is not less than three and not equal to it +7 <= 3 & ! returns 0 +``` + +Analogous to "`=<`" and constructs: + +```qsp +([expression_1] < [expression_2]) or ([expression_1] = [expression_2]) + +no [expression_1] > [expression_2] +``` + +You can also compare text values: + +```qsp +"a" <= "z" & ! true +"z" <= "zz" & ! true +"aaaaaa" <= "z" & ! true +"z" <= "z" & ! true +``` + +And tuples: + +```qsp +[1, 2, 3] <= [1, 2, 9] & ! true +[1, 2, 3] <= [2, 2, 3] & ! true +[1, 2] <= [1, 2, 3] & ! true +[1, 2, 3] <= [1, 2, 3] & ! true +``` + +## `<>` (not equal) + +`<>` — comparison operation "NOT EQUAL". General syntax: + +```qsp +[expression_1] <> [expression_2] +``` + +If the value of expression `[expression_1]` is not equal to the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns `0`. In other words: true if the expressions are not equal. + +Analogous to "`!`", or construct: + +```qsp +no [expression_1] = [expression_2] +``` + +Examples: + +```qsp +! 2 is not equal to 4 — returns 1 +2 <> 4 +! 5 equals 5 — returns 0 +5 <> 5 +``` + +You can compare string values: + +```qsp +"abc" <> "def" & ! returns 1 +"abc" <> "abc" & ! returns 0 +``` + +You can compare tuples: + +```qsp +[1, 2, 3] <> [4, 6, 7] & ! returns 1 +[1, 2, 3] <> [1, 2, 3] & ! returns 0 +``` + +## `=` (equal) + +`=` — comparison operation "EQUAL". General syntax: + +```qsp +[expression_1] = [expression_2] +``` + +If the value of expression `[expression_1]` equals the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns `0`. In other words: true if the expressions are equal. + +Analogous to construct: + +```qsp +no [expression_1] <> [expression_2] +``` + +Examples: + +```qsp +! 2 is not equal to 4 — returns 0 +(2 = 4) +! 5 equals 5 — returns 1 +(5 = 5) +``` + +You can compare string values: + +```qsp +("abc" = "def") & ! returns 0 +("abc" = "abc") & ! returns 1 +``` + +You can compare tuples: + +```qsp +([1, 2, 3] = [4, 6, 7]) & ! returns 0 +([1, 2, 3] = [1, 2, 3]) & ! returns 1 +``` + +:::warning[Attention!] +Don't confuse with the [assignment operation](#-assignment). +::: + +## `=` (assignment) + +`=` — assignment operation. General syntax: + +```qsp +ARRAY_NAME = [value] +``` + +, where `ARRAY_NAME` — variable name (not in quotes) or array name with cell specification (not in quotes), `[value]` — any value or expression. + +Examples: + +```qsp +! assign value 13 to variable BOX +BOX = 13 +! assign value "Text string" to variable $text +$text = "Text string" +! assign value 365 to zero cell of array day +day[0] = 365 +! assign tuple [1, 'unit', 3] to variable tuple: +%tuple = [1, 'unit', 3] +``` + +String variable/array names must start with the `$` symbol. + +Variable/array names containing tuples must start with the `%` symbol. + +:::warning[Attention!] +The assignment operation should not be confused with the "EQUAL TO" comparison operation, although they look very similar: + +```qsp +! assignment operation +alukard = 1000 +! comparison operation +(alukard = 1000) +``` + +In this case, the player understands that inside the brackets is a comparison operation because brackets are used for writing expressions. The notation: + +```qsp +"abc" = "abc" +``` + +is syntactically incorrect. The player will give an error: invalid variable/array name. Since in this case it doesn't understand that this is a comparison operation. + +If an operator explicitly precedes the comparison operation, brackets can be omitted: + +```qsp +if alukard = 150: *pl "Not enough strength" +*pl "abc" = "abc" +``` + +::: + +### Multiple Assignment + +Multiple assignment allows assigning values to several variables or array cells with one `=` command. General syntax: + +```qsp +ARRAY_NAME_1, ARRAY_NAME_2, ... , ARRAY_NAME_N = [VALUE_1], [VALUE_2], ... , [VALUE_N] +``` + +, where variable names (or array names with cell index specification in square brackets) are written to the left of the `=` sign, and values to be assigned to variables or array cells are listed to the right of the `=` sign. + +:::warning[Important to remember!] +There must be as many variables to the left of the equals sign as there are values to the right. The number of variables and the number of assigned values must match. + +This rule is not followed when unpacking tuples. +::: + +Examples: + +```qsp +apples_in_pocket, apples_in_basket, apples_at_lyoshka = 58, 11, 19 +$string_1, $string_2 = 'Grekha rode across the river', 'Grekha sees a crab in the river' +$name, count = 'Old sword', 2 +``` + +Instead of directly specifying values, you can assign values of other variables, expressions, functions: + +```qsp +! three variables = three values +red, green, blue = rand(0,255), rand(0,255), rand(0,255) +! two variables = two values +apples_in_pocket, apples_in_basket = apples_at_lyoshka, apples_on_tree+15 +``` + +Thanks to the ability to simultaneously assign values to several variables, you can swap data in two variables without using a third: + +```qsp +! assign variables x and y values 12 and 99 +x, y = 12, 99 +! swap values. Now x contains number 99, and y — 12 +x, y = y, x +``` + +### Tuple Unpacking + +Since tuples contain several values at once, the notation for assigning values to variables from tuples can differ from the usual: + +```qsp +! %unit = [187, 94, 'steel', [0, 2]] +height, weight, $material, %coordinates = %unit +``` + +As you can see, here we have four variable names on the left, but only one tuple variable name on the right. Such assignment is called unpacking — values are extracted from the tuple and placed in the specified variables. + +A tuple not placed in a variable is unpacked the same way: + +```qsp +height, weight, $material, %coordinates = [187, 94, 'steel', [0, 2]] +``` + +Such notation differs little from multiple assignment, so external square brackets are not required: + +```qsp +height, weight, $material, %coordinates = 187, 94, 'steel', [0, 2] +``` + +It should be emphasized that **multiple assignment is essentially tuple unpacking**. + +Since if there are more variables to the left of the equals sign than values in the tuple, default values for those variables will be written to the "extra" variables, the same will happen with multiple assignment. + +```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 +``` + +At the same time, if there are fewer variables to the left of the equals sign than values to the right in multiple assignment, this will cause a data type mismatch error: + +```qsp title="Data type mismatch" +coords = 23, 34 +age, weight, material = 27, 94, 'steel', 'biorobot' +``` + +If the type of the last listed variable is a tuple, such assignment won't cause an error: + +```qsp +age, weight, %type = 27, 94, 'steel', 'biorobot' +! age = 27, weight = 94, %type = ['steel', 'biorobot'] +``` + +## `=<` (equal or less) + +:::warning[Attention!] +This notation, although acceptable in QSP, is not recommended for use. Use "`<=` (less than or equal)" instead. +::: + +`=<` — comparison operation "EQUAL OR LESS". General syntax: + +```qsp +[expression_1] =< [expression_2] +``` + +If the value of expression `[expression_1]` is less than or equal to the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns 0. In other words: true if the first is less than the second, or equal to it. + +Examples: + +```qsp +! 2 is less than 4 — returns 1 +2 =< 4 +! 5 equals 5 — returns 1 +5 =< 5 +! 7 is not less than three and not equal to it +7 =< 3 & ! returns 0 +``` + +Analogous to "`<=`" and constructs: + +```qsp +([expression_1] < [expression_2]) or ([expression_1] = [expression_2]) + +no [expression_1] > [expression_2] +``` + +## `=>` (equal or greater) + +:::warning[Attention!] +This notation, although acceptable in QSP, is not recommended for use. Use "`>=` (greater than or equal)" instead. +::: + +`=>` — comparison operation "EQUAL OR GREATER". General syntax: + +```qsp +[expression_1] => [expression_2] +``` + +If the value of expression `[expression_1]` is greater than or equal to the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns 0. In other words: true if the first is greater than the second, or equal to it. + +Examples: + +```qsp +! 2 is not greater than and not equal to 4 — returns 0 +2 => 4 +! 5 equals 5 — returns 1 +5 => 5 +! 7 is greater than 3 +7 => 3 & ! returns 1 +``` + +Analogous to "`>=`" and constructs: + +```qsp +([expression_1] > [expression_2]) or ([expression_1] = [expression_2]) +no [expression_1] < [expression_2] +``` + +## `>` (greater than) + +`>` — comparison operation "GREATER THAN". General syntax: + +```qsp +[expression_1] > [expression_2] +``` + +If the value of expression `[expression_1]` is greater than the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns `0`. In other words: true if the first is greater than the second. + +Examples: + +```qsp +! 2 is not greater than 4 — returns 0 +2 > 4 +! 5 is not greater than 5 — returns 0 +5 > 5 +! 7 is greater than 3 — returns 1 +7 > 3 +``` + +You can compare text values, where characters are compared sequentially, and the character closer to the end of the alphabet is considered greater. + +```qsp +"z" > "a" & ! true +"zz" > "z" & ! true +"z" > "aaaaaa" & ! true +``` + +And you can compare tuples: + +```qsp +[1, 2, 9] > [1, 2, 3] & ! true +[1, 2, 3] > [2, 2, 3] & ! false +[1, 2, 3] > [1, 2] & ! true +``` + +## `>=` (greater than or equal) + +`>=` — comparison operation "GREATER THAN OR EQUAL". General syntax: + +```qsp +[expression_1] >= [expression_2] +``` + +If the value of expression `[expression_1]` is greater than or equal to the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns 0. In other words: true if the first is greater than the second, or equal to it. + +Examples: + +```qsp +! 2 is not greater than and not equal to 4 — returns 0 +2 >= 4 +! 5 equals 5 — returns 1 +5 >= 5 +! 7 is greater than 3 +7 >= 3 & ! returns 1 +``` + +Analogous to "`=>`" and constructs: + +```qsp +([expression_1] > [expression_2]) or ([expression_1] = [expression_2]) +no [expression_1] < [expression_2] +``` + +You can compare text values, where characters are compared sequentially, and the character closer to the end of the alphabet is considered greater. + +```qsp +"z" >= "a" & ! true +"zz" >= "z" & ! true +"z" >= "aaaaaa" & ! true +"z" >= "z" & ! true +``` + +And tuples: + +```qsp +[1, 2, 9] >= [1, 2, 3] & ! true +[1, 2, 3] >= [2, 2, 3] & ! false +[1, 2] >= [1, 2, 3] & ! false +[1, 2, 3] >= [1, 2, 3] & ! true +``` + +## `!` (not equal) + +:::warning[Attention!] +Don't confuse with the comment operator. + +For better code readability, we recommend using `<>`. +::: + +`!` — comparison operation "NOT EQUAL". General syntax: + +```qsp +[expression_1]![expression_2] +``` + +If the value of expression `[expression_1]` is not equal to the value of expression `[expression_2]`, the operation returns `1`, otherwise it returns `0`. In other words: true if the expressions are not equal. + +Analogous to "`<>`", or construct: + +```qsp +no [expression_1] = [expression_2] +``` + +Examples: + +```qsp +! 2 is not equal to 4 — returns 1 +2 ! 4 +! 5 equals 5 — returns 0 +5 ! 5 +``` + +## `&` (concatenation) + +`&` — concatenation, operation for combining string expressions or tuples. General syntax: + +```qsp +([$expression 1] & [$expression 2]) +([%expression 1] & [%expression 2]) +``` + +:::warning[Attention!] +Concatenation must always be enclosed in brackets! +::: + +If you try to combine numeric values, they will be converted to strings, and then the strings will be combined. + +Examples: + +```qsp +*pl ('hello, ' & 'World!') +! we'll see the string 'hello, World!' on screen +*pl ([1, 2, 3] & [4, 5, 6]) +! we'll see the tuple [1, 2, 3, 4, 5, 6] on screen +``` + +:::warning[Attention!] +Don't confuse with the command enumeration symbol: + +```qsp +! in this case, strings "26" and "27" will be +! output to screen sequentially +"26" & "27" +! and here the string "2627" will be output to screen +("26" & "27") +``` + +::: + +:::tip +It's not recommended to use this operation for combining strings, since strings can be combined through [`+`](qsp-keyword-operacion.md#-addition): + +```qsp +! the string "2627" will be output to screen +"26"+"27" +``` + +Such notation creates less confusion when reading code and works similarly. + +You can't join two tuples into one using the `+` operation: + +```qsp +[2, 5] + [3, 7] +! the tuple [[5,9],[8,12]] will be on screen +``` + +::: + +## AND + +`AND` — logical "AND". General syntax: + +```qsp +[#expression 1] AND [#expression 2] +``` + +The entire expression will be true if both `[#expression 1]` and `[#expression 2]` are true. + +Examples: + +```qsp +! both parts of expression are true, so entire expression is true +(2 = 2) and (3 <> 2) & ! expression returns 1 (true) +! one part of expression is not true, so entire expression is false +(2 <> 2) and (3 <> 2) & ! expression returns 0 (false) +! both parts of expression are not true, so entire expression is not true +(2 <> 2) and (3 = 2) & ! expression returns 0 (false) +``` + +:::note[5.7.0] +In older player versions, the operation was bitwise. +::: + +## LOC + +`LOC` — operation checks for location existence and returns `1` if location exists, and `0` if location doesn't exist. General syntax: + +```qsp +LOC([$location]) +``` + +, where `[$location]` — location name whose existence needs to be checked in the game. Expression is true if location exists in the game. + +Examples: + +```qsp +! checks if location "start" exists in game +loc("start") & ! if location exists, returns 1 + +! if location "street" is not added to game +if loc("street") = 0: + act "Go outside": *pl "I can't go outside, the door won't open." +end +``` + +## NO + +`NO` — negation operation. General syntax: + +```qsp +NO [#expression] +``` + +If `[#expression]` is true, then the entire expression is false, and vice versa. In other words, returns `0` if the expression value is not zero, and returns `1` if the expression value equals `0`. + +Example: + +```qsp +! 4 equals 4 is true, so entire expression is false +no (4 = 4) & ! returns 0 (false) +! can be read as question: four does not equal four? No — false. + +! that 5 equals 3 is false, so entire expression is true +no (5 = 3) & ! returns 1 (true) +! can be read as question: five does not equal three? Yes — true. +``` + +:::note[5.7.0] +In older player versions, the operation was bitwise. +::: + +## OBJ + +`OBJ` — operation checks for item presence in inventory and returns `1` if item exists, and `0` if item doesn't exist. General syntax: + +```qsp +OBJ([$name]) +``` + +, where `[$name]` — item name whose presence needs to be checked in the objects window. Expression is true if item is added to the objects window. + +Examples: + +```qsp +! checks if "Screwdriver" item is added to objects window +obj("Screwdriver") & ! if item exists, returns 1 + +! depending on presence of this or that item +! this or that action is output +if obj("Full jug") = 1: + act "Empty jug": + delobj "Full jug" + addobj "Empty jug" + goto $curloc + end +elseif obj("Empty jug") = 1: + act "Fill jug": + addobj "Full jug" + delobj "Empty jug" + goto $curloc + end +end +``` + +## OR + +`OR` — logical "OR". General syntax: + +```qsp +[#expression 1] OR [#expression 2] +``` + +The entire expression will be true if at least one of expressions `[#expression 1]` and `[#expression 2]` is true. + +Examples: + +```qsp +! both parts of expression are true, so entire expression is true +(2 = 2) or (3 <> 2) & ! expression returns 1 (true) +! one part of expression is true, so entire expression is true +(2 <> 2) or (3 <> 2) & ! expression returns 1 (true) +! both parts of expression are not true, so entire expression is not true +(2 <> 2) or (3 = 2) & ! expression returns 0 (false) +``` + +:::note[5.7.0] +In older player versions, the operation was bitwise. +::: \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md new file mode 100644 index 0000000..906301d --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md @@ -0,0 +1,1573 @@ +--- +id: qsp-keyword-operators +title: Operators +sidebar_position: 2 +--- + +# Operators + +## Implicit Operator + +The implicit operator is an operator that is not written in QSP code but produces output of values to the screen. It is implied everywhere where an expression without an operator is present in a command. The implicit operator outputs values to the **Main Description Window** in the same way as if you used the explicit `*pl` operator, i.e., it outputs the value and makes a line break. Examples: + +```qsp +$AAA + '989' +'You are in the park' +'Preformatted + + string' +$curloc & ! will output the location name to the screen +``` + +Unlike the `*pl` operator, the implicit operator does not output an empty string with a line break to the screen if no value is passed to it. This means that if a function returns no value, the implicit operator is simply ignored. Example: + +```qsp +# start +! this is location code calling a function location +$curloc +$func('foo') +$func('foo') +$curloc +- start + +# foo +! this is function location code +local i = 0 +- foo +``` + +In this case, the `foo` function location returns nothing, so we will see two lines with the word "start" on the screen, with no empty lines between them, since the implicit operator in the lines with `$func` on the `start` location will simply be ignored. Compare with: + +```qsp +# start +! this is location code calling a function location +*pl $curloc +*pl $func('foo') +*pl $func('foo') +*pl $curloc +- start + +# foo +! this is function location code +local i=0 +- foo +``` + +## `!` (comment) + +`!` — comment operator. What is in the line after the comment operator and until the end of the line is ignored by the interpreter. The comment operator allows you to "comment out" (disable) an unnecessary operator/function temporarily during game debugging. Additionally, writing comments to program code is one of the signs of good programming style. + +It's important to clearly understand that this is exactly an operator, so if you're commenting some line of code, the `!` should come after `&`: + +```qsp +*pl "Hello, world!" & ! comment +``` + +Comments can be single-line, i.e., ending on the same line where the comment operator is: + +```qsp +! single-line comment +*pl "text string" & ! also a single-line comment +``` + +:::tip[Exception] +The only exception to this rule is writing a comment after a colon in multi-line operators: + +```qsp +act "Multi-line action": ! comment + *pl "Text on screen" +end +``` + +::: + +Comments can be multi-line. For this, after the comment operator, you need to write quotes, apostrophes, or curly braces. For example: + +```qsp +! "this is the first line of the comment + this is the second line of the comment + this is the third line of the comment +" +``` + +Multi-line comments can take various forms: + +```qsp +! line before quotes " text inside quotes +can go to other lines " as well as { +you can use other groups of symbols to +continue the multi-line comment +} and the comment won't end until the line ends +``` + +## `*CLEAR` + +`*CLEAR` — clears the main description window. Has the short form `*clr`. + +## `*NL` + +`*NL` — line break, then text output in the main description window. General syntax: + +```qsp +*NL [$text] +``` + +, where `[$text]` — any text string, number, or expression of any type. If `[$text]` is absent, just a line break occurs. Example: + +```qsp +*p "Text without line break." +*nl "Line break + text output." +*p "Text without line break." +``` + +## `*P` + +`*P` — text output to the main description window without line break. Text output by any other operator immediately after `*p` will add new text right after the current one. General syntax: + +```qsp +*P [$text] +``` + +, where `[$text]` — any text string, number, or expression of any type. `[$text]` can be an empty string `''`, but must not be absent. Example: + +```qsp +*p "Text without line break." +*p "Text without line break." +*p "" +*p "Text without line break." +``` + +## `*PL` + +`*PL` — text output to the main description window, then line break. General syntax: + +```qsp +*PL [$text] +``` + +where `[$text]` — any text string, number, or expression of any type. `[$text]` can be absent, then just a line break. Example: + +```qsp +*pl "Output text, then line break." +*pl "Output text, then line break." +*p "Text without line break." +*pl "Output text, then line break." +``` + +Similarly, you can output text by simply writing the desired expression instead of this operator. For example, the lines: + +```qsp +*pl $AAA + '989' +*pl 'You are in the park' +*pl 'Preformatted + + string' +``` + +and: + +```qsp +$AAA + '989' +'You are in the park' +'Preformatted + + string' +``` + +will work identically. + +## ACT + +`ACT` — creates and outputs a new action to the actions window. + +General syntax in single-line form: + +```qsp +ACT [$name], [$image_path]: [operator] & [operator] & [operator] +``` + +General syntax in multi-line form: + +```qsp +ACT [$name], [$image_path]: + [operator] + [operator] + [operator] +END +``` + +A new action with the name `[$name]` and image located at `[$image_path]` is added to the actions list in the actions window. When the action is clicked, the specified operators are executed. + +The `[$image_path]` parameter can be absent, in which case the action is added without an image. + +Examples: + +```qsp +! action in single-line form +act "Pick apple from birch": apple += 1 & *pl "You picked an apple, ripe and white." + +! action in multi-line form, with image +act "Pick watermelon from bush", "img/watermelon.png": + watermelon += 1 + *pl "You picked a watermelon from the bush" +end +``` + +If there is already an action with the specified name in the actions list, no new action is created, and it doesn't replace the existing one; the player simply ignores the `act` command. Thus, you cannot output actions with identical names. Example: + +```qsp +act "Action 1": *pl "Old action." +act "Action 1": *pl "New action." +``` + +However, you can simulate actions with identical names in HTML recognition mode by adding HTML tags to action names: + +```qsp +usehtml = 1 +act 'Action 1': *pl "Old action." +act 'Action 1': *pl "New action." +``` +## ADDOBJ + +`ADDOBJ` — adding a new item to the objects window. General syntax: + +```qsp +ADDOBJ [$name], [$image_path], [#position] +``` + +, where `[$name]` — the item name, `[$image_path]` — the path to the item's image file (displayed next to the item name), and `[#position]` — what position in the inventory the item is added to. The `[#position]` parameter can be absent. By default, items are added to the end of the list. Item numbering in the inventory starts from `1`. The `[$image_path]` parameter can be absent, default value is `''`, in which case the item is added without an image. + +:::note[Deprecated but acceptable legacy form:] + +```qsp +ADD OBJ [$name],[$image_path],[#index] +``` + +::: + +You can add items with the same name, however, if you plan to add many identical items, it's better to use an additional variable to count these items and add one item to the objects window to avoid cluttering the inventory with a list of 137 Ruble / Bullet items: + +```qsp +if obj('Bullets'): +! if the "Bullets" item is already added, just increase their number + bullets += 10 +else +! if the "Bullets" item is not yet added, add it and increase the number + addobj 'Bullets' + bullets += 10 +end +``` + +For storing the number of items, you can use arrays indexed by strings: + +```qsp +objects['money'] = 12 +objects['bullets'] = 137 +'Quantity: <>' +``` + +Example of adding an item to the very top of the list (all other items will shift down): + +```qsp +addobj "Screwdriver", "", 1 +``` + +## CLA + +`CLA` - clears the current actions list (removes all actions from the actions window). + +## CLEAR + +`CLEAR` — clears the additional description window. Has the short form `clr`. + +## CLOSE + +`CLOSE` — stops playing the specified sound file. General syntax: + +```qsp +CLOSE [$sound_file_path] +``` + +, where `[$sound_file_path]` — path to the sound file relative to the game file. If the `[$sound_file_path]` parameter is not specified, all sound files stop playing. + +## CLOSE ALL + +`CLOSE ALL` — stops playing all active sound files. Has the short form `close`. + +## CLS + +`CLS` — clears all windows except the objects list. Equivalent to: + +```qsp +clear & *clear & cla & cmdclear +``` + +## CMDCLEAR + +`CMDCLEAR` — clears the input line. Has the short form `cmdclr`. + +## COPYARR + +`COPYARR` — copies the contents of one array to another. General syntax: + +```qsp +COPYARR [$destination], [$source], [#start], [#count] +``` + +, where: `[$destination]` — the array to copy to, size and content don't matter; `[$source]` — the array to copy from; `[#start]` — the element number to start copying from; `[#count]` — how many elements to copy. The `[#count]` parameter is optional; default is until the end of the source array. The `[#start]` parameter is optional; default is 0. + +Examples: + +```qsp +! copy all elements of array '$b' to array '$a' +copyarr '$a', '$b' +! also copied all elements of array 'b' to array 'a' + +! copy elements of array 'd' to array 'c', starting from the sixth +copyarr 'c', 'd', 6 + +! copy the first six elements of array 'd' to array 'c' +copyarr 'c', 'd', 0, 6 +``` + +Due to player specifics, when copying, for example, numeric array `mass1` to `mass2`, the text array `$mass1` is also copied to `$mass2`. + +Other examples: + +```qsp +copyarr $arrname1, $arrname2, 10, 5 +copyarr 'a<<$arrname1>>', 'a<<$arrname2>>' +``` + +## DELACT + +`DELACT` — removes an action from the actions list (if such an action exists). General syntax: + +```qsp +DELACT [$name] +``` + +, where `[$name]` — the name of the action to remove. + +Examples: + +```qsp +! remove action with specific name +delact 'Go forward' +! remove selected action +delact $selact +``` + +:::note[Deprecated but acceptable legacy form:] + +```qsp +DEL ACT [$name] +``` + +::: + +## DELOBJ + +`DELOBJ` — removes an item from inventory by name (if such an item exists). General syntax: + +```qsp +DELOBJ [$name] +``` + +, where `[$name]` — the name of the item to remove. + +If there are identical items in the inventory, the command will remove the topmost one with the specified index. + +Examples: + +```qsp +! remove item with specific name +delobj "Screwdriver" +! remove selected item +delobj $selobj +``` + +:::note[Deprecated but acceptable legacy form:] + +```qsp +DEL OBJ [$name] +``` + +::: + +## DYNAMIC + +`DYNAMIC` — executes code passed as a text string. General syntax: + +```qsp + DYNAMIC([$code], [argument 0], [argument 1], ... , [argument 18]) +``` + +, where `[$code]` — regular QSP code written as text. Executing such code is analogous to executing `GOSUB` operator code. Arguments `[argument 0]`, `[argument 1]`, etc. can be used inside `[$code]`, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After execution, old `args` parameters are restored, then code execution continues from the next command after `dynamic`. + +Examples: + +```qsp +dynamic '$a = "string<<$b>>"' +dynamic '$a' +dynamic 'if $a = "string": "text!"' +dynamic " + $args[0] + addobj $args[1] +", 'Text', 'Fork' +``` + +The following information is also valid for the [`dyneval`](qsp-keyword-functions.md#dyneval) function. + +**Important!** If code is specified using apostrophes (`''`) or quotes (`""`), sub-expressions are calculated in the text: + +```qsp +$args[0] = 'qwerty' +$code = ' + *pl "<<$args[0]>>" + *pl $args[0] +' + +dynamic $code, 'asdfg' +``` + +In this case, when setting the `$code` variable, the sub-expression will be calculated, so 'qwerty' will be output on the first line, and 'asdfg' on the second line. + +Curly braces are the third type of quotes used specifically for writing dynamic code. Here, bracket nesting is supported, and sub-expressions are not calculated before code execution: + +```qsp +$args[0]='qwerty' +$code = { + *pl "<<$args[0]>>" + *pl $args[0] +} + +dynamic $code, 'asdfg' +``` + +In this case, two lines 'asdfg' will be output. + +## EXIT + +`EXIT` — terminates execution of the current code block (premature exit from a subroutine, function, event handler, etc.). + +A code block can be a location, action, code passed to `dynamic` or `dyneval`, or code in a hyperlink. + +Example: + +```qsp +if args[1] = 0: + exit +else + if args[0] mod args[1] = 0: + result = 1 + else + result = 0 + end +end +``` + +:::warning[Attention!!!] +In players version 5.8.0, the `loop` cycle operator appeared. + +The loop body is also considered a separate code block, however, the `exit` operator interrupts not only the loop itself but also the code block in which the loop is located. +::: + +## FREELIB + +`FREELIB` — removes all locations added with the `inclib` operator. + +:::note[5.7.0] +In older player versions, the command was called `dellib` and `killqst`. +::: + +## GOSUB + +`GOSUB` — executes code of the specified location without direct transition to it. + +General syntax: + +```qsp +GOSUB [$location],[argument 0],[argument 1], ... ,[argument 8] +``` + +, where `[$location]` — the name of the location whose code we want to execute without direct transition to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After processing the location, previous `args` values are restored. Using arguments is not mandatory. + +When calling a location via `gosub`, the base description of the location is added to the current description, base actions are added to current actions, and operators in the "Execute on visit" field are executed, then return to the original line (continue code execution after `gosub`). + +Examples of calling locations via `gosub`: + +```qsp +!processing location "move". The args[] array is empty. +gosub 'move' + +!processing location with name from variable $location +!One parameter is passed - args[0] equals 1. +gosub $location,1 + +!processing location "move" with 3 parameters passed. +! $args[0] = $var (value), args[1] = 2, +! $args[2] = "data". Note the '$' symbols. +gosub 'move',$var,2,'data' +``` + +Another example: + +```qsp +! this is code calling location "transition" +gosub 'transition', 'location' + +! and this is code of the "transition" location itself +# transition +*pl $args[0] & ! the text 'location' will be output to the screen +! a new action will appear in the actions window: +act 'go': + goto "street" +end +- transition +``` + +The operator has a short form `gs`: + +```qsp +GS [$location], [argument 0], [argument 1], ... , [argument 18] +``` + +## GOTO + +`GOTO` — transition to the specified location. General syntax: + +```qsp +GOTO [$location], [argument 0], [argument 1], ... , [argument 18] +``` + +, where `[$location]` — the name of the location to transition to. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. Using arguments is not mandatory. + +When transitioning to a new location using `goto`, the main description window is cleared, as well as the current actions list, then the base description text is output to the main description window, base actions to the actions window, and code from the "Execute on visit" field of location `[$location]` is executed. Also, when transitioning to a new location, the value returned by the `$curloc` function changes. + +Examples: + +```qsp +! transition to location "house". +! The args array at location "house" will be empty. +goto 'house' + +! transition to location "street" with 2 parameters passed. +! at location "street" args[0] equals 1, +! $args[1] contains the string "data". +goto 'street',1,'data' +``` + +The operator has a short form `gt`: + +```qsp +GT [$location],[argument 0],[argument 1], ... ,[argument 8] +``` + +## IF + +`IF` — the main operator for writing conditional constructs. Constructs written using this operator (let's call them "simple conditions") have two forms: single-line and multi-line, — and generally look like this: + +General syntax: + +```qsp +! single-line form +IF [#expression]: {command 1} & {command 2} & ... + +! multi-line form +IF [#expression]: + {command 1} + {command 2} + ... +END +``` + +In this case, if the condition `[#expression]` is true, commands `{command 1}`, `{command 2}`, etc. are executed. + +- For **single-line form**, these will only be those commands that are on the same line as the `IF` operator until the end of the line; +- and for **multi-line form**, these will be those commands that are in subsequent lines after the colon and until the special keyword `END`. + +Comparison operations, logical operations, and other expressions returning numeric values can serve as conditions. + +The `END` keyword in multi-line form must be on a separate line. + +If the condition `[#expression]` is not true, the commands will not be executed. + +Examples of single-line conditional forms: + +```qsp +! if the sum of a and b equals two, +! variable c is assigned the value 30 +if a + b = 2: c = 30 +! If there's no orange in inventory, text is output +if no obj("Orange"): pl "You don't have an orange." +! this is also a simple single-line form +if ((a+b)/c)=45+54 or (b<5 or c>45) and no obj 'shovel' and $f=$vvv+'RRRRR': p 'OK' & goto 'Next' +``` + +Examples of multi-line conditional forms: + +```qsp +if library = 0: + learned_about_party = 0 + library_returned = 1 + gt 'library' +end +if a+b=2: + c=30 +end +``` + +:::warning[Pay attention!!!] + +In multi-line form, no commands should follow the colon on the same line as the IF operator, otherwise the player will consider such a conditional operator single-line, and commands in subsequent lines will be executed regardless of whether the condition is true or not. Example of such erroneous notation: + +```qsp +if library = 0: learned_about_party = 0 + library_returned = 1 &! this line will execute regardless of condition truth + gt 'library' &! and this one too +end &! the end keyword is simply ignored +``` + +The exception is a comment operator written after the colon: + +```qsp +if library = 0: ! if haven't visited library + learned_about_party = 0 + library_returned = 1 + gt 'library' +end +``` + +But if the comment is separated by an ampersand, the condition will be considered single-line: + +```qsp +if library = 0: & ! such a comment makes the condition single-line! + learned_about_party = 0 & ! this line will execute regardless of condition truth + library_returned = 1 & ! and this one + gt 'library' &! and this one too +end &! the end keyword is simply ignored +``` + +::: + +For multi-line forms, unlimited nesting depth is allowed. Each nesting level must end with its own `end` line. + +Examples: + +```qsp +if a+b<3 or y=8: + p 'A+B<3 or Y=8' + nl + if j=88: nl & p 'NEXT' + if $h='ooo': + p 'loo' & jump 'lll' + end +end +``` + +```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 +``` + +Several examples of incorrect notation: + +```qsp {4} +! in this case, if the condition is not met, +! the player will ignore only the command `k1=34` +! since it will consider this a single-line condition +if abcd=3: k1=34 + k2=35 & ! this command will always execute + k3=36 & ! this command will always execute +end & ! this end will be ignored +``` + +```qsp {3,9} +! this line will output an error unknown action +! since single-line forms should not end with end +if abcd=3: k1=34 else k1=25 end +``` + +## ELSE + +`ELSE` — keyword used together with the `IF` operator, which serves to provide an alternative if the condition is not met. The `ELSE` keyword also has two forms: single-line and multi-line. + +- Multi-line form of `ELSE` can only be used in multi-line `IF` constructs, +- single-line form can be used in both single-line and multi-line `IF` constructs. General syntax: + +```qsp +! single-line form +IF [#expression]: {command y1} & {command y2} & ... ELSE {command n1} & {command n2} & ... + +! in multi-line IF: + +! multi-line ELSE form +IF [#expression]: + {command y1} + {command y2} + ... +ELSE + {command n1} + {command n2} + ... +END + +! single-line ELSE form +IF [#expression]: + {command y1} + {command y2} + ... +ELSE {command n1} & {command n2} & ... + ! commands in subsequent lines + ! until END are ignored +END +``` + +Here, if condition `[#expression]` is true, commands from the colon to the `ELSE` keyword are executed, and if condition `[#expression]` is not true, commands from the `ELSE` keyword to the end of the conditional construct are executed. + +You can put a colon after `ELSE` or not. + +**For single-line form:** + +- both commands and the `ELSE` keyword must be written on one line +- the end of the alternative command list is the end of the line. +- if single-line `ELSE` form is used in multi-line `IF` form, all commands in subsequent lines after `ELSE` until `END` are ignored. + +Single-line examples: + +```qsp +! if the sum of a and b equals two, variable c is assigned value 30 +! otherwise (i.e., if the sum of a and b does not equal two) +! variable c is assigned value 10 +if a+b=2: c=30 else c=10 + +! depending on whether there's an orange in inventory +! corresponding text is output +if obj("Orange"): pl "You have an orange." else pl "You don't have an orange." + +! single-line else form inside multi-line if +if $left_hand = 'Great sword': + gosub 'attack', 300 + gosub 'health.prove' + gosub 'win.prove' +else gosub 'attack', attack_power +end +``` + +**For multi-line form:** + +- all commands must be in subsequent lines after `ELSE`; + +Multi-line examples: + +```qsp +if a+b=2: + c=30 +else + c=10 +end + +if obj("Orange"): + pl "You have an orange." +else + pl "You don't have an orange." +end + +if len($curtoken) > 0: + $tokens[curtoken_num] = $curtoken tokens_count = curtoken_num + 1 +else + tokens_count = curtoken_num +end +``` + +## ELSEIF + +`ELSEIF` — keyword used together with the `IF` operator and allows defining sequentially-exclusive conditions at one nesting level. Has single-line and multi-line forms. + +- Multi-line form can only be used in multi-line `IF` constructs, +- single-line — in both multi-line and single-line `IF` constructs. + +General syntax: + +```qsp +! single-line in single-line condition +IF [#expression 1]: {command set 1} ELSEIF [#expression 2]: {command set 2} ELSE {last command set} + +! multi-line in multi-line condition +IF [#expression 1]: + {command set 1} + ... +ELSEIF [#expression 2]: + {command set 2} + ... +ELSEIF ... : + ... +ELSE + {last command set} + ... +END + +! single-line in multi-line condition +IF [#expression 1]: + {command set 1} + ... +ELSEIF [#expression 2]: {command set 2} +ELSEIF ... : ... +ELSE {last command set} +END +``` + +This works as follows. If `[#expression 1]` is true, `{command set 1}` is executed. If `[#expression 1]` is false but `[#expression 2]` is true, `{command set 2}` is executed, and so on. Only if all expressions in the current conditional construct are false, the commands after `ELSE` will be executed. The truth of expression `[#expression 1]` does not exclude the truth of expression `[#expression 2]`, but the truth of expression `[#expression 2]` excludes the truth of expression `[#expression 1]`. + +`ELSEIF` notation features: + +- The variant `ELSE IF` can be used. Works exactly the same. +- If in a multi-line `IF` construct operators follow `ELSEIF` on the same line (single-line form), then all subsequent lines are ignored until the next `ELSEIF`, or until `ELSE` or `END`. +- In an `IF` construct with `ELSEIF`, the `ELSE` part may or may not be present. + +Examples: + +```qsp +if obj('Health Potion'): health += 100 elseif obj('Apple'): health += 15 else *pl 'Nothing to restore strength with!' + +IF SCORE>124: + GOTO 'END3' +ELSEIF SCORE>99: + GOTO 'END4' +ELSE + GOTO 'END5' +END + +if money mod 10=1 and money mod 100<>11: + *pl "You have <> coin." +elseif money mod 10>1 and money mod 10<5 and (money mod 100<5 or money mod 100>20): + *pl "You have <> coins." +elseif money mod 10=0 or money mod 10>4 or (money mod 100>10 and money mod 100<21): + *pl "You have <> coins." +end +``` + +Example of `ELSEIF` notation with operators on the same line: + +```qsp +! switch/case implementation in QSP +if r = 0: + 'Option 0' + elseif r = 1: 'Option 1' + elseif r = 2: 'Option 2' + elseif r = 3: 'Option 3' + else: 'No options' +end +``` + +:::tip[Note:] + +For better code readability, it's recommended to use `elseif` constructs only in multi-line `if` operator form. + +::: + +## INCLIB + +`INCLIB` — from the specified game file, adds all locations whose names are absent among current game locations. Loaded locations are fully equivalent to locations from the main game file. General syntax: + +```qsp +INCLIB [$game_file_path] +``` + +Example: + +```qsp +inclib "lib/easy.math.qsp" +inclib "lib/easy.title.qsp" +inclib "res/drive.qsp" +inclib "res/base.qsp" +inclib "res/intro.qsp" +``` + +:::note[5.7.0] +In older player versions, the command was called `addqst` and `addlib`. +::: + +## JUMP + +`JUMP` — jump within the current code block to the specified label. General syntax: + +```qsp +JUMP [$label] +``` + +, where `[$label]` — a label below or above in the code (see section ["Labels"](qsp-keyword-syntaxems.md#labels-)). + +`jump` finds labels only within the current code block, i.e., labels are local. + +Separate code blocks in QSP are: + +- "Execute on visit" code of a specific location (each location is a separate code block), +- action code even if the action is added programmatically, +- code in hyperlinks, +- `DYNAMIC`/`DYNEVAL` code + +Example: + +```qsp +jump 'End' +p 'This message will not be output' +:end +p 'But this message the user will see' +``` + +:::note[5.7.0] +Using the `jump` operator in older player versions, you could organize loops: + +```qsp +:loop +if s<9: + s=s+1 + pl s + jump 'loop' +end +p 'Done!' +``` + +Double loop with one label: + +```qsp +:loop +if y<9: + if x<9: + *p "<> - " + x=x+1 + jump 'loop' + end + *pl ":<>" + y=y+1 + x=0 + jump 'loop' +end +``` + +Starting from version 5.8.0, a dedicated `loop` operator was introduced for loops. +::: + +## KILLALL + +`KILLALL` — destroys all variables and removes all items from the objects window. Equivalent to: + +```qsp +killvar & killobj +``` + +:::warning[Attention!] +Remember that `killall` is not equivalent to: + +```qsp +killobj & killvar +``` + +since in this case variable values are deleted after item removal, so the item removal handler location code has time to execute (see `$onobjdel`). +::: + +Usually `killall` is used at the beginning of the game if a "Start over" action is provided at the end of the game. + +## KILLOBJ + +`KILLOBJ` — removes an item located at the specified position. General syntax: + +```qsp +KILLOBJ [#number] +``` + +, where `[#number]` — the item number in the inventory window. Item numbering starts from 1. If the `[#number]` parameter is not specified, all items are removed. When removing each item with `killobj`, the item removal handler location code is executed (see `$onobjdel`). + +Example: + +```qsp +! remove the topmost item in the list +killobj 1 +! remove the bottommost item in the list +killobj countobj +! remove all items +killobj +``` + +## KILLVAR + +`KILLVAR` — removes the specified array element. General syntax: + +```qsp +KILLVAR [$array_name], [element_index] +``` + +, where `[$array_name]` — the name of the array from which we want to remove an element, and `[element_index]` — the number, text index, or multi-dimensional index of the array element we want to remove. Array element numbering starts from 0. + +If the element index is not specified, the entire array is cleared. If the operator is called without arguments, all variables and arrays are deleted. + +Examples: + +```qsp +killvar 'a', 3 & ! will remove element with index 3 from array 'a' +killvar 'unit', 'Paratrooper' & ! removes element with index 'Paratrooper' from array +killvar 'a' & ! removes array 'a' +killvar & ! removes all variables, arrays +killvar '$map_cell', (3, 4) & ! removal by multi-dimensional index +``` + +When removing an element, all following elements shift up one position. + +Example: + +```qsp +a[0] = 4 +a[1] = 3 +a[2] = 23 +a[3] = 15 +KILLVAR 'a', 1 +! now the array looks like this: +! a[0] = 4 +! a[1] = 23 +! a[2] = 15 +``` + +## LET + +`LET` — deprecated operator for setting variable values. General syntax: + +```qsp +LET [variable_name] = [expression] +``` + +, where `[variable_name]` — a valid variable name, `[expression]` — a valid value for this variable. + +- Numeric variable names are written without `$` and `%` symbols at the beginning. +- Text variable names are written with the `$` symbol at the beginning. +- Variable names containing tuples are written with the `%` symbol at the beginning. + +Examples: + +```qsp +! set text variable +let $text = "text string" +! set numeric variable +let abs = 123 +! set tuple +let %tuple = [123, "text string"] +``` + +:::tip +This operator is considered deprecated. Use the `set` operator instead, and only in cases where it improves code readability. + +```qsp +! assignment can be done without set or let operators: +$text = "text string" +``` + +::: + +## LOCAL + +`LOCAL` — declares a local variable (or several variables) in the current code block. + +General syntax: + +```qsp +LOCAL [variable 1], [variable 2], ... +LOCAL [variable 1], [variable 2], ... = [value 1], [value 2], ... +``` + +, where `[variable 1]`, `[variable 2]`, etc. — variable/array names written directly (not in quotes), and `[value 1]`, `[value 2]`, etc. — any values, constants, expression values, functions, or other variables. + +The number of variables and values must match (except for unpacking cases). + +```qsp +! declare one local variable +local tempora = 12 +! declare several local variables +local x, y, $item = 11, 19, "Old sword" +! declaration with unpacking +local i, j = %map_cell +local z, $a = [13, '37'] +``` + +Unlike `set` and `let` operators, a variable can be declared without assigning a value. + +```qsp +local tempora +local x, y, $item, %map_cell +``` + +However, despite the variable being created, `arrsize` will return `0` for it. I.e., you cannot check if a variable is declared. + +```qsp +local arr +*pl arrsize('arr') & ! will output 0 +``` + +You can create your own local variables in the following code blocks: + +- Locations themselves. +- Code passed to the `DYNAMIC` operator or `DYNEVAL` function as text. +- Code executed when clicking a hyperlink. +- Code of each individual Action ([ACT](qsp-keyword-operators.md#act)). +- Code of each individual Loop ([LOOP](qsp-keyword-operators.md#loop)) + +:::warning[**Attention!**] +Local variables have one feature that needs to be clearly understood. The value of a local variable declared in a given code block is also translated to all nested or called code blocks. For example, if a local variable is declared on a location, its value is translated to all locations called with `GOSUB` or `FUNC`, to `DYNAMIC`/`DYNEVAL` code blocks, to loop blocks, etc. Example: + +```qsp +# start +! from this location we will call location foo +i = 99 & ! declare global variable +gosub 'foo' +*nl i & ! we'll see number 99 on screen +--- start --- + +# foo +! declare local variable on this location +local i = 0 +! local variable is translated to the loop +loop while i < 10 step i += 1: + ! in the loop we call location undo + gosub 'undo' + ! and also in the loop we work with the variable + ! declared on location foo +end +*nl i & ! we'll see number 10 on screen +--- foo --- + +# undo +! to this location from the loop on location foo +! the same local variable declared on location foo is translated +i+=1 & ! increase variable value, affecting the value in foo +*p 'undo:<>, ' & ! numbers 1,3,5,7,9 will appear on screen with undo: prefix +--- undo --- +``` + +**However!** Local variable values are not translated to actions (unlike `ARGS` array values at the current location): + +```qsp +$args[0] = 'current location' +local $var = 'local variable' +*pl $args[0] +*pl $var +act "Output values": + *pl $args[0] + *pl $var +end +``` + +::: + +### Examples of local variable assignment + +```qsp title="Two locations, each with its own variable i" +# location 1 +if i = 0: i = 99 & ! variable i value is set only once +*pl "Global i = <>" +act "To location 2": goto 'location 2' +--- location 1 --- + +# location 2 +*pl "Global i = <>" +local i = 137 & ! variable i value is set only once +*pl "Local i = <>" +act "To location 1": goto 'location 1' +--- location 2 --- +``` + +```qsp title="Another example with two locations" +! this code will sequentially output numbers 12, 549 and 99, 549 +# start +x = 99 +z = 4608 +gosub 'foo' +*pl x & *pl z & ! numbers 99 and 549 will be output +--- start --- + +# foo +local x & ! declare variable x local for this location +x = 12 & ! change variable x value +z = 549 +*pl x & *pl z & ! numbers 12 and 549 will be output +--- foo --- +``` + +```qsp title="Example of declaring local variables in DYNEVAL code and in a loop" +$chkObjWord = { + ! this is code written as text in variable $chkObjWord + ! write the search word to local variable $word + local $word = $args[0] + loop local i = 1 while no i > countobj step i += 1: + ! use local variable i inside the loop + ! loop executes while counter doesn't exceed item count + if instr($getobj(i), $word) <> 0: + ! as soon as the considered word is found + ! in the next item name + result = i & ! return position + exit & ! close function + end + end +} +object_position = dyneval($chkObjWord, 'grenade') +``` + +```qsp title="Local variables can also be declared inside actions" +i=99 +act "Action with local i": + local i = 449933 + *pl i +end +act "Action with global i": + *pl i +end +``` + +## LOOP + +`LOOP` — loop operator. Necessary for organizing cyclical calculations. General single-line syntax: + +```qsp +LOOP {commands before loop start} WHILE [condition] STEP {commands at end of iteration}: {loop body operators} +``` + +General multi-line syntax: + +```qsp +LOOP {commands before loop start} WHILE [condition] STEP {commands at end of iteration}: + {loop body operators} +END +``` + +, where: + +- `{commands before loop start}` — commands executed before the loop is started. These commands belong to the loop block but don't fall into iterations (passes), i.e., executed only once. Here you can, for example, declare a loop counter. And here you can write multiple commands, listing them through the separator `&` (ampersand). +- `[condition]` — an expression by whose value the condition is checked. Comparison operations and logical operations in any combinations can be used here. If the `[condition]` expression value equals zero, the loop is interrupted. +- `{commands at end of iteration}` — commands executed at the end of each loop pass. Commands that don't directly relate to the loop body but should be executed on each iteration can be placed here. Here you can, for example, change the loop counter value. And here you can actually write multiple commands, listing them through the separator `&` (ampersand). +- `{loop body operators}` — commands that need to be executed on each pass and are main for the loop. I.e., we make the loop exactly for these commands. + +A loop in QSP is a separate code block, which means we can declare local variables inside this code block. This is very convenient because we can declare a local variable for the counter, and this won't affect other variables at the location: + +```qsp +i = 99 +*pl "i before loop <>" +loop local i = 0 & *p "i in loop: " while i < 6 step i += 1: + *p "<>, " +end +*nl "i after loop <>" +``` + +Loops are very convenient for iterating through arrays. For example, you can use a loop to sum all numbers stored in an array: + +```qsp +summ=0 & ! here we'll write the sum of numbers +! our numbers are in array **mass** +loop local i, size = 0, arrsize('mass') while i < size step i += 1: + summ += mass[i] +end +*pl 'Sum of all elements in mass array: <>' +``` + +## MENU + +`MENU` — displays a popup menu anywhere in the game, whose items are defined in the specified array. General syntax: + +```qsp +MENU [$array_name] +``` + +Before using this operator, you need to fill the array on which the menu items will be based. Menu items are tuples of three values, sequentially placed in consecutive array cells starting from zero. The contents of each tuple should be approximately like this: + +```qsp +["menu item name", "location name", "icon file path"] +``` + +Menu item name is what we'll see on screen when the menu is displayed; location name is the name of the location whose code will be executed when the corresponding menu item is clicked; icon file path is the path to the image file that will be displayed next to the menu item name. + +Knowing this, we can fill the array to create our menu items: + +```qsp +%stone[0] = ['Take stone', 'takestone'] +%stone[1] = ['Throw stone', 'throwstone'] +%stone[2] = ['Examine stone', 'lookstone'] +``` + +Here the array name (`%stone`) is the menu name, and the tuples are actions with specified item names and menu item selection handler location names. When selecting "Take stone", the location named "takestone" will be called. The same will happen with other items. + +To display the menu on screen, use the `MENU` operator: + +```qsp +menu '%stone' +``` + +Example of creating a menu with icons: + +```qsp +! no icon +%usr_menu[0] = ['Take item', 'take_item'] +! icon specified by gif file +%usr_menu[1] = ['Put item', 'put_item', 'images/put_item.gif'] +! icon specified by $icon_file value +%usr_menu[2] = ['Destroy item','del_item', $icon_file] +! menu item specified by 3 variables +%usr_menu[3] = [$name, $location, $icon_file] + +menu 'usr_menu' &! will show menu with 4 items +``` + +The menu ends at an array element with an empty tuple, or with a tuple missing a value for the menu item name or item handler location. + +Examples where the last two menu items won't be created: + +```qsp +%usr_menu[0]=['Take item','take_item'] & ! we'll see this item on screen +$usr_menu[1]=['Examine item','look_item'] & ! and we'll see this item on screen +$usr_menu[2]=[] & ! empty tuple, player will consider the menu ended +$usr_menu[3]=['Put item','put_item'] & ! we won't see this item +``` + +```qsp +%usr_menu[0]=['Take item','take_item'] & ! we'll see this item on screen +$usr_menu[1]=['Examine item','look_item'] & ! and we'll see this item on screen +$usr_menu[2]=['destroy item', ''] & ! no handler location specified, won't see item +$usr_menu[3]=['Put item','put_item'] & ! and we won't see this item +``` + +```qsp +%usr_menu[0]=['Take item','take_item'] & ! we'll see this item on screen +$usr_menu[1]=['Examine item','look_item'] & ! and we'll see this item on screen +$usr_menu[2]=['', 'del_item'] & ! no name specified, won't see item +$usr_menu[3]=['Put item','put_item'] & ! and we won't see this item +``` + +To insert a separator in the menu, use a tuple with `-` values. I.e., if you need to put a separator instead of the 3rd element: + +```qsp +%usr_menu[0]=['Take item','take_item'] +$usr_menu[1]=['Examine item','look_item'] +$usr_menu[2]=['-', '-'] & ! separator instead of menu item +$usr_menu[3]=['Put item','put_item'] +``` + +An argument (`args[0]`) - the position of the selected item - is passed to the menu item selection handler location. Menu item positions are numbered from 1. + +## MSG + +`MSG` — outputs the specified message in a dialog box. General syntax: + +```qsp +MSG [message] +``` + +, where `[message]` — any text string, number, expression of any type. Examples: + +```qsp +! simple message output. +msg 'Many ripe pears.' +! we get a window with message 'Many ripe pears' +``` + +```qsp +! Example message in ACT action. +act 'Eat pears': + msg 'Mmm pears are very tasty.' +end +! We get message output when clicking "Eat pears" action +``` + +```qsp +! Example with condition. +if breadready = 1: + msg 'Looks like the bread is ready.' +end +! We get message output when condition breadready = 1 +``` + +## OPENGAME + +`OPENGAME` — loads the specified game state file. General syntax: + +```qsp +OPENGAME [$path] +``` + +, where `[$path]` — path to the saved game state file. If the `[$path]` parameter is absent, the game state loading window is called. + +Example: + +```qsp +! load state from file 1.sav +opengame "1.sav" +! open state loading window +opengame +``` + +See also the game state loading event handler location ([$ongload](qsp-keyword-sys-var.md#ongload)). + +## OPENQST + +`OPENQST` — opens and runs the specified game file. General syntax: + +```qsp +OPENQST [$path] +``` + +, where [$path] — path to the game file to run. Example: + +```qsp +openqst "gamespool/cubesgame.qsp" +``` + +When using this operator, variables are not deleted, inventory items are not removed, additional description and input line are not cleared, and playing files are not stopped. If you need to clear the screen and all variable values, you can write such commands at the beginning of the loaded game file: + +```qsp +killall & cls & close all +``` + +## REFINT + +`REFINT` — forced interface update (including color and font changes assigned with system variables). + +By default, interface updates occur 2 times per second (every 500 ms). Also see the [`settimer`](#settimer) operator. + +## SAVEGAME + +`SAVEGAME` — saves game state to the specified file. General syntax: + +```qsp +SAVEGAME [$path] +``` + +, where `[$path]` — path to the created game state save file. If the `[$path]` parameter is absent, the game state save window is called. + +Example: + +```qsp +! save state to file 1.sav +savegame "1.sav" +! open state save window +savegame +``` + +See also [game state save event handler location ($ongsave)](qsp-keyword-sys-var.md#ongsave). + +## SETTIMER + +`SETTIMER` — sets the interval for calling the counter location. General syntax: + +```qsp +SETTIMER [#expression] +``` + +, where `[#expression]` — period for calling the counter location in milliseconds. By default, the player calls the counter location every 500 ms, i.e., 2 times per second. + +Setting the counter location call period also affects the frequency of automatic interface settings updates. + +Examples: + +```qsp +! counter location will run every 2 seconds: +settimer 2000 +``` + +```qsp +! counter location will run 4 times per second: +settimer 250 +``` + +```qsp +! if we set frequency (times per second) +frequency=10 & ! ten times per second +settimer 1000/frequency +``` + +```qsp +! if we set period (every how many seconds) +period=2 & ! every two seconds +settimer 1000*period +``` + +The minimum period value can thus be 1 millisecond: + +```qsp +settimer 1 +``` + +However, in practice, the minimum value is limited by your computer's power, and it's usually higher than 1 millisecond. + +## VIEW + +`VIEW` — displays the specified image on screen. In the classic player, the image is displayed in a separate window (preview window), in qSpider the image is displayed as a layer. General syntax: + +```qsp +VIEW [$graphics_file_path] +``` + +, where `[$graphics_file_path]` — path to the image file. If the `[$graphics_file_path]` parameter is absent or set as `''` (empty string), the preview window closes. + +Examples: + +```qsp +! display image in preview window +view 'content/monster.png' +! close preview window +view '' + +! you can also close the preview window like this +view +``` + +## WAIT + +`WAIT` — pauses program code execution for the specified number of milliseconds. General syntax: + +```qsp +WAIT [#milliseconds] +``` + +, where `[#milliseconds]` — time in milliseconds to stop program code execution. + +Example: + +```qsp +! stop program execution for 5 seconds +wait 5000 +``` + +:::warning[Caution!] +This operator must be used carefully since pausing code execution blocks the player's ability to interact with the game. +::: + +`WAIT` not only interrupts code execution but also forces the player to output information from the screen buffer. During normal location code execution, all text for `*pl`, `*p` `pl`, `nl` etc. operators is placed in a special screen buffer and output to screen only after all location code is executed. When using `WAIT`, text from the buffer is output immediately when `WAIT` is executed, which is sometimes useful as it allows tracking value changes step by step. + +In the example below, numbers will first be written to the screen buffer and only then appear on screen: + +```qsp +loop i=0 while i<5 step i+=1: + *p i +end +*pl +``` + +In the next example, they will be output one after another with approximately 100 ms intervals. + +```qsp +loop i=0 while i<5 step i+=1: + wait 100 + *p i +end +*pl +``` + diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md new file mode 100644 index 0000000..ac92e24 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md @@ -0,0 +1,646 @@ +--- +id: qsp-keyword-syntaxems +title: Syntax Elements and Special Symbols +sidebar_position: 5 +--- + +# Syntax Elements and Special Symbols + +:::tips[Definition] + +In the context of programming, a syntax element can be considered as a **minimal unit of syntax** that defines the structure and rules for writing code. + +Thus, a syntax element can be a variable, operator, function, declaration keyword, or special symbols used to structure code. + +::: + +Here are syntax elements/special symbols not included in other sections with keywords and system variables. + +## END + +Keyword (operator) marking the end of a multi-line construct. Actions, conditional constructs, and loops can be multi-line. Examples: + +```qsp +! open condition +if obj "Jug": + *pl "You have a jug." +! close condition +end + +! open action +act "Take apple": + apple += 1 + addobj "Apple" +! close action +end + +loop local i = 0 while i < 10 step i += 1: + *pl "Pass <>: i=<>" +end +``` + +Each multi-line construct must end with the `end` keyword. However, the same rules apply here as for HTML tags or brackets: if we nest one construct inside another, we must first close the last opened construct: + +```qsp +! open condition +if obj "Empty jug": + ! code related to the condition + *pl "You have an empty jug." + ! open action + act "Fill jug": + ! code related to the action + delobj "Empty jug" + addobj "Full jug" + ! close ACTION + end + *pl "The jug can be filled from the well." +! close CONDITION +end +``` + +You can use not just `end`, but `end if`, `end act` and `end loop`: + +```qsp +! open action +act "Buy 10 arrows at 5 rubles each": + ! open condition level 1 + if money >= 10 * 5: + arrow += 10 + money -= 10 * 5 + ! open condition level 2 + if no (obj "Arrows"): + addobj "Arrows" + ! close condition level 2 + end if + else + *pl "You don't have enough money." + ! close condition level 1 + end if +! close action +end act +``` + +Generally, any text is allowed after the `end` keyword, but not approved. All text until the next command is ignored. If a command is written on the same line as `end`, this command must come after an ampersand (`&`): + +```qsp +! open action +act "Take apple": + apple += 1 + addobj "Apple" +! close action +end the presence of this text after end is not approved & *pl "New command" +``` + +## Labels `:` + +Labels are special syntactic constructs (or rather less than constructs — syntax elements) that mark the specified code line and serve for quick movement to such lines using the [`JUMP`](qsp-keyword-operators.md#jump) operator. General syntax: + +```qsp +:[label_name] +``` + +, where `[label_name]` — theoretically any combination of symbols, but in practice it's desirable to use only letters, numbers, underscores, and spaces. Spaces and tabs can precede the colon in any amount. Adjacent spaces and tabs around the label name are also ignored (but not recommended for code readability). + +```qsp +! recommended label usage +jump 'label' +! ... +:label +``` + +```qsp +! working variant with ignored adjacent spaces in label +jump "label with adjacent spaces" +! ... +: label with adjacent spaces +``` + +```qsp +! working variant with ignored adjacent spaces in jump +jump " label with adjacent spaces " +! ... +:label with adjacent spaces +``` + +Any other commands can follow directly after the label on the same line through an ampersand (`&`), but this is not recommended. + +```qsp +! label with commands after it +jump 'markdown' +! ... +:markdown & *pl "output text" & ! comment +``` + +Labels are case-insensitive: + +```qsp +jump "FoR" +! ... +:for +``` + +The `jump` operator "sees" labels only within the current code block. In other words, labels are local. + +Labels with identical names can be located on different locations (in different code blocks). + +If labels with identical names are located in one code block, all duplicate labels except the first one are ignored by the player. + +Separate code blocks for labels are considered: + +* "Execute on visit" code of a specific location (each location is a separate code block), +* action code even if the action is added programmatically, +* code in hyperlinks, +* code passed to `DYNAMIC`/`DYNEVAL`. + +Labels inside loops belong to the same code block where the loop is located. + +If an action is added programmatically, labels placed in this action become available from the code block where this action was created. However, from the action it's impossible to jump to a label located outside the action. + +Random labels, i.e., labels that have no jump to them with `jump` in the current code block, are simply ignored by the interpreter. + +## Ampersand `&` + +`&` — the ampersand symbol serves to list commands on one line. General syntax: + +```qsp +[command 1] & [command 2] & ... +``` + +This symbol should not be confused with the [string concatenation operation](qsp-keyword-operacion.md#-concatenation), and should be used carefully. + +Examples: + +```qsp +*pl "I picked an apple from the branch." & addobj "Apple" & apple+=1 + +a = 3 & b = 7 & g = rand(1, 6) & ("26" & "27") & ! in parentheses — concatenation +``` + +## Comma `,` + +The comma `,` in QSP is used to list arguments passed to various operators and functions: + +```qsp +rgb(25, 67, 250) + +max(12, 45, 67, 89, 90, 122, 135, 168, 90) + +addobj "Screwdriver", "img/screwdriver.png" + +gosub "add_object", "Orange", 2, "Food", 37 +``` + +The comma is also used to list values in a tuple: + +```qsp +%personage = [26, 192, 85, 'Peter', 'boxer'] +``` + +## Round Brackets `()` + +Round brackets `()` in QSP are used in three cases: + +1. In various expressions, brackets increase operation priority (operations in brackets are executed first): + + ```qsp + ! increasing priority of arithmetic operations + (256 + 789) * (789 - 256) + ! increasing priority of comparison operations + if A = (A <> B): ... + ``` + +2. If you need to pass more than one argument to a function, you should place the entire group of arguments in brackets: + + ```qsp + rgb(25, 67, 250) + max(12, 45, 67, 89, 90, 122, 135, 168, 90) + rand(1, 1000) + ``` + + It's good practice to place even one function argument in brackets: + + ```qsp + rand(999) + ``` + + It won't be criticized, though it's not usually done, to place argument groups for operators in brackets: + + ```qsp + showinput(0) + + addobj("Screwdriver", "img/screwdriver.png") + + gosub("add_object", "Orange", 2, "Food", 37) + gosub("add_object", "Rec", rand(23, 45), "Artifact", max(36, 67, 90, a)) + ``` + +3. If you need to organize a tuple of values: + + ```qsp + %tuple = (123, 234, 'string') + %mass[23] = ('Petrov', 'Peter', 'Petrovich') + ``` + +:::warning[Recommendation!] +For organizing tuples, it's recommended to use square brackets. + +```qsp +%tuple = [123, 234, 'string'] +%mass[23] = ['Petrov', 'Peter', 'Petrovich'] +``` + +::: + +## Square Brackets `[]` + +Square brackets `[]` in QSP are used to specify the index of an array cell: + +```qsp +! assign value to the seventh cell of array $mass +$mass[7] = "textstring" +``` + +You can use string values for array cell indexing: + +```qsp +$mass["x:4,y:6"] = "map-dot" +``` + +You can also use tuples for array cell indexing. Duplicating brackets is not necessary: + +```qsp +$mass[4, 6] = "map_cell" +! equivalent to +$mass[[4, 6]] = "map_cell" +``` + +If square brackets don't follow the array name, work is done with the zero cell of the array: + +```qsp +$mass = "text" +! equivalent to +$mass[0] = "text" +``` + +If the index in square brackets is not specified, we work with the last cell of the array: + +```qsp +! create new cell at the end of array and assign value to it +$mass[] = "last_cell" + +! get value from the last array cell: +$mass[] +``` + +Square brackets are also used to create tuples: + +```qsp +%tuple = [123, 234, 'string'] +%mass[23] = ['Petrov', 'Peter', 'Petrovich'] +``` + +## Curly Brackets `{}` + +Curly brackets `{}` in QSP act as special symbols marking the beginning and end of string values. In other words, by the presence of such brackets, the player can understand where a string value begins and ends: + +```qsp +*pl {Text that will be output to the screen.} +``` + +The feature of specifying text value using curly brackets is that sub-expressions are not expanded in such strings: + +```qsp +health = 150 +*pl {Health: <>} +! the text 'Health: <>' will be output to the screen +*pl "Health: <>" +! the text 'Health: 150' will be output to the screen +``` + +For better compatibility with various player versions, and for reading convenience, curly brackets should mainly be used for writing code intended for the `dynamic` operator or `dyneval` function: + +```qsp +*pl $dyneval({$result = $mid("abcd", 2, 1) + "qwerty"}) +dynamic { + $args[0] + addobj $args[1] +}, 'Text', 'Fork' +``` + +Curly brackets can also be used for writing multi-line comments: + +```qsp +! { + multi-line + comment +} +``` + +Any number of curly brackets can be nested within each other. + +## Quote `"` + +Quotes `"` (double apostrophe) in QSP act as a special symbol marking the beginning and end of string values. In other words, by the presence of quotes, the player can understand where a string value begins and ends: + +```qsp +*pl "Text that will be output to the screen." +``` + +The feature of specifying text value using quotes is that sub-expressions are expanded in such strings: + +```qsp +health = 150 +*pl "Health: <>" +! the text 'Health: 150' will be output to the screen +``` + +Quotes inside a string can be escaped by doubling: + +```qsp +*pl "At the tavern ""At Mo's"" it's cheerful and noisy today." +``` + +Quotes can also be used for writing multi-line comments: + +```qsp +! " + multi-line + comment +" +``` + +## Apostrophe `'` + +Apostrophe `'` in QSP acts as a special symbol marking the beginning and end of string values. In other words, by the presence of apostrophes, the player can understand where a string value begins and ends: + +```qsp +*pl 'Text that will be output to the screen.' +``` + +The feature of specifying text value using apostrophes is that sub-expressions are expanded in such strings: + +```qsp +health = 150 +*pl 'Health: <>' +! the text 'Health: 150' will be output to the screen +``` + +Apostrophes inside a string can be escaped by doubling: + +```qsp +*pl 'Rug''Sta''Rag said: — What do you want, mora? Want a fly agaric?' +``` + +Apostrophes can also be used for writing multi-line comments: + +```qsp +! ' + multi-line + comment +' +``` + +## "At" Symbol `@` + +The "at" symbol `@` is used to organize implicit function-location calls, simplifying notation and replacing the `gosub` operator or `func` function. General syntax: + +```qsp +@[$location]([argument 0], [argument 1], ... , [argument 18]) +``` + +, where `[$location]` — the name of the location whose code we want to execute without direct transition to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After processing the location, previous `args` values are restored. Using arguments is not mandatory; in this case, brackets can be omitted. + +When calling a location using `@`, the base description of the location is added to the current description, base actions are added to current actions, and operators in the "Execute on visit" field are executed, then return to the original line (continue code execution after the command with `@`). + +The location name in implicit calls must not contain special characters, otherwise this may lead to non-working code. You can use letters, numbers, underscores, and dots. + +Examples: + +```qsp +!processing location "move". The args[] array is empty. +@move() + +!processing location "move" with 3 parameters passed. +! $args[0] = $var (value), args[1] = 2, +! $args[2] = "data". Note the ' symbols. +@move($var, 2, 'data') +``` + +```qsp +! this is code calling location "transition" +@transition('location') + +! and this is code of the "transition" location itself +# transition +*pl $args[0] & ! the text 'location' will be output to the screen +! a new action will appear in the actions window: +act 'go': + goto "street" +end +- transition +``` + +```qsp +! location code for function getting sum of series of numbers from one to specified value +# summ +! args[0] will contain the number we specify as [argument 0] +loop while args[0] > 0 step args[0] -= 1: + result += args[0] +end +- summ + +! example of calling location "summ" as function +*pl @summ(19) & ! will output 190 to screen +``` + +:::warning[Pay attention!] +Implicit function-location call replaces both `gosub` and `func`, therefore: + +1. if your function-location returns a result, implicit call of such location will work exactly like explicit call through `func`; +2. if the function-location does not return a result, then when using it with the **[implicit operator](qsp-keyword-operators.md#implicit-operator)** it will work like explicit call through `gosub`. + +::: + +## Dollar Sign `--- +sidebar_position: 5 +--- + +# Syntax Elements and Special Symbols + +:::tips[Definition] + +In the context of programming, a syntax element can be considered as a **minimal unit of syntax** that defines the structure and rules for writing code. + +Thus, a syntax element can be a variable, operator, function, declaration keyword, or special symbols used to structure code. + +::: + +Here are syntax elements/special symbols not included in other sections with keywords and system variables. + +## END + +Keyword (operator) marking the end of a multi-line construct. Actions, conditional constructs, and loops can be multi-line. Examples: + +```qsp +! open condition +if obj "Jug": + *pl "You have a jug." +! close condition +end + +! open action +act "Take apple": + apple += 1 + addobj "Apple" +! close action +end + +loop local i = 0 while i < 10 step i += 1: + *pl "Pass <>: i=<>" +end +``` + +Each multi-line construct must end with the `end` keyword. However, the same rules apply here as for HTML tags or brackets: if we nest one construct inside another, we must first close the last opened construct: + +```qsp +! open condition +if obj "Empty jug": + ! code related to the condition + *pl "You have an empty jug." + ! open action + act "Fill jug": + ! code related to the action + delobj "Empty jug" + addobj "Full jug" + ! close ACTION + end + *pl "The jug can be filled from the well." +! close CONDITION +end +``` + +You can use not just `end`, but `end if`, `end act` and `end loop`: + +```qsp +! open action +act "Buy 10 arrows at 5 rubles each": + ! open condition level 1 + if money >= 10 * 5: + arrow += 10 + money -= 10 * 5 + ! open condition level 2 + if no (obj "Arrows"): + addobj "Arrows" + ! close condition level 2 + end if + else + *pl "You don't have enough money." + ! close condition level 1 + end if +! close action +end act +``` + +Generally, any text is allowed after the `end` keyword, but not approved. All text until the next command is ignored. If a command is written on the same line as `end`, this command must come after an ampersand (`&`): + +```qsp +! open action +act "Take apple": + apple += 1 + addobj "Apple" +! close action +end the presence of this text after end is not approved & *pl "New command" +``` + +## Labels `:` + +Labels are special syntactic constructs (or rather less than constructs — syntax elements) that mark the specified code line and serve for quick movement to such lines using the [`JUMP`](qsp-keyword-operators.md#jump) operator. General syntax: + +```qsp +:[label_name] +``` + +, where `[label_name]` — theoretically any combination of symbols, but in practice it's desirable to use only letters, numbers, underscores, and spaces. Spaces and tabs can precede the colon in any amount. Adjacent spaces and tabs around the label name are also ignored (but not recommended for code readability). + +```qsp +! recommended label usage +jump 'label' +! ... +:label +``` + +```qsp +! working variant with ignored adjacent spaces in label +jump "label with adjacent spaces" +! ... +: label with adjacent spaces +``` + +```qsp +! working variant with ignored adjacent spaces in jump +jump " label with adjacent spaces " +! ... +:label with adjacent spaces +``` + +Any other commands can follow directly after the label on the same line through an ampersand (`&`), but this is not recommended. + +```qsp +! label with commands after it +jump 'markdown' +! ... +:markdown & *pl "output text" & ! comment +``` + +Labels are case-insensitive: + +```qsp +jump "FoR" +! ... +:for +``` + + + +Acts as a type prefix for naming variables and functions of string type. It must be specified if you want to assign a string value to a variable: + +```qsp +$string = 'This is so long string. Very very long string' +``` + +If you don't specify the dollar sign before the string type variable name during assignment, this will cause error #101: "Data type mismatch": + +```qsp title="Don't do this!" +string = 'Short string' +``` + +If you assigned a value of another type to a variable and try to get a string, this won't cause a data type mismatch error, but the variable will return a value corresponding to the default value for string values, i.e., an empty string (`''`). + +```qsp +number = 123 +*pl 'Number ' + $number + '.' +! we'll see 'Number .' on screen because $number will return an empty string. +``` + +## Percent Sign `%` + +Acts as a type prefix for naming variables and functions containing or returning tuples. It must be specified if you want to assign a tuple to a variable: + +```qsp +%tuple = [13, 37, 'string'] +``` + +If you don't specify the percent sign before the tuple type variable name during assignment, this will cause error #101: "Data type mismatch": + +```qsp title="Don't do this!" +tuple = [13, 37, 'string'] +``` + +If you assigned a value of another type to a variable and try to get a tuple, this won't cause a data type mismatch error, but the variable will return a value corresponding to the default value, i.e., empty strings (`''`) if a text value is extracted, or zeros (`0`) if a numeric value is extracted. + +```qsp +number = 123 +$var[0], $var[1] = %number +*pl '[<<$var[0]>>,<<$var[1]>>]' +! We'll see '[,]' on screen +``` \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md new file mode 100644 index 0000000..73fd9b0 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md @@ -0,0 +1,519 @@ +--- +id: qsp-keyword-sys-var +title: System Variables +sidebar_position: 4 +--- + +# System Variables + +## $BACKIMAGE + +`$BACKIMAGE` — contains the path to the background image file for the main description window. The background in the main description window is displayed if the value of this variable is not `''` (i.e., not an empty string) and the image file was successfully loaded. + +Example: + +```qsp +$backimage = "img/bg.png" & ! set background image located in "img" folder. +``` + +```qsp +$backimage = "" & ! remove image from main description window background. +``` + +## $COUNTER + +`$COUNTER` — contains the name of the counter location. The counter location can be used for real-time events (i.e., events occurring in real time); for example, smooth background color change, gradual text output to screen, playlist for continuous music playback, and others. + +The counter location is called at equal time intervals, by default every 500 ms, i.e., 2 times per second. Automatic interface updates trigger at the same frequency. Intervals are set by the `settimer` operator in milliseconds. + +If your counter location is called "Counter", you need to write on the very first location in the game: + +```qsp +$counter = 'Counter' +``` + +As a rule, to avoid confusion, the location is named the same as the service variable — "Counter": + +```qsp +$counter = 'Counter' +``` + +To disable counter location execution, you need to set an empty value for the `$COUNTER` variable: + +```qsp +$counter = "" +``` + +:::note[< 5.7.0] + +In older player versions, the counter location was used to automate everything possible, but now we recommend using it only where interface work is required or actions requiring some reaction speed from the player. + +You shouldn't tie health restoration algorithms or checks for whether the character died to the counter location, and especially shouldn't do object or action selection checks through the counter location. QSP provides several handler locations that more than cover most code automation needs. + +::: + +## $FNAME + +`$FNAME` — contains the name of the currently used font. If equal to `''` (empty string), then the font specified in the program settings is used. + +Example: + +```qsp +! set Courier New font for entire game +$fname = "Courier New" +``` + +## $ONACTSEL + +`$ONACTSEL` — contains the name of the "action selection" event handler location (hereinafter "*action selection handler*"). In other words, this variable specifies the name of the location whose code triggers when one of the actions displayed on screen is selected. + +Remember that action selection occurs when hovering the mouse pointer over it, not when directly clicking. + +Assign the "on_mouse" location as *action selection handler*: + +```qsp +$onactsel = "on_mouse" +``` + +This location is useful, for example, for displaying images or playing sounds when selecting actions. You can get the selected action name through the `$selact` function. + +```qsp +if instr($selact, 'go', 1): play 'sounds\walk.mp3' +``` + +To disable the *action selection handler*, you need to set the `$onactsel` variable to an empty value: + +```qsp +$onactsel = "" +``` + +## $ONGLOAD + +`$ONGLOAD` — contains the name of the "*game state loading*" event handler location (hereinafter "*load state handler*"). In other words, this variable contains the name of the location whose code will be executed every time after a game state save file ("save file") is loaded using the `opengame` command. + +Assign the "on_game_load" location as load state handler: + +```qsp +$ongload = "on_game_load" +``` + +To disable the load state handler, you need to set the `$ongload` variable to an empty value: + +```qsp +$ongload = "" +``` + +## $ONGSAVE + +`$ONGSAVE` - contains the name of the "*game state saving*" event handler location (hereinafter "*save state handler*"). In other words, this variable contains the name of the location whose code will be executed every time before the game state is written to a new or existing game state save file ("save file") using the `savegame` command. + +Assign the "on_game_save" location as *save state handler*: + +```qsp +$ongsave = "on_game_save" +``` + +To disable the *save state handler*, you need to set the `$ongsave` variable to an empty value: + +```qsp +$ongsave="" +``` + +## $ONNEWLOC + +`$ONNEWLOC` — contains the name of the new location transition handler (analog of "common" location in URQ; hereinafter "*new location transition handler*"). In other words, this variable contains the name of the location whose code is executed every time after executing the code of the location that was transitioned to using `goto` or `xgoto` operators. Game control is passed to the player only after executing code at this handler location. + +Assign the "on_goto_newloc" location as new location transition handler: + +```qsp +$onnewloc = "on_goto_newloc" +``` + +You can get the name of the location that was transitioned to using the `$curloc` function. + +```qsp +if $curloc = 'house': cat = 1 +``` + +To disable the new location transition handler location, you need to set the `$onnewloc` variable to an empty value: + +```qsp +$onnewloc = "" +``` + +## $ONOBJADD + +`$ONOBJADD` — contains the name of the "*item addition*" event handler location (hereinafter "*item addition handler*"). In other words, this variable contains the name of the location whose code is executed every time after adding an item to the objects window using the `addobj` command. + +When adding an item, two arguments are passed to this handler location, whose values can be obtained from `$args[0]` and `$args[1]` respectively: + +* `$ARGS[0]` - name of the added item +* `$ARGS[1]` - path to the image of the added item + +This location is useful, for example, for limiting backpack capacity. + +Assign the "on_object_add" location as *item addition handler*: + +```qsp +$onobjadd = "on_object_add" +``` + +To disable the *item addition handler*, you need to set the `$onobjadd` variable to an empty value: + +```qsp +$onobjadd = "" +``` + +## $ONOBJDEL + +`$ONOBJDEL` — contains the name of the "*item removal*" event handler location (hereinafter "*item removal handler*"). In other words, this variable contains the name of the location whose code is executed every time when removing an item using the `delobj` command. If you use the `killobj` command, this will be equivalent to a series of `delobj` commands, so the handler location will be called as many times as items are removed with `killobj`. + +When using the `killall` command, the item removal handler location is not called since the `$onobjdel` system variable is destroyed before item removal. + +When removing an item, an argument is passed to this handler location, whose value can be obtained from `$args[0]`: + +* `$ARGS[0]` - name of the removed item + +Assign the "on_object_del" location as *item removal handler*: + +```qsp +$onobjdel = "on_object_del" +``` + +This location is useful, for example, for checking the possibility of item removal: + +```qsp +! for example there's an item we'll need for the plot +if $args[0] = "Important artifact": + ! restore the item + addobj $args[0] +end +``` + +To disable the *item removal handler*, you need to set the `$onobjdel` variable to an empty value: + +```qsp +$onobjdel = "" +``` + +## $ONOBJSEL + +`$ONOBJSEL` — contains the name of the "*item selection*" event handler location (hereinafter "*item selection handler*"). In other words, this variable specifies the name of the location whose code is executed every time when selecting an item. Item selection occurs directly when "clicking" on an item (mouse click on item). + +Assign the "on_object_select" location as *item selection handler*: + +```qsp +$onobjsel = "on_object_select" +``` + +This location is useful, for example, for displaying item information or item menu. You can get the selected item name through the `$selobj` function. + +```qsp +if $selobj = 'teapot': + p 'The most ordinary cast iron teapot.' +end +``` + +When a player selects any item, it remains selected. You can remove selection with the `unselect` command. + +To disable the *item selection handler*, you need to set the `$onobjsel` variable to an empty value: + +```qsp +$onobjsel = "" +``` + +## $USERCOM + +`$USERCOM` — contains the name of the input line (input field) handler location (hereinafter "*input line handler*"). The code of this handler location is executed if the cursor is in the input line when the "Enter" key is pressed. + +Assign the "user_command_line" location as *input line handler*: + +```qsp +$usercom = "user_command_line" +``` + +Useful for organizing a parser (game control through input line) or for organizing a debugger. Example code for handler location: + +```qsp +! if entered text corresponds to existing location name +if loc($user_text): + ! transition to this location + goto $user_text +end +``` + +To disable the *input line handler*, you need to set the `$usercom` variable to an empty value: + +```qsp +$usercom = "" +``` + +## ARGS + +`ARGS` — specific system array in which argument values passed by the user when calling a location or code written as text are placed. + +Example: + +```qsp +gosub "em.arr.sort", "$mass", "rug", "$time_ar" +``` + +Here, three arguments will be passed to the "`em.arr.sort`" location, which will be placed in the first three cells of the `$args` array respectively. I.e., at the moment of starting code execution at the "`em.arr.sort`" location, `$args[0]` will already contain the value "`$mass`", `$args[1]` — the value "`rug`", `$args[2]` — the value "`$time_ar`". + +When using `gosub`, `goto`, `xgoto`, `dynamic` operators and `dyneval`, `func` functions, you can specify up to nineteen such arguments, and they will all be placed in `args` array cells from zero to eighteenth. However, since `args` is still an array, you can work with it like a regular array, i.e., use more than nineteen cells, assign text indices, etc. + +A distinctive feature of the `args` array is that a separate `args` array is created for each separate code block. I.e., if you call location "2" from location "1", then location "1" has its own `args` array, and location "2" has its own, and values in these arrays don't intersect. + +Example: + +```qsp +# location_1 +args[0]=23 +gosub "location_2", 34 +*pl args[0] +- + +# location_2 +*pl args[0] +- +``` + +Running this code, you'll see that first the number `34` will be output, and only then `23`. + +Moreover, if you make a recursive call of a location from itself, a separate array will be created for each location call. Thus, the `args` array is local for each separate code block call by default. + +Separate code blocks in QSP are considered: + +* location code +* code passed to `dynamic`/`dyneval` +* code in hyperlinks +* loop code +* action code + +In the first three cases, the player will create a separate `args` array for each separate session of such code blocks. + +**However:** + +* loops will use the `args` array created in the code block from which the loop was called. +* actions will use the `args` array created at the location that was transitioned to using `goto` or `xgoto` operators. + +## BCOLOR + +`BCOLOR` — contains the current background color. If equal to `0`, then the color specified in the program settings is used. Examples: + +```qsp +! black background color +bcolor = -16777216 +! red background color +bcolor = -16776961 +! white background color +bcolor = -1 +``` + +Since background color is encoded by a special number, and calculating this number manually is inconvenient, you should use the `rgb` function, which takes three color components as arguments: + +```qsp +! set background color through rgb(red,green,blue) function +! blue background +bcolor = rgb(0, 0, 255) +! yellow background +bcolor = rgb(255, 255, 0) +! orange background +bcolor = rgb(255, 130, 0) +! cyan background +bcolor = rgb(0, 255, 255) +! magenta background +bcolor = rgb(255, 0, 255) +``` + +## DEBUG + +`DEBUG` — if the variable value is not zero, game identifier checking is disabled when loading state. Otherwise, every time the game file changes, you won't be able to use save files made before changing the game. + +:::tip[Tip:] +during game development and testing, the `debug` variable value should always be non-zero, and when you release the final game version (release), you need to set the `debug` variable to `0` so players can't load save files from other games. +::: + +## DISABLESCROLL + +`DISABLESCROLL` — if the variable value is not zero, auto-scrolling of text in main and additional description windows is disabled. + +:::note[**What this means**] +Suppose we output a large amount of text to the screen, and then when clicking an `action` we output another text fragment. If `DISABLESCROLL = 0`, this text fragment will force the screen to scroll down when output. If we don't want the screen to scroll down in this case, we assign `1` to the `DISABLESCROLL` variable. +::: + +Quite murky behavior in the classic player — under some circumstances, text doesn't scroll anyway. + +:::note[**Note from Byte:**] + +Supposedly `disablescroll` is used when updating the window. if at the moment of update the value is 0 and there was no transition to a new location (`GT/XGT`), then the description scrolls to the end of the text + +Window update occurs in different cases - for example, after the player performed some action (selected action / object), or the game called `refint` or some modal window (`input` / `msg` / `menu` - what I can remember off the top of my head) + +I.e., imho, there are 2 conditions for text scrolling that must be met. if at least one is not fulfilled, then there will be no scrolling regardless of disablescroll value +::: + +## DISABLESUBEX + +:::warning[Be careful!] +In players version 5.8.0 and higher, this variable is no longer used. +::: + +`DISABLESUBEX` — if the variable value is not zero, sub-expression calculation in strings is disabled. Example: + +```qsp +var = 123 +$text = '<>' & ! variable $text will be assigned string '123' +*pl 'string <>' & ! string 'string 123' will be output to screen +*pl '<<5+6>>' & ! string '11' will be output to screen + +disablesubex = 1 & ! disable sub-expression calculation +$text = '<>' & ! variable $text will be assigned string '<>' +*pl 'string <>' & ! string 'string <>' will be output to screen +*pl '<<5+6>>' & ! string '<<5+6>>' will be output to screen +``` + +## FCOLOR + +`FCOLOR` — contains the color of the currently used font. If equal to `0`, then the color specified in the program settings is used. Changing the variable value changes the color of all game text except hyperlinks and text whose color is reassigned through HTML. Example: + +```qsp +! black text color +fcolor = -16777216 +! red text color +fcolor = -16776961 +! white text color +fcolor = -1 +``` + +Since font color is encoded by a special number, and calculating this number manually is inconvenient, you should use the `rgb` function, which takes three color components as arguments: + +```qsp +! set text color through rgb(red,green,blue) function +! black text +fcolor = rgb(0, 0, 0) +! white text +fcolor = rgb(255, 255, 255) +! red text +fcolor = rgb(255, 0, 0) +! green text +fcolor = rgb(0, 255, 0) +``` + +## FSIZE + +`FSIZE` — contains the size of the currently used font. If equal to `0`, then the size specified in the program settings is used. Font sizes of the HTML `` tag are calculated relative to this value in HTML mode. Example: + +```qsp +fsize = 18 +``` + +Font size is set for all text in the game except text whose size is reassigned through HTML. + +## LCOLOR + +`LCOLOR` — contains the current hyperlink font color. If equal to `0`, then the color specified in the program settings is used. Changing the variable value changes the text color of all hyperlinks except those whose color is reassigned through HTML. Example: + +```qsp +! black hyperlink color +lcolor = -16777216 +! red hyperlink color +lcolor = -16776961 +! white hyperlink color +lcolor = -1 +``` + +Since color in QSP is encoded by a special number, and calculating this number manually is inconvenient, you should use the `rgb` function, which takes three color components as arguments: + +```qsp +! set hyperlink color through rgb(red,green,blue) function +! blue hyperlinks +lcolor = rgb(0, 0, 255) +! yellow hyperlinks +lcolor = rgb(255, 255, 0) +! orange hyperlinks +lcolor = rgb(255, 130, 0) +! cyan hyperlinks +lcolor = rgb(0, 255, 255) +! magenta hyperlinks +lcolor = rgb(255, 0, 255) +``` + +## NOSAVE + +`NOSAVE` — if the value of this variable is not `0`, the player menu item "Save game state" becomes unavailable to the player, i.e., the player cannot save the game independently. At the same time, the `savegame` operator continues to work at the QSP code level. Example: + +```qsp +! disable game saving possibility +nosave = 1 +act "Roll dice": + cubes = rand(1, 6) + ! enable saving possibility back + nosave = 0 + delact $selact +end +``` + +## RESULT + +`RESULT` — specific system variable intended for getting a value in the current code block and passing this value to the `func` or `dyneval` function. In other words, for `func` or `dyneval` functions to return some value, you need to assign a value to the `result` variable in the code block they call. + +For example: + +```qsp +$dyneval { + if args[0] mod 2 = 0: + $result = 'even number' + else + $result = 'odd number' + end +}, 279 +``` + +A separate `result` variable is created for each separate code block by the player. I.e., if you call location "2" from location "1", then location "1" creates its own `result` variable, and location "2" creates its own, and values in these variables don't intersect. Thus, the `result` variable is local for each separate code block call. + +If both `result`, `$result`, and `%result` were set during code block processing, the value written to the variable last will be returned as the result. + +:::note +In players version 5.7.0, a small problem with value intersection in `result` on different locations may be observed. It's recommended to use the `result` variable only at the end of location code. + +In newer player versions, this problem was fixed and `result` can be used alongside `args`. +::: + +## USEHTML + +`USEHTML` — if the value of this variable is not zero, HTML recognition mode is enabled. In this case, HTML markup can be used in action names, object names, in text output to main and additional description windows, as well as in dialog boxes called by the `msg` operator and `$input` function. + +```qsp +! enable HTML +usehtml = 1 +! output text with HTML markup +*pl "Red text." +``` + +:::note[qSpider] +In **qSpider**, recognition is always enabled and is not disabled by changing the `usehtml` variable value. +::: + +## Notes for the Curious + +1. It's possible to define any system variable as local for a separate code block, and then this system variable can be used as a regular local variable, i.e., it won't affect player operation. However, it's **strongly** not recommended to do this to avoid possible errors. +2. Like all other variables in QSP, system variables are also arrays. + * Interface setting variables allow using any cells except zero without consequences; this won't affect player operation, but it's still not recommended unless it's some necessary technical solution. + * But system variables that specify event handler location names give a very peculiar effect when filling cells sequentially. If you write location names in several cells in a row, each location entered in the array will be called sequentially. This way you can unload code from event handler locations. For example, the counter location: + + ```qsp + $counter[] = 'playlist' + $counter[] = 'animation' + $counter[] = 'time.acts' + ``` + + It's very important that location names are listed consecutively in the array. If there are empty cells between location names, only those locations that are in the array before the first encountered empty cell will be executed: + + ```qsp + ! only 'playlist' and 'animation' locations will be executed + $counter[] = 'playlist' + $counter[] = 'animation' + $counter[] = '' + $counter[] = 'time.acts' + ``` \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md new file mode 100644 index 0000000..73cc07c --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md @@ -0,0 +1,8 @@ +--- +id: parsers +title: Parsers +--- + +# Parsers + +The task of a syntax analyzer (i.e., parser) is to take source code written in the [QSP language](../language/) and transform it into a form that can be conveniently worked with later (interpreted, compiled, used for analysis, etc.) \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md new file mode 100644 index 0000000..c4e0fd4 --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md @@ -0,0 +1,24 @@ +--- +id: qsp-fsharp-parser +title: QSP Fsharp Parser +--- + +# Qsp.FSharp.Parser + +[Qsp.FSharp.Parser](https://github.com/QSPFoundation/Qsp.FSharp/tree/master/src/Qsp.FSharp.Core) is developed for development environments that support LSP (for example, VS Code, for whose [extension](https://github.com/QSPFoundation/Qsp.FSharp.VsCode) all this was started). + +Qsp.FSharp.Parser parses the entire source code at once (which differs from the [parser in QSPLib](./qsplib-parser.md)) and simultaneously collects: + +* tokens and their locations (it seems this should be done by a *lexical* analyzer, not a syntactic one, but everything is not so simple there) +* semantic meaning of tokens +* builds a syntax tree + +The main humor is that the syntax tree is not needed at all for the LSP server, but the parser still stubbornly builds it and then discards it. However, it is used for code formatting (which is called, for example, from the LSP server, so it is still needed!) and other not yet documented things. + +Technically, nothing prevents writing an interpreter that could be fed a syntax tree as input, but let QSPLib handle this since it's designed for this purpose. + +Qsp.FSharp.Parser tries to honestly follow the specification, but there are also plenty of personal interpretations and shortcomings. + + + +Written in F#, which, on one hand, ties it to the .Net platform, and on the other hand, allows it to be compiled to JS and other languages using Fable. If there was a desire, as they say. \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md new file mode 100644 index 0000000..3e7d8df --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md @@ -0,0 +1,14 @@ +--- +id: qsplib-parser +title: QSPlib Parser +--- + +# QSPLib Parser + +[QSPLib](https://github.com/QSPFoundation/qsp/tree/master/qsp) was parsing source files long before it became fashionable, and continues to do so to this day. + +It is the parser closest to the language specification (actually, the specification is written from it), and others align with it with varying degrees of success. + +It works on a "lazy" principle: it parses the source line by line and immediately interprets it. Thus, syntax errors are caught only when the parser encounters them. + + \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md new file mode 100644 index 0000000..a96541a --- /dev/null +++ b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md @@ -0,0 +1,41 @@ +--- +id: syntax-highlighting +title: Syntax Highlighting +--- + +# Syntax Highlighting + +Syntax highlighting in editors and other environments is achieved through quite specific means, for which, unfortunately, there is no common solution. And since there is no common solution, difficulties arise with maintaining code for each individual solution. + + + +## Highlighting in VS Code + +VS Code has two highlighting methods: + +* TextMate format +* Semantic highlighting + + + +### Ready-made Solutions {#vscode-text-solutions} + +* TextMate format + * `glife/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json` + * [LangQSP by someone called Xorgroth](https://gitlab.com/kevinsmartstfg/girl-life/-/raw/master/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json) + +* Semantic highlighting + * Combination of `Qsp.FSharp.Parser`, `Qsp.FSharp.ServerLanguage` and `Qsp.FSharp.VsCode` + +## Highlighting in Sublime Text + +### Ready-made Solutions {#sublime-text-solutions} + +* [JAD_for_QSP](https://github.com/AleksVersus/JAD_for_QSP/blob/master/QSP.sublime-package/qsp.sublime-syntax) + +## Highlighting in Other Environments + +* [highlighting on wiki.qsp.org](https://wiki.qsp.org/lib/plugins/syntaxhighlighter3/sxh3/scripts/shBrushQsp.js) +* highlighting in [howdo_faq](https://github.com/AleksVersus/howdo_faq) by Aleks Versus + + The function that converts QSP code is [here](https://github.com/AleksVersus/howdo_faq/blob/7aea086c17ac34171f785f2ef3fc500dc132af6b/res/%5Bconverters%5D/nodes.py#L1204-L1271) \ No newline at end of file From 40596345bffd74a4e12fda63c9ec115b2780e1e1 Mon Sep 17 00:00:00 2001 From: Awesome158 Date: Fri, 8 Aug 2025 10:42:04 +0200 Subject: [PATCH 2/4] fix: replaced broken link with a working alternative --- docs/syntax-highlighting.md | 6 +++--- .../current/syntax-highlighting.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/syntax-highlighting.md b/docs/syntax-highlighting.md index 90acf53..d6f01eb 100644 --- a/docs/syntax-highlighting.md +++ b/docs/syntax-highlighting.md @@ -20,9 +20,9 @@ VS Code есть два способа подсветки: ### Готовые решения {#vscode-text-solutions} -* TextMate формат - * `glife/src/master/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json` - * [LangQSP от некого slanon](https://git.tfgames.site/slanon/LangQSP/src/master/qsrc/syntaxes/QSP.tmLanguage.json) +* TextMate Формат + * `glife/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json` + * [Формат TextMate от некого Xorgroth](https://gitlab.com/kevinsmartstfg/girl-life/-/raw/master/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json) * семантическая подсветка * Связка `Qsp.FSharp.Parser`, `Qsp.FSharp.ServerLanguage` и `Qsp.FSharp.VsCode` diff --git a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md index a96541a..feb2360 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md @@ -22,7 +22,7 @@ VS Code has two highlighting methods: * TextMate format * `glife/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json` - * [LangQSP by someone called Xorgroth](https://gitlab.com/kevinsmartstfg/girl-life/-/raw/master/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json) + * [TextMate format by someone called Xorgroth](https://gitlab.com/kevinsmartstfg/girl-life/-/raw/master/tools/syntax/VSCode/qsrc/syntaxes/QSP.tmLanguage.json) * Semantic highlighting * Combination of `Qsp.FSharp.Parser`, `Qsp.FSharp.ServerLanguage` and `Qsp.FSharp.VsCode` From b9bc9a0626bedd3c5a54c5b8752f6fa037006f80 Mon Sep 17 00:00:00 2001 From: Awesome158 Date: Sat, 9 Aug 2025 15:03:48 +0200 Subject: [PATCH 3/4] Fix: remove title front matter and fixed some errors --- docs/all-together.md | 1 - docs/co-development/index.md | 1 - docs/language/index.md | 1 - docs/language/qsp-keywords/_category_.yml | 2 - .../qsp-keywords/qsp-keyword-functions.md | 1 - .../qsp-keywords/qsp-keyword-operacion.md | 1 - .../qsp-keywords/qsp-keyword-operators.md | 1 - .../qsp-keywords/qsp-keyword-syntaxems.md | 3 +- .../qsp-keywords/qsp-keyword-sys-var.md | 1 - docs/parsers/index.md | 1 - docs/parsers/qsp-fsharp-parser.md | 1 - docs/parsers/qsplib-parser.md | 1 - docs/syntax-highlighting.md | 1 - .../current/all-together.md | 1 - .../current/co-development/index.md | 1 - .../current/intro.md | 1 - .../current/language/index.md | 1 - .../current/language/qsp-keywords/index.md | 12 +- .../qsp-keywords/qsp-keyword-functions.md | 3 +- .../qsp-keywords/qsp-keyword-operacion.md | 1 - .../qsp-keywords/qsp-keyword-operators.md | 883 +++++++++++++----- .../qsp-keywords/qsp-keyword-syntaxems.md | 298 ++---- .../qsp-keywords/qsp-keyword-sys-var.md | 1 - .../current/parsers/index.md | 1 - .../current/parsers/qsp-fsharp-parser.md | 1 - .../current/parsers/qsplib-parser.md | 1 - .../current/syntax-highlighting.md | 1 - 27 files changed, 754 insertions(+), 468 deletions(-) delete mode 100644 docs/language/qsp-keywords/_category_.yml diff --git a/docs/all-together.md b/docs/all-together.md index 6b23539..09550b6 100644 --- a/docs/all-together.md +++ b/docs/all-together.md @@ -1,6 +1,5 @@ --- id: all-together -title: Всё вместе --- # Всё вместе diff --git a/docs/co-development/index.md b/docs/co-development/index.md index 5d61b0f..0a134db 100644 --- a/docs/co-development/index.md +++ b/docs/co-development/index.md @@ -1,6 +1,5 @@ --- id: co-development -title: Совместная разработка --- # Совместная разработка diff --git a/docs/language/index.md b/docs/language/index.md index 5daf6de..16dc2a1 100644 --- a/docs/language/index.md +++ b/docs/language/index.md @@ -1,6 +1,5 @@ --- id: language -title: Язык QSP sidebar_position: 1 --- diff --git a/docs/language/qsp-keywords/_category_.yml b/docs/language/qsp-keywords/_category_.yml deleted file mode 100644 index 438662f..0000000 --- a/docs/language/qsp-keywords/_category_.yml +++ /dev/null @@ -1,2 +0,0 @@ -position: 99 -label: Зарезервированные слова, системные переменные, спецсимволы diff --git a/docs/language/qsp-keywords/qsp-keyword-functions.md b/docs/language/qsp-keywords/qsp-keyword-functions.md index dd42f3c..f2ac854 100644 --- a/docs/language/qsp-keywords/qsp-keyword-functions.md +++ b/docs/language/qsp-keywords/qsp-keyword-functions.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-functions -title: Функции sidebar_position: 3 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-operacion.md b/docs/language/qsp-keywords/qsp-keyword-operacion.md index 498990b..61f1f25 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operacion.md +++ b/docs/language/qsp-keywords/qsp-keyword-operacion.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-operacion -title: Операции sidebar_position: 1 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-operators.md b/docs/language/qsp-keywords/qsp-keyword-operators.md index c69d5d7..e3005ed 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operators.md +++ b/docs/language/qsp-keywords/qsp-keyword-operators.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-operators -title: Операторы sidebar_position: 2 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-syntaxems.md b/docs/language/qsp-keywords/qsp-keyword-syntaxems.md index f15c8f2..9322f67 100644 --- a/docs/language/qsp-keywords/qsp-keyword-syntaxems.md +++ b/docs/language/qsp-keywords/qsp-keyword-syntaxems.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-syntaxems -title: Синтаксемы и спецсимволы sidebar_position: 5 --- @@ -504,4 +503,4 @@ number = 123 $var[0], $var[1] = %number *pl '[<<$var[0]>>,<<$var[1]>>]' ! На экране увидим '[,]' -``` +``` \ No newline at end of file diff --git a/docs/language/qsp-keywords/qsp-keyword-sys-var.md b/docs/language/qsp-keywords/qsp-keyword-sys-var.md index e206c49..55c7ee3 100644 --- a/docs/language/qsp-keywords/qsp-keyword-sys-var.md +++ b/docs/language/qsp-keywords/qsp-keyword-sys-var.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-sys-var -title: Системные переменные sidebar_position: 4 --- diff --git a/docs/parsers/index.md b/docs/parsers/index.md index b8433c5..64ff722 100644 --- a/docs/parsers/index.md +++ b/docs/parsers/index.md @@ -1,6 +1,5 @@ --- id: parsers -title: Парсеры --- # Парсеры diff --git a/docs/parsers/qsp-fsharp-parser.md b/docs/parsers/qsp-fsharp-parser.md index 90d783a..4355659 100644 --- a/docs/parsers/qsp-fsharp-parser.md +++ b/docs/parsers/qsp-fsharp-parser.md @@ -1,6 +1,5 @@ --- id: qsp-fsharp-parser -title: Qsp Fsharp Parser --- # Qsp.FSharp.Parser diff --git a/docs/parsers/qsplib-parser.md b/docs/parsers/qsplib-parser.md index 2371249..cc9bc30 100644 --- a/docs/parsers/qsplib-parser.md +++ b/docs/parsers/qsplib-parser.md @@ -1,6 +1,5 @@ --- id: qsplib-parser -title: QSPlib Parser --- # QSPLib Parser diff --git a/docs/syntax-highlighting.md b/docs/syntax-highlighting.md index d6f01eb..5db6f58 100644 --- a/docs/syntax-highlighting.md +++ b/docs/syntax-highlighting.md @@ -1,6 +1,5 @@ --- id: syntax-highlighting -title: Подсветка синтаксиса --- # Подсветка синтаксиса diff --git a/i18n/en/docusaurus-plugin-content-docs/current/all-together.md b/i18n/en/docusaurus-plugin-content-docs/current/all-together.md index 203002e..86ec09f 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/all-together.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/all-together.md @@ -1,6 +1,5 @@ --- id: all-together -title: All Together --- # All Together diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md b/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md index 342b1a9..f58c46c 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md @@ -1,6 +1,5 @@ --- id: co-development -title: Collaborative Development --- # Collaborative Development diff --git a/i18n/en/docusaurus-plugin-content-docs/current/intro.md b/i18n/en/docusaurus-plugin-content-docs/current/intro.md index 453cc79..1eada20 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/intro.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/intro.md @@ -1,6 +1,5 @@ --- id: intro -title: QSP Foundation sidebar_position: 1 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/index.md b/i18n/en/docusaurus-plugin-content-docs/current/language/index.md index c54730c..62fba28 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/index.md @@ -1,6 +1,5 @@ --- id: language -title: Language sidebar_position: 1 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md index 9e3936c..cc210fe 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md @@ -1,13 +1,13 @@ --- id: qsp-keywords -title: Reserved Words, System Variables, Special Symbols +title: Reserved Words, System Variables, Special Characters sidebar_position: 6 --- # Index :::warning[Attention!] -Crossed-out commands do not work in players version 5.8.0 and higher. +Crossed out commands do not work in players version 5.8.0 and above. ::: - [Implicit operator](qsp-keyword-operators#implicit-operator) @@ -19,12 +19,12 @@ Crossed-out commands do not work in players version 5.8.0 and higher. - [`,` (argument separator)](qsp-keyword-syntaxems.md#comma-) - [`""` (quotes)](qsp-keyword-syntaxems.md#quote-) - [`''` (apostrophes)](qsp-keyword-syntaxems.md#apostrophe-) -- [`{}` (Curly brackets)](qsp-keyword-syntaxems.md#curly-brackets-) +- [`{}` (Curly braces)](qsp-keyword-syntaxems.md#curly-braces-) - [`()` (round brackets)](qsp-keyword-syntaxems.md#round-brackets-) - [`[]` (square brackets)](qsp-keyword-syntaxems.md#square-brackets-) -- [`@` (commercial "at")](qsp-keyword-syntaxems#at-symbol-) - 5.8.0 -- [`$` (dollar sign)](qsp-keyword-syntaxems#dollar-sign-) -- [`%` (percent sign)](qsp-keyword-syntaxems#percent-sign-) - 5.9.0 +- [`@` (commercial "at")](qsp-keyword-syntaxems#commercial-at-symbol-) - 5.8.0 +- [`$` (dollar sign)](qsp-keyword-syntaxems#dollar-sign-symbol-) +- [`%` (percent sign)](qsp-keyword-syntaxems#percent-sign-symbol-) - 5.9.0 - [`*`](qsp-keyword-operacion.md#-multiplication) - [`*=`](qsp-keyword-operacion.md#-multiplication-assignment) - [`+`](qsp-keyword-operacion.md#-addition) diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md index 86a77e7..2124381 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-functions -title: Functions sidebar_position: 3 --- @@ -213,7 +212,7 @@ $name_loc = "summ" *pl func($name_loc, 23) & ! will output 276 to screen ``` -Also see ["Implicit `FUNC` function call"](qsp-keyword-syntaxems.md#at-symbol-). +Also see ["Implicit `FUNC` function call"](qsp-keyword-syntaxems#commercial-at-symbol-). ## `$GETOBJ` diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md index 0d94414..ed67fd9 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-operacion -title: Operations sidebar_position: 1 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md index 906301d..da210d6 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md @@ -1,14 +1,13 @@ --- id: qsp-keyword-operators -title: Operators sidebar_position: 2 --- # Operators -## Implicit Operator +## Implicit operator -The implicit operator is an operator that is not written in QSP code but produces output of values to the screen. It is implied everywhere where an expression without an operator is present in a command. The implicit operator outputs values to the **Main Description Window** in the same way as if you used the explicit `*pl` operator, i.e., it outputs the value and makes a line break. Examples: +The implicit operator is an operator that is not written in QSP code but outputs values to the screen. It is implied wherever an expression without an operator is present in a command. The implicit operator outputs values to the **Main Description Window** in the same way as if you used explicit specification of the `*pl` operator, i.e., it outputs the value and makes a line break. Examples: ```qsp $AAA + '989' @@ -19,11 +18,11 @@ $AAA + '989' $curloc & ! will output the location name to the screen ``` -Unlike the `*pl` operator, the implicit operator does not output an empty string with a line break to the screen if no value is passed to it. This means that if a function returns no value, the implicit operator is simply ignored. Example: +Unlike the `*pl` operator, the implicit operator does not output an empty line with a line break to the screen if no value is passed to it. This means that if a function returns no value, the implicit operator is simply ignored. Example: ```qsp # start -! this is location code calling a function location +! this is the code of a location calling a location-function $curloc $func('foo') $func('foo') @@ -31,16 +30,16 @@ $curloc - start # foo -! this is function location code +! this is the code of the location-function local i = 0 - foo ``` -In this case, the `foo` function location returns nothing, so we will see two lines with the word "start" on the screen, with no empty lines between them, since the implicit operator in the lines with `$func` on the `start` location will simply be ignored. Compare with: +In this case, the location-function `foo` returns nothing, so we will see two lines with the word "start" on the screen, with no empty lines between them, since the implicit operator in the lines with `$func` at location `start` will be simply ignored. Compare with: ```qsp # start -! this is location code calling a function location +! this is the code of a location calling a location-function *pl $curloc *pl $func('foo') *pl $func('foo') @@ -48,22 +47,22 @@ In this case, the `foo` function location returns nothing, so we will see two li - start # foo -! this is function location code +! this is the code of the location-function local i=0 - foo ``` ## `!` (comment) -`!` — comment operator. What is in the line after the comment operator and until the end of the line is ignored by the interpreter. The comment operator allows you to "comment out" (disable) an unnecessary operator/function temporarily during game debugging. Additionally, writing comments to program code is one of the signs of good programming style. +`!` — comment operator. What is in the line after the comment operator and until the end of the line is ignored by the interpreter. The comment operator allows you to "comment out" (disable) an unnecessary operator/function temporarily during game debugging. In addition, writing comments to program code is one of the signs of good programming style. -It's important to clearly understand that this is exactly an operator, so if you're commenting some line of code, the `!` should come after `&`: +It is necessary to clearly understand that this is an operator, so if you are commenting some line of code, then `!` should come after `&`: ```qsp *pl "Hello, world!" & ! comment ``` -Comments can be single-line, i.e., ending on the same line where the comment operator is: +Comments can be single-line, i.e., end on the same line where the comment operator is located: ```qsp ! single-line comment @@ -94,15 +93,15 @@ Multi-line comments can take various forms: ```qsp ! line before quotes " text inside quotes -can go to other lines " as well as { -you can use other groups of symbols to +can move to other lines " as well as { +you can use other character groups to continue the multi-line comment } and the comment won't end until the line ends ``` ## `*CLEAR` -`*CLEAR` — clears the main description window. Has the short form `*clr`. +`*CLEAR` — clears the main description window. Has a short form `*clr`. ## `*NL` @@ -112,7 +111,7 @@ continue the multi-line comment *NL [$text] ``` -, where `[$text]` — any text string, number, or expression of any type. If `[$text]` is absent, just a line break occurs. Example: +where `[$text]` is any text string, number, or expression of any type. If `[$text]` is absent, a simple line break occurs. Example: ```qsp *p "Text without line break." @@ -122,13 +121,13 @@ continue the multi-line comment ## `*P` -`*P` — text output to the main description window without line break. Text output by any other operator immediately after `*p` will add new text right after the current one. General syntax: +`*P` — text output to the main description window without line break. Text output by any other operator immediately after `*p` will add new text immediately after the current text. General syntax: ```qsp *P [$text] ``` -, where `[$text]` — any text string, number, or expression of any type. `[$text]` can be an empty string `''`, but must not be absent. Example: +where `[$text]` is any text string, number, or expression of any type. `[$text]` can be an empty string `''`, but should not be absent. Example: ```qsp *p "Text without line break." @@ -145,16 +144,16 @@ continue the multi-line comment *PL [$text] ``` -where `[$text]` — any text string, number, or expression of any type. `[$text]` can be absent, then just a line break. Example: +where `[$text]` is any text string, number, or expression of any type. `[$text]` can be absent, then just a line break. Example: ```qsp -*pl "Output text, then line break." -*pl "Output text, then line break." +*pl "Text output, then line break." +*pl "Text output, then line break." *p "Text without line break." -*pl "Output text, then line break." +*pl "Text output, then line break." ``` -Similarly, you can output text by simply writing the desired expression instead of this operator. For example, the lines: +You can output text in the same way by simply writing the needed expression instead of this operator. For example, the lines: ```qsp *pl $AAA + '989' @@ -183,28 +182,28 @@ will work identically. General syntax in single-line form: ```qsp -ACT [$name], [$image_path]: [operator] & [operator] & [operator] +ACT [$name], [$path to image file]: [operator] & [operator] & [operator] ``` General syntax in multi-line form: ```qsp -ACT [$name], [$image_path]: +ACT [$name], [$path to image file]: [operator] [operator] [operator] END ``` -A new action with the name `[$name]` and image located at `[$image_path]` is added to the actions list in the actions window. When the action is clicked, the specified operators are executed. +A new action with name `[$name]` and image located at `[$path to image file]` is added to the actions list in the actions window. When the action is clicked, the specified operators are executed. -The `[$image_path]` parameter can be absent, in which case the action is added without an image. +The `[$path to image file]` parameter can be absent, in which case the action is added without an image. Examples: ```qsp ! action in single-line form -act "Pick apple from birch": apple += 1 & *pl "You picked an apple, ripe and white." +act "Pick apple from birch": apple += 1 & *pl "You picked a ripe white apple." ! action in multi-line form, with image act "Pick watermelon from bush", "img/watermelon.png": @@ -213,7 +212,7 @@ act "Pick watermelon from bush", "img/watermelon.png": end ``` -If there is already an action with the specified name in the actions list, no new action is created, and it doesn't replace the existing one; the player simply ignores the `act` command. Thus, you cannot output actions with identical names. Example: +If there is already an action with the specified name in the actions list, no new action is created, and it does not replace the existing one, the player simply ignores the `act` command. Thus, you cannot output actions with identical names. Example: ```qsp act "Action 1": *pl "Old action." @@ -227,46 +226,47 @@ usehtml = 1 act 'Action 1': *pl "Old action." act 'Action 1': *pl "New action." ``` + ## ADDOBJ -`ADDOBJ` — adding a new item to the objects window. General syntax: +`ADDOBJ` — adding a new object to the objects window. General syntax: ```qsp -ADDOBJ [$name], [$image_path], [#position] +ADDOBJ [$name], [$path to image file], [#position] ``` -, where `[$name]` — the item name, `[$image_path]` — the path to the item's image file (displayed next to the item name), and `[#position]` — what position in the inventory the item is added to. The `[#position]` parameter can be absent. By default, items are added to the end of the list. Item numbering in the inventory starts from `1`. The `[$image_path]` parameter can be absent, default value is `''`, in which case the item is added without an image. +where `[$name]` is the object name, `[$path to image file]` is the path to the object's image file (displayed next to the object name), and `[#position]` is the position in the inventory where the object is added. The `[#position]` parameter can be absent. By default, objects are added to the end of the list. Object numbering in the inventory starts from `1`. The `[$path to image file]` parameter can be absent, default value is `''`, in which case the object is added without an image. -:::note[Deprecated but acceptable legacy form:] +:::note[Allowed but not recommended, deprecated form:] ```qsp -ADD OBJ [$name],[$image_path],[#index] +ADD OBJ [$name],[$path to image file],[#index] ``` ::: -You can add items with the same name, however, if you plan to add many identical items, it's better to use an additional variable to count these items and add one item to the objects window to avoid cluttering the inventory with a list of 137 Ruble / Bullet items: +You can add objects with the same name, but if you plan to add many identical objects, it's better to use an additional variable to count these objects and add one object to the objects window to avoid cluttering the inventory with a list of 137 Ruble / Cartridge objects: ```qsp -if obj('Bullets'): -! if the "Bullets" item is already added, just increase their number - bullets += 10 +if obj('Cartridges'): +! if object "Cartridges" is already added, just increase their number + cartridges += 10 else -! if the "Bullets" item is not yet added, add it and increase the number - addobj 'Bullets' - bullets += 10 +! if object "Cartridges" is not yet added, add it and increase the number + addobj 'Cartridges' + cartridges += 10 end ``` -For storing the number of items, you can use arrays indexed by strings: +You can use arrays indexed by strings to store object counts: ```qsp objects['money'] = 12 -objects['bullets'] = 137 +objects['cartridges'] = 137 'Quantity: <>' ``` -Example of adding an item to the very top of the list (all other items will shift down): +Example of adding an object to the very top of the list (all other objects will shift down): ```qsp addobj "Screwdriver", "", 1 @@ -274,29 +274,29 @@ addobj "Screwdriver", "", 1 ## CLA -`CLA` - clears the current actions list (removes all actions from the actions window). +`CLA` - clearing the list of current actions (removing all actions from the actions window). ## CLEAR -`CLEAR` — clears the additional description window. Has the short form `clr`. +`CLEAR` — clears the additional description window. Has a short form `clr`. ## CLOSE `CLOSE` — stops playing the specified sound file. General syntax: ```qsp -CLOSE [$sound_file_path] +CLOSE [$path to sound file] ``` -, where `[$sound_file_path]` — path to the sound file relative to the game file. If the `[$sound_file_path]` parameter is not specified, all sound files stop playing. +where `[$path to sound file]` is the path to the sound file relative to the game file. If the `[$path to sound file]` parameter is not specified, all sound files stop playing. ## CLOSE ALL -`CLOSE ALL` — stops playing all active sound files. Has the short form `close`. +`CLOSE ALL` — stops playing all active sound files. Has a short form `close`. ## CLS -`CLS` — clears all windows except the objects list. Equivalent to: +`CLS` — clears all windows except the objects list. Equivalent to the construction: ```qsp clear & *clear & cla & cmdclear @@ -304,33 +304,33 @@ clear & *clear & cla & cmdclear ## CMDCLEAR -`CMDCLEAR` — clears the input line. Has the short form `cmdclr`. +`CMDCLEAR` — clearing the input line. Has a short form `cmdclr`. ## COPYARR -`COPYARR` — copies the contents of one array to another. General syntax: +`COPYARR` — copying the contents of one array to another. General syntax: ```qsp -COPYARR [$destination], [$source], [#start], [#count] +COPYARR [$receiver], [$source], [#start], [#count] ``` -, where: `[$destination]` — the array to copy to, size and content don't matter; `[$source]` — the array to copy from; `[#start]` — the element number to start copying from; `[#count]` — how many elements to copy. The `[#count]` parameter is optional; default is until the end of the source array. The `[#start]` parameter is optional; default is 0. +where: `[$receiver]` is the array to which copying is performed, size and content don't matter; `[$source]` is the array from which copying is performed; `[#start]` is the element number from which to start copying; `[#count]` is how many elements to copy. The `[#count]` parameter is optional; by default — until the end of the source array. The `[#start]` parameter is optional; by default — 0. Examples: ```qsp ! copy all elements of array '$b' to array '$a' copyarr '$a', '$b' -! also copied all elements of array 'b' to array 'a' +! at the same time, all elements of array 'b' were also copied to array 'a' -! copy elements of array 'd' to array 'c', starting from the sixth +! copy elements of array 'd' starting from the sixth to array 'c' copyarr 'c', 'd', 6 ! copy the first six elements of array 'd' to array 'c' copyarr 'c', 'd', 0, 6 ``` -Due to player specifics, when copying, for example, numeric array `mass1` to `mass2`, the text array `$mass1` is also copied to `$mass2`. +Due to player peculiarities, when copying, for example, numeric array `mass1` to `mass2`, text array `$mass1` is also copied to `$mass2`. Other examples: @@ -341,13 +341,13 @@ copyarr 'a<<$arrname1>>', 'a<<$arrname2>>' ## DELACT -`DELACT` — removes an action from the actions list (if such an action exists). General syntax: +`DELACT` — removes an action from the actions list (if such action exists). General syntax: ```qsp DELACT [$name] ``` -, where `[$name]` — the name of the action to remove. +where `[$name]` is the name of the action we want to remove. Examples: @@ -358,7 +358,7 @@ delact 'Go forward' delact $selact ``` -:::note[Deprecated but acceptable legacy form:] +:::note[Allowed but not recommended, deprecated form:] ```qsp DEL ACT [$name] @@ -368,26 +368,26 @@ DEL ACT [$name] ## DELOBJ -`DELOBJ` — removes an item from inventory by name (if such an item exists). General syntax: +`DELOBJ` — removing an object from inventory by name (if such object exists). General syntax: ```qsp DELOBJ [$name] ``` -, where `[$name]` — the name of the item to remove. +where `[$name]` is the name of the object we want to remove. -If there are identical items in the inventory, the command will remove the topmost one with the specified index. +If there are identical objects in the inventory, the command will remove the topmost one with the specified index. Examples: ```qsp -! remove item with specific name +! remove object with specific name delobj "Screwdriver" -! remove selected item +! remove selected object delobj $selobj ``` -:::note[Deprecated but acceptable legacy form:] +:::note[Allowed but not recommended, deprecated form:] ```qsp DEL OBJ [$name] @@ -403,7 +403,7 @@ DEL OBJ [$name] DYNAMIC([$code], [argument 0], [argument 1], ... , [argument 18]) ``` -, where `[$code]` — regular QSP code written as text. Executing such code is analogous to executing `GOSUB` operator code. Arguments `[argument 0]`, `[argument 1]`, etc. can be used inside `[$code]`, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After execution, old `args` parameters are restored, then code execution continues from the next command after `dynamic`. +where `[$code]` is regular QSP code written as text. Execution of such code is similar to executing `GOSUB` operator code. Arguments `[argument 0]`, `[argument 1]`, etc. can be used inside `[$code]`, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After execution, old `args` parameters are restored, then code execution continues from the next command after `dynamic`. Examples: @@ -417,9 +417,9 @@ dynamic " ", 'Text', 'Fork' ``` -The following information is also valid for the [`dyneval`](qsp-keyword-functions.md#dyneval) function. +The following information is also true for the [`dyneval`](qsp-keyword-functions.md#dyneval) function. -**Important!** If code is specified using apostrophes (`''`) or quotes (`""`), sub-expressions are calculated in the text: +**Important!** If code is specified using apostrophes (`''`) or quotes (`""`), sub-expressions are evaluated in the text: ```qsp $args[0] = 'qwerty' @@ -431,9 +431,9 @@ $code = ' dynamic $code, 'asdfg' ``` -In this case, when setting the `$code` variable, the sub-expression will be calculated, so 'qwerty' will be output on the first line, and 'asdfg' on the second line. +In this case, when setting the `$code` variable, the sub-expression will be evaluated, so the first line will output 'qwerty', the second line will output 'asdfg'. -Curly braces are the third type of quotes used specifically for writing dynamic code. Here, bracket nesting is supported, and sub-expressions are not calculated before code execution: +Curly braces are the third type of quotes used specifically for writing dynamic code. Here, bracket nesting is supported, and sub-expressions are not evaluated before code execution: ```qsp $args[0]='qwerty' @@ -449,7 +449,7 @@ In this case, two lines 'asdfg' will be output. ## EXIT -`EXIT` — terminates execution of the current code block (premature exit from a subroutine, function, event handler, etc.). +`EXIT` — termination of the current code block execution (premature exit from subroutine, function, event handler, etc.). A code block can be a location, action, code passed to `dynamic` or `dyneval`, or code in a hyperlink. @@ -468,9 +468,9 @@ end ``` :::warning[Attention!!!] -In players version 5.8.0, the `loop` cycle operator appeared. +In players version 5.8.0, the `loop` operator appeared. -The loop body is also considered a separate code block, however, the `exit` operator interrupts not only the loop itself but also the code block in which the loop is located. +The loop body is also considered a separate code block, but the `exit` operator interrupts not only the loop itself, but also the code block in which the loop is located. ::: ## FREELIB @@ -483,7 +483,7 @@ In older player versions, the command was called `dellib` and `killqst`. ## GOSUB -`GOSUB` — executes code of the specified location without direct transition to it. +`GOSUB` — executing code of the specified location without directly going to it. General syntax: @@ -491,9 +491,9 @@ General syntax: GOSUB [$location],[argument 0],[argument 1], ... ,[argument 8] ``` -, where `[$location]` — the name of the location whose code we want to execute without direct transition to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After processing the location, previous `args` values are restored. Using arguments is not mandatory. +where `[$location]` is the name of the location whose code we want to execute without directly going to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used on this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After processing the location, previous `args` values are restored. Using arguments is not mandatory. -When calling a location via `gosub`, the base description of the location is added to the current description, base actions are added to current actions, and operators in the "Execute on visit" field are executed, then return to the original line (continue code execution after `gosub`). +When accessing a location via `gosub`, the base description of the location is added to the current description, base actions are added to current actions, and operators in the "Execute on visit" field are executed, then return to the original line (continuing code execution after `gosub`). Examples of calling locations via `gosub`: @@ -505,7 +505,7 @@ gosub 'move' !One parameter is passed - args[0] equals 1. gosub $location,1 -!processing location "move" with 3 parameters passed. +!processing location "move" with passing 3 parameters. ! $args[0] = $var (value), args[1] = 2, ! $args[2] = "data". Note the '$' symbols. gosub 'move',$var,2,'data' @@ -514,10 +514,10 @@ gosub 'move',$var,2,'data' Another example: ```qsp -! this is code calling location "transition" +! this is the code for calling location "transition" gosub 'transition', 'location' -! and this is code of the "transition" location itself +! and this is the code of the location "transition" itself # transition *pl $args[0] & ! the text 'location' will be output to the screen ! a new action will appear in the actions window: @@ -541,9 +541,9 @@ GS [$location], [argument 0], [argument 1], ... , [argument 18] GOTO [$location], [argument 0], [argument 1], ... , [argument 18] ``` -, where `[$location]` — the name of the location to transition to. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. Using arguments is not mandatory. +where `[$location]` is the name of the location to which the transition should be made. Arguments `[argument 0]`, `[argument 1]`, etc. can be used on this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. Using arguments is not mandatory. -When transitioning to a new location using `goto`, the main description window is cleared, as well as the current actions list, then the base description text is output to the main description window, base actions to the actions window, and code from the "Execute on visit" field of location `[$location]` is executed. Also, when transitioning to a new location, the value returned by the `$curloc` function changes. +When transitioning to a new location using `goto`, the main description window is cleared, as well as the list of current actions, then the base description text is output to the main description window, base actions to the actions window, and code from the "Execute on visit" field of location `[$location]` is executed. Also, when transitioning to a new location, the value returned by the `$curloc` function changes. Examples: @@ -552,9 +552,9 @@ Examples: ! The args array at location "house" will be empty. goto 'house' -! transition to location "street" with 2 parameters passed. +! transition to location "street" with passing 2 parameters. ! at location "street" args[0] equals 1, -! $args[1] contains the string "data". +! $args[1] contains string "data". goto 'street',1,'data' ``` @@ -566,9 +566,9 @@ GT [$location],[argument 0],[argument 1], ... ,[argument 8] ## IF -`IF` — the main operator for writing conditional constructs. Constructs written using this operator (let's call them "simple conditions") have two forms: single-line and multi-line, — and generally look like this: +`IF` — the main operator for writing conditional constructions. Constructions written using this operator (let's call them "simple conditions") have two forms: single-line and multi-line, and generally look like this: -General syntax: +General form: ```qsp ! single-line form @@ -582,22 +582,22 @@ IF [#expression]: END ``` -In this case, if the condition `[#expression]` is true, commands `{command 1}`, `{command 2}`, etc. are executed. +In this case, if condition `[#expression]` is true, commands `{command 1}`, `{command 2}`, etc. are executed. -- For **single-line form**, these will only be those commands that are on the same line as the `IF` operator until the end of the line; +- For **single-line form**, these will be only those commands that are on the same line as the `IF` operator until the end of the line; - and for **multi-line form**, these will be those commands that are in subsequent lines after the colon and until the special keyword `END`. Comparison operations, logical operations, and other expressions returning numeric values can serve as conditions. The `END` keyword in multi-line form must be on a separate line. -If the condition `[#expression]` is not true, the commands will not be executed. +If condition `[#expression]` is not true, commands will not be executed. Examples of single-line conditional forms: ```qsp ! if the sum of a and b equals two, -! variable c is assigned the value 30 +! variable c is assigned value 30 if a + b = 2: c = 30 ! If there's no orange in inventory, text is output if no obj("Orange"): pl "You don't have an orange." @@ -620,16 +620,16 @@ end :::warning[Pay attention!!!] -In multi-line form, no commands should follow the colon on the same line as the IF operator, otherwise the player will consider such a conditional operator single-line, and commands in subsequent lines will be executed regardless of whether the condition is true or not. Example of such erroneous notation: +In multi-line form, after the colon on the same line where the IF operator is located, there should be no commands, otherwise the player will consider such a conditional operator single-line, and commands in subsequent lines will be executed in any case, regardless of whether the condition turns out to be true or not. Example of such erroneous notation: ```qsp if library = 0: learned_about_party = 0 - library_returned = 1 &! this line will execute regardless of condition truth + library_returned = 1 &! this line will be executed regardless of the condition's truth gt 'library' &! and this one too end &! the end keyword is simply ignored ``` -The exception is a comment operator written after the colon: +The exception is the comment operator written after the colon: ```qsp if library = 0: ! if haven't visited library @@ -643,7 +643,7 @@ But if the comment is separated by an ampersand, the condition will be considere ```qsp if library = 0: & ! such a comment makes the condition single-line! - learned_about_party = 0 & ! this line will execute regardless of condition truth + learned_about_party = 0 & ! this line will be executed regardless of the condition's truth library_returned = 1 & ! and this one gt 'library' &! and this one too end &! the end keyword is simply ignored @@ -651,7 +651,7 @@ end &! the end keyword is simply ignored ::: -For multi-line forms, unlimited nesting depth is allowed. Each nesting level must end with its own `end` line. +For multi-line forms, unlimited depth nesting is allowed. Each nesting level must end with its own `end` line. Examples: @@ -691,8 +691,8 @@ Several examples of incorrect notation: ! the player will ignore only the command `k1=34` ! since it will consider this a single-line condition if abcd=3: k1=34 - k2=35 & ! this command will always execute - k3=36 & ! this command will always execute + k2=35 & ! this command will always be executed + k3=36 & ! this command will always be executed end & ! this end will be ignored ``` @@ -706,8 +706,8 @@ if abcd=3: k1=34 else k1=25 end `ELSE` — keyword used together with the `IF` operator, which serves to provide an alternative if the condition is not met. The `ELSE` keyword also has two forms: single-line and multi-line. -- Multi-line form of `ELSE` can only be used in multi-line `IF` constructs, -- single-line form can be used in both single-line and multi-line `IF` constructs. General syntax: +- Multi-line form of `ELSE` can only be used in multi-line construction of the `IF` operator, +- single-line form can be used both in single-line and multi-line constructions of the `IF` operator. General form: ```qsp ! single-line form @@ -715,7 +715,7 @@ IF [#expression]: {command y1} & {command y2} & ... ELSE {command n1} & {command ! in multi-line IF: -! multi-line ELSE form +! multi-line form of ELSE IF [#expression]: {command y1} {command y2} @@ -726,28 +726,28 @@ ELSE ... END -! single-line ELSE form +! single-line form of ELSE IF [#expression]: {command y1} {command y2} ... ELSE {command n1} & {command n2} & ... - ! commands in subsequent lines + ! commands in following lines ! until END are ignored END ``` -Here, if condition `[#expression]` is true, commands from the colon to the `ELSE` keyword are executed, and if condition `[#expression]` is not true, commands from the `ELSE` keyword to the end of the conditional construct are executed. +Here, if condition `[#expression]` is true, commands from the colon to the `ELSE` keyword are executed, and if condition `[#expression]` is not true, commands from the `ELSE` keyword to the end of the conditional construction are executed. -You can put a colon after `ELSE` or not. +After `ELSE` you can put or not put a colon. **For single-line form:** - both commands and the `ELSE` keyword must be written on one line - the end of the alternative command list is the end of the line. -- if single-line `ELSE` form is used in multi-line `IF` form, all commands in subsequent lines after `ELSE` until `END` are ignored. +- if single-line form of `ELSE` is used in multi-line form of `IF`, all commands that follow in subsequent lines after `ELSE` until `END` are ignored. -Single-line examples: +Examples of single-line notation: ```qsp ! if the sum of a and b equals two, variable c is assigned value 30 @@ -759,12 +759,12 @@ if a+b=2: c=30 else c=10 ! corresponding text is output if obj("Orange"): pl "You have an orange." else pl "You don't have an orange." -! single-line else form inside multi-line if +! single-line form of else inside multi-line if if $left_hand = 'Great sword': - gosub 'attack', 300 + gosub 'atack', 300 gosub 'health.prove' gosub 'win.prove' -else gosub 'attack', attack_power +else gosub 'atack', atack_power end ``` @@ -772,7 +772,7 @@ end - all commands must be in subsequent lines after `ELSE`; -Multi-line examples: +Examples of multi-line notation: ```qsp if a+b=2: @@ -798,10 +798,10 @@ end `ELSEIF` — keyword used together with the `IF` operator and allows defining sequentially-exclusive conditions at one nesting level. Has single-line and multi-line forms. -- Multi-line form can only be used in multi-line `IF` constructs, -- single-line — in both multi-line and single-line `IF` constructs. +- Multi-line form can only be used in multi-line constructions with the `IF` operator, +- single-line form can be used in both multi-line and single-line constructions with the `IF` operator. -General syntax: +General forms: ```qsp ! single-line in single-line condition @@ -831,22 +831,22 @@ ELSE {last command set} END ``` -This works as follows. If `[#expression 1]` is true, `{command set 1}` is executed. If `[#expression 1]` is false but `[#expression 2]` is true, `{command set 2}` is executed, and so on. Only if all expressions in the current conditional construct are false, the commands after `ELSE` will be executed. The truth of expression `[#expression 1]` does not exclude the truth of expression `[#expression 2]`, but the truth of expression `[#expression 2]` excludes the truth of expression `[#expression 1]`. +This works as follows. If `[#expression 1]` is true, commands `{command set 1}` are executed. If `[#expression 1]` is false, but `[#expression 2]` is true, commands `{command set 2}` are executed, and so on. And only if all expressions in the current conditional construction are false, commands after `ELSE` will be executed. The truth of expression `[#expression 1]` does not exclude the truth of expression `[#expression 2]`, but the truth of expression `[#expression 2]` excludes the truth of expression `[#expression 1]`. -`ELSEIF` notation features: +Features of `ELSEIF` notation: - The variant `ELSE IF` can be used. Works exactly the same. -- If in a multi-line `IF` construct operators follow `ELSEIF` on the same line (single-line form), then all subsequent lines are ignored until the next `ELSEIF`, or until `ELSE` or `END`. -- In an `IF` construct with `ELSEIF`, the `ELSE` part may or may not be present. +- If in multi-line `IF` construction after `ELSEIF` operators are on the same line (single-line form), then all subsequent lines are ignored until the next `ELSEIF`, or until `ELSE` or `END`. +- In `IF` construction with `ELSEIF`, the part with `ELSE` can be either present or absent. Examples: ```qsp -if obj('Health Potion'): health += 100 elseif obj('Apple'): health += 15 else *pl 'Nothing to restore strength with!' +if obj('Health potion'): health += 100 esleif obj('Apple'): health += 15 else *pl 'Nothing to restore strength!' -IF SCORE>124: +IF POINTS>124: GOTO 'END3' -ELSEIF SCORE>99: +ELSEIF POINTS>99: GOTO 'END4' ELSE GOTO 'END5' @@ -864,7 +864,7 @@ end Example of `ELSEIF` notation with operators on the same line: ```qsp -! switch/case implementation in QSP +! implementing switch/case in QSP if r = 0: 'Option 0' elseif r = 1: 'Option 1' @@ -876,16 +876,16 @@ end :::tip[Note:] -For better code readability, it's recommended to use `elseif` constructs only in multi-line `if` operator form. +For better code readability, it's recommended to use constructions with `elseif` only in multi-line form of the `if` operator. ::: ## INCLIB -`INCLIB` — from the specified game file, adds all locations whose names are absent among current game locations. Loaded locations are fully equivalent to locations from the main game file. General syntax: +`INCLIB` — from the specified game file, adds all locations whose names are absent among the current game locations. Loaded locations are fully equivalent to locations from the main game file. General syntax: ```qsp -INCLIB [$game_file_path] +INCLIB [$path to game file] ``` Example: @@ -904,21 +904,21 @@ In older player versions, the command was called `addqst` and `addlib`. ## JUMP -`JUMP` — jump within the current code block to the specified label. General syntax: +`JUMP` — jump in the current code block to the specified label. General syntax: ```qsp JUMP [$label] ``` -, where `[$label]` — a label below or above in the code (see section ["Labels"](qsp-keyword-syntaxems.md#labels-)). +where `[$label]` is a label below or above in the code (see section ["Labels"](qsp-keyword-syntaxems.md#labels-)). -`jump` finds labels only within the current code block, i.e., labels are local. +`jump` finds a label only within the current code block, i.e., labels are local. Separate code blocks in QSP are: - "Execute on visit" code of a specific location (each location is a separate code block), - action code even if the action is added programmatically, -- code in hyperlinks, +- code in a hyperlink, - `DYNAMIC`/`DYNEVAL` code Example: @@ -960,73 +960,73 @@ if y<9: end ``` -Starting from version 5.8.0, a dedicated `loop` operator was introduced for loops. +Starting from version 5.8.0, the `loop` operator was introduced for loops. ::: ## KILLALL -`KILLALL` — destroys all variables and removes all items from the objects window. Equivalent to: +`KILLALL` — destroys all variables and removes all objects from the objects window. Equivalent to the construction: ```qsp killvar & killobj ``` :::warning[Attention!] -Remember that `killall` is not equivalent to: +Remember that `killall` is not equivalent to the construction: ```qsp killobj & killvar ``` -since in this case variable values are deleted after item removal, so the item removal handler location code has time to execute (see `$onobjdel`). +since in this case variable values are deleted after object deletion, meaning the object deletion handler location code has time to execute (see `$onobjdel`). ::: -Usually `killall` is used at the beginning of the game if a "Start over" action is provided at the end of the game. +Usually `killall` is used at the beginning of the game if there's a "Start over" action at the end of the game. ## KILLOBJ -`KILLOBJ` — removes an item located at the specified position. General syntax: +`KILLOBJ` — removing an object located at the specified position. General syntax: ```qsp KILLOBJ [#number] ``` -, where `[#number]` — the item number in the inventory window. Item numbering starts from 1. If the `[#number]` parameter is not specified, all items are removed. When removing each item with `killobj`, the item removal handler location code is executed (see `$onobjdel`). +where `[#number]` is the object number in the inventory window. Object numbering starts from 1. If the `[#number]` parameter is not specified, all objects are removed. When removing each object using `killobj`, the object deletion handler location code is executed (see `$onobjdel`). Example: ```qsp -! remove the topmost item in the list +! remove the topmost object in the list killobj 1 -! remove the bottommost item in the list +! remove the bottommost object in the list killobj countobj -! remove all items +! remove all objects killobj ``` ## KILLVAR -`KILLVAR` — removes the specified array element. General syntax: +`KILLVAR` — removing the specified array element. General syntax: ```qsp -KILLVAR [$array_name], [element_index] +KILLVAR [$array name], [element index] ``` -, where `[$array_name]` — the name of the array from which we want to remove an element, and `[element_index]` — the number, text index, or multi-dimensional index of the array element we want to remove. Array element numbering starts from 0. +where `[$array name]` is the name of the array from which we want to remove an element, and `[element index]` is the number, text index, or multi-dimensional index of the array element we want to remove. Array element numbering starts from 0. If the element index is not specified, the entire array is cleared. If the operator is called without arguments, all variables and arrays are deleted. Examples: ```qsp -killvar 'a', 3 & ! will remove element with index 3 from array 'a' -killvar 'unit', 'Paratrooper' & ! removes element with index 'Paratrooper' from array -killvar 'a' & ! removes array 'a' -killvar & ! removes all variables, arrays -killvar '$map_cell', (3, 4) & ! removal by multi-dimensional index +killvar 'a', 3 & ! will delete element with index 3 from array 'a'. +killvar 'unit', 'Paratrooper' & ! deletes element with index 'Paratrooper' from array +killvar 'a' & ! deletes array 'a' +killvar & ! deletes all variables, arrays +killvar '$map_cell', (3, 4) & ! deletion by multi-dimensional index ``` -When removing an element, all following elements shift up one position. +When deleting an element, all elements following it shift up one position. Example: @@ -1044,17 +1044,17 @@ KILLVAR 'a', 1 ## LET -`LET` — deprecated operator for setting variable values. General syntax: +`LET` — deprecated operator for setting variable value. General syntax: ```qsp -LET [variable_name] = [expression] +LET [variable name] = [expression] ``` -, where `[variable_name]` — a valid variable name, `[expression]` — a valid value for this variable. +where `[variable name]` is a valid variable name, `[expression]` is a valid value for this variable. - Numeric variable names are written without `$` and `%` symbols at the beginning. -- Text variable names are written with the `$` symbol at the beginning. -- Variable names containing tuples are written with the `%` symbol at the beginning. +- Text variable names are written with `$` symbol at the beginning. +- Variable names containing tuples are written with `%` symbol at the beginning. Examples: @@ -1068,7 +1068,7 @@ let %tuple = [123, "text string"] ``` :::tip -This operator is considered deprecated. Use the `set` operator instead, and only in cases where it improves code readability. +This operator is considered deprecated. Use the `set` operator instead, and only in cases when it improves code readability. ```qsp ! assignment can be done without set or let operators: @@ -1088,7 +1088,7 @@ LOCAL [variable 1], [variable 2], ... LOCAL [variable 1], [variable 2], ... = [value 1], [value 2], ... ``` -, where `[variable 1]`, `[variable 2]`, etc. — variable/array names written directly (not in quotes), and `[value 1]`, `[value 2]`, etc. — any values, constants, expression values, functions, or other variables. +where `[variable 1]`, `[variable 2]`, etc. are variable/array names written directly (not in quotes), and `[value 1]`, `[value 2]`, etc. are any values, constants, expression values, functions, or other variables. The number of variables and values must match (except for unpacking cases). @@ -1102,7 +1102,7 @@ local i, j = %map_cell local z, $a = [13, '37'] ``` -Unlike `set` and `let` operators, a variable can be declared without assigning a value. +Unlike `set` and `let` operators, you can declare a variable but not assign it a value. ```qsp local tempora @@ -1120,12 +1120,12 @@ You can create your own local variables in the following code blocks: - Locations themselves. - Code passed to the `DYNAMIC` operator or `DYNEVAL` function as text. -- Code executed when clicking a hyperlink. -- Code of each individual Action ([ACT](qsp-keyword-operators.md#act)). -- Code of each individual Loop ([LOOP](qsp-keyword-operators.md#loop)) +- Code executed when clicking on a hyperlink. +- Code of each separate Action ([ACT](qsp-keyword-operators.md#act)). +- Code of each separate Loop ([LOOP](qsp-keyword-operators.md#loop)) :::warning[**Attention!**] -Local variables have one feature that needs to be clearly understood. The value of a local variable declared in a given code block is also translated to all nested or called code blocks. For example, if a local variable is declared on a location, its value is translated to all locations called with `GOSUB` or `FUNC`, to `DYNAMIC`/`DYNEVAL` code blocks, to loop blocks, etc. Example: +Local variables have one feature that needs to be very clearly understood. The value of a local variable declared in a given code block is translated to all nested or called code blocks from this one. For example, if a local variable is declared on a location, its value is translated to all locations called using `GOSUB` or `FUNC`, to code blocks for `DYNAMIC`/`DYNEVAL`, to loop blocks, and so on. Example: ```qsp # start @@ -1136,7 +1136,7 @@ gosub 'foo' --- start --- # foo -! declare local variable on this location +! on this location we declare a local variable local i = 0 ! local variable is translated to the loop loop while i < 10 step i += 1: @@ -1152,7 +1152,7 @@ end ! to this location from the loop on location foo ! the same local variable declared on location foo is translated i+=1 & ! increase variable value, affecting the value in foo -*p 'undo:<>, ' & ! numbers 1,3,5,7,9 will appear on screen with undo: prefix +*p 'undo:<>, ' & ! numbers 1,3,5,7,9 with prefix undo: will appear on screen --- undo --- ``` @@ -1194,28 +1194,29 @@ act "To location 1": goto 'location 1' x = 99 z = 4608 gosub 'foo' -*pl x & *pl z & ! numbers 99 and 549 will be output +*pl x & *pl z & ! numbers 99 and 549 will be output to screen --- start --- # foo local x & ! declare variable x local for this location x = 12 & ! change variable x value z = 549 -*pl x & *pl z & ! numbers 12 and 549 will be output +*pl x & *pl z & ! numbers 12 and 549 will be output to screen --- foo --- ``` -```qsp title="Example of declaring local variables in DYNEVAL code and in a loop" +```qsp title="Example of declaring local variables in DYNEVAL code and in loop" $chkObjWord = { ! this is code written as text in variable $chkObjWord - ! write the search word to local variable $word + ! in local variable $word we write the word + ! by which we search local $word = $args[0] loop local i = 1 while no i > countobj step i += 1: ! use local variable i inside the loop - ! loop executes while counter doesn't exceed item count + ! loop executes while counter doesn't exceed number of objects if instr($getobj(i), $word) <> 0: ! as soon as the considered word is found - ! in the next item name + ! in the name of the next object result = i & ! return position exit & ! close function end @@ -1237,13 +1238,13 @@ end ## LOOP -`LOOP` — loop operator. Necessary for organizing cyclical calculations. General single-line syntax: +`LOOP` — loop operator. Necessary for organizing cyclic calculations. General syntax of single-line form: ```qsp LOOP {commands before loop start} WHILE [condition] STEP {commands at end of iteration}: {loop body operators} ``` -General multi-line syntax: +General syntax of multi-line form: ```qsp LOOP {commands before loop start} WHILE [condition] STEP {commands at end of iteration}: @@ -1251,14 +1252,14 @@ LOOP {commands before loop start} WHILE [condition] STEP {commands at end of ite END ``` -, where: +where: -- `{commands before loop start}` — commands executed before the loop is started. These commands belong to the loop block but don't fall into iterations (passes), i.e., executed only once. Here you can, for example, declare a loop counter. And here you can write multiple commands, listing them through the separator `&` (ampersand). -- `[condition]` — an expression by whose value the condition is checked. Comparison operations and logical operations in any combinations can be used here. If the `[condition]` expression value equals zero, the loop is interrupted. -- `{commands at end of iteration}` — commands executed at the end of each loop pass. Commands that don't directly relate to the loop body but should be executed on each iteration can be placed here. Here you can, for example, change the loop counter value. And here you can actually write multiple commands, listing them through the separator `&` (ampersand). -- `{loop body operators}` — commands that need to be executed on each pass and are main for the loop. I.e., we make the loop exactly for these commands. +- `{commands before loop start}` — these are commands executed before the loop is started. These commands belong to the loop block but don't fall into iterations (passes), i.e., are executed only once. Here you can, for example, declare a loop counter. And here you can write multiple commands, listing them with the `&` (ampersand) separator. +- `[condition]` — this is an expression by whose value the condition is checked. Comparison operations and logical operations in any combinations can be used here. If the value of expression `[condition]` equals zero, the loop is interrupted. +- `{commands at end of iteration}` — these are commands executed at the end of each loop pass. Commands that don't directly relate to the loop body but nevertheless should be executed on each iteration can be placed here. Here you can, for example, change the loop counter value. And here you can actually write multiple commands, listing them with the `&` (ampersand) separator. +- `{loop body operators}` — these are commands that need to be executed on each pass and are the main ones for the loop. I.e., we make the loop specifically for these commands. -A loop in QSP is a separate code block, which means we can declare local variables inside this code block. This is very convenient because we can declare a local variable for the counter, and this won't affect other variables at the location: +The loop in QSP is a separate code block, which means we can declare local variables inside this code block. This is very convenient because we can declare a local variable for the counter, and this won't affect other variables at the location: ```qsp i = 99 @@ -1269,7 +1270,7 @@ end *nl "i after loop <>" ``` -Loops are very convenient for iterating through arrays. For example, you can use a loop to sum all numbers stored in an array: +Loops are very convenient for iterating through arrays. For example, you can use a loop to add all numbers stored in an array: ```qsp summ=0 & ! here we'll write the sum of numbers @@ -1277,24 +1278,24 @@ summ=0 & ! here we'll write the sum of numbers loop local i, size = 0, arrsize('mass') while i < size step i += 1: summ += mass[i] end -*pl 'Sum of all elements in mass array: <>' +*pl 'Sum of all elements in array mass: <>' ``` ## MENU -`MENU` — displays a popup menu anywhere in the game, whose items are defined in the specified array. General syntax: +`MENU` — displays a popup menu anywhere in the game, whose items are written in the specified array. General syntax: ```qsp -MENU [$array_name] +MENU [$array name] ``` -Before using this operator, you need to fill the array on which the menu items will be based. Menu items are tuples of three values, sequentially placed in consecutive array cells starting from zero. The contents of each tuple should be approximately like this: +Before using this operator, you need to fill the array based on whose contents the menu items will be formed. Menu items are tuples of three values, sequentially placed in consecutive array cells starting from zero. The contents of each tuple should be approximately like this: ```qsp -["menu item name", "location name", "icon file path"] +["menu item name", "location name", "path to icon file"] ``` -Menu item name is what we'll see on screen when the menu is displayed; location name is the name of the location whose code will be executed when the corresponding menu item is clicked; icon file path is the path to the image file that will be displayed next to the menu item name. +Menu item name is what we'll see on screen when the menu is displayed; location name is the name of the location whose code will be executed when clicking on the corresponding menu item; path to icon file is the path to the image file that will be displayed next to the menu item name. Knowing this, we can fill the array to create our menu items: @@ -1304,7 +1305,7 @@ Knowing this, we can fill the array to create our menu items: %stone[2] = ['Examine stone', 'lookstone'] ``` -Here the array name (`%stone`) is the menu name, and the tuples are actions with specified item names and menu item selection handler location names. When selecting "Take stone", the location named "takestone" will be called. The same will happen with other items. +Here the array name (`%stone`) is the menu name, and the tuples are actions for which item names and handler location names for menu item selection are specified. When selecting the "Take stone" item, the location named "takestone" will be called. Similarly for other items. To display the menu on screen, use the `MENU` operator: @@ -1324,17 +1325,17 @@ Example of creating a menu with icons: ! menu item specified by 3 variables %usr_menu[3] = [$name, $location, $icon_file] -menu 'usr_menu' &! will show menu with 4 items +menu 'usr_menu' &! will show menu of 4 items ``` -The menu ends at an array element with an empty tuple, or with a tuple missing a value for the menu item name or item handler location. +The menu ends on an array element with an empty tuple, or with a tuple missing a value for the menu item name or item handler location. Examples where the last two menu items won't be created: ```qsp %usr_menu[0]=['Take item','take_item'] & ! we'll see this item on screen $usr_menu[1]=['Examine item','look_item'] & ! and we'll see this item on screen -$usr_menu[2]=[] & ! empty tuple, player will consider the menu ended +$usr_menu[2]=[] & ! empty tuple, player will consider menu ended $usr_menu[3]=['Put item','put_item'] & ! we won't see this item ``` @@ -1352,7 +1353,7 @@ $usr_menu[2]=['', 'del_item'] & ! no name specified, won't see item $usr_menu[3]=['Put item','put_item'] & ! and we won't see this item ``` -To insert a separator in the menu, use a tuple with `-` values. I.e., if you need to put a separator instead of the 3rd element: +To insert a separator in the menu, use a tuple with "-" values. I.e., if you need to put a separator instead of the 3rd element: ```qsp %usr_menu[0]=['Take item','take_item'] @@ -1363,15 +1364,98 @@ $usr_menu[3]=['Put item','put_item'] An argument (`args[0]`) - the position of the selected item - is passed to the menu item selection handler location. Menu item positions are numbered from 1. +:::note[Deprecated array filling variant. Strings] + +This variant can be used both in players version 5.9.0 and in earlier versions. + +Here menu items are string values of an array with a special format: + +```qsp +"menu item name:location name:path to icon file" +``` + +- Menu item name is what we'll see on screen when the menu is displayed; +- location name is the name of the menu item handler location whose code will be executed when clicking on the corresponding menu item; +- path to icon file is the path to the image file that will be displayed next to the menu item name. If the path to icon file is not specified or the specified file is unavailable, the menu item will be displayed without an icon. + +The search for ":" symbols starts from the end of the string, meaning the menu item name can contain colons, but then there must be a colon after the location name, even if you don't use icons for menu items. + +```qsp +$stone[0]='Stone: take:takestone:' +$stone[1]='Stone: throw:throwstone:' +$stone[2]='Stone: examine:lookstone:' +``` + +If the path to icon file is not specified or the specified file is unavailable, the menu item will be displayed without an icon. + +Thus we should fill the array to create our menu items: + +```qsp +$stone[0]='Take stone:takestone' +$stone[1]='Throw stone:throwstone' +$stone[2]='Examine stone:lookstone' +``` + +Here the array name (`$stone`) is the menu name, and the text array values are actions for which names and handler location names for menu item selection are specified. When selecting "Take stone", the location named "takestone" will be processed. Similarly for other items. + +To call the menu on screen, use the `menu` operator: + +```qsp +menu '$stone' +``` + +Menus can be called anywhere in the game, for example, from hyperlinks: + +```qsp +'Stone' +``` + +Example of creating a menu with icons: + +```qsp +! no icon +$usr_menu[0] = 'Take item:take_item' +! icon specified by gif file +$usr_menu[1] = 'Put item:put_item:images/put_item.gif' +! icon specified by $icon_file value +$usr_menu[2] = 'Examine item:look_item:<<$icon_file>>' +! menu item specified by 3 variables +$usr_menu[3] = '<<$name>>:<<$location>>:<<$file>>' + +menu 'usr_menu' &! will show menu of 4 items +``` + +The menu ends on an array element with value `''` (empty string). I.e., if the menu array consists of elements 'Take', 'Examine', '', 'Throw', then the last 2 menu items won't be created: + +```qsp +$usr_menu[0] = 'Take item:take_item' & ! we'll see this item on screen +$usr_menu[1] = 'Examine item:look_item' & ! and we'll see this item on screen +$usr_menu[2] = '' & ! empty value here, player will consider menu ended +$usr_menu[3] = 'Put item:put_item' & ! we won't see this item +``` + +To insert a separator in the menu, write `"-:-"` instead of the corresponding array element. I.e., if you need to put a separator instead of the 3rd element: + +```qsp +$usr_menu[0] = 'Take item:take_item' +$usr_menu[1] = 'Examine item:look_item' +$usr_menu[2] = '-:-' +$usr_menu[3] = 'Put item:put_item' +``` + +::: + ## MSG -`MSG` — outputs the specified message in a dialog box. General syntax: +`MSG` — displays the specified message in a dialog box. General syntax: ```qsp MSG [message] ``` -, where `[message]` — any text string, number, expression of any type. Examples: +where `[message]` is any text string, number, expression of any type. Examples: + +Examples: ```qsp ! simple message output. @@ -1380,30 +1464,46 @@ msg 'Many ripe pears.' ``` ```qsp -! Example message in ACT action. +! Example of message in ACT action. act 'Eat pears': msg 'Mmm pears are very tasty.' end -! We get message output when clicking "Eat pears" action +! We get message output when clicking on action "Eat pears" ``` ```qsp -! Example with condition. +!Example with condition. if breadready = 1: msg 'Looks like the bread is ready.' end ! We get message output when condition breadready = 1 ``` +## NL + +`NL` — line break, then text output in the additional description window. General syntax: + +```qsp +NL [$text] +``` + +where `[$text]` is any text string, number, or expression of any type. If `[$text]` is absent, a simple line break occurs. Example: + +```qsp +p "Text without line break." +nl "Line break + text output." +p "Text without line break." +``` + ## OPENGAME -`OPENGAME` — loads the specified game state file. General syntax: +`OPENGAME` — loading the specified game state file. General syntax: ```qsp OPENGAME [$path] ``` -, where `[$path]` — path to the saved game state file. If the `[$path]` parameter is absent, the game state loading window is called. +where `[$path]` is the path to the saved game state file. If the `[$path]` parameter is absent, the game state loading window is called. Example: @@ -1418,39 +1518,106 @@ See also the game state loading event handler location ([$ongload](qsp-keyword-s ## OPENQST -`OPENQST` — opens and runs the specified game file. General syntax: +`OPENQST` — opening and running the specified game file. General syntax: ```qsp OPENQST [$path] ``` -, where [$path] — path to the game file to run. Example: +where [$path] is the path to the game file to be run. Example: ```qsp openqst "gamespool/cubesgame.qsp" ``` -When using this operator, variables are not deleted, inventory items are not removed, additional description and input line are not cleared, and playing files are not stopped. If you need to clear the screen and all variable values, you can write such commands at the beginning of the loaded game file: +When using this operator, variables are not deleted, inventory objects are not removed, the additional description and input line are not cleared, and playing files are not stopped. If you need to clear the screen and all variable values, you can write such commands at the beginning of the loaded game file: ```qsp killall & cls & close all ``` +## P + +`P` — text output to the additional description window without line break. Text output by any other operator immediately after p will add new text immediately after the current text. General syntax: + +```qsp +P [$text] +``` + +where `[$text]` is any text string, number, or expression of any type. `[$text]` can be an empty string `''`, but should not be absent. Example: + +```qsp +p "Text without line break." +p "Text without line break." +p "" +p "Text without line break." +``` + +## PL + +`PL` — text output to the additional description window, then line break. General syntax: + +```qsp +PL [$text] +``` + +where `[$text]` is any text string, number, or expression of any type. `[$text]` can be absent, then just a line break. Example: + +```qsp +pl "Text output, then line break." +pl & ! line break without text output +pl "Text output, then line break." +p "Text without line break." +pl "Text output, then line break." +``` + +## PLAY + +`PLAY` — playing the specified sound file with given volume. General syntax: + +```qsp +PLAY [$path to sound file],[#volume] +``` + +where `[$path to sound file]` is the path to the sound file relative to the game file, `[#volume]` is playback volume as percentage from 0 to 100. The `[#volume]` parameter can be absent, in which case volume is taken as 100%. Examples: + +```qsp +!Volume 100% +play 'sound/music.mp3' +!Volume 50% +play 'sound/music.mp3', 50 +!Volume 0% (no sound) +play 'sound/music.mp3', 0 +``` + +```qsp +!Playing file by address from variable $file +! with extension 'mid' +! and volume volume +$file = "melody" +play '<<$file>>.mid', volume +! similarly: +$file = "melody.mid" +play $file, volume +``` + +If the file is already playing, the volume changes without "restarting" it. Multiple audio formats are supported and simultaneous playback of up to 32 compositions. + ## REFINT -`REFINT` — forced interface update (including color and font changes assigned with system variables). +`REFINT` — forced interface update (including color and font changes assigned using system variables). -By default, interface updates occur 2 times per second (every 500 ms). Also see the [`settimer`](#settimer) operator. +By default, interface update occurs 2 times per second (every 500 ms). See also the [`settimer`](#settimer) operator. ## SAVEGAME -`SAVEGAME` — saves game state to the specified file. General syntax: +`SAVEGAME` — saving game state to the specified file. General syntax: ```qsp SAVEGAME [$path] ``` -, where `[$path]` — path to the created game state save file. If the `[$path]` parameter is absent, the game state save window is called. +where `[$path]` is the path to the created game state save file. If the `[$path]` parameter is absent, the game state save window is called. Example: @@ -1463,38 +1630,98 @@ savegame See also [game state save event handler location ($ongsave)](qsp-keyword-sys-var.md#ongsave). +## SCANSTR + +`SCANSTR` — searching for non-overlapping occurrences in a string that match a pattern, and placing these occurrences in an array. General syntax: + +```qsp +SCANSTR [$array_name], [$text_to_parse], [$regexp], [#group_number] +``` + +where `[$array_name]` is the array where strings matching the regular expression `[$regexp]` are placed. The search is performed on string `[$text_to_parse]`. If parameter `[#group_number]` is specified, not the entire string matching the regular expression will be placed in the array, but only the part corresponding to the specified group in this regular expression. + +Examples: + +```qsp +! extract all words from string: +$text = 'Sasha walked down the highway, and Greka across the river.' +scanstr '$words', $text, '\b\w+\b' +!The $words array will contain values: 'Sasha', 'walked', 'down', 'highway', 'and', 'Greka', 'across', 'river' + +! split string by delimiter: +$text = 'morning|day|evening|night' +scanstr '$words', $text, '[^|]+' +!The $words array will contain values: 'morning', 'day', 'evening', 'night' + +! extract all words placed in square brackets from string, but without square brackets: +$text = '[first] ignoredtext [second][third] also ignored' +scanstr '$words', $text, '\[(.*?)\]', 1 +!The $words array will contain values: 'first', 'second', 'third' +``` + +## SET + +`SET` — operator for setting variable value. General syntax: + +```qsp +SET [variable name] = [expression] +``` + +where `[variable name]` is a valid variable name, `[expression]` is a valid value for this variable. + +Numeric variable names are written without the `$` symbol at the beginning. Text variable names are written with the `$` symbol at the beginning. Examples: + +```qsp +! set text variable +set $text = "text string" +! set numeric variable +set abs = 123 +! set tuple +set %tuple = [27, 184, 'steel'] +``` + +:::note[Recommendation:] +Since assignment can be done without the `set` operator, we recommend using this operator only for cases when it improves code readability. For example, with multiple assignment: + +```qsp +set apples_in_pocket, apples_in_basket, apples_at_Lyosha = 58, 11, 19 +set $string_1, $string_2 = 'Greka Rode Across River', 'Greka Sees Crab In River' +``` + +::: + ## SETTIMER -`SETTIMER` — sets the interval for calling the counter location. General syntax: +`SETTIMER` — sets the interval for accessing the counter location. General syntax: ```qsp SETTIMER [#expression] ``` -, where `[#expression]` — period for calling the counter location in milliseconds. By default, the player calls the counter location every 500 ms, i.e., 2 times per second. +where `[#expression]` is the period of accessing the counter location in milliseconds. By default, the player accesses the counter location every 500 ms, i.e., 2 times per second. -Setting the counter location call period also affects the frequency of automatic interface settings updates. +Setting the counter location access period also affects the frequency of automatic interface settings update. Examples: ```qsp -! counter location will run every 2 seconds: +! counter location will be launched every 2 seconds: settimer 2000 ``` ```qsp -! counter location will run 4 times per second: +! counter location will be launched 4 times per second: settimer 250 ``` ```qsp -! if we set frequency (times per second) +! if we set frequency of access (times per second) frequency=10 & ! ten times per second settimer 1000/frequency ``` ```qsp -! if we set period (every how many seconds) +! if we set access period (after how many seconds) period=2 & ! every two seconds settimer 1000*period ``` @@ -1507,15 +1734,207 @@ settimer 1 However, in practice, the minimum value is limited by your computer's power, and it's usually higher than 1 millisecond. +## SETVAR + +`SETVAR` — assigns a value to a variable or array cell. + +This function allows avoiding the use of `dynamic` in cases where you need to assign a value to a variable whose name is not known in advance. + +General syntax: + +```qsp +SETVAR [$array_name], [value], [index] +``` + +where `[$array_name]` is the name of the array or variable to which the value should be assigned; `[value]` is a value of any type: string, number, tuple — however, the type of value that will be placed in the variable is determined by the type prefix before the variable name; `[index]` is if the value is assigned to an array cell, you need to specify the cell index with this parameter (can be of any type). + +Examples: + +```qsp +SETVAR 'A', 65 +SETVAR '$X', 'name', 4 +SETVAR '$X', 'name', 'string index' +SETVAR '%Q', ['example', 'tuple'], 3 +SETVAR '%Q', ['example', 'tuple'], [x, y] + +$arr_pref = '%' +$arr_name = 'tuple' +SETVAR $arr_pref+$arr_name, ['tuple', 1], 3 +``` + +## SHOWACTS + +`SHOWACTS` — controls the display of the actions window on screen. General syntax: + +```qsp +SHOWACTS [#expression] +``` + +where `[#expression]` is a number. Usually values `0` and `1` are used. If the value of expression `[#expression]` is not zero, the actions window is displayed. If the value of expression `[#expression]` equals zero, the actions window is hidden. Examples: + +```qsp +showacts 1 & ! shows actions list +showacts 0 & ! hides actions list +``` + +For code readability, you can pre-define `on` and `off` variables and use them: + +```qsp +on = 1 +off = 0 +showacts on & ! shows actions list +showacts off & ! hides actions list +``` + +## SHOWINPUT + +`SHOWINPUT` — controls the display of the input line on screen. General syntax: + +```qsp +SHOWINPUT [#expression] +``` + +where `[#expression]` is a number. Usually values `0` and `1` are used. If the value of expression `[#expression]` is not zero, the input line is displayed. If the value of expression `[#expression]` equals zero, the input line is hidden. Examples: + +```qsp +showinput on & ! shows input line +showinput off & ! hides input line +``` + +## SHOWOBJS + +`SHOWOBJS` — controls the display of inventory on screen. General syntax: + +```qsp +SHOWOBJS [#expression] +``` + +where `[#expression]` is a number. Usually values 0 and 1 are used. If the value of expression `[#expression]` is not zero, inventory is displayed. If the value of expression `[#expression]` equals zero, inventory is hidden. Examples: + +```qsp +showobjs 1 & ! shows inventory +showobjs 0 & ! hides inventory +``` + +For code readability, you can pre-define `on` and `off` variables and use them: + +```qsp +on = 1 +off = 0 +showobjs on & ! shows inventory +showobjs off & ! hides inventory +``` + +## SHOWSTAT + +`SHOWSTAT` — controls the display of the additional description window on screen. General syntax: + +```qsp +SHOWSTAT [#expression] +``` + +where `[#expression]` is a number. Usually values `0` and `1` are used. If the value of expression `[#expression]` is not zero, the additional description window is displayed. If the value of expression `[#expression]` equals zero, the additional description window is hidden. Examples: + +```qsp +showstat 1 & ! shows additional description window +showstat 0 & ! hides additional description window +``` + +For code readability, you can pre-define `on` and `off` variables and use them: + +```qsp +on = 1 +off = 0 +showstat on & ! shows additional description window +showstat off & ! hides additional description window +``` + +## SORTARR + +`SORTARR` — sorting the specified array. General syntax: + +```qsp +SORTARR [$array_name], [#order] +``` + +Here `[$array_name]` is the name of the array to be sorted. The `[#order]` parameter can be omitted. If not specified or equals `0`, sorts the array in ascending order (from smaller to larger). If equals `1`, sorts the array in descending order (from larger to smaller). + +Can sort arrays of any types (numbers, strings, tuples), but mixing values of different types in one array is not allowed. + +To specify the type of sorted values, you need to specify the type prefix as part of the array name (`$`, `%`). + +Example of sorting a text array: + +```qsp +$a[] = 'nn' +$a[] = 'zz' +$a[] = 'aa' +sortarr '$a' + +!check sorting result: +loop local i=0 while i>} -! the text 'Health: <>' will be output to the screen +! the text 'Health: <>' will be displayed on screen *pl "Health: <>" -! the text 'Health: 150' will be output to the screen +! the text 'Health: 150' will be displayed on screen ``` -For better compatibility with various player versions, and for reading convenience, curly brackets should mainly be used for writing code intended for the `dynamic` operator or `dyneval` function: +For better compatibility with different player versions, as well as for reading convenience, curly braces should be used mainly for writing code intended for the `dynamic` operator or `dyneval` function: ```qsp *pl $dyneval({$result = $mid("abcd", 2, 1) + "qwerty"}) @@ -327,7 +326,7 @@ dynamic { }, 'Text', 'Fork' ``` -Curly brackets can also be used for writing multi-line comments: +Curly braces can also be used for writing multi-line comments: ```qsp ! { @@ -336,22 +335,22 @@ Curly brackets can also be used for writing multi-line comments: } ``` -Any number of curly brackets can be nested within each other. +Any number of curly braces can be nested within each other. ## Quote `"` -Quotes `"` (double apostrophe) in QSP act as a special symbol marking the beginning and end of string values. In other words, by the presence of quotes, the player can understand where a string value begins and ends: +Quotes `"` (double apostrophe) in QSP act as special symbols marking the beginning and end of string values. In other words, by the presence of quotes, the player can understand where a string value begins and ends: ```qsp -*pl "Text that will be output to the screen." +*pl "Text that will be displayed on screen." ``` -The feature of specifying text value using quotes is that sub-expressions are expanded in such strings: +A special feature of specifying text values using quotes is that sub-expressions are expanded in such strings: ```qsp health = 150 *pl "Health: <>" -! the text 'Health: 150' will be output to the screen +! the text 'Health: 150' will be displayed on screen ``` Quotes inside a string can be escaped by doubling: @@ -371,24 +370,24 @@ Quotes can also be used for writing multi-line comments: ## Apostrophe `'` -Apostrophe `'` in QSP acts as a special symbol marking the beginning and end of string values. In other words, by the presence of apostrophes, the player can understand where a string value begins and ends: +The apostrophe `'` in QSP acts as a special symbol marking the beginning and end of string values. In other words, by the presence of apostrophes, the player can understand where a string value begins and ends: ```qsp -*pl 'Text that will be output to the screen.' +*pl 'Text that will be displayed on screen.' ``` -The feature of specifying text value using apostrophes is that sub-expressions are expanded in such strings: +A special feature of specifying text values using apostrophes is that sub-expressions are expanded in such strings: ```qsp health = 150 *pl 'Health: <>' -! the text 'Health: 150' will be output to the screen +! the text 'Health: 150' will be displayed on screen ``` Apostrophes inside a string can be escaped by doubling: ```qsp -*pl 'Rug''Sta''Rag said: — What do you want, mora? Want a fly agaric?' +*pl 'Rug''Sta''Rag said: — What do you want, mora? Do you want a fly agaric?' ``` Apostrophes can also be used for writing multi-line comments: @@ -400,19 +399,19 @@ Apostrophes can also be used for writing multi-line comments: ' ``` -## "At" Symbol `@` +## Commercial "At" Symbol `@` -The "at" symbol `@` is used to organize implicit function-location calls, simplifying notation and replacing the `gosub` operator or `func` function. General syntax: +The commercial "at" symbol `@` is used to organize implicit calling of location-functions, simplifying syntax and replacing the `gosub` operator or `func` function. General syntax: ```qsp @[$location]([argument 0], [argument 1], ... , [argument 18]) ``` -, where `[$location]` — the name of the location whose code we want to execute without direct transition to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used at this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After processing the location, previous `args` values are restored. Using arguments is not mandatory; in this case, brackets can be omitted. +where `[$location]` is the name of the location whose code we want to execute without directly going to it. Arguments `[argument 0]`, `[argument 1]`, etc. can be used on this location, their values are automatically placed in variables `args[0]`, `args[1]`, etc. respectively. After processing the location, previous `args` values are restored. Using arguments is not mandatory; in this case, brackets can be omitted. -When calling a location using `@`, the base description of the location is added to the current description, base actions are added to current actions, and operators in the "Execute on visit" field are executed, then return to the original line (continue code execution after the command with `@`). +When accessing a location using `@`, the base description of the location is added to the current description, base actions are added to current actions, and operators in the "Execute on visit" field are executed, then return to the original line (continuing code execution after the command with `@`). -The location name in implicit calls must not contain special characters, otherwise this may lead to non-working code. You can use letters, numbers, underscores, and dots. +The location name in implicit calling should not contain special characters, otherwise this may lead to non-functional code. You can use letters, numbers, underscores, and periods. Examples: @@ -420,19 +419,19 @@ Examples: !processing location "move". The args[] array is empty. @move() -!processing location "move" with 3 parameters passed. +!processing location "move" with passing 3 parameters. ! $args[0] = $var (value), args[1] = 2, -! $args[2] = "data". Note the ' symbols. +! $args[2] = "data". Note the '$' symbols. @move($var, 2, 'data') ``` ```qsp -! this is code calling location "transition" +! this is the code for calling location "transition" @transition('location') -! and this is code of the "transition" location itself +! and this is the code of the location "transition" itself # transition -*pl $args[0] & ! the text 'location' will be output to the screen +*pl $args[0] & ! the text 'location' will be displayed on screen ! a new action will appear in the actions window: act 'go': goto "street" @@ -441,7 +440,7 @@ end ``` ```qsp -! location code for function getting sum of series of numbers from one to specified value +! location code for a function that gets the sum of a series of numbers from one to the specified value # summ ! args[0] will contain the number we specify as [argument 0] loop while args[0] > 0 step args[0] -= 1: @@ -449,158 +448,19 @@ loop while args[0] > 0 step args[0] -= 1: end - summ -! example of calling location "summ" as function -*pl @summ(19) & ! will output 190 to screen +! example of calling location "summ" as a function +*pl @summ(19) & ! will display 190 on screen ``` -:::warning[Pay attention!] -Implicit function-location call replaces both `gosub` and `func`, therefore: +:::warning[Note!] +Implicit location-function calling replaces both `gosub` and `func`, therefore: -1. if your function-location returns a result, implicit call of such location will work exactly like explicit call through `func`; -2. if the function-location does not return a result, then when using it with the **[implicit operator](qsp-keyword-operators.md#implicit-operator)** it will work like explicit call through `gosub`. +1. if your location-function returns a result, implicit calling of such a location will work exactly the same as explicit calling through `func`; +2. if the location-function doesn't return a result, then when using it with the **[implicit operator](qsp-keyword-operators.md#implicit-operator)** it will work like explicit calling through `gosub`. ::: -## Dollar Sign `--- -sidebar_position: 5 ---- - -# Syntax Elements and Special Symbols - -:::tips[Definition] - -In the context of programming, a syntax element can be considered as a **minimal unit of syntax** that defines the structure and rules for writing code. - -Thus, a syntax element can be a variable, operator, function, declaration keyword, or special symbols used to structure code. - -::: - -Here are syntax elements/special symbols not included in other sections with keywords and system variables. - -## END - -Keyword (operator) marking the end of a multi-line construct. Actions, conditional constructs, and loops can be multi-line. Examples: - -```qsp -! open condition -if obj "Jug": - *pl "You have a jug." -! close condition -end - -! open action -act "Take apple": - apple += 1 - addobj "Apple" -! close action -end - -loop local i = 0 while i < 10 step i += 1: - *pl "Pass <>: i=<>" -end -``` - -Each multi-line construct must end with the `end` keyword. However, the same rules apply here as for HTML tags or brackets: if we nest one construct inside another, we must first close the last opened construct: - -```qsp -! open condition -if obj "Empty jug": - ! code related to the condition - *pl "You have an empty jug." - ! open action - act "Fill jug": - ! code related to the action - delobj "Empty jug" - addobj "Full jug" - ! close ACTION - end - *pl "The jug can be filled from the well." -! close CONDITION -end -``` - -You can use not just `end`, but `end if`, `end act` and `end loop`: - -```qsp -! open action -act "Buy 10 arrows at 5 rubles each": - ! open condition level 1 - if money >= 10 * 5: - arrow += 10 - money -= 10 * 5 - ! open condition level 2 - if no (obj "Arrows"): - addobj "Arrows" - ! close condition level 2 - end if - else - *pl "You don't have enough money." - ! close condition level 1 - end if -! close action -end act -``` - -Generally, any text is allowed after the `end` keyword, but not approved. All text until the next command is ignored. If a command is written on the same line as `end`, this command must come after an ampersand (`&`): - -```qsp -! open action -act "Take apple": - apple += 1 - addobj "Apple" -! close action -end the presence of this text after end is not approved & *pl "New command" -``` - -## Labels `:` - -Labels are special syntactic constructs (or rather less than constructs — syntax elements) that mark the specified code line and serve for quick movement to such lines using the [`JUMP`](qsp-keyword-operators.md#jump) operator. General syntax: - -```qsp -:[label_name] -``` - -, where `[label_name]` — theoretically any combination of symbols, but in practice it's desirable to use only letters, numbers, underscores, and spaces. Spaces and tabs can precede the colon in any amount. Adjacent spaces and tabs around the label name are also ignored (but not recommended for code readability). - -```qsp -! recommended label usage -jump 'label' -! ... -:label -``` - -```qsp -! working variant with ignored adjacent spaces in label -jump "label with adjacent spaces" -! ... -: label with adjacent spaces -``` - -```qsp -! working variant with ignored adjacent spaces in jump -jump " label with adjacent spaces " -! ... -:label with adjacent spaces -``` - -Any other commands can follow directly after the label on the same line through an ampersand (`&`), but this is not recommended. - -```qsp -! label with commands after it -jump 'markdown' -! ... -:markdown & *pl "output text" & ! comment -``` - -Labels are case-insensitive: - -```qsp -jump "FoR" -! ... -:for -``` - - +## Dollar Sign Symbol `$` Acts as a type prefix for naming variables and functions of string type. It must be specified if you want to assign a string value to a variable: @@ -614,7 +474,7 @@ If you don't specify the dollar sign before the string type variable name during string = 'Short string' ``` -If you assigned a value of another type to a variable and try to get a string, this won't cause a data type mismatch error, but the variable will return a value corresponding to the default value for string values, i.e., an empty string (`''`). +If you assigned a variable a value of another type and try to get a string, this won't cause a data type mismatch error, but the variable will return a value corresponding to the default value for string values, i.e., an empty string (`''`). ```qsp number = 123 @@ -622,7 +482,7 @@ number = 123 ! we'll see 'Number .' on screen because $number will return an empty string. ``` -## Percent Sign `%` +## Percent Sign Symbol `%` Acts as a type prefix for naming variables and functions containing or returning tuples. It must be specified if you want to assign a tuple to a variable: @@ -636,7 +496,7 @@ If you don't specify the percent sign before the tuple type variable name during tuple = [13, 37, 'string'] ``` -If you assigned a value of another type to a variable and try to get a tuple, this won't cause a data type mismatch error, but the variable will return a value corresponding to the default value, i.e., empty strings (`''`) if a text value is extracted, or zeros (`0`) if a numeric value is extracted. +If you assigned a variable a value of another type and try to get a tuple, this won't cause a data type mismatch error, but the variable will return a value corresponding to the default value, i.e., empty strings (`''`) if a text value is extracted, or zeros (`0`) if a numeric value is extracted. ```qsp number = 123 diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md index 73fd9b0..b150971 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md @@ -1,6 +1,5 @@ --- id: qsp-keyword-sys-var -title: System Variables sidebar_position: 4 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md index 73cc07c..1b19a35 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md @@ -1,6 +1,5 @@ --- id: parsers -title: Parsers --- # Parsers diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md index c4e0fd4..95f521e 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md @@ -1,6 +1,5 @@ --- id: qsp-fsharp-parser -title: QSP Fsharp Parser --- # Qsp.FSharp.Parser diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md index 3e7d8df..768d28b 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md @@ -1,6 +1,5 @@ --- id: qsplib-parser -title: QSPlib Parser --- # QSPLib Parser diff --git a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md index feb2360..0f8869a 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md @@ -1,6 +1,5 @@ --- id: syntax-highlighting -title: Syntax Highlighting --- # Syntax Highlighting From 1f53af6618f17f812fe195a01f003e5ccb1ca525 Mon Sep 17 00:00:00 2001 From: Awesome158 Date: Sun, 10 Aug 2025 07:33:21 +0200 Subject: [PATCH 4/4] fix: remove id front matter as it's not needed --- docs/all-together.md | 6 ++--- docs/co-development/index.md | 4 +-- docs/intro.md | 2 -- docs/language/index.md | 1 - docs/language/qsp-keywords/index.md | 1 - .../qsp-keywords/qsp-keyword-functions.md | 25 +++++++++---------- .../qsp-keywords/qsp-keyword-operacion.md | 1 - .../qsp-keywords/qsp-keyword-operators.md | 1 - .../qsp-keywords/qsp-keyword-syntaxems.md | 1 - .../qsp-keywords/qsp-keyword-sys-var.md | 1 - docs/parsers/index.md | 6 ++--- docs/parsers/qsp-fsharp-parser.md | 6 ++--- docs/parsers/qsplib-parser.md | 6 ++--- docs/syntax-highlighting.md | 3 --- .../current/all-together.md | 6 ++--- .../current/co-development/index.md | 4 +-- .../current/intro.md | 1 - .../current/language/index.md | 1 - .../current/language/qsp-keywords/index.md | 1 - .../qsp-keywords/qsp-keyword-functions.md | 1 - .../qsp-keywords/qsp-keyword-operacion.md | 1 - .../qsp-keywords/qsp-keyword-operators.md | 1 - .../qsp-keywords/qsp-keyword-syntaxems.md | 1 - .../qsp-keywords/qsp-keyword-sys-var.md | 1 - .../current/parsers/index.md | 6 ++--- .../current/parsers/qsp-fsharp-parser.md | 6 ++--- .../current/parsers/qsplib-parser.md | 6 ++--- .../current/syntax-highlighting.md | 4 +-- 28 files changed, 31 insertions(+), 73 deletions(-) diff --git a/docs/all-together.md b/docs/all-together.md index 09550b6..4596f3c 100644 --- a/docs/all-together.md +++ b/docs/all-together.md @@ -1,8 +1,6 @@ ---- -id: all-together ---- -# Всё вместе + +# Всё вместе Здесь вкратце расписаны всевозможные тернистые пути от начала разработки игры на QSP (с использованием различных средств и инструментов) до ее реализации и запуска игры у конечного игрока. diff --git a/docs/co-development/index.md b/docs/co-development/index.md index 0a134db..0359ee7 100644 --- a/docs/co-development/index.md +++ b/docs/co-development/index.md @@ -1,6 +1,4 @@ ---- -id: co-development ---- + # Совместная разработка diff --git a/docs/intro.md b/docs/intro.md index cc63abd..0a260f5 100644 --- a/docs/intro.md +++ b/docs/intro.md @@ -1,6 +1,4 @@ --- -id: intro -title: QSP Foundation sidebar_position: 1 --- diff --git a/docs/language/index.md b/docs/language/index.md index 16dc2a1..9867dc3 100644 --- a/docs/language/index.md +++ b/docs/language/index.md @@ -1,5 +1,4 @@ --- -id: language sidebar_position: 1 --- diff --git a/docs/language/qsp-keywords/index.md b/docs/language/qsp-keywords/index.md index d30ee24..df32c34 100644 --- a/docs/language/qsp-keywords/index.md +++ b/docs/language/qsp-keywords/index.md @@ -1,5 +1,4 @@ --- -id: qsp-keywords title: Зарезервированные слова, системные переменные, спецсимволы sidebar_position: 6 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-functions.md b/docs/language/qsp-keywords/qsp-keyword-functions.md index f2ac854..a14842a 100644 --- a/docs/language/qsp-keywords/qsp-keyword-functions.md +++ b/docs/language/qsp-keywords/qsp-keyword-functions.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-functions sidebar_position: 3 --- @@ -184,14 +183,14 @@ func('возвести_в_степень', 3, 3) Другие примеры: ```qsp -!Обработка локации "функция" как функции. +!Обработка локации "функция" как функции. !Массив ARGS пуст. яблоки = FUNC('функция') - + !обработка локации с названием лежащим в переменной $name как функции. ARGS[0] равен 1. pl func($name, 1) * 78 - -!обработка локации с названием в $name как функции. + +!обработка локации с названием в $name как функции. !$ARGS[0] содержит строку "строка", ARGS[1] равен 2. msg "text" + func($name, "строка", 2) ``` @@ -302,7 +301,7 @@ $name = $input('Как звать тебя, герой?') Другие примеры: ```qsp -! Вопрос с одним правильным ответом. +! Вопрос с одним правильным ответом. if $input('Что приходит после тьмы?') = 'свет': msg 'Все верно.' else @@ -668,7 +667,7 @@ $strfind('идти к пещере', '\b\w{4}\b') &! на экране увид ``` ```qsp title="Выборка с вложенными группами" -$strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 1) &! на экране увидим '671' +$strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 1) &! на экране увидим '671' $strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 2) &! на экране увидим '-190-23-999' $strfind('+33-671-190-23-999', '\+\d{1,2}-(\d{3})((-\d+)+)', 3) &! на экране увидим '-999' ``` @@ -786,8 +785,8 @@ arrcomp('$A', 'This', 0) arrcomp('$A', 'abc\d+', 2) ! аналогично предыдущему примеру, ! но поиск осуществляется по всем элементам массива -arrcomp('$A', '.*string.*', 0) - +arrcomp('$A', '.*string.*', 0) + arrcomp('$A', 'This') & ! эквивалентно 1му варианту ``` @@ -946,13 +945,13 @@ ARRTYPE([$имя_массива], [индекс]) ```qsp $ddd = 'text' arrtype('ddd') & ! '$' - + $g = 'text' & g = 13 arrtype('g') & ! '#' - + %tuple['index'] = [12, 'string'] arrtype('tuple', 'index') & ! '%' - + ! $empty not exist arrtype('$empty') & ! '' ``` @@ -1099,7 +1098,7 @@ if i < 100000: end new_time = msecscount pl "Скорость работы старого цикла: " + $str(new_time - old_time) - + old_time = msecscount loop i = 0 while i < 100000 step i += 1: b[i] = i diff --git a/docs/language/qsp-keywords/qsp-keyword-operacion.md b/docs/language/qsp-keywords/qsp-keyword-operacion.md index 61f1f25..98bce6d 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operacion.md +++ b/docs/language/qsp-keywords/qsp-keyword-operacion.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-operacion sidebar_position: 1 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-operators.md b/docs/language/qsp-keywords/qsp-keyword-operators.md index e3005ed..e2ceed4 100644 --- a/docs/language/qsp-keywords/qsp-keyword-operators.md +++ b/docs/language/qsp-keywords/qsp-keyword-operators.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-operators sidebar_position: 2 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-syntaxems.md b/docs/language/qsp-keywords/qsp-keyword-syntaxems.md index 9322f67..63d10ab 100644 --- a/docs/language/qsp-keywords/qsp-keyword-syntaxems.md +++ b/docs/language/qsp-keywords/qsp-keyword-syntaxems.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-syntaxems sidebar_position: 5 --- diff --git a/docs/language/qsp-keywords/qsp-keyword-sys-var.md b/docs/language/qsp-keywords/qsp-keyword-sys-var.md index 55c7ee3..a097748 100644 --- a/docs/language/qsp-keywords/qsp-keyword-sys-var.md +++ b/docs/language/qsp-keywords/qsp-keyword-sys-var.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-sys-var sidebar_position: 4 --- diff --git a/docs/parsers/index.md b/docs/parsers/index.md index 64ff722..83af10e 100644 --- a/docs/parsers/index.md +++ b/docs/parsers/index.md @@ -1,7 +1,5 @@ ---- -id: parsers ---- -# Парсеры + +# Парсеры Задача синтаксического анализатора (то есть парсера) заключается в том, чтобы взять исходник, написанный на [языке QSP](../language/), и преобразовать его в такую форму, с которой можно в дальнейшем удобно работать (интерпретировать, компилировать, использовать для анализа и т.д.) diff --git a/docs/parsers/qsp-fsharp-parser.md b/docs/parsers/qsp-fsharp-parser.md index 4355659..9d0ef5f 100644 --- a/docs/parsers/qsp-fsharp-parser.md +++ b/docs/parsers/qsp-fsharp-parser.md @@ -1,8 +1,6 @@ ---- -id: qsp-fsharp-parser ---- -# Qsp.FSharp.Parser + +# Qsp.FSharp.Parser [Qsp.FSharp.Parser](https://github.com/QSPFoundation/Qsp.FSharp/tree/master/src/Qsp.FSharp.Core) разрабатывается для сред разработки, которые поддерживают LSP (к примеру, VS Code, для [расширения](https://github.com/QSPFoundation/Qsp.FSharp.VsCode) которого всё это и затевалось). diff --git a/docs/parsers/qsplib-parser.md b/docs/parsers/qsplib-parser.md index cc9bc30..2c5d675 100644 --- a/docs/parsers/qsplib-parser.md +++ b/docs/parsers/qsplib-parser.md @@ -1,8 +1,6 @@ ---- -id: qsplib-parser ---- -# QSPLib Parser + +# QSPLib Parser [QSPLib](https://github.com/QSPFoundation/qsp/tree/master/qsp) парсил исходники ещё задолго до того, как это стало модным, и продолжает этим заниматься и по сей день. diff --git a/docs/syntax-highlighting.md b/docs/syntax-highlighting.md index 5db6f58..f580e31 100644 --- a/docs/syntax-highlighting.md +++ b/docs/syntax-highlighting.md @@ -1,6 +1,3 @@ ---- -id: syntax-highlighting ---- # Подсветка синтаксиса diff --git a/i18n/en/docusaurus-plugin-content-docs/current/all-together.md b/i18n/en/docusaurus-plugin-content-docs/current/all-together.md index 86ec09f..2768749 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/all-together.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/all-together.md @@ -1,8 +1,6 @@ ---- -id: all-together ---- -# All Together + +# All Together This section briefly outlines various thorny paths from starting QSP game development (using various tools and instruments) to implementing and launching the game for the end player. diff --git a/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md b/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md index f58c46c..beeb02a 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/co-development/index.md @@ -1,6 +1,4 @@ ---- -id: co-development ---- + # Collaborative Development diff --git a/i18n/en/docusaurus-plugin-content-docs/current/intro.md b/i18n/en/docusaurus-plugin-content-docs/current/intro.md index 1eada20..913c7a9 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/intro.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/intro.md @@ -1,5 +1,4 @@ --- -id: intro sidebar_position: 1 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/index.md b/i18n/en/docusaurus-plugin-content-docs/current/language/index.md index 62fba28..824b5e3 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/index.md @@ -1,5 +1,4 @@ --- -id: language sidebar_position: 1 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md index cc210fe..5c3aad1 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/index.md @@ -1,5 +1,4 @@ --- -id: qsp-keywords title: Reserved Words, System Variables, Special Characters sidebar_position: 6 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md index 2124381..ceda974 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-functions.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-functions sidebar_position: 3 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md index ed67fd9..6fe3d5a 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operacion.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-operacion sidebar_position: 1 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md index da210d6..12d436d 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-operators.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-operators sidebar_position: 2 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md index 72317d0..babcfac 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-syntaxems.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-syntaxems sidebar_position: 5 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md index b150971..828830f 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/language/qsp-keywords/qsp-keyword-sys-var.md @@ -1,5 +1,4 @@ --- -id: qsp-keyword-sys-var sidebar_position: 4 --- diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md index 1b19a35..f468c80 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/index.md @@ -1,7 +1,5 @@ ---- -id: parsers ---- -# Parsers + +# Parsers The task of a syntax analyzer (i.e., parser) is to take source code written in the [QSP language](../language/) and transform it into a form that can be conveniently worked with later (interpreted, compiled, used for analysis, etc.) \ No newline at end of file diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md index 95f521e..8cb887c 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsp-fsharp-parser.md @@ -1,8 +1,6 @@ ---- -id: qsp-fsharp-parser ---- -# Qsp.FSharp.Parser + +# Qsp.FSharp.Parser [Qsp.FSharp.Parser](https://github.com/QSPFoundation/Qsp.FSharp/tree/master/src/Qsp.FSharp.Core) is developed for development environments that support LSP (for example, VS Code, for whose [extension](https://github.com/QSPFoundation/Qsp.FSharp.VsCode) all this was started). diff --git a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md index 768d28b..d882081 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/parsers/qsplib-parser.md @@ -1,8 +1,6 @@ ---- -id: qsplib-parser ---- -# QSPLib Parser + +# QSPLib Parser [QSPLib](https://github.com/QSPFoundation/qsp/tree/master/qsp) was parsing source files long before it became fashionable, and continues to do so to this day. diff --git a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md index 0f8869a..62823b4 100644 --- a/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md +++ b/i18n/en/docusaurus-plugin-content-docs/current/syntax-highlighting.md @@ -1,6 +1,4 @@ ---- -id: syntax-highlighting ---- + # Syntax Highlighting