Defines.fs 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. module Qsp.Defines
  2. module Tools =
  3. open FParsec
  4. type 'a Parser = Parser<'a, unit>
  5. let removeEmptyLines () =
  6. Clipboard.getSet (fun str ->
  7. // let x = System.Text.RegularExpressions.Regex.Replace(str, "^\n", "", System.Text.RegularExpressions.RegexOptions.Multiline)
  8. // x
  9. let ws = manySatisfy (fun c -> System.Char.IsWhiteSpace c && c <> '\n')
  10. let wsLine = ws .>>? skipNewline
  11. let p =
  12. spaces
  13. >>. many
  14. (
  15. ws >>. many1Satisfy ((<>) '\n')
  16. .>> (skipNewline <|> eof)
  17. .>> many wsLine
  18. )
  19. |>> String.concat "\n"
  20. match run p str with
  21. | Success(x, _, _) -> x
  22. | Failure(x, _, _) -> failwithf "%A" x
  23. )
  24. // removeEmptyLines()
  25. module Show =
  26. open FsharpMyExtension
  27. open FsharpMyExtension.ShowList
  28. let print tabsCount isFunction xs =
  29. let tab = replicate 4 ' '
  30. let showStr x =
  31. showAutoParen "\""
  32. (showString
  33. (x
  34. |> String.collect (
  35. function
  36. | '"' -> "\\\""
  37. | '\\' -> "\\\\"
  38. | x -> string x )))
  39. xs
  40. |> List.collect (fun (descs, varName) ->
  41. let desc =
  42. [
  43. yield showChar '['
  44. yield!
  45. descs
  46. |> List.map (fun x ->
  47. tab << showStr x)
  48. yield showChar ']' << showString " |> String.concat \"\\n\""
  49. ]
  50. [
  51. yield showString "let dscr ="
  52. yield! List.map ((<<) tab) desc
  53. let signature =
  54. if isFunction then
  55. showString ", " << showString "failwith \"not implemented\""
  56. else
  57. empty
  58. yield
  59. showAutoParen "\"" (showString varName) << showString ", " << showString "dscr"
  60. << signature
  61. ]
  62. )
  63. |> List.map ((<<) (showReplicate tabsCount tab))
  64. |> joinEmpty "\n"
  65. |> show
  66. let parse tabsCount isFunction =
  67. Clipboard.getSet (fun str ->
  68. let description =
  69. many1
  70. (pstring "///" >>. optional (skipChar ' ') >>. manySatisfy ((<>) '\n') .>> spaces)
  71. let expr =
  72. between
  73. (skipChar '"')
  74. (skipChar '"')
  75. (manySatisfy ((<>) '"'))
  76. let p = spaces >>. many (description .>>. expr .>> spaces)
  77. match run (p .>> eof) str with
  78. | Success(xs, _, _) -> Show.print tabsCount isFunction xs
  79. | Failure(x, _, _) -> failwithf "%A" x
  80. )
  81. // parse 2 true
  82. type VarType =
  83. | Any
  84. | String
  85. | Numeric
  86. // type X () =
  87. // member __.F(x:string, [<System.ParamArray>] args: string[]) =
  88. // printfn "first"
  89. // for arg in args do
  90. // printfn "%A" arg
  91. // member __.F(x:string, y:string, [<System.ParamArray>] args: string[]) =
  92. // printfn "second"
  93. // for arg in args do
  94. // printfn "%A" arg
  95. // let x = X()
  96. // x.F("1")
  97. // x.F("1", y = "2")
  98. // x.F("1", y = "2", "3")
  99. type 'Func OverloadType =
  100. | JustOverloads of (VarType [] * 'Func) list
  101. /// Если говорить родным F#, то это:
  102. /// ```fsharp
  103. /// member __.F(x:Type1, y:Type2, [&lt;System.ParamArray>] args: Type3 []) =
  104. /// ```
  105. /// выражается так:
  106. /// ```fsharp
  107. /// {| Requireds: [ Type1; Type2 ]; ArgList: Type3 |}
  108. /// ```
  109. | ParamArrayOverload of {| Requireds: VarType []; ArgList: VarType |} * 'Func
  110. module Show =
  111. open FsharpMyExtension.ShowList
  112. let showVarType = function
  113. | Any -> showString "any"
  114. | String -> showString "string"
  115. | Numeric -> showString "numeric"
  116. let showParamArray typ =
  117. // На Lua:
  118. // ```lua
  119. // function f(...)
  120. // -- ...
  121. // end
  122. // ```
  123. // В Python:
  124. // ```python
  125. // def my_function(*argName):
  126. // # ...
  127. // ```
  128. // Но это то, как оно объявляется, а сигнатуру-то как написать?
  129. // showChar '*' << showChar ':' << showVarType typ
  130. showVarType typ << showSpace << showString "[]"
  131. let showArgs varTypes =
  132. varTypes
  133. |> Array.map showVarType
  134. |> List.ofArray
  135. |> joins (showChar ',' << showSpace)
  136. let printSignature (name:string) =
  137. function
  138. | JustOverloads xs ->
  139. xs
  140. |> List.map (fun (varTypes, _) ->
  141. showString name << showParen true (showArgs varTypes)
  142. )
  143. |> lines
  144. | ParamArrayOverload(x, _) ->
  145. showString name
  146. << showParen true
  147. (showArgs x.Requireds << showChar ',' << showSpace
  148. << showParamArray x.ArgList)
  149. >> show
  150. let printFuncSignature (name:string) (returnType:VarType) =
  151. function
  152. | JustOverloads xs ->
  153. xs
  154. |> List.map (fun (varTypes, _) ->
  155. showString name << showParen true (showArgs varTypes)
  156. << showChar ':' << showSpace << showVarType returnType
  157. )
  158. |> lines
  159. | ParamArrayOverload(x, _) ->
  160. showString name
  161. << showParen true
  162. (showArgs x.Requireds << showChar ',' << showSpace
  163. << showParamArray x.ArgList)
  164. << showChar ':' << showSpace << showVarType returnType
  165. >> show
  166. let getFuncByOverloadType overloadType (inputArgs: _ []) =
  167. let inputArgsLength = Array.length inputArgs
  168. match overloadType with
  169. | JustOverloads os ->
  170. os
  171. |> List.tryPick (fun (x, func) ->
  172. if x.Length = inputArgsLength then
  173. Some func
  174. else None
  175. )
  176. | ParamArrayOverload(x, func) ->
  177. if inputArgsLength < x.Requireds.Length then
  178. None
  179. else
  180. Some func
  181. let arg x =
  182. [[|x|] , ()] |> JustOverloads
  183. let unit' =
  184. [[||] , ()] |> JustOverloads
  185. let args xs =
  186. [xs |> Array.ofList, ()] |> JustOverloads
  187. let argsAndOptional xs opt =
  188. [
  189. xs |> Array.ofList, ()
  190. xs @ [opt] |> Array.ofList, ()
  191. ] |> JustOverloads
  192. let argList typ =
  193. ({| Requireds = [||]; ArgList = typ |}, ())
  194. |> ParamArrayOverload
  195. let argAndArgList x typ =
  196. ({| Requireds = [|x|]; ArgList = typ |}, ())
  197. |> ParamArrayOverload
  198. type VarName = string
  199. type Description = string
  200. let proceduresWithAsterix =
  201. [
  202. let dscr =
  203. [
  204. "`*CLEAR` или `*CLR` - очистка основного окна описаний."
  205. ] |> String.concat "\n"
  206. ("*clear":VarName), (dscr:Description), unit'
  207. let dscr =
  208. [
  209. "`*CLEAR` или `*CLR` - очистка основного окна описаний."
  210. ] |> String.concat "\n"
  211. "*clr", dscr, unit'
  212. let dscr =
  213. [
  214. "`*NL [выражение]` - переход на новую строку, затем вывод текста в основном окне описаний. Если `[выражение]` не указано, то перевод строки. Отличается от *PL порядком вывода текста."
  215. ] |> String.concat "\n"
  216. let funcs =
  217. [
  218. [| String |], ()
  219. [| |], ()
  220. ] |> JustOverloads
  221. "*nl", dscr, funcs
  222. let dscr =
  223. [
  224. "`*P [выражение]` - вывод текста в основное окно описаний (по умолчанию находится слева сверху и не может быть отключено)."
  225. ]|> String.concat "\n"
  226. "*p", dscr, arg Any
  227. let dscr =
  228. [
  229. "`*PL [выражение]` - вывод текста, затем переход на новую строку в основном окне описаний. Если `[выражение]` не указано, то перевод строки. Аналогичным образом можно вывести текст, просто написав нужное выражение вместо данного оператора. Например, строки:"
  230. "```qsp"
  231. "*PL $AAA+'989'"
  232. "*PL 'Вы находитесь в парке'"
  233. "*PL 'Преформатированная"
  234. "строка'"
  235. "```"
  236. "и"
  237. "```qsp"
  238. "$AAA+'989'"
  239. "'Вы находитесь в парке'"
  240. "'Преформатированная"
  241. "строка'"
  242. "```"
  243. "выполнят одно и то же действие."
  244. ] |> String.concat "\n"
  245. "*pl", dscr, arg Any
  246. ]
  247. |> List.map (fun (name, dscr, sign) -> name, (dscr, sign))
  248. |> Map.ofList
  249. /// Заданные переменные
  250. let vars =
  251. [
  252. let dscr =
  253. [
  254. "содержит путь к файлу изображения локации. Изображение локации показывается в том случае, если значение данной переменной отлично от '' (не пустая строка) и файл изображения удалось загрузить."
  255. ] |> String.concat "\n"
  256. ("$backimage":VarName), (dscr:Description)
  257. let dscr =
  258. [
  259. "Название выделенного действия."
  260. ] |> String.concat "\n"
  261. "$selact", dscr
  262. let dscr =
  263. [
  264. "содержит название локации-счётчика. Локация-счётчик полезна для проверки выделенных предметов, введённого текста..."
  265. ] |> String.concat "\n"
  266. "$counter", dscr
  267. let dscr =
  268. [
  269. "текущие действия в виде текста. Сохранив значение в переменной, восстановить действия можно в любой момент игры с помощью оператора `DYNAMIC`."
  270. ] |> String.concat "\n"
  271. "$curacts", dscr
  272. let dscr =
  273. [
  274. "текст, находящийся в основном окне описаний. Также есть функция `maintxt`"
  275. ] |> String.concat "\n"
  276. "$maintxt", dscr
  277. let dscr =
  278. [
  279. "содержит название используемого в данный момент шрифта. Если равна '' (пустая строка), то используется шрифт, заданный в настройках программы."
  280. ] |> String.concat "\n"
  281. "$fname", dscr
  282. let dscr =
  283. [
  284. "содержит название локации-обработчика выбора действия. Данная локация полезна, к примеру, для вывода изображений или проигрывания звуков при выборе действий. Получить название выбранного действия можно через функцию `SELACT`."
  285. ] |> String.concat "\n"
  286. "$onactsel", dscr
  287. let dscr =
  288. [
  289. "содержит название локации-обработчика загрузки состояния. Данная локация полезна для выполнения каких-либо действий после загрузки состояния игры."
  290. ] |> String.concat "\n"
  291. "$ongload", dscr
  292. let dscr =
  293. [
  294. "содержит название локации-обработчика сохранения состояния. Данная локация полезна для выполнения каких-либо действий перед сохранением состояния игры."
  295. ] |> String.concat "\n"
  296. "$ongsave", dscr
  297. let dscr =
  298. [
  299. "содержит название локации-обработчика перехода на новую локацию (аналог локации \"common\" в URQ). Может заменить часть функций локации-счётчика. Получить название локации, на которую был осуществлён переход, можно с помощью функции `CURLOC`."
  300. ] |> String.concat "\n"
  301. "$onnewloc", dscr
  302. let dscr =
  303. [
  304. "содержит название локации-обработчика добавления предмета. При добавлении предмета локация вызывается с аргументом `$ARGS[0]` - названием добавленного предмета. Данная локация полезна, к примеру, для ограничения вместительности рюкзака."
  305. ] |> String.concat "\n"
  306. "$onobjadd", dscr
  307. let dscr =
  308. [
  309. "содержит название локации-обработчика удаления предмета. При удалении предмета локация вызывается с аргументом `$ARGS[0]` - названием удалённого предмета. Данная локация полезна, к примеру, для проверки возможности удаления предмета."
  310. ] |> String.concat "\n"
  311. "$onobjdel", dscr
  312. let dscr =
  313. [
  314. "содержит название локации-обработчика выбора предмета. Данная локация полезна, к примеру, для вывода меню предметов. Получить название выбранного предмета можно через функцию `SELOBJ`."
  315. ] |> String.concat "\n"
  316. "$onobjsel", dscr
  317. let dscr =
  318. [
  319. "текст, находящийся в окне пользователя. Также есть функция `stattxt`"
  320. ] |> String.concat "\n"
  321. "$stattxt", dscr
  322. let dscr =
  323. [
  324. "содержит название локации-обработчика строки ввода. Полезна при организации парсера (управление игрой с помощью строки ввода). Текущий текст строки ввода возвращает функция `USER_TEXT`."
  325. ] |> String.concat "\n"
  326. "$usercom", dscr
  327. let dscr =
  328. [
  329. "название текущей локации, также можно использовать `curloc`"
  330. ] |> String.concat "\n"
  331. "$curloc", dscr
  332. let dscr =
  333. [
  334. "содержит размер используемого в данный момент шрифта. Если равна 0, то используется размер, заданный в настройках программы. Относительно данного значения в HTML-режиме вычисляются размеры шрифтов тега \"FONT\"."
  335. ] |> String.concat "\n"
  336. "fsize", dscr
  337. let dscr =
  338. [
  339. "содержит цвет текущего фона. Если равна 0, то используется цвет, заданный в настройках программы."
  340. ] |> String.concat "\n"
  341. "bcolor", dscr
  342. let dscr =
  343. [
  344. "содержит цвет используемого в данный момент шрифта. Если равна 0, то используется цвет, заданный в настройках программы."
  345. ] |> String.concat "\n"
  346. "fcolor", dscr
  347. let dscr =
  348. [
  349. "содержит текущий цвет ссылок. Если равна 0, то используется цвет, заданный в настройках программы."
  350. ] |> String.concat "\n"
  351. "lcolor", dscr
  352. let dscr =
  353. [
  354. "если отлична от 0, включает возможность использования HTML в описании локации, в дополнительном описании, в списках действий и предметов, а также в диалоге ввода текста, вызываемого функцией `INPUT`. Выводимый текст распознаётся как HTML. Список поддерживаемых тегов и их атрибутов смотрите в приложении."
  355. ] |> String.concat "\n"
  356. "usehtml", dscr
  357. let dscr =
  358. [
  359. "Массив, который содержит аргументы текущей локации. Подробнее расписано в процедуре `GOSUB` и ей подобной."
  360. ] |> String.concat "\n"
  361. "args", dscr
  362. "#args", dscr
  363. "$args", dscr
  364. let dscr =
  365. "Если текущая локация вызвана с помощью `FUNC` или создана динамически с помощью `DYNEVAL`, то по итогу вернется это значение. Ах да, эта переменная бывает нескольких типов: `result`, `#result` и `$result`. И возникает вопрос: а что, собственно, вернет, скажем, вызов `DYNEVAL(\"$result = 'string' & #result = 1\")`? Что ж, сработает только `$x = DYNEVAL(\"$result = 'string' & #result = 1\") & $x`, а `#x = DYNEVAL(\"$result = 'string' & #result = 1\") & #x` — выбьет ошибку про несоответствие данных, что довольно странно."
  366. "result", dscr
  367. "$result", dscr
  368. "#result", dscr
  369. let dscr =
  370. [
  371. "если значение переменной не равно 0, то отключается проверка идентификатора игры при загрузке состояния. Полезно для отладки."
  372. ] |> String.concat "\n"
  373. "debug", dscr
  374. let dscr =
  375. [
  376. "если значение переменной не равно 0, то запрещает автопрокрутку текста при его выводе в основное или дополнительное окно описания локации."
  377. ] |> String.concat "\n"
  378. "disablescroll", dscr
  379. let dscr =
  380. [
  381. "если значение переменной не равно 0, то запрещает использование \"подвыражений\" в тексте (например, значением `'<<5+6>>'` будет строка `'<<5+6>>'`, а не `'11'`)."
  382. ] |> String.concat "\n"
  383. "disablesubex", dscr
  384. let dscr =
  385. [
  386. "Если её значение отлично от 0, то сохранение состояния игры пользователем невозможно."
  387. ] |> String.concat "\n"
  388. "nosave", dscr
  389. ]
  390. |> Map.ofList
  391. let functions =
  392. let arg x (return':VarType) = arg x, return'
  393. let unit' (return':VarType) = unit', return'
  394. let args xs (return':VarType) = args xs, return'
  395. let argList typ (return':VarType) = argList typ, return'
  396. let argAndArgList x typ (return':VarType) = argAndArgList x typ, return'
  397. [
  398. let dscr =
  399. [
  400. "`RAND([#выражение 1],[#выражение 2])` - возвращает случайное число между числами `[#выражение 1]` и `[#выражение 2]`. Параметр `[#выражение 2]` может отсутствовать, при этом он принимается равным 0."
  401. ] |> String.concat "\n"
  402. let os =
  403. [
  404. [| Numeric; Numeric |], ()
  405. [| Numeric |], ()
  406. ] |> JustOverloads
  407. "rand", dscr, (os, Numeric)
  408. let dscr =
  409. [
  410. "возвращает название текущей локации, также можно использовать переменную `$curloc`"
  411. ] |> String.concat "\n"
  412. "curloc", dscr, unit' String
  413. let dscr =
  414. [
  415. "возвращает случайное значение от 1 до 1000."
  416. ] |> String.concat "\n"
  417. "rnd", dscr, unit' Numeric
  418. let dscr =
  419. [
  420. "`INPUT([$выражение])` - выводит окно ввода с приглашением [$выражение]. Возвращает введённый играющим текст, либо '' (пустая строка), если была нажата кнопка \"Отмена\"."
  421. ] |> String.concat "\n"
  422. "input", dscr, arg String String
  423. let dscr =
  424. [
  425. "возвращает текст, находящийся в строке ввода. Синоним `usrtxt`"
  426. ] |> String.concat "\n"
  427. "user_text", dscr, unit' String
  428. let dscr =
  429. [
  430. "возвращает текст, находящийся в строке ввода. Синоним `user_text`"
  431. ] |> String.concat "\n"
  432. "usrtxt", dscr, unit' String
  433. let dscr =
  434. [
  435. "`MAX([выражение 1],[выражение 2], ...)` - возвращает максимальное из значений выражений-аргументов. Если передан один аргумент, то считается, что указано имя массива - в этом случае поиск максимального элемента происходит среди строковых (если название массива указано со знаком \"$\") или среди числовых значений элементов массива. Например:"
  436. "```qsp"
  437. "MAX(1,2,5,2,0) & ! вернёт 5"
  438. "MAX(a,b,c) & ! вернёт максимальное из значений переменных"
  439. "MAX('aa','ab','zz') & ! вернёт 'zz'"
  440. "MAX('a') & ! вернёт максимальное из числовых значений элементов массива \"A\""
  441. "MAX('$b') & ! вернёт максимальное из строковых значений элементов массива \"B\""
  442. "```"
  443. ] |> String.concat "\n"
  444. "max", dscr, argList Any Any
  445. let dscr =
  446. [
  447. "`MIN([выражение 1],[выражение 2], ...)` - возвращает минимальное из значений выражений-аргументов. Если передан один аргумент, то считается, что указано имя массива - в этом случае поиск минимального элемента происходит среди строковых (если название массива указано со знаком \"$\") или среди числовых значений элементов массива."
  448. ] |> String.concat "\n"
  449. "min", dscr, argList Any Any
  450. let dscr =
  451. [
  452. "`IIF([#выражение],[выражение_да],[выражение_нет])` - возвращает значение выражения [выражение_да], если [#выражение] верно, иначе значение выражения [выражение_нет]."
  453. ] |> String.concat "\n"
  454. "iif", dscr, args [Numeric; Any; Any] Any
  455. let dscr =
  456. [
  457. "`RGB([#выражение 1],[#выражение 2],[#выражение 3])` - возвращает код цвета на основе 3-х числовых аргументов. [#выражение 1], [#выражение 2] и [#выражение 3] определяют соответственно уровни красного, зелёного и синего цветов. Все значения аргументов должны быть в отрезке [0, 255]. Данная функция используется совместно с системными переменными `BCOLOR`, `FCOLOR` и `LCOLOR`."
  458. ] |> String.concat "\n"
  459. "rgb", dscr, args [Numeric; Numeric; Numeric] Numeric
  460. let dscr =
  461. [
  462. "`ISPLAY([$выражение])` - проверяет, проигрывается ли файл с заданным названием в текущий момент времени и возвращает -1, если файл воспроизводится, иначе 0."
  463. ] |> String.concat "\n"
  464. "isplay", dscr, arg String Numeric
  465. let dscr =
  466. [
  467. "возвращает количество миллисекунд, прошедших с момента начала игры."
  468. ] |> String.concat "\n"
  469. "msecscount", dscr, unit' Numeric
  470. let dscr =
  471. [
  472. "`DESC([$выражение])` - возвращает текст базового описания локации с заданным в [$выражение] названием."
  473. ] |> String.concat "\n"
  474. "desc", dscr, arg String String
  475. let dscr =
  476. [
  477. "возвращает текст, находящийся в основном окне описаний. Также есть переменная `$maintxt`"
  478. ] |> String.concat "\n"
  479. "maintxt", dscr, unit' String
  480. let dscr =
  481. [
  482. "возвращает текст, находящийся в окне пользователя. Также есть переменная `$stattxt`"
  483. ] |> String.concat "\n"
  484. "stattxt", dscr, unit' String
  485. let dscr =
  486. [
  487. "возвращает версию интерпретатора в формате \"X.Y.Z\""
  488. ] |> String.concat "\n"
  489. "qspver", dscr, unit' String
  490. let dscr =
  491. [
  492. "`FUNC([$выражение],[параметр 1],[параметр 2], ...)` - обработка локации с названием `[$выражение]`. Указанные параметры передаются в массиве `ARGS`. Результат функции равен значению `$RESULT` при возврате строкового значения или `RESULT` при возврате числового значения. Если при обработке локации были установлены и `RESULT`, и `$RESULT`, то предпочтение отдаётся строковому значению. После обработки локации предыдущие значения `ARGS` и `RESULT` восстанавливаются. Примеры:"
  493. "```qsp"
  494. "PL 4 + FUNC('функция') & ! обработка локации \"функция\" как функции. Массив ARGS пуст. Результат передается через `$RESULT` или `RESULT`, в зависимости от кода обрабатываемой локации."
  495. "PL FUNC($name, 1) * 78 & ! обработка локации с названием в $name как функции. `ARGS[0]` равен 1."
  496. "MSG \"text\" + FUNC($name, \"строка\", 2) & ! обработка локации с названием в $name как функции. `$ARGS[0]` содержит строку \"строка\", `ARGS[1]` равен 2."
  497. "```"
  498. ] |> String.concat "\n"
  499. "func", dscr, argList Any Any
  500. let dscr =
  501. [
  502. "То же, что и `FUNC`, только возвращает строчный тип:"
  503. "```qsp"
  504. "# start"
  505. "$func('toString', 1) & ! -> '1'"
  506. "-"
  507. ""
  508. "# toString"
  509. "$result = ARGS[0]"
  510. "-"
  511. "```"
  512. ] |> String.concat "\n"
  513. "$func", dscr, argList Any String
  514. let dscr =
  515. [
  516. "`DYNEVAL([$выражение],[параметр 1],[параметр 2], ...)` - возвращает значение указанного выражения. Функция позволяет вычислять значения динамически сгенерированных выражений. Указанные параметры передаются в массиве `ARGS`, а после вычисления выражения предыдущие значения `ARGS` восстанавливаются. Примеры:"
  517. "```qsp"
  518. "DYNEVAL('3+4')"
  519. "PL DYNEVAL('mid(\"abcd\",2,1)+\"qwerty\"')"
  520. "PL DYNEVAL($test + ' + val(\"<<$test>>\")')"
  521. "DYNEVAL(\" $args[0] <> 'текст' \", 'строка')"
  522. "$x = DYNEVAL(\"$result = 'текст'\") & $x"
  523. "```"
  524. ] |> String.concat "\n"
  525. "dyneval", dscr, argAndArgList String Any Any
  526. let dscr =
  527. [
  528. "возвращает количество предметов в рюкзаке."
  529. ] |> String.concat "\n"
  530. "countobj", dscr, unit' Numeric
  531. let dscr =
  532. [
  533. "возвращает название выделенного предмета."
  534. ] |> String.concat "\n"
  535. "selobj", dscr, unit' String
  536. let dscr =
  537. [
  538. "`GETOBJ([#выражение])` - возвращает название предмета в рюкзаке, расположенного в заданной позиции. Индексация предметов рюкзака ведётся с 1."
  539. "Если предмета с заданным индексом не существует, возвращается пустая строка ('')."
  540. ""
  541. "Примеры:"
  542. "```qsp"
  543. "GETOBJ(1) & ! вернёт название первого предмета в рюкзаке"
  544. "GETOBJ(COUNTOBJ) &! вернёт название последнего добавленного предмета"
  545. "```"
  546. ""
  547. "Код, подсчитывающий в массиве `OBJECTS` число предметов с одинаковым названием:"
  548. "```qsp"
  549. "i = 1"
  550. ":loop"
  551. "IF i <= COUNTOBJ:"
  552. " OBJECTS[$GETOBJ(i)] = OBJECTS[$GETOBJ(i)] + 1"
  553. " i = i + 1"
  554. " JUMP 'loop'"
  555. "END"
  556. "```"
  557. ] |> String.concat "\n"
  558. "getobj", dscr, arg Numeric String
  559. let dscr =
  560. [
  561. "`ARRCOMP([#выражение 1],[$выражение 2],[$выражение 3])` - возвращает индекс элемента массива с названием `[$выражение 2]`, соответствующего регулярному выражению `[$выражение 3]`. Поиск начинается с элемента номер `[#выражение 1]`; индексация элементов массива ведётся с нуля. Параметр `[#выражение 1]` может отсутствовать, при этом он принимается равным 0. Если элемент не найден, функция возвращает -1."
  562. "Поиск происходит среди текстовых элементов массива. Примеры:"
  563. "```qsp"
  564. "ARRCOMP(0,'A','This') & ! найдёт строку 'This' среди текстовых элементов массива \"A\" (или вернёт -1, если такого значения не существует)"
  565. "ARRCOMP(2,'A','abc\\d+') & ! найдёт строку, соответствующую регулярному выражению \"abc\\d+\", в текстовых значениях массива \"A\" (первые два элемента массива игнорируются)"
  566. "ARRCOMP(0,'A','.*string.*') & ! аналогично предыдущему примеру, но поиск осуществляется по всем текстовым элементам массива"
  567. "ARRCOMP('A','This') & ! эквивалентно 1-му варианту"
  568. "```"
  569. ] |> String.concat "\n"
  570. let funcs =
  571. [
  572. [| Numeric; String; String |], ()
  573. [| String; String |], ()
  574. ] |> JustOverloads
  575. "arrcomp", dscr, (funcs, String)
  576. let dscr =
  577. [
  578. "`STRCOMP([$выражение],[$шаблон])` - проводит сравнение строки `[$выражение]` на соответствие регулярному выражению `[$шаблон]`. Возвращает -1, если строка соответствует шаблону, иначе 0. Сравни с функцией `STRFIND`."
  579. ] |> String.concat "\n"
  580. "strcomp", dscr, args [String; String] Numeric
  581. let dscr =
  582. [
  583. "`STRFIND([$выражение],[$шаблон],[#номер])` - возвращает подстроку в строке `[$выражение]`, соответствующую группе с номером `[#номер]` регулярного выражения `[$шаблон]`. Если подстрока с указанным номером отсутствует, то возвращается пустая строка. Нумерация групп подстрок начинается с 1. Если параметр `[#номер]` отсутствует или равен 0, то возвращается подстрока, соответствующая всему регулярному выражению `[$шаблон]`. Примеры:"
  584. "```qsp"
  585. "STRFIND(' идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 0) & ! -> ''"
  586. "STRFIND('идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 1) & ! -> 'идти'"
  587. "STRFIND('идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 2) & ! -> 'к'"
  588. "STRFIND('идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 3) & ! -> 'пещере'"
  589. "STRFIND('идти к пещере', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 4) & ! -> 'пещере'"
  590. "STRFIND('искать ключ', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 1) & ! -> 'искать'"
  591. "STRFIND('искать', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 0) & ! -> ''"
  592. "STRFIND('искать', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 1) & ! -> ''"
  593. "STRFIND('искать', '^(\\S+)(\\s(\\S+)(\\s(\\S+))?)?$', 1) & ! -> 'искать'"
  594. "STRFIND('идти к дому', 'к\\s(\\S+)', 0) & ! -> 'к дому'"
  595. "STRFIND('идти к дому', 'к\\s(\\S+)') & ! -> 'к дому'"
  596. "STRFIND('идти к дому', 'к\\s(\\S+)', 1) & ! -> 'дому'"
  597. "STRFIND('идти к своему дому', 'к\\s(\\S+)', 1) & ! -> 'своему'"
  598. "```"
  599. ] |> String.concat "\n"
  600. "strfind", dscr, (argsAndOptional [ String; String ] Numeric, String)
  601. "$strfind", dscr, (argsAndOptional [ String; String ] Numeric, String)
  602. let dscr =
  603. [
  604. "`STRPOS([$выражение],[$шаблон],[#номер])` - возвращает позицию символа, с которого начинается вхождение подстроки в строке `[$выражение]`, соответствующей группе с номером `[#номер]` регулярного выражения `[$шаблон]`. Если подстрока с указанным номером отсутствует, то возвращается 0. Нумерация групп подстрок начинается с 1. Если параметр `[#номер]` отсутствует или равен 0, то возвращается позиция символа, с которого начинается вхождение подстроки, соответствующей всему регулярному выражению `[$шаблон]`."
  605. "Примеры:"
  606. "```qsp"
  607. "STRPOS(' идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 0) & ! -> 0"
  608. "STRPOS('идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 1) & ! -> 1"
  609. "STRPOS('идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 2) & ! -> 6"
  610. "STRPOS('идти к пещере', '^(\\S+)\\s(\\S+)\\s(\\S+)$', 3) & ! -> 8"
  611. "STRPOS('идти к пещере', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 4) & ! -> 8"
  612. "STRPOS('искать ключ', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 1) & ! -> 1"
  613. "STRPOS('искать', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 0) & ! -> 0"
  614. "STRPOS('искать', '^(\\S+)\\s(\\S+)(\\s(\\S+))?$', 1) & ! -> 0"
  615. "STRPOS('искать', '^(\\S+)(\\s(\\S+)(\\s(\\S+))?)?$', 1) & ! -> 1"
  616. "STRPOS('идти к дому', 'к\\s(\\S+)', 0) & ! -> 6"
  617. "STRPOS('идти к дому', 'к\\s(\\S+)') & ! -> 6"
  618. "STRPOS('идти к дому', 'к\\s(\\S+)', 1) & ! -> 8"
  619. "STRPOS('идти к своему дому', 'к\\s(\\S+)', 1) & ! -> 8"
  620. "```"
  621. ] |> String.concat "\n"
  622. "strpos", dscr, (argsAndOptional [ String; String ] Numeric, Numeric)
  623. let dscr =
  624. [
  625. "возвращает текущие действия в виде текста. Сохранив значение в переменной, восстановить действия можно в любой момент игры с помощью оператора `DYNAMIC`."
  626. ] |> String.concat "\n"
  627. "curacts", dscr, unit' String
  628. let dscr =
  629. [
  630. "`ARRPOS([#выражение 1],[$выражение 2],[выражение 3])` - возвращает индекс элемента массива с названием `[$выражение 2]`, равного значению выражения `[выражение 3]`. Поиск начинается с элемента номер `[#выражение 1]`; индексация элементов массива ведётся с нуля. Параметр [#выражение 1] может отсутствовать, при этом он принимается равным 0. Если указанное значение не найдено, функция возвращает -1."
  631. "Чтобы найти числовое значение в массиве, нужно в `[$выражение 2]` подставить лишь название массива (в кавычках), для строкового - название массива с символом \"$\" перед его названием. Примеры:"
  632. "`ARRPOS(0,'$A','This')` - найдёт строку 'This' в текстовых значениях массива \"A\" (или вернёт -1, если такого значения не существует)"
  633. "`ARRPOS(2,'A',65)` - найдёт число 65 в числовых значениях массива \"A\" (при этом первые два элемента массива игнорируются)"
  634. "`ARRPOS('$B','test')` - поиск строки 'test' среди текстовых значений массива \"B\""
  635. ] |> String.concat "\n"
  636. let funcs =
  637. [
  638. [| Numeric; String; Any |], ()
  639. [| String; Any |], ()
  640. ] |> JustOverloads
  641. "arrpos", dscr, (funcs, Numeric)
  642. let dscr =
  643. [
  644. "`ARRSIZE([$выражение])` - возвращает число элементов в массиве с названием `[$выражение]`."
  645. ] |> String.concat "\n"
  646. "arrsize", dscr, arg String Numeric
  647. let dscr =
  648. [
  649. "`INSTR([#выражение 1],[$выражение 2],[$выражение 3])` - возвращает номер позиции символа, с которого начинается вхождение строки `[$выражение 3]` в строку `[$выражение 2]` (или 0, если такой строки нет). Поиск начинается с символа номер `[#выражение 1]`. Параметр `[#выражение 1]` может отсутствовать, при этом он принимается равным 1. Примеры:"
  650. "`INSTR(1,'ABCDefgh','BC')` равно `2`"
  651. "`INSTR(1,'ABCDefgh','Be')` равно `0`"
  652. "`INSTR('abcdef','abc')` равно `1`"
  653. ] |> String.concat "\n"
  654. let funcs =
  655. [
  656. [| Numeric; String; String |], ()
  657. [| String; String |], ()
  658. ] |> JustOverloads
  659. "instr", dscr, (funcs, Numeric)
  660. let dscr =
  661. [
  662. "`ISNUM([$выражение])` - функция проверяет, все ли символы в строке являются цифрами (учитывая знак \"-\" в начале, прилегающие пробелы и символы табуляции). Если в указанной строке есть хотя бы один символ - не-цифра (исключая возможный \"-\" в начале и прилегающие пробелы / символы табуляции), то функция возвращает 0 (ложь), иначе -1 (истина)."
  663. "Функция полезна при проверке введённой играющим строки на число. Примеры:"
  664. "`ISNUM('9999 ')` равно `-1`"
  665. "`ISNUM(' -888')` равно `-1`"
  666. "`ISNUM('777a6')` равно `0`"
  667. ] |> String.concat "\n"
  668. "isnum", dscr, arg String Numeric
  669. let dscr =
  670. [
  671. "`LCASE([$выражение])` - возвращает строку маленьких букв, полученную изменением регистра букв исходной строки `[$выражение]`. Пример:"
  672. "```qsp"
  673. "LCASE('TExT#') & ! 'text#'"
  674. "```"
  675. ] |> String.concat "\n"
  676. "lcase", dscr, arg String String
  677. let dscr =
  678. [
  679. "`LEN([$выражение])` - возвращает длину строки `[$выражение]`."
  680. ] |> String.concat "\n"
  681. "len", dscr, arg String Numeric
  682. let dscr =
  683. [
  684. "`MID([$выражение],[#выражение 1],[#выражение 2])` - вырезает из строки `[$выражение]` строку, которая начинается с символа номер `[#выражение 1]` и имеет длину `[#выражение 2]`. Индексация символов в строке ведётся с 1."
  685. "Параметр `[#выражение 2]` может отсутствовать, при этом вырезается вся строка, начиная с символа [#выражение 1]. Примеры:"
  686. "```qsp"
  687. "MID('abcd', 1, 2) равно 'ab'"
  688. "MID('abcd', 2, 3) равно 'bcd'"
  689. "MID('abcd', 2) равно 'bcd'"
  690. "```"
  691. ] |> String.concat "\n"
  692. "mid", dscr, (argsAndOptional [ String; Numeric ] Numeric, String)
  693. "$mid", dscr, (argsAndOptional [ String; Numeric ] Numeric, String)
  694. let dscr =
  695. [
  696. "`REPLACE([$выражение 1],[$выражение 2],[$выражение 3])` - заменяет в строке [$выражение 1] все вхождения строки [$выражение 2] строкой [$выражение 3]. Если [$выражение 3] отсутствует или указана пустая строка, то удаляет в исходной строке все вхождения искомой строки. Примеры:"
  697. "`REPLACE('test', '12', '4')` равно `'test'`"
  698. "`REPLACE('test', 'e', 's')` равно `'tsst'`"
  699. "`REPLACE('test', 't', '34')` равно `'34es34'`"
  700. "`REPLACE('test', 't')` равно `'es'`"
  701. ] |> String.concat "\n"
  702. "replace", dscr, (argsAndOptional [ String; String ] String, String)
  703. let dscr =
  704. "Синоним `REPLACE`"
  705. "$replace", dscr, (argsAndOptional [ String; String ] String, String)
  706. let dscr =
  707. [
  708. "`STR([#выражение])` - переводит число (числовое выражение) `[#выражение]` в соответствующую строку. Например,"
  709. "`PL STR(56)` выведет строку `56`."
  710. ] |> String.concat "\n"
  711. "str", dscr, arg Numeric String
  712. let dscr =
  713. [
  714. "`TRIM([$выражение])` - удаляет прилегающие пробелы и символы табуляции из `[$выражение]`. Затем возвращает полученную строку. Пример:"
  715. "`TRIM(' TRIM TEST ')` равно `'TRIM TEST'`"
  716. ] |> String.concat "\n"
  717. "trim", dscr, arg String String
  718. "$trim", dscr, arg String String
  719. let dscr =
  720. [
  721. "`UCASE([$выражение])` - возвращает строку больших букв, полученную изменением регистра букв исходной строки `[$выражение]`. Пример:"
  722. "```qsp"
  723. "UCASE('TexT#') & ! -> 'TEXT#'"
  724. "```"
  725. ] |> String.concat "\n"
  726. "ucase", dscr, arg String String
  727. let dscr =
  728. [
  729. "`VAL([$выражение])` - переводит строку цифр `[$выражение]` в соответствующее число. Если [$выражение] равно '' (пустая строка) или если оно содержит не-цифры, то возвращается 0."
  730. ] |> String.concat "\n"
  731. "val", dscr, arg String Numeric
  732. let dscr =
  733. [
  734. "возвращает название выделенного действия."
  735. ] |> String.concat "\n"
  736. "selact", dscr, unit' String
  737. ]
  738. |> List.map (fun (name, dscr, sign) -> name, (dscr, sign))
  739. |> Map.ofList
  740. /// Да-да, всё это — процедуры: они что-то выполняют и никуда не перемещают.
  741. let procedures =
  742. [
  743. let dscr =
  744. [
  745. "`OPENGAME [$выражение]` - если `[$выражение]` равно '' (пустая строка) или отсутствует, то вызов окна загрузки состояния игры, иначе загрузка состояния из указанного файла. См. также локацию-обработчик события загрузки игры."
  746. ] |> String.concat "\n"
  747. let os =
  748. [
  749. [||], ()
  750. [| String |], ()
  751. ] |> JustOverloads
  752. "opengame", dscr, os
  753. let dscr =
  754. [
  755. "`CMDCLEAR` или `CMDCLR` - очистка строки ввода."
  756. ] |> String.concat "\n"
  757. "cmdclear", dscr, unit'
  758. let dscr =
  759. [
  760. "`CMDCLEAR` или `CMDCLR` - очистка строки ввода."
  761. ] |> String.concat "\n"
  762. "cmdclr", dscr, unit'
  763. let dscr =
  764. [
  765. "`SAVEGAME [$выражение]` - если `[$выражение]` равно '' (пустая строка) или отсутствует, то вызов окна сохранения состояния игры, иначе сохранение состояния в указанный файл. См. также локацию-обработчик события сохранения игры."
  766. ] |> String.concat "\n"
  767. let os =
  768. [
  769. [||], ()
  770. [| String |], ()
  771. ] |> JustOverloads
  772. "savegame", dscr, os
  773. let dscr =
  774. [
  775. "`OPENQST [$выражение]` - открытие и запуск заданного файла игры. При использовании данного оператора, не происходит удаления переменных, удаления предметов инвентаря, очистки дополнительного описания и строки ввода, а также остановки проигрываемых файлов (для этого в начале загружаемой игры можно выполнить \"KILLALL & CLS & CLOSE ALL\")."
  776. ] |> String.concat "\n"
  777. "openqst", dscr, arg String
  778. let dscr =
  779. [
  780. "`ADDQST [$выражение]` - из заданного файла игры добавляет все локации, названия которых отсутствуют среди текущих игровых локаций. Загруженные локации полностью эквивалентны локациям из основного файла игры."
  781. ] |> String.concat "\n"
  782. "addqst", dscr, arg String
  783. let dscr =
  784. "Синоним `addqst`"
  785. "addlib", dscr, arg String
  786. let dscr =
  787. "Синоним `addqst`"
  788. "inclib", dscr, arg String
  789. let dscr =
  790. [
  791. "KILLQST - удаляет все локации, добавленные с помощью оператора `ADDQST`"
  792. ] |> String.concat "\n"
  793. "killqst", dscr, unit'
  794. "freelib", dscr, unit'
  795. "dellib", dscr, unit'
  796. let dscr =
  797. [
  798. "`DELACT [$название]` или `DEL ACT [$название]` - удаляет действие из списка действий на локации (если такое действие существует). Например:"
  799. "```qsp"
  800. "DELACT 'Идти вперед'"
  801. "DELACT $SELACT"
  802. "```"
  803. ] |> String.concat "\n"
  804. "delact", dscr, arg String
  805. let dscr =
  806. [
  807. "CLA - очистка списка текущих действий."
  808. ] |> String.concat "\n"
  809. "cla", dscr, unit'
  810. let dscr =
  811. [
  812. "`ADDOBJ [$название],[$путь к файлу изображения]` или `ADD OBJ [$название],[$путь к файлу изображения]` - добавление предмета с заданным изображением в рюкзак."
  813. "К предметам добавляется новый с названием `[$название]` и изображением `[$путь к файлу изображения]`."
  814. ""
  815. "Параметр `[$путь к файлу изображения]` может отсутствовать, при этом предмет добавится без изображения."
  816. ""
  817. "Обратите внимание - для использования одинаковых предметов инвентаря, например денег, патронов и т.п., лучше использовать дополнительную переменную, обозначающую количество этих предметов, чтобы не загромождать инвентарь списком из 137 предметов Рубль / Патрон. Для хранения числа предметов можно использовать массивы, индексируемые через строки:"
  818. ""
  819. "```qsp"
  820. "OBJECTS['деньги'] = 12"
  821. "OBJECTS['патроны'] = 137"
  822. "'Количество: <<OBJECTS[$getobj(countobj)]>>'"
  823. "```"
  824. ] |> String.concat "\n"
  825. "addobj", dscr, argsAndOptional [String] String
  826. let dscr =
  827. [
  828. "`DELOBJ [$название]` или `DEL OBJ [$название]` - удаление предмета из рюкзака, если таковой имеется. Также см. локацию-обработчик удаления предмета."
  829. ] |> String.concat "\n"
  830. "delobj", dscr, arg String
  831. let dscr =
  832. [
  833. "`KILLOBJ [#выражение]` - удаление предмета, расположенного в заданной позиции. Если параметр [#выражение] не указан, то очистка рюкзака."
  834. "Индексация предметов рюкзака ведётся с 1. Также см. локацию-обработчик удаления предмета."
  835. ] |> String.concat "\n"
  836. let os =
  837. [
  838. [||], ()
  839. [| Numeric |], ()
  840. ] |> JustOverloads
  841. "killobj", dscr, os
  842. let dscr =
  843. [
  844. "`UNSELECT` или `UNSEL` - отмена выбора предмета. При выборе играющим какого-либо предмета, он остаётся выделенным. Данная команда снимает выделение."
  845. ] |> String.concat "\n"
  846. "unsel", dscr, unit'
  847. "unselect", dscr, unit'
  848. let dscr =
  849. [
  850. "KILLALL - эквивалентен конструкции `KILLVAR & KILLOBJ`."
  851. ] |> String.concat "\n"
  852. "killall", dscr, unit'
  853. let dscr =
  854. [
  855. "`KILLVAR [$название массива],[#индекс элемента]` - удаление элемента массива. Если индекс элемента не указан, то очищается весь массив. Если оператор вызван без аргументов, то удаляются все переменные - обычно применяется в начале игры, чтобы при возврате в начальную локацию после неудачного прохождения какого-то этапа игры обнулить все переменные (в противном случае, может оказаться, что запертые двери уже открыты, жена похищена до свадьбы, а Баба-Яга уже отдала кому-то нужный клубочек). Примеры:"
  856. "```qsp"
  857. "KILLVAR"
  858. "KILLVAR 'a'"
  859. "KILLVAR 'a',3"
  860. "```"
  861. ] |> String.concat "\n"
  862. let funcs =
  863. [
  864. [| String; Numeric |], ()
  865. [| String; |], ()
  866. [||], ()
  867. ] |> JustOverloads
  868. "killvar", dscr, funcs
  869. let dscr =
  870. [
  871. "`COPYARR [$массив-приёмник],[$массив-источник]` - копирование содержимого массива в другой массив. Копируются как текстовые, так и числовые значения массива. Размер массива-приёмника при копировании не имеет значения. Примеры:"
  872. "```qsp"
  873. "COPYARR '$a','$b'"
  874. "COPYARR 'a','b'"
  875. "COPYARR $arrname1,$arrname2"
  876. "COPYARR 'a<<$arrname1>>','a<<$arrname2>>'"
  877. "```"
  878. ] |> String.concat "\n"
  879. "copyarr", dscr, args [String; String]
  880. let dscr =
  881. [
  882. "`CLEAR` или `CLR` - очистка окна пользователя."
  883. ] |> String.concat "\n"
  884. "clear", dscr, unit'
  885. let dscr =
  886. [
  887. "`CLEAR` или `CLR` - очистка окна пользователя."
  888. ] |> String.concat "\n"
  889. "clr", dscr, unit'
  890. let dscr =
  891. [
  892. "`CLOSE [$путь к звуковому файлу]` - остановка проигрывания звукового файла с заданным названием."
  893. "`CLOSE ALL` - остановка проигрывания всех активных звуковых файлов."
  894. ] |> String.concat "\n"
  895. "close", dscr, arg String
  896. let dscr = "`CLOSE ALL` - остановка проигрывания всех активных звуковых файлов."
  897. "close all", dscr, unit' // особый-преособый случай
  898. let dscr =
  899. [
  900. "`CLS` - эквивалентен конструкции `CLEAR & *CLEAR & CLA & CMDCLEAR`, т.е. очищает всё, кроме списка предметов."
  901. ] |> String.concat "\n"
  902. "cls", dscr, unit'
  903. let dscr =
  904. [
  905. "`DYNAMIC [$строка кода],[параметр 1],[параметр 2], ...` - выполнение кода. Данный оператор позволяет динамически генерировать код игры. Переданные параметры хранятся в массиве `ARGS`. После выполнения кода предыдущие значения `ARGS` восстанавливаются. Примеры:"
  906. "```qsp"
  907. "DYNAMIC '$a=\"string<<$b>>\"'"
  908. "DYNAMIC '$a'"
  909. "DYNAMIC 'if $a=\"string\":''text!'''"
  910. "DYNAMIC \""
  911. "$args[0]"
  912. "addobj $args[1]"
  913. "\",'Текст','Вилка'"
  914. "```"
  915. ] |> String.concat "\n"
  916. "dynamic", dscr, argAndArgList String Any
  917. let dscr =
  918. [
  919. "`MENU [$выражение]` - вызов меню с заданным названием"
  920. ] |> String.concat "\n"
  921. "menu", dscr, arg String
  922. let dscr =
  923. [
  924. "`MSG [выражение]` - вывод заданного сообщения в информационном окне."
  925. ] |> String.concat "\n"
  926. "msg", dscr, arg String
  927. let dscr =
  928. [
  929. "`NL [выражение]` - переход на новую строку (перевод каретки), затем вывод текста в окне пользователя. Если `[выражение]` не указано, то перевод строки. Отличается от `PL` порядком вывода текста."
  930. ] |> String.concat "\n"
  931. let funcs =
  932. [
  933. [| String |], ()
  934. [| |], ()
  935. ] |> JustOverloads
  936. "nl", dscr, funcs
  937. let dscr =
  938. [
  939. "`P [выражение]` - вывод текста в окно пользователя (по умолчанию находится справа внизу, обычно служит для вспомогательных целей)."
  940. ] |> String.concat "\n"
  941. "p", dscr, arg String
  942. let dscr =
  943. [
  944. "`PL [выражение]` - вывод текста, затем переход на новую строку в окне пользователя. Если `[выражение]` не указано, то перевод строки"
  945. ] |> String.concat "\n"
  946. "pl", dscr, arg String
  947. let dscr =
  948. [
  949. "`PLAY [$путь к звуковому файлу],[#громкость]` - проигрывание звукового файла с заданным названием и громкостью. Громкость указывается в процентах от 0 до 100."
  950. "Параметр `[#громкость]` может отсутствовать, при этом громкость принимается равной 100%. Примеры:"
  951. "`PLAY 'sound/music.mp3'` - проигрывает файл с громкостью 100%"
  952. "`PLAY 'sound/music.mp3',50` - проигрывает файл в половину возможной громкости"
  953. "`PLAY 'sound/music.mp3',0` - проигрывает файл с громкостью 0% (без звука)"
  954. "`PLAY '<<$file>>.mid',volume` - проигрывает файл, имя которого хранится в $file (расширение \"mid\") с громкостью, значение которой задано в volume"
  955. "`PLAY $file,volume` - аналогично"
  956. "Если файл уже проигрывается, то изменяется громкость звучания без его \"перезапуска\". Поддерживается множество различных аудиоформатов и одновременное звучание до 32-х композиций."
  957. ] |> String.concat "\n"
  958. "play", dscr, argsAndOptional [ String ] Numeric
  959. let dscr =
  960. [
  961. "обновление интерфейса (а также смена цветов, шрифта, назначенных с помощью системных переменных `BCOLOR`, `FCOLOR`, `LCOLOR`, `FSIZE`, `$FNAME`)."
  962. ] |> String.concat "\n"
  963. "refint", dscr, unit'
  964. let dscr =
  965. [
  966. "`SETTIMER [#выражение]` - задает интервал таймера для локации-счётчика (по умолчанию 500мс, т.е. локация-счётчик обрабатывается 2 раза в секунду). Также влияет на частоту автоматического обновления интерфейса."
  967. ] |> String.concat "\n"
  968. "settimer", dscr, arg Numeric
  969. let dscr =
  970. [
  971. "`SHOWACTS [#выражение]` - если значение выражения отлично от 0, то показывает список действий, иначе скрывает его. Примеры:"
  972. "`SHOWACTS 1` - показывает список действий"
  973. "`SHOWACTS 0` - скрывает список действий"
  974. ] |> String.concat "\n"
  975. "showacts", dscr, arg Numeric
  976. let dscr =
  977. [
  978. "`SHOWINPUT [#выражение]` - если значение выражения отлично от 0, то показывает строку ввода, иначе скрывает её."
  979. ] |> String.concat "\n"
  980. "showinput", dscr, arg Numeric
  981. let dscr =
  982. [
  983. "`SHOWOBJS [#выражение]` - если значение выражения отлично от 0, то показывает список предметов, иначе скрывает его."
  984. ] |> String.concat "\n"
  985. "showobjs", dscr, arg Numeric
  986. let dscr =
  987. [
  988. "`SHOWSTAT [#выражение]` - если значение выражения отлично от 0, то показывает дополнительное описание, иначе скрывает его."
  989. ] |> String.concat "\n"
  990. "showstat", dscr, arg Numeric
  991. let dscr =
  992. [
  993. "`VIEW [$путь к графическому файлу]` - просмотр картинки из указанного файла. Если вместо `[$путь к графическому файлу]` указана пустая строка (`''`) или параметр не указан, то это скроет окно с картинкой."
  994. ] |> String.concat "\n"
  995. let funcs =
  996. [
  997. [| String |], ()
  998. [| |], ()
  999. ] |> JustOverloads
  1000. "view", dscr, funcs
  1001. let dscr =
  1002. [
  1003. "`WAIT [#выражение]` - остановка выполнения программы на заданное количество миллисекунд (1 секунда = 1000 миллисекунд)."
  1004. ] |> String.concat "\n"
  1005. "wait", dscr, arg Numeric
  1006. ]
  1007. let jump =
  1008. let dscr =
  1009. [
  1010. "`JUMP [$выражение]` - переход в текущем коде (при обработке локации / выбора действия) на метку `[$выражение]`. Метка на локации обозначается как `:[название метки]`. После описания метки (через \"&\") могут идти операторы. Если интерпретатор находит случайную метку, то он её просто игнорирует. Например:"
  1011. "```qsp"
  1012. "jump 'КонеЦ'"
  1013. "p 'Это сообщение не будет выведено'"
  1014. ":конец"
  1015. "p 'А это сообщение пользователь увидит'"
  1016. "```"
  1017. "С помощью оператора `JUMP` можно организовывать циклы:"
  1018. "```qsp"
  1019. "s = 0"
  1020. ":loop"
  1021. "if s < 9:"
  1022. " s=s+1"
  1023. " pl s"
  1024. " jump 'LOOP'"
  1025. "end"
  1026. "p 'Всё!'"
  1027. "```"
  1028. "Оператор `JUMP` также полезен во время отладки квеста, чтобы \"обойти\" группу операторов, которые временно не нужны."
  1029. ] |> String.concat "\n"
  1030. "jump", dscr, arg String
  1031. let transferOperators =
  1032. [
  1033. let dscr =
  1034. [
  1035. "`GOSUB [$выражение],[параметр 1],[параметр 2], ...` или `GS [$выражение],[параметр 1],[параметр 2], ...` - обработка локации с названием `[$выражение]`. Базовое описание локации добавляется к текущему описанию, базовые действия добавляются к текущим действиям, и происходит выполнение операторов в поле \"Выполнить при посещении\", затем возврат на исходную строку (продолжение выполнения программы)."
  1036. "Переданные параметры хранятся в массиве `ARGS`. После обработки локации предыдущие значения `ARGS` восстанавливаются. Примеры:"
  1037. "```qsp"
  1038. "GS 'ход' & ! обработка локации \"ход\". Массив `ARGS` пуст."
  1039. "GS $loc,1 & ! обработка локации, название которой хранится в $loc с передачей одного параметра. ARGS[0] равен 1."
  1040. "GS 'ход',$var,2,'данные' & ! обработка локации \"ход\" с передачей 3-х параметров. `$ARGS[0]` равен значению `$var`, `ARGS[1]` равен 2, `$ARGS[2]` содержит строку \"данные\"."
  1041. "```"
  1042. ] |> String.concat "\n"
  1043. let sign = argAndArgList String Any
  1044. "gosub", dscr, sign
  1045. "gs", dscr, sign
  1046. let dscr =
  1047. [
  1048. "`GOTO [$выражение],[параметр 1],[параметр 2], ...` или `GT [$выражение],[параметр 1],[параметр 2], ...` - переход на локацию с названием `[$выражение]`. Поле основного описания локации, а также список текущих действий заменяются описанием и действиями новой локации."
  1049. "Переданные параметры хранятся в массиве `ARGS`. Примеры:"
  1050. "```qsp"
  1051. "GT 'локация' & ! переход на локацию \"локация\". Массив `ARGS` пуст."
  1052. "GT 'локация',1,'данные' & ! переход на локацию \"локация\" с передачей 2-х параметров. `ARGS[0]` равен 1, `$ARGS[1]` содержит строку \"данные\"."
  1053. "```"
  1054. ] |> String.concat "\n"
  1055. let sign = argAndArgList String Any
  1056. "goto", dscr, sign
  1057. "gt", dscr, sign
  1058. let dscr =
  1059. [
  1060. "`XGOTO [$выражение],[параметр 1],[параметр 2], ...` или `XGT [$выражение],[параметр 1],[параметр 2], ...` - отличается от \"`GOTO` / `GT`\" тем, что при переходе не очищается поле основного описания локации, а базовое описание новой локации добавляется к текущему основному описанию. Тем не менее, список действий заменяется действиями новой локации."
  1061. ] |> String.concat "\n"
  1062. let sign = argAndArgList String Any
  1063. "xgoto", dscr, sign
  1064. "xgt", dscr, sign
  1065. ]
  1066. let transferOperatorsSet =
  1067. transferOperators
  1068. |> List.map (fun (name, dscr, sign) -> name)
  1069. |> Set.ofList
  1070. /// Всевозможные процедуры
  1071. let procs =
  1072. jump::(procedures @ transferOperators)
  1073. |> List.map (fun (name, dscr, sign) -> name, ((dscr:Description), sign))
  1074. |> Map.ofList
  1075. let exprSymbolicOperators =
  1076. let arg x (return':VarType) = arg x, return'
  1077. let unit' (return':VarType) = unit', return'
  1078. let args xs (return':VarType) = args xs, return'
  1079. let argList typ (return':VarType) = argList typ, return'
  1080. let argAndArgList x typ (return':VarType) = argAndArgList x typ, return'
  1081. [
  1082. let dscr =
  1083. "`[$выражение 1] & [$выражение 2]` - операция объединения строковых выражений."
  1084. "&", dscr, args [String; String] String
  1085. ]
  1086. let exprNamedOperators =
  1087. let arg x (return':VarType) = arg x, return'
  1088. let unit' (return':VarType) = unit', return'
  1089. let args xs (return':VarType) = args xs, return'
  1090. let argList typ (return':VarType) = argList typ, return'
  1091. let argAndArgList x typ (return':VarType) = argAndArgList x typ, return'
  1092. [
  1093. // Для значения "верно" настоятельно рекомендуется использовать -1.
  1094. let dscr =
  1095. [
  1096. "`[#выражение 1] AND [#выражение 2]` - операция \"и\". Если оба рядом стоящие выражения верны, то верно и всё выражение."
  1097. ] |> String.concat "\n"
  1098. "and", dscr, args [Numeric; Numeric] Numeric
  1099. let dscr =
  1100. [
  1101. "`[#выражение 1] OR [#выражение 2]` - операция \"или\". Если хотя бы одно из рядом стоящих выражений верно, то верно и всё выражение."
  1102. ] |> String.concat "\n"
  1103. "or", dscr, args [Numeric; Numeric] Numeric
  1104. let dscr =
  1105. [
  1106. "`[#выражение 1] MOD [#выражение 2]` - операция вычисления остатка от деления."
  1107. ] |> String.concat "\n"
  1108. "mod", dscr, args [Numeric; Numeric] Numeric
  1109. let dscr =
  1110. [
  1111. "`NO [#выражение]` - отрицание. Верно, если `[#выражение]` ложно и наоборот (аналогично \"NOT\" в Basic)."
  1112. ] |> String.concat "\n"
  1113. "no", dscr, arg Numeric Numeric
  1114. let dscr =
  1115. [
  1116. "`OBJ [$выражение]` - верно, если в рюкзаке есть предмет `[$выражение]`."
  1117. ] |> String.concat "\n"
  1118. "obj", dscr, arg String Numeric
  1119. let dscr =
  1120. [
  1121. "`LOC [$выр]` - верно, если в игре есть локация с названием `[$выр]`."
  1122. ] |> String.concat "\n"
  1123. "loc", dscr, arg String Numeric
  1124. ]
  1125. let keywords =
  1126. [
  1127. let dscr =
  1128. [
  1129. "`IF [#выражение]:[оператор1] & [оператор2] & ... ELSE [оператор3] & [оператор4] & ...` - если `[#выражение]` верно (не равно 0), то выполнить заданные операторы до ключевого слова `ELSE`, иначе выполнить операторы после `ELSE`."
  1130. "Если ключевое слово `ELSE` не указано, то при верном значении [#выражение], выполняются все операторы, находящиеся после символа `:`."
  1131. "Примеры:"
  1132. "```qsp"
  1133. "if ((a+b)/c)=45+54 or (b<5 or c>45) and no obj 'лопата' and $f=$vvv+'RRRRR':p 'OK' & goto 'Next'"
  1134. "if был_здесь[$curloc]:exit"
  1135. "if a<3:jump 'sss'"
  1136. "if $имя = '':msg 'Введите имя!' & jump 'ввод'"
  1137. "if a+b=2:c=30 & gt 'next' else c=10"
  1138. "```"
  1139. ] |> String.concat "\n"
  1140. "if", dscr
  1141. "else", dscr
  1142. "elseif", dscr
  1143. "end", "Завершает конструкции `ACT`, `IF` или `FOR`."
  1144. let dscr =
  1145. [
  1146. "`ACT [$название],[$путь к файлу изображения]:[оператор] & [оператор] & ...` - добавление действия к существующим на локации."
  1147. "К действиям добавляется новое с описанием `[$название]` и изображением `[$путь к файлу изображения]`. При нажатии на него выполнятся заданные операторы."
  1148. "Параметр `[$путь к файлу изображения]` может отсутствовать, при этом действие добавится без изображения."
  1149. ] |> String.concat "\n"
  1150. "act", dscr
  1151. let dscr =
  1152. [
  1153. "`SET [название переменной]=[выражение]`, `LET [название переменной]=[выражение]` или `[название переменной]=[выражение]` - установка значения переменной. Если нужно установить текстовое значение переменной, то перед её названием ставится `$`."
  1154. "Примеры:"
  1155. "```qsp"
  1156. "SET A=123"
  1157. "SET $B='строка'"
  1158. "LET C=A"
  1159. "D=456"
  1160. "$D='ещё строка'"
  1161. "$D='и ещё"
  1162. " одна"
  1163. "строка'"
  1164. "```"
  1165. ] |> String.concat "\n"
  1166. "set", dscr
  1167. "let", dscr
  1168. let dscr =
  1169. [
  1170. "завершение выполнения текущего кода (преждевременный выход из подпрограммы / обработчика какого-либо события...)."
  1171. ] |> String.concat "\n"
  1172. "exit", dscr
  1173. let dscr =
  1174. [
  1175. "**FOR** `[#переменная]` **=** `[#выражение]` **TO** `[#выражение]`**:** `[операторы]` - Выполняет `[#операторы]` несколько раз, по очереди присваивая `[#переменной]` все численные значения от первого до второго `[#выражения]`."
  1176. ""
  1177. "Однострочная форма записи:"
  1178. "```qsp"
  1179. "for номер_нпц = 1 to количество_нпц: gs 'инициализировать нпц', номер_нпц"
  1180. "стоимость['меч'] = 10"
  1181. "стоимость['доспех'] = 250"
  1182. "стоимость['щит'] = 15"
  1183. "стоимость_снаряжения = 0"
  1184. "for номер_предмета = 0 to arrsize('стоимость')-1: стоимость_снаряжения += стоимость[номер предмета]"
  1185. "```"
  1186. ""
  1187. "Многострочная форма записи:"
  1188. "* После символа `:` ставится перенос строки"
  1189. "* Заканчивается FOR строкой `END`"
  1190. "* Допускается вложенность неограниченной глубины. Каждый уровень вложения должен заканчиваться своей строкой `END`."
  1191. "* Пример:"
  1192. " ```qsp"
  1193. " for i = 0 to arrsize('arr')-1:"
  1194. " *pl arr[i]"
  1195. " if arr[i] > 10:"
  1196. " jump конец"
  1197. " end"
  1198. " end"
  1199. " ```"
  1200. ""
  1201. "Можно еще задать шаг цикла, для этого используется **STEP**:"
  1202. "```qsp"
  1203. "for нечётные = 1 to 10 step 2: *pl нечётные"
  1204. "```"
  1205. ] |> String.concat "\n"
  1206. "for", dscr
  1207. "to", "**TO** — ключевое слово для конструкции FOR"
  1208. "step", "**STEP** — ключевое слово для конструкции FOR"
  1209. ]