sci2-ts 0.0.0-stage → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/LICENSE +21 -0
  3. package/README.md +113 -2
  4. package/apps/viewer/editor.html +43 -0
  5. package/apps/viewer/explore.html +27 -0
  6. package/apps/viewer/index.html +26 -0
  7. package/apps/viewer/package.json +27 -0
  8. package/apps/viewer/play.html +26 -0
  9. package/apps/viewer/plugin.d.ts +18 -0
  10. package/apps/viewer/plugin.js +75 -0
  11. package/apps/viewer/plugin.ts +84 -0
  12. package/apps/viewer/src/adlib.d.ts +20 -0
  13. package/apps/viewer/src/adlib.js +55 -0
  14. package/apps/viewer/src/adlib.ts +62 -0
  15. package/apps/viewer/src/app.d.ts +5 -0
  16. package/apps/viewer/src/app.js +5 -0
  17. package/apps/viewer/src/app.ts +5 -0
  18. package/apps/viewer/src/asset-index.d.ts +22 -0
  19. package/apps/viewer/src/asset-index.js +74 -0
  20. package/apps/viewer/src/asset-index.ts +90 -0
  21. package/apps/viewer/src/audio.d.ts +28 -0
  22. package/apps/viewer/src/audio.js +102 -0
  23. package/apps/viewer/src/audio.ts +110 -0
  24. package/apps/viewer/src/editor-handles.d.ts +63 -0
  25. package/apps/viewer/src/editor-handles.js +332 -0
  26. package/apps/viewer/src/editor-handles.ts +368 -0
  27. package/apps/viewer/src/editor-languages.d.ts +23 -0
  28. package/apps/viewer/src/editor-languages.js +157 -0
  29. package/apps/viewer/src/editor-languages.ts +135 -0
  30. package/apps/viewer/src/editor.css +213 -0
  31. package/apps/viewer/src/editor.d.ts +1 -0
  32. package/apps/viewer/src/editor.js +393 -0
  33. package/apps/viewer/src/editor.ts +412 -0
  34. package/apps/viewer/src/explore/classes.d.ts +7 -0
  35. package/apps/viewer/src/explore/classes.js +63 -0
  36. package/apps/viewer/src/explore/classes.ts +61 -0
  37. package/apps/viewer/src/explore/context.d.ts +33 -0
  38. package/apps/viewer/src/explore/context.js +96 -0
  39. package/apps/viewer/src/explore/context.ts +124 -0
  40. package/apps/viewer/src/explore/explore.css +93 -0
  41. package/apps/viewer/src/explore/explore.d.ts +1 -0
  42. package/apps/viewer/src/explore/explore.js +102 -0
  43. package/apps/viewer/src/explore/explore.ts +104 -0
  44. package/apps/viewer/src/explore/inspect.d.ts +5 -0
  45. package/apps/viewer/src/explore/inspect.js +208 -0
  46. package/apps/viewer/src/explore/inspect.ts +279 -0
  47. package/apps/viewer/src/explore/live.d.ts +22 -0
  48. package/apps/viewer/src/explore/live.js +318 -0
  49. package/apps/viewer/src/explore/live.ts +365 -0
  50. package/apps/viewer/src/explore/map.d.ts +11 -0
  51. package/apps/viewer/src/explore/map.js +182 -0
  52. package/apps/viewer/src/explore/map.ts +193 -0
  53. package/apps/viewer/src/files.d.ts +21 -0
  54. package/apps/viewer/src/files.js +69 -0
  55. package/apps/viewer/src/files.ts +72 -0
  56. package/apps/viewer/src/game-profile.d.ts +19 -0
  57. package/apps/viewer/src/game-profile.js +4 -0
  58. package/apps/viewer/src/game-profile.ts +26 -0
  59. package/apps/viewer/src/main.d.ts +1 -0
  60. package/apps/viewer/src/main.js +473 -0
  61. package/apps/viewer/src/main.ts +527 -0
  62. package/apps/viewer/src/music.d.ts +14 -0
  63. package/apps/viewer/src/music.js +32 -0
  64. package/apps/viewer/src/music.ts +34 -0
  65. package/apps/viewer/src/opl-worklet.d.ts +1 -0
  66. package/apps/viewer/src/opl-worklet.js +47 -0
  67. package/apps/viewer/src/opl-worklet.ts +55 -0
  68. package/apps/viewer/src/overlay.d.ts +31 -0
  69. package/apps/viewer/src/overlay.js +103 -0
  70. package/apps/viewer/src/overlay.ts +123 -0
  71. package/apps/viewer/src/play.css +14 -0
  72. package/apps/viewer/src/play.d.ts +1 -0
  73. package/apps/viewer/src/play.js +179 -0
  74. package/apps/viewer/src/play.ts +177 -0
  75. package/apps/viewer/src/saves.d.ts +10 -0
  76. package/apps/viewer/src/saves.js +50 -0
  77. package/apps/viewer/src/saves.ts +51 -0
  78. package/apps/viewer/src/session.d.ts +91 -0
  79. package/apps/viewer/src/session.js +301 -0
  80. package/apps/viewer/src/session.ts +321 -0
  81. package/apps/viewer/src/sound-preview.d.ts +7 -0
  82. package/apps/viewer/src/sound-preview.js +214 -0
  83. package/apps/viewer/src/sound-preview.ts +228 -0
  84. package/apps/viewer/src/style.css +64 -0
  85. package/apps/viewer/vite.config.ts +25 -0
  86. package/bin/sci-ts.mjs +9 -0
  87. package/lib/994.sc +49 -0
  88. package/lib/995.sc +53 -0
  89. package/lib/996.sc +299 -0
  90. package/lib/997.sc +198 -0
  91. package/lib/998.sc +338 -0
  92. package/lib/999.sc +189 -0
  93. package/lib/resources.d.ts +2 -0
  94. package/lib/resources.js +84 -0
  95. package/lib/resources.ts +88 -0
  96. package/lib/system.sh +62 -0
  97. package/package.json +75 -4
  98. package/packages/content/room.schema.json +267 -0
  99. package/packages/content/src/index.d.ts +3 -0
  100. package/packages/content/src/index.js +3 -0
  101. package/packages/content/src/index.ts +3 -0
  102. package/packages/content/src/room.d.ts +111 -0
  103. package/packages/content/src/room.js +886 -0
  104. package/packages/content/src/room.ts +1011 -0
  105. package/packages/content/src/target.d.ts +80 -0
  106. package/packages/content/src/target.js +1 -0
  107. package/packages/content/src/target.ts +60 -0
  108. package/packages/content/src/yarn.d.ts +90 -0
  109. package/packages/content/src/yarn.js +214 -0
  110. package/packages/content/src/yarn.ts +261 -0
  111. package/packages/sci/src/analysis/game.d.ts +90 -0
  112. package/packages/sci/src/analysis/game.js +221 -0
  113. package/packages/sci/src/analysis/game.ts +305 -0
  114. package/packages/sci/src/analysis/runtime.d.ts +58 -0
  115. package/packages/sci/src/analysis/runtime.js +133 -0
  116. package/packages/sci/src/analysis/runtime.ts +163 -0
  117. package/packages/sci/src/audio/adlib.d.ts +73 -0
  118. package/packages/sci/src/audio/adlib.js +280 -0
  119. package/packages/sci/src/audio/adlib.ts +329 -0
  120. package/packages/sci/src/audio/index.d.ts +43 -0
  121. package/packages/sci/src/audio/index.js +99 -0
  122. package/packages/sci/src/audio/index.ts +122 -0
  123. package/packages/sci/src/audio/midi.d.ts +92 -0
  124. package/packages/sci/src/audio/midi.js +242 -0
  125. package/packages/sci/src/audio/midi.ts +262 -0
  126. package/packages/sci/src/audio/opl2.d.ts +74 -0
  127. package/packages/sci/src/audio/opl2.js +283 -0
  128. package/packages/sci/src/audio/opl2.ts +283 -0
  129. package/packages/sci/src/audio/sol.d.ts +32 -0
  130. package/packages/sci/src/audio/sol.js +81 -0
  131. package/packages/sci/src/audio/sol.ts +100 -0
  132. package/packages/sci/src/audio/write.d.ts +35 -0
  133. package/packages/sci/src/audio/write.js +91 -0
  134. package/packages/sci/src/audio/write.ts +108 -0
  135. package/packages/sci/src/gfx/cel.d.ts +36 -0
  136. package/packages/sci/src/gfx/cel.js +82 -0
  137. package/packages/sci/src/gfx/cel.ts +110 -0
  138. package/packages/sci/src/gfx/palette.d.ts +24 -0
  139. package/packages/sci/src/gfx/palette.js +49 -0
  140. package/packages/sci/src/gfx/palette.ts +56 -0
  141. package/packages/sci/src/gfx/pic-file.d.ts +46 -0
  142. package/packages/sci/src/gfx/pic-file.js +114 -0
  143. package/packages/sci/src/gfx/pic-file.ts +155 -0
  144. package/packages/sci/src/gfx/pic.d.ts +27 -0
  145. package/packages/sci/src/gfx/pic.js +34 -0
  146. package/packages/sci/src/gfx/pic.ts +53 -0
  147. package/packages/sci/src/gfx/quantize.d.ts +42 -0
  148. package/packages/sci/src/gfx/quantize.js +199 -0
  149. package/packages/sci/src/gfx/quantize.ts +218 -0
  150. package/packages/sci/src/gfx/view-file.d.ts +62 -0
  151. package/packages/sci/src/gfx/view-file.js +182 -0
  152. package/packages/sci/src/gfx/view-file.ts +233 -0
  153. package/packages/sci/src/gfx/view.d.ts +28 -0
  154. package/packages/sci/src/gfx/view.js +45 -0
  155. package/packages/sci/src/gfx/view.ts +62 -0
  156. package/packages/sci/src/index.d.ts +38 -0
  157. package/packages/sci/src/index.js +38 -0
  158. package/packages/sci/src/index.ts +38 -0
  159. package/packages/sci/src/motion/pathfinding.d.ts +40 -0
  160. package/packages/sci/src/motion/pathfinding.js +140 -0
  161. package/packages/sci/src/motion/pathfinding.ts +147 -0
  162. package/packages/sci/src/resource/archive.d.ts +16 -0
  163. package/packages/sci/src/resource/archive.js +51 -0
  164. package/packages/sci/src/resource/archive.ts +56 -0
  165. package/packages/sci/src/resource/lzs.d.ts +12 -0
  166. package/packages/sci/src/resource/lzs.js +64 -0
  167. package/packages/sci/src/resource/lzs.ts +66 -0
  168. package/packages/sci/src/resource/manager.d.ts +45 -0
  169. package/packages/sci/src/resource/manager.js +158 -0
  170. package/packages/sci/src/resource/manager.ts +184 -0
  171. package/packages/sci/src/resource/map.d.ts +18 -0
  172. package/packages/sci/src/resource/map.js +34 -0
  173. package/packages/sci/src/resource/map.ts +44 -0
  174. package/packages/sci/src/resource/types.d.ts +37 -0
  175. package/packages/sci/src/resource/types.js +45 -0
  176. package/packages/sci/src/resource/types.ts +57 -0
  177. package/packages/sci/src/script/assembly.d.ts +67 -0
  178. package/packages/sci/src/script/assembly.js +748 -0
  179. package/packages/sci/src/script/assembly.ts +714 -0
  180. package/packages/sci/src/script/compiler.d.ts +75 -0
  181. package/packages/sci/src/script/compiler.js +993 -0
  182. package/packages/sci/src/script/compiler.ts +1040 -0
  183. package/packages/sci/src/script/disasm.d.ts +81 -0
  184. package/packages/sci/src/script/disasm.js +318 -0
  185. package/packages/sci/src/script/disasm.ts +323 -0
  186. package/packages/sci/src/script/kernel-names.d.ts +6 -0
  187. package/packages/sci/src/script/kernel-names.js +165 -0
  188. package/packages/sci/src/script/kernel-names.ts +165 -0
  189. package/packages/sci/src/script/opcodes.d.ts +22 -0
  190. package/packages/sci/src/script/opcodes.js +45 -0
  191. package/packages/sci/src/script/opcodes.ts +72 -0
  192. package/packages/sci/src/script/script.d.ts +56 -0
  193. package/packages/sci/src/script/script.js +63 -0
  194. package/packages/sci/src/script/script.ts +111 -0
  195. package/packages/sci/src/script/sexpr.d.ts +45 -0
  196. package/packages/sci/src/script/sexpr.js +151 -0
  197. package/packages/sci/src/script/sexpr.ts +139 -0
  198. package/packages/sci/src/script/vocab.d.ts +15 -0
  199. package/packages/sci/src/script/vocab.js +44 -0
  200. package/packages/sci/src/script/vocab.ts +48 -0
  201. package/packages/sci/src/script/world.d.ts +25 -0
  202. package/packages/sci/src/script/world.js +65 -0
  203. package/packages/sci/src/script/world.ts +70 -0
  204. package/packages/sci/src/text/font.d.ts +37 -0
  205. package/packages/sci/src/text/font.js +103 -0
  206. package/packages/sci/src/text/font.ts +125 -0
  207. package/packages/sci/src/text/message.d.ts +69 -0
  208. package/packages/sci/src/text/message.js +171 -0
  209. package/packages/sci/src/text/message.ts +205 -0
  210. package/packages/sci/src/vm/kernels/arrays.d.ts +19 -0
  211. package/packages/sci/src/vm/kernels/arrays.js +182 -0
  212. package/packages/sci/src/vm/kernels/arrays.ts +164 -0
  213. package/packages/sci/src/vm/kernels/audio.d.ts +70 -0
  214. package/packages/sci/src/vm/kernels/audio.js +347 -0
  215. package/packages/sci/src/vm/kernels/audio.ts +349 -0
  216. package/packages/sci/src/vm/kernels/core.d.ts +5 -0
  217. package/packages/sci/src/vm/kernels/core.js +87 -0
  218. package/packages/sci/src/vm/kernels/core.ts +91 -0
  219. package/packages/sci/src/vm/kernels/graphics.d.ts +141 -0
  220. package/packages/sci/src/vm/kernels/graphics.js +467 -0
  221. package/packages/sci/src/vm/kernels/graphics.ts +502 -0
  222. package/packages/sci/src/vm/kernels/index.d.ts +8 -0
  223. package/packages/sci/src/vm/kernels/index.js +29 -0
  224. package/packages/sci/src/vm/kernels/index.ts +32 -0
  225. package/packages/sci/src/vm/kernels/lists.d.ts +6 -0
  226. package/packages/sci/src/vm/kernels/lists.js +127 -0
  227. package/packages/sci/src/vm/kernels/lists.ts +111 -0
  228. package/packages/sci/src/vm/kernels/motion.d.ts +7 -0
  229. package/packages/sci/src/vm/kernels/motion.js +204 -0
  230. package/packages/sci/src/vm/kernels/motion.ts +194 -0
  231. package/packages/sci/src/vm/kernels/palette.d.ts +82 -0
  232. package/packages/sci/src/vm/kernels/palette.js +292 -0
  233. package/packages/sci/src/vm/kernels/palette.ts +303 -0
  234. package/packages/sci/src/vm/kernels/saves.d.ts +45 -0
  235. package/packages/sci/src/vm/kernels/saves.js +123 -0
  236. package/packages/sci/src/vm/kernels/saves.ts +149 -0
  237. package/packages/sci/src/vm/kernels/system.d.ts +62 -0
  238. package/packages/sci/src/vm/kernels/system.js +110 -0
  239. package/packages/sci/src/vm/kernels/system.ts +128 -0
  240. package/packages/sci/src/vm/kernels/text.d.ts +13 -0
  241. package/packages/sci/src/vm/kernels/text.js +338 -0
  242. package/packages/sci/src/vm/kernels/text.ts +328 -0
  243. package/packages/sci/src/vm/memory.d.ts +138 -0
  244. package/packages/sci/src/vm/memory.js +168 -0
  245. package/packages/sci/src/vm/memory.ts +266 -0
  246. package/packages/sci/src/vm/replace.d.ts +11 -0
  247. package/packages/sci/src/vm/replace.js +14 -0
  248. package/packages/sci/src/vm/replace.ts +16 -0
  249. package/packages/sci/src/vm/savegame.d.ts +89 -0
  250. package/packages/sci/src/vm/savegame.js +161 -0
  251. package/packages/sci/src/vm/savegame.ts +188 -0
  252. package/packages/sci/src/vm/value.d.ts +17 -0
  253. package/packages/sci/src/vm/value.js +12 -0
  254. package/packages/sci/src/vm/value.ts +25 -0
  255. package/packages/sci/src/vm/vm.d.ts +155 -0
  256. package/packages/sci/src/vm/vm.js +1053 -0
  257. package/packages/sci/src/vm/vm.ts +914 -0
  258. package/tools/adlib-render.d.ts +1 -0
  259. package/tools/adlib-render.js +49 -0
  260. package/tools/adlib-render.ts +42 -0
  261. package/tools/analyze.d.ts +1 -0
  262. package/tools/analyze.js +25 -0
  263. package/tools/analyze.ts +25 -0
  264. package/tools/art/build.d.ts +34 -0
  265. package/tools/art/build.js +175 -0
  266. package/tools/art/build.ts +153 -0
  267. package/tools/art.d.ts +1 -0
  268. package/tools/art.js +31 -0
  269. package/tools/art.ts +29 -0
  270. package/tools/asm.d.ts +1 -0
  271. package/tools/asm.js +61 -0
  272. package/tools/asm.ts +55 -0
  273. package/tools/cli.d.ts +1 -0
  274. package/tools/cli.js +99 -0
  275. package/tools/cli.ts +100 -0
  276. package/tools/editor-server.d.ts +29 -0
  277. package/tools/editor-server.js +162 -0
  278. package/tools/editor-server.ts +176 -0
  279. package/tools/explore.d.ts +1 -0
  280. package/tools/explore.js +305 -0
  281. package/tools/explore.ts +250 -0
  282. package/tools/game/audio.d.ts +19 -0
  283. package/tools/game/audio.js +143 -0
  284. package/tools/game/audio.ts +130 -0
  285. package/tools/game/build.d.ts +46 -0
  286. package/tools/game/build.js +259 -0
  287. package/tools/game/build.ts +283 -0
  288. package/tools/game/defaults.d.ts +26 -0
  289. package/tools/game/defaults.js +82 -0
  290. package/tools/game/defaults.ts +83 -0
  291. package/tools/game/font.d.ts +3 -0
  292. package/tools/game/font.js +124 -0
  293. package/tools/game/font.ts +126 -0
  294. package/tools/game/kit.d.ts +7 -0
  295. package/tools/game/kit.js +7 -0
  296. package/tools/game/kit.ts +10 -0
  297. package/tools/game/new.d.ts +8 -0
  298. package/tools/game/new.js +39 -0
  299. package/tools/game/new.ts +38 -0
  300. package/tools/game/target.d.ts +7 -0
  301. package/tools/game/target.js +41 -0
  302. package/tools/game/target.ts +42 -0
  303. package/tools/game/template/resources.ts.tmpl +43 -0
  304. package/tools/game/template/rooms/1.room.yaml +9 -0
  305. package/tools/game/template/rooms/1.yarn +17 -0
  306. package/tools/game/template/scripts/0.sc +24 -0
  307. package/tools/game.d.ts +1 -0
  308. package/tools/game.js +77 -0
  309. package/tools/game.ts +70 -0
  310. package/tools/mod-build.d.ts +28 -0
  311. package/tools/mod-build.js +173 -0
  312. package/tools/mod-build.ts +179 -0
  313. package/tools/mod-target.d.ts +16 -0
  314. package/tools/mod-target.js +26 -0
  315. package/tools/mod-target.ts +32 -0
  316. package/tools/mod.d.ts +1 -0
  317. package/tools/mod.js +47 -0
  318. package/tools/mod.ts +45 -0
  319. package/tools/msg.d.ts +1 -0
  320. package/tools/msg.js +40 -0
  321. package/tools/msg.ts +36 -0
  322. package/tools/node-files.d.ts +3 -0
  323. package/tools/node-files.js +34 -0
  324. package/tools/node-files.ts +33 -0
  325. package/tools/patches.d.ts +3 -0
  326. package/tools/patches.js +13 -0
  327. package/tools/patches.ts +13 -0
  328. package/tools/pic-build.d.ts +9 -0
  329. package/tools/pic-build.js +26 -0
  330. package/tools/pic-build.ts +27 -0
  331. package/tools/pic.d.ts +1 -0
  332. package/tools/pic.js +64 -0
  333. package/tools/pic.ts +61 -0
  334. package/tools/play.d.ts +1 -0
  335. package/tools/play.js +54 -0
  336. package/tools/play.ts +54 -0
  337. package/tools/png.d.ts +16 -0
  338. package/tools/png.js +124 -0
  339. package/tools/png.ts +123 -0
  340. package/tools/res.d.ts +1 -0
  341. package/tools/res.js +48 -0
  342. package/tools/res.ts +50 -0
  343. package/tools/scenario.d.ts +1 -0
  344. package/tools/scenario.js +74 -0
  345. package/tools/scenario.ts +80 -0
  346. package/tools/site/build.d.ts +8 -0
  347. package/tools/site/build.js +110 -0
  348. package/tools/site/build.ts +116 -0
  349. package/tools/site/markdown.d.ts +11 -0
  350. package/tools/site/markdown.js +88 -0
  351. package/tools/site/markdown.ts +84 -0
  352. package/tools/view-build.d.ts +34 -0
  353. package/tools/view-build.js +47 -0
  354. package/tools/view-build.ts +71 -0
  355. package/tools/view.d.ts +1 -0
  356. package/tools/view.js +54 -0
  357. package/tools/view.ts +52 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * What the compiler needs to know about the game it builds for: which classes rooms
3
+ * subclass, where the system objects live (globals) and how messages are numbered. The
4
+ * compiler itself knows nothing about any particular game.
5
+ */
6
+ export interface Target {
7
+ /** The class new rooms subclass: the game's own room class. */
8
+ roomClass: string;
9
+ /** Property values every room gets unless the YAML overrides them. */
10
+ roomDefaults: Record<string, number>;
11
+ /** Global variable numbers (SCI's script 0 locals). */
12
+ globals: {
13
+ ego: number;
14
+ game: number;
15
+ curRoom: number;
16
+ /** The Messager instance whose `say:` shows a message. */
17
+ messager: number;
18
+ /** The narrator object (what unknown talker numbers fall back to). */
19
+ narratorObject: number;
20
+ /** The Sound object playing the music, and the one for sound effects. */
21
+ music: number;
22
+ sound: number;
23
+ };
24
+ /** Message talker number for narration (no speaker). */
25
+ narrator: number;
26
+ /** Message talker number for the hero (`Hero:` lines, and the topics they pick). */
27
+ heroTalker: number;
28
+ /**
29
+ * Talker numbers from here up are characters defined by compiled rooms: the game asks
30
+ * the current room's `findTalker:` for them (needs the target's support patch).
31
+ */
32
+ firstRoomTalker: number;
33
+ /** A character without a portrait: a plain text box, this class and properties. */
34
+ voice: {
35
+ class: string;
36
+ props: Record<string, number>;
37
+ };
38
+ /**
39
+ * A character with a portrait view: loop 0 the bust, loop 1 mouth shapes, loop 2 eyes
40
+ * (cel 0 open), all cels the same size so the parts line up. The talker class gets
41
+ * `init: mouth bust eyes frame`; parts are a View (bust) and Props at `at`.
42
+ */
43
+ portrait: {
44
+ class: string;
45
+ props: Record<string, number>;
46
+ at: [number, number];
47
+ frameSignal: number;
48
+ partSignal: number;
49
+ };
50
+ /**
51
+ * Conversations: an instance of this class runs a menu of topics for a thing (e.g. a
52
+ * Teller with `init: client modNum sayNoun verb rootNoun`; topic labels are messages at
53
+ * rootNoun/verb/cond, answers at sayNoun/verb/cond).
54
+ */
55
+ teller: {
56
+ class: string;
57
+ props: Record<string, number>;
58
+ verb: number;
59
+ };
60
+ /** The class that cycles a prop's cels forever (<<animate x forever>>, cycle: forward). */
61
+ forwardCycle: string;
62
+ /** Verb number for "said on arrival" messages. */
63
+ narrationVerb: number;
64
+ /** Verb names as used in Yarn node titles (lower case) -> verb numbers. */
65
+ verbs: Record<string, number>;
66
+ /** Message file version written in new message files. */
67
+ messageVersion: number;
68
+ /**
69
+ * Flags (Yarn's true/false variables): procedures `set`, `clear`, `test` (export numbers
70
+ * of `script`, each taking the flag number), and the range a mod may use.
71
+ */
72
+ flags: {
73
+ script: number;
74
+ set: number;
75
+ clear: number;
76
+ test: number;
77
+ first: number;
78
+ last: number;
79
+ };
80
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ /**
2
+ * What the compiler needs to know about the game it builds for: which classes rooms
3
+ * subclass, where the system objects live (globals) and how messages are numbered. The
4
+ * compiler itself knows nothing about any particular game.
5
+ */
6
+ export interface Target {
7
+ /** The class new rooms subclass: the game's own room class. */
8
+ roomClass: string;
9
+ /** Property values every room gets unless the YAML overrides them. */
10
+ roomDefaults: Record<string, number>;
11
+ /** Global variable numbers (SCI's script 0 locals). */
12
+ globals: {
13
+ ego: number;
14
+ game: number;
15
+ curRoom: number;
16
+ /** The Messager instance whose `say:` shows a message. */
17
+ messager: number;
18
+ /** The narrator object (what unknown talker numbers fall back to). */
19
+ narratorObject: number;
20
+ /** The Sound object playing the music, and the one for sound effects. */
21
+ music: number;
22
+ sound: number;
23
+ };
24
+ /** Message talker number for narration (no speaker). */
25
+ narrator: number;
26
+ /** Message talker number for the hero (`Hero:` lines, and the topics they pick). */
27
+ heroTalker: number;
28
+ /**
29
+ * Talker numbers from here up are characters defined by compiled rooms: the game asks
30
+ * the current room's `findTalker:` for them (needs the target's support patch).
31
+ */
32
+ firstRoomTalker: number;
33
+ /** A character without a portrait: a plain text box, this class and properties. */
34
+ voice: { class: string; props: Record<string, number> };
35
+ /**
36
+ * A character with a portrait view: loop 0 the bust, loop 1 mouth shapes, loop 2 eyes
37
+ * (cel 0 open), all cels the same size so the parts line up. The talker class gets
38
+ * `init: mouth bust eyes frame`; parts are a View (bust) and Props at `at`.
39
+ */
40
+ portrait: { class: string; props: Record<string, number>; at: [number, number]; frameSignal: number; partSignal: number };
41
+ /**
42
+ * Conversations: an instance of this class runs a menu of topics for a thing (e.g. a
43
+ * Teller with `init: client modNum sayNoun verb rootNoun`; topic labels are messages at
44
+ * rootNoun/verb/cond, answers at sayNoun/verb/cond).
45
+ */
46
+ teller: { class: string; props: Record<string, number>; verb: number };
47
+ /** The class that cycles a prop's cels forever (<<animate x forever>>, cycle: forward). */
48
+ forwardCycle: string;
49
+ /** Verb number for "said on arrival" messages. */
50
+ narrationVerb: number;
51
+ /** Verb names as used in Yarn node titles (lower case) -> verb numbers. */
52
+ verbs: Record<string, number>;
53
+ /** Message file version written in new message files. */
54
+ messageVersion: number;
55
+ /**
56
+ * Flags (Yarn's true/false variables): procedures `set`, `clear`, `test` (export numbers
57
+ * of `script`, each taking the flag number), and the range a mod may use.
58
+ */
59
+ flags: { script: number; set: number; clear: number; test: number; first: number; last: number };
60
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Yarn Spinner's file format (https://docs.yarnspinner.dev), the part rooms use so far:
3
+ *
4
+ * title: wisp.talk <- headers, `key: value`, until ---
5
+ * ---
6
+ * Golden pods hang from the rock. <- a line; `Speaker: text` names who says it
7
+ * <<if $met_wisp>> <- conditions on true/false variables:
8
+ * They hum when you're near. not, and, or, ==, !=, (...), true, false
9
+ * <<else>>
10
+ * They're silent.
11
+ * <<endif>>
12
+ * <<set $looked to true>>
13
+ * -> Who are you? <- a choice; its body is indented below it
14
+ * Wisp: A memory of this place.
15
+ * -> Sing for me <<if $met_wisp>> <- a choice only offered when its condition holds
16
+ * Wisp: Not yet.
17
+ * // a comment
18
+ * ===
19
+ *
20
+ * Other commands (<<walk hero 110 160>>, <<wait 2>>...) are kept as name + arguments for
21
+ * the compiler to check. Choices inside choices or inside <<if>> are rejected with the
22
+ * line they're on, until the compiler supports them.
23
+ */
24
+ export interface YarnNode {
25
+ title: string;
26
+ headers: Record<string, string>;
27
+ body: YarnItem[];
28
+ /** Where the node starts, for error messages. */
29
+ line: number;
30
+ }
31
+ export type YarnItem = YarnLine | YarnChoice | YarnSet | YarnIf | YarnCommand;
32
+ /** Any other <<command arg arg ...>>; the compiler knows which exist (walk, wait, ...). */
33
+ export interface YarnCommand {
34
+ kind: "command";
35
+ name: string;
36
+ args: string[];
37
+ line: number;
38
+ }
39
+ export interface YarnLine {
40
+ kind: "line";
41
+ speaker?: string;
42
+ text: string;
43
+ line: number;
44
+ }
45
+ export interface YarnChoice {
46
+ kind: "choice";
47
+ text: string;
48
+ /** Only offered when this holds. */
49
+ when?: YarnExpr;
50
+ body: YarnItem[];
51
+ line: number;
52
+ }
53
+ export interface YarnSet {
54
+ kind: "set";
55
+ name: string;
56
+ value: YarnExpr;
57
+ line: number;
58
+ }
59
+ export interface YarnIf {
60
+ kind: "if";
61
+ /** `if` and `elseif` branches in order; a final `else` has no condition. */
62
+ branches: {
63
+ when?: YarnExpr;
64
+ body: YarnItem[];
65
+ }[];
66
+ line: number;
67
+ }
68
+ /** Boolean expressions over variables (each a flag). */
69
+ export type YarnExpr = {
70
+ kind: "var";
71
+ name: string;
72
+ } | {
73
+ kind: "const";
74
+ value: boolean;
75
+ } | {
76
+ kind: "not";
77
+ of: YarnExpr;
78
+ } | {
79
+ kind: "and" | "or";
80
+ a: YarnExpr;
81
+ b: YarnExpr;
82
+ };
83
+ export declare class YarnError extends Error {
84
+ readonly file: string;
85
+ readonly line: number;
86
+ constructor(file: string, line: number, message: string);
87
+ }
88
+ export declare function parseYarn(source: string, file?: string): YarnNode[];
89
+ /** `$a and not ($b or $c == false)`: Yarn's boolean operators, both spellings. */
90
+ export declare function parseExpr(source: string, fail: (why: string) => never): YarnExpr;
@@ -0,0 +1,214 @@
1
+ export class YarnError extends Error {
2
+ file;
3
+ line;
4
+ constructor(file, line, message) {
5
+ super(`${file}:${line}: ${message}`);
6
+ this.file = file;
7
+ this.line = line;
8
+ }
9
+ }
10
+ /** Trailing #tags (Yarn's line ids and metadata) don't belong to the text. */
11
+ const stripTags = (s) => s.replace(/(\s+#[^\s#]+)+\s*$/, "");
12
+ const indentOf = (s) => /^[ \t]*/.exec(s)[0].replace(/\t/g, " ").length;
13
+ export function parseYarn(source, file = "<yarn>") {
14
+ const nodes = [];
15
+ const lines = source.split(/\r?\n/);
16
+ let i = 0;
17
+ const fail = (line, why) => {
18
+ throw new YarnError(file, line, why);
19
+ };
20
+ while (i < lines.length) {
21
+ // Headers.
22
+ const start = i + 1;
23
+ const headers = {};
24
+ for (; i < lines.length && lines[i].trim() !== "---"; i++) {
25
+ const raw = lines[i].trim();
26
+ if (!raw || raw.startsWith("//"))
27
+ continue;
28
+ const m = /^([A-Za-z_][\w.-]*)\s*:\s*(.*)$/.exec(raw);
29
+ if (!m)
30
+ fail(i + 1, `expected a header (key: value) or ---, got "${raw}"`);
31
+ headers[m[1]] = m[2].trim();
32
+ }
33
+ if (i >= lines.length) {
34
+ if (Object.keys(headers).length)
35
+ fail(start, "node has no body: expected --- after its headers");
36
+ break;
37
+ }
38
+ const title = headers.title;
39
+ if (!title)
40
+ fail(start, "node has no title: header");
41
+ if (nodes.some((n) => n.title === title))
42
+ fail(start, `a node called "${title}" already exists`);
43
+ i++; // ---
44
+ // The body's lines up to ===, then parsed into a tree.
45
+ const body = [];
46
+ let closed = false;
47
+ for (; i < lines.length; i++) {
48
+ const raw = lines[i].trim();
49
+ if (raw === "===") {
50
+ closed = true;
51
+ i++;
52
+ break;
53
+ }
54
+ if (!raw || raw.startsWith("//"))
55
+ continue;
56
+ body.push({ text: raw, indent: indentOf(lines[i]), line: i + 1 });
57
+ }
58
+ if (!closed)
59
+ fail(start, `node "${title}" isn't closed with ===`);
60
+ const parser = new BodyParser(body, fail);
61
+ nodes.push({ title: title, headers, body: parser.block(-1, false, false, []), line: start });
62
+ if (parser.at < body.length) {
63
+ const extra = body[parser.at];
64
+ fail(extra.line, `unexpected ${extra.text.split(/\s/)[0]} (no <<if>> is open)`);
65
+ }
66
+ }
67
+ return nodes;
68
+ }
69
+ class BodyParser {
70
+ lines;
71
+ fail;
72
+ at = 0;
73
+ constructor(lines, fail) {
74
+ this.lines = lines;
75
+ this.fail = fail;
76
+ }
77
+ /**
78
+ * Items until a line indented at most `parentIndent` (the end of a choice's body) or, in
79
+ * an <<if>>, one of `stopAt` (elseif/else/endif).
80
+ */
81
+ block(parentIndent, inChoice, inIf, stopAt) {
82
+ const items = [];
83
+ let choiceIndent;
84
+ while (this.at < this.lines.length) {
85
+ const { text, indent, line } = this.lines[this.at];
86
+ if (indent <= parentIndent)
87
+ break;
88
+ const command = /^<<\s*(\w+)\s*(.*?)\s*>>$/.exec(text);
89
+ if (command && stopAt.includes(command[1]))
90
+ break;
91
+ this.at++;
92
+ if (text.startsWith("->")) {
93
+ if (inChoice)
94
+ this.fail(line, "choices inside choices aren't supported yet");
95
+ if (inIf)
96
+ this.fail(line, "choices inside <<if>> aren't supported yet (use -> text <<if $x>>)");
97
+ if (choiceIndent !== undefined && indent !== choiceIndent)
98
+ this.fail(line, "choices in a group must line up");
99
+ choiceIndent = indent;
100
+ let rest = stripTags(text.slice(2).trim());
101
+ let when;
102
+ const cond = /^(.*?)\s*<<\s*if\s+(.+?)\s*>>$/.exec(rest);
103
+ if (cond) {
104
+ rest = cond[1];
105
+ when = parseExpr(cond[2], (why) => this.fail(line, why));
106
+ }
107
+ if (!rest)
108
+ this.fail(line, "a choice needs text after ->");
109
+ items.push({ kind: "choice", text: rest, when, body: this.block(indent, true, false, []), line });
110
+ continue;
111
+ }
112
+ if (command) {
113
+ const [, name, args] = command;
114
+ if (name === "set") {
115
+ const m = /^\$([A-Za-z_]\w*)\s*(?:to|=)\s*(.+)$/.exec(args);
116
+ if (!m)
117
+ this.fail(line, "expected <<set $name to true>> (or false, or a condition)");
118
+ items.push({ kind: "set", name: m[1], value: parseExpr(m[2], (why) => this.fail(line, why)), line });
119
+ }
120
+ else if (name === "if") {
121
+ items.push(this.ifBlock(args, line, indent, inChoice));
122
+ }
123
+ else if (["elseif", "else", "endif"].includes(name)) {
124
+ this.fail(line, `<<${name}>> without an <<if>>`);
125
+ }
126
+ else {
127
+ items.push({ kind: "command", name: name, args: args ? args.split(/[\s,]+/).filter(Boolean) : [], line });
128
+ }
129
+ continue;
130
+ }
131
+ if (text.startsWith("<<"))
132
+ this.fail(line, `expected <<command ...>>, got "${text}"`);
133
+ const clean = stripTags(text);
134
+ const m = /^([A-Za-z][\w ]*?)\s*:\s+(.+)$/.exec(clean);
135
+ items.push(m ? { kind: "line", speaker: m[1], text: m[2], line } : { kind: "line", text: clean, line });
136
+ }
137
+ return items;
138
+ }
139
+ ifBlock(firstCond, line, indent, inChoice) {
140
+ const fail = (why) => this.fail(line, why);
141
+ const branches = [{ when: parseExpr(firstCond, fail), body: [] }];
142
+ // An <<if>>'s body is whatever comes before its <<elseif>>/<<else>>/<<endif>>, at any
143
+ // indentation deeper than the enclosing choice (Yarn doesn't require indenting it).
144
+ for (;;) {
145
+ branches[branches.length - 1].body = this.block(inChoice ? indent - 1 : -1, inChoice, true, ["elseif", "else", "endif"]);
146
+ const next = this.lines[this.at];
147
+ const command = next && /^<<\s*(\w+)\s*(.*?)\s*>>$/.exec(next.text);
148
+ if (!command)
149
+ this.fail(line, "<<if>> without <<endif>>");
150
+ this.at++;
151
+ if (command[1] === "endif")
152
+ return { kind: "if", branches, line };
153
+ if (branches.at(-1).when === undefined)
154
+ this.fail(next.line, `<<${command[1]}>> after <<else>>`);
155
+ if (command[1] === "else")
156
+ branches.push({ body: [] });
157
+ else
158
+ branches.push({ when: parseExpr(command[2], (why) => this.fail(next.line, why)), body: [] });
159
+ }
160
+ }
161
+ }
162
+ /** `$a and not ($b or $c == false)`: Yarn's boolean operators, both spellings. */
163
+ export function parseExpr(source, fail) {
164
+ const tokens = source.match(/\$[A-Za-z_]\w*|&&|\|\||==|!=|[()!]|[A-Za-z_]\w*|\S/g) ?? [];
165
+ let p = 0;
166
+ const peek = () => tokens[p];
167
+ const take = () => tokens[p++];
168
+ const word = (t, ...names) => t !== undefined && names.includes(t.toLowerCase());
169
+ const or = () => {
170
+ let a = and();
171
+ while (word(peek(), "or", "||"))
172
+ (take(), (a = { kind: "or", a, b: and() }));
173
+ return a;
174
+ };
175
+ const and = () => {
176
+ let a = compare();
177
+ while (word(peek(), "and", "&&"))
178
+ (take(), (a = { kind: "and", a, b: compare() }));
179
+ return a;
180
+ };
181
+ const compare = () => {
182
+ const a = unary();
183
+ if (word(peek(), "==", "!=", "is", "eq", "neq")) {
184
+ const op = take().toLowerCase();
185
+ const b = unary();
186
+ // a == b is (a and b) or (not a and not b).
187
+ const same = { kind: "or", a: { kind: "and", a, b }, b: { kind: "and", a: { kind: "not", of: a }, b: { kind: "not", of: b } } };
188
+ return op === "!=" || op === "neq" ? { kind: "not", of: same } : same;
189
+ }
190
+ return a;
191
+ };
192
+ const unary = () => {
193
+ const t = take();
194
+ if (t === undefined)
195
+ fail(`incomplete condition "${source}"`);
196
+ if (word(t, "not", "!"))
197
+ return { kind: "not", of: unary() };
198
+ if (t === "(") {
199
+ const e = or();
200
+ if (take() !== ")")
201
+ fail(`missing ) in "${source}"`);
202
+ return e;
203
+ }
204
+ if (word(t, "true", "false"))
205
+ return { kind: "const", value: t.toLowerCase() === "true" };
206
+ if (t.startsWith("$"))
207
+ return { kind: "var", name: t.slice(1) };
208
+ return fail(`unexpected "${t}" in "${source}" (variables are $name; numbers and text aren't supported yet)`);
209
+ };
210
+ const e = or();
211
+ if (p < tokens.length)
212
+ fail(`unexpected "${tokens[p]}" in "${source}"`);
213
+ return e;
214
+ }