##// END OF EJS Templates
Remove curact, implement selact
naryl -
r45:0669fc21 default
parent child Browse files
Show More
@@ -1,533 +1,531 b''
1
1
2 (in-package sugar-qsp.api)
2 (in-package sugar-qsp.api)
3
3
4 ;;; API deals with DOM manipulation and some bookkeeping for the
4 ;;; API deals with DOM manipulation and some bookkeeping for the
5 ;;; intrinsics, namely variables
5 ;;; intrinsics, namely variables
6 ;;; API is an implementation detail and has no QSP documentation. It
6 ;;; API is an implementation detail and has no QSP documentation. It
7 ;;; doesn't call intrinsics
7 ;;; doesn't call intrinsics
8
8
9 ;;; Utils
9 ;;; Utils
10
10
11 (defun make-act-html (title img)
11 (defun make-act-html (title img)
12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
12 (+ "<a class='qsp-act' href='" (href-call call-act title) "' onmouseover='" (inline-call select-act title) "'>"
13 (if img (+ "<img src='" img "'>") "")
13 (if img (+ "<img src='" img "'>") "")
14 title
14 title
15 "</a>"))
15 "</a>"))
16
16
17 (defun make-menu-item-html (num title img loc)
17 (defun make-menu-item-html (num title img loc)
18 (+ "<a href='" (href-call finish-menu loc) "'>"
18 (+ "<a href='" (href-call finish-menu loc) "'>"
19 (if img (+ "<img src='" img "'>") "")
19 (if img (+ "<img src='" img "'>") "")
20 title
20 title
21 "</a>"))
21 "</a>"))
22
22
23 (defun make-obj (title img selected)
23 (defun make-obj (title img selected)
24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
24 (+ "<li onclick='" (inline-call select-obj title img) "'>"
25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
25 "<a class='qsp-obj" (if selected " qsp-obj-selected" "") "'>"
26 (if img (+ "<img src='" img "'>") "")
26 (if img (+ "<img src='" img "'>") "")
27 title
27 title
28 "</a>"))
28 "</a>"))
29
29
30 (defun make-menu-delimiter ()
30 (defun make-menu-delimiter ()
31 "<hr>")
31 "<hr>")
32
32
33 (defun copy-obj (obj)
33 (defun copy-obj (obj)
34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
34 (chain *j-s-o-n (parse (chain *j-s-o-n (stringify obj)))))
35
35
36 (defun report-error (text)
36 (defun report-error (text)
37 (alert text))
37 (alert text))
38
38
39 (defun start-sleeping ()
39 (defun start-sleeping ()
40 (chain (by-id "qsp") class-list (add "disable")))
40 (chain (by-id "qsp") class-list (add "disable")))
41
41
42 (defun finish-sleeping ()
42 (defun finish-sleeping ()
43 (chain (by-id "qsp") class-list (remove "disable")))
43 (chain (by-id "qsp") class-list (remove "disable")))
44
44
45 (defun sleep (msec)
45 (defun sleep (msec)
46 (with-sleep (resume)
46 (with-sleep (resume)
47 (set-timeout resume msec)))
47 (set-timeout resume msec)))
48
48
49 (defun init-dom ()
49 (defun init-dom ()
50 ;; Save/load buttons
50 ;; Save/load buttons
51 (let ((btn (by-id "qsp-btn-save")))
51 (let ((btn (by-id "qsp-btn-save")))
52 (setf (@ btn onclick) savegame)
52 (setf (@ btn onclick) savegame)
53 (setf (@ btn href) "#"))
53 (setf (@ btn href) "#"))
54 (let ((btn (by-id "qsp-btn-open")))
54 (let ((btn (by-id "qsp-btn-open")))
55 (setf (@ btn onclick) opengame)
55 (setf (@ btn onclick) opengame)
56 (setf (@ btn href) "#"))
56 (setf (@ btn href) "#"))
57 ;; Close image on click
57 ;; Close image on click
58 (setf (@ (by-id "qsp-image-container") onclick)
58 (setf (@ (by-id "qsp-image-container") onclick)
59 show-image)
59 show-image)
60 ;; Enter in input field
60 ;; Enter in input field
61 (setf (@ (get-frame :input) onkeyup)
61 (setf (@ (get-frame :input) onkeyup)
62 on-input-key)
62 on-input-key)
63 ;; Close the dropdown on any click
63 ;; Close the dropdown on any click
64 (setf (@ window onclick)
64 (setf (@ window onclick)
65 (lambda (event)
65 (lambda (event)
66 (setf (@ window mouse)
66 (setf (@ window mouse)
67 (list (@ event page-x)
67 (list (@ event page-x)
68 (@ event page-y)))
68 (@ event page-y)))
69 (finish-menu nil))))
69 (finish-menu nil))))
70
70
71 (defun call-serv-loc (var-name &rest args)
71 (defun call-serv-loc (var-name &rest args)
72 (let ((loc-name (get-global var-name 0)))
72 (let ((loc-name (get-global var-name 0)))
73 (when loc-name
73 (when loc-name
74 (let ((loc (getprop *locs loc-name)))
74 (let ((loc (getprop *locs loc-name)))
75 (when loc
75 (when loc
76 (call-loc loc-name args))))))
76 (call-loc loc-name args))))))
77
77
78 (defun filename-game (filename)
78 (defun filename-game (filename)
79 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
79 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
80 (getprop *games game-name))
80 (getprop *games game-name))
81
81
82 (defun run-game (name)
82 (defun run-game (name)
83 (let ((game (filename-game name)))
83 (let ((game (filename-game name)))
84 (setf *main-game name)
84 (setf *main-game name)
85 ;; Replace locations with the new game's
85 ;; Replace locations with the new game's
86 (setf *locs game)
86 (setf *locs game)
87 (funcall (getprop game
87 (funcall (getprop game
88 (chain *object (keys game) 0))
88 (chain *object (keys game) 0))
89 (list))))
89 (list))))
90
90
91 ;;; Misc
91 ;;; Misc
92
92
93 (defun newline (key)
93 (defun newline (key)
94 (append-id (key-to-id key) "<br>" t))
94 (append-id (key-to-id key) "<br>" t))
95
95
96 (defun clear-id (id)
96 (defun clear-id (id)
97 (setf (inner-html (by-id id)) ""))
97 (setf (inner-html (by-id id)) ""))
98
98
99 (defun escape-html (text)
99 (defun escape-html (text)
100 (chain text
100 (chain text
101 (replace (regex "/&/g") "&amp;")
101 (replace (regex "/&/g") "&amp;")
102 (replace (regex "/</g") "&lt;")
102 (replace (regex "/</g") "&lt;")
103 (replace (regex "/>/g") "&gt;")
103 (replace (regex "/>/g") "&gt;")
104 (replace (regex "/\"/g") "&quot;")
104 (replace (regex "/\"/g") "&quot;")
105 (replace (regex "/'/g") "&apos;")))
105 (replace (regex "/'/g") "&apos;")))
106
106
107 (defun prepare-contents (s &optional force-html)
107 (defun prepare-contents (s &optional force-html)
108 (setf s (chain s (to-string)))
108 (setf s (chain s (to-string)))
109 (if (or force-html (get-global "USEHTML" 0))
109 (if (or force-html (get-global "USEHTML" 0))
110 s
110 s
111 (escape-html s)))
111 (escape-html s)))
112
112
113 (defun get-id (id &optional force-html)
113 (defun get-id (id &optional force-html)
114 (inner-html (by-id id)))
114 (inner-html (by-id id)))
115
115
116 (defun set-id (id contents &optional force-html)
116 (defun set-id (id contents &optional force-html)
117 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
117 (setf (inner-html (by-id id)) (prepare-contents contents force-html)))
118
118
119 (defun append-id (id contents &optional force-html)
119 (defun append-id (id contents &optional force-html)
120 (when contents
120 (when contents
121 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
121 (incf (inner-html (by-id id)) (prepare-contents contents force-html))))
122
122
123 (defun on-input-key (ev)
123 (defun on-input-key (ev)
124 (when (= 13 (@ ev key-code))
124 (when (= 13 (@ ev key-code))
125 (chain ev (prevent-default))
125 (chain ev (prevent-default))
126 (call-serv-loc "$USERCOM")))
126 (call-serv-loc "$USERCOM")))
127
127
128 ;;; Function calls
128 ;;; Function calls
129
129
130 (defun init-args (args)
130 (defun init-args (args)
131 (dotimes (i (length args))
131 (dotimes (i (length args))
132 (let ((arg (elt args i)))
132 (let ((arg (elt args i)))
133 (if (numberp arg)
133 (if (numberp arg)
134 (set-var args i :num arg)
134 (set-var args i :num arg)
135 (set-var args i :str arg)))))
135 (set-var args i :str arg)))))
136
136
137 (defun get-result ()
137 (defun get-result ()
138 (or (get-global "$RESULT" 0)
138 (or (get-global "$RESULT" 0)
139 (get-global "RESULT" 0)))
139 (get-global "RESULT" 0)))
140
140
141 (defun call-loc (name args)
141 (defun call-loc (name args)
142 (setf name (chain name (to-upper-case)))
142 (setf name (chain name (to-upper-case)))
143 (with-frame
143 (with-frame
144 (with-call-args args
144 (with-call-args args
145 (funcall (getprop *locs name))))
145 (funcall (getprop *locs name))))
146 (void))
146 (void))
147
147
148 (defun call-act (title)
148 (defun call-act (title)
149 (setf *current-action title)
150 (with-frame
149 (with-frame
151 (funcall (getprop *acts title :act)))
150 (funcall (getprop *acts title :act)))
152 (setf *current-action nil)
153 (void))
151 (void))
154
152
155 ;;; Text windows
153 ;;; Text windows
156
154
157 (defun key-to-id (key)
155 (defun key-to-id (key)
158 (case key
156 (case key
159 (:all "qsp")
157 (:all "qsp")
160 (:main "qsp-main")
158 (:main "qsp-main")
161 (:stat "qsp-stat")
159 (:stat "qsp-stat")
162 (:objs "qsp-objs")
160 (:objs "qsp-objs")
163 (:acts "qsp-acts")
161 (:acts "qsp-acts")
164 (:input "qsp-input")
162 (:input "qsp-input")
165 (:image "qsp-image")
163 (:image "qsp-image")
166 (:dropdown "qsp-dropdown")
164 (:dropdown "qsp-dropdown")
167 (t (report-error "Internal error!"))))
165 (t (report-error "Internal error!"))))
168
166
169 (defun get-frame (key)
167 (defun get-frame (key)
170 (by-id (key-to-id key)))
168 (by-id (key-to-id key)))
171
169
172 (defun add-text (key text)
170 (defun add-text (key text)
173 (append-id (key-to-id key) text))
171 (append-id (key-to-id key) text))
174
172
175 (defun get-text (key)
173 (defun get-text (key)
176 (get-id (key-to-id key)))
174 (get-id (key-to-id key)))
177
175
178 (defun clear-text (key)
176 (defun clear-text (key)
179 (clear-id (key-to-id key)))
177 (clear-id (key-to-id key)))
180
178
181 (defun enable-frame (key enable)
179 (defun enable-frame (key enable)
182 (let ((obj (get-frame key)))
180 (let ((obj (get-frame key)))
183 (setf (@ obj style display) (if enable "block" "none"))
181 (setf (@ obj style display) (if enable "block" "none"))
184 (void)))
182 (void)))
185
183
186 ;;; Actions
184 ;;; Actions
187
185
188 (defun add-act (title img act)
186 (defun add-act (title img act)
189 (setf (getprop *acts title)
187 (setf (getprop *acts title)
190 (create :title title :img img :act act :selected nil))
188 (create :title title :img img :act act :selected nil))
191 (update-acts))
189 (update-acts))
192
190
193 (defun del-act (&optional title)
191 (defun del-act (title)
194 (delete (getprop *acts (or title *current-action)))
192 (delete (getprop *acts title))
195 (update-acts))
193 (update-acts))
196
194
197 (defun clear-act ()
195 (defun clear-act ()
198 (setf *acts (create))
196 (setf *acts (create))
199 (update-acts))
197 (update-acts))
200
198
201 (defun update-acts ()
199 (defun update-acts ()
202 (clear-id "qsp-acts")
200 (clear-id "qsp-acts")
203 (let ((elt (by-id "qsp-acts")))
201 (let ((elt (by-id "qsp-acts")))
204 (for-in (title *acts)
202 (for-in (title *acts)
205 (let ((obj (getprop *acts title)))
203 (let ((obj (getprop *acts title)))
206 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
204 (incf (inner-html elt) (make-act-html title (getprop obj :img)))))))
207
205
208 (defun select-act (title)
206 (defun select-act (title)
209 (loop :for (k v) :of *acts
207 (loop :for (k v) :of *acts
210 :do (setf (getprop v :selected) nil))
208 :do (setf (getprop v :selected) nil))
211 (setf (getprop *acts title :selected) t)
209 (setf (getprop *acts title :selected) t)
212 (call-serv-loc "$ONACTSEL"))
210 (call-serv-loc "$ONACTSEL"))
213
211
214 ;;; "Syntax"
212 ;;; "Syntax"
215
213
216 (defun qspfor (name index from to step body)
214 (defun qspfor (name index from to step body)
217 (for ((i from))
215 (for ((i from))
218 ((< i to))
216 ((< i to))
219 ((incf i step))
217 ((incf i step))
220 (set-var name index :num i)
218 (set-var name index :num i)
221 (unless (await (funcall body))
219 (unless (await (funcall body))
222 (return-from qspfor))))
220 (return-from qspfor))))
223
221
224 ;;; Variables
222 ;;; Variables
225
223
226 (defun new-var (slot &rest indexes)
224 (defun new-var (slot &rest indexes)
227 (let ((v (list)))
225 (let ((v (list)))
228 (dolist (index indexes)
226 (dolist (index indexes)
229 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
227 (setf (elt v index) (if (eq #\$ (elt slot 0)) "" 0)))
230 (setf (@ v :indexes) (create))
228 (setf (@ v :indexes) (create))
231 v))
229 v))
232
230
233 (defun set-str-element (slot index value)
231 (defun set-str-element (slot index value)
234 (if (has index (getprop slot :indexes))
232 (if (has index (getprop slot :indexes))
235 (setf (elt (getprop slot)
233 (setf (elt (getprop slot)
236 (getprop slot :indexes index))
234 (getprop slot :indexes index))
237 value)
235 value)
238 (progn
236 (progn
239 (chain slot (push value))
237 (chain slot (push value))
240 (setf (elt slot index)
238 (setf (elt slot index)
241 (length slot))))
239 (length slot))))
242 (void))
240 (void))
243
241
244 (defun set-any-element (slot index value)
242 (defun set-any-element (slot index value)
245 (cond ((null index)
243 (cond ((null index)
246 (chain (elt slot) (push value)))
244 (chain (elt slot) (push value)))
247 ((numberp index)
245 ((numberp index)
248 (setf (elt slot index) value))
246 (setf (elt slot index) value))
249 ((stringp index)
247 ((stringp index)
250 (set-str-element slot index value))
248 (set-str-element slot index value))
251 (t (report-error "INTERNAL ERROR")))
249 (t (report-error "INTERNAL ERROR")))
252 (void))
250 (void))
253
251
254 (defun set-serv-var (name index value)
252 (defun set-serv-var (name index value)
255 (let ((slot (getprop *globals name)))
253 (let ((slot (getprop *globals name)))
256 (set-any-element slot index value))
254 (set-any-element slot index value))
257 (funcall (getprop serv-vars name :body) value index)
255 (funcall (getprop serv-vars name :body) value index)
258 (void))
256 (void))
259
257
260 (defun get-element (slot index)
258 (defun get-element (slot index)
261 (if (numberp index)
259 (if (numberp index)
262 (elt slot index)
260 (elt slot index)
263 (elt slot (getprop slot :indexes index))))
261 (elt slot (getprop slot :indexes index))))
264
262
265 (defun get-global (name index)
263 (defun get-global (name index)
266 (elt (getprop *globals name) index))
264 (elt (getprop *globals name) index))
267
265
268 (defun kill-var (store name &optional index)
266 (defun kill-var (store name &optional index)
269 (setf name (chain name (to-upper-case)))
267 (setf name (chain name (to-upper-case)))
270 (if (and index (not (= 0 index)))
268 (if (and index (not (= 0 index)))
271 (chain (getprop *globals name) (kill index))
269 (chain (getprop *globals name) (kill index))
272 (delete (getprop *globals name)))
270 (delete (getprop *globals name)))
273 (void))
271 (void))
274
272
275 (defun array-size (name)
273 (defun array-size (name)
276 (@ (var-ref name) :values length))
274 (@ (var-ref name) :values length))
277
275
278 ;;; Locals
276 ;;; Locals
279
277
280 (defun push-local-frame ()
278 (defun push-local-frame ()
281 (chain *locals (push (create)))
279 (chain *locals (push (create)))
282 (void))
280 (void))
283
281
284 (defun pop-local-frame ()
282 (defun pop-local-frame ()
285 (chain *locals (pop))
283 (chain *locals (pop))
286 (void))
284 (void))
287
285
288 (defun current-local-frame ()
286 (defun current-local-frame ()
289 (elt *locals (1- (length *locals))))
287 (elt *locals (1- (length *locals))))
290
288
291 ;;; Objects
289 ;;; Objects
292
290
293 (defun select-obj (title img)
291 (defun select-obj (title img)
294 (loop :for (k v) :of *objs
292 (loop :for (k v) :of *objs
295 :do (setf (getprop v :selected) nil))
293 :do (setf (getprop v :selected) nil))
296 (setf (getprop *objs title :selected) t)
294 (setf (getprop *objs title :selected) t)
297 (call-serv-loc "$ONOBJSEL" title img))
295 (call-serv-loc "$ONOBJSEL" title img))
298
296
299 (defun update-objs ()
297 (defun update-objs ()
300 (let ((elt (by-id "qsp-objs")))
298 (let ((elt (by-id "qsp-objs")))
301 (setf (inner-html elt) "<ul>")
299 (setf (inner-html elt) "<ul>")
302 (loop :for (name obj) :of *objs
300 (loop :for (name obj) :of *objs
303 :do (incf (inner-html elt)
301 :do (incf (inner-html elt)
304 (make-obj name (@ obj :img) (@ obj :selected))))
302 (make-obj name (@ obj :img) (@ obj :selected))))
305 (incf (inner-html elt) "</ul>")))
303 (incf (inner-html elt) "</ul>")))
306
304
307 ;;; Menu
305 ;;; Menu
308
306
309 (defun open-menu (menu-data)
307 (defun open-menu (menu-data)
310 (let ((elt (get-frame :dropdown))
308 (let ((elt (get-frame :dropdown))
311 (i 0))
309 (i 0))
312 (loop :for item :in menu-data
310 (loop :for item :in menu-data
313 :do (incf i)
311 :do (incf i)
314 :do (incf (inner-html elt)
312 :do (incf (inner-html elt)
315 (if (eq item :delimiter)
313 (if (eq item :delimiter)
316 (make-menu-delimiter i)
314 (make-menu-delimiter i)
317 (make-menu-item-html i
315 (make-menu-item-html i
318 (@ item :text)
316 (@ item :text)
319 (@ item :icon)
317 (@ item :icon)
320 (@ item :loc)))))
318 (@ item :loc)))))
321 (let ((mouse (@ window mouse)))
319 (let ((mouse (@ window mouse)))
322 (setf (@ elt style left) (+ (elt mouse 0) "px"))
320 (setf (@ elt style left) (+ (elt mouse 0) "px"))
323 (setf (@ elt style top) (+ (elt mouse 1) "px"))
321 (setf (@ elt style top) (+ (elt mouse 1) "px"))
324 ;; Make sure it's inside the viewport
322 ;; Make sure it's inside the viewport
325 (when (> (@ document body inner-width)
323 (when (> (@ document body inner-width)
326 (+ (elt mouse 0) (@ elt inner-width)))
324 (+ (elt mouse 0) (@ elt inner-width)))
327 (incf (@ elt style left) (@ elt inner-width)))
325 (incf (@ elt style left) (@ elt inner-width)))
328 (when (> (@ document body inner-height)
326 (when (> (@ document body inner-height)
329 (+ (elt mouse 0) (@ elt inner-height)))
327 (+ (elt mouse 0) (@ elt inner-height)))
330 (incf (@ elt style top) (@ elt inner-height))))
328 (incf (@ elt style top) (@ elt inner-height))))
331 (setf (@ elt style display) "block")))
329 (setf (@ elt style display) "block")))
332
330
333 (defun finish-menu (loc)
331 (defun finish-menu (loc)
334 (when *menu-resume
332 (when *menu-resume
335 (let ((elt (get-frame :dropdown)))
333 (let ((elt (get-frame :dropdown)))
336 (setf (inner-html elt) "")
334 (setf (inner-html elt) "")
337 (setf (@ elt style display) "none")
335 (setf (@ elt style display) "none")
338 (funcall *menu-resume)
336 (funcall *menu-resume)
339 (setf *menu-resume nil))
337 (setf *menu-resume nil))
340 (when loc
338 (when loc
341 (call-loc loc)))
339 (call-loc loc)))
342 (void))
340 (void))
343
341
344 (defun menu (menu-data)
342 (defun menu (menu-data)
345 (with-sleep (resume)
343 (with-sleep (resume)
346 (open-menu menu-data)
344 (open-menu menu-data)
347 (setf *menu-resume resume))
345 (setf *menu-resume resume))
348 (void))
346 (void))
349
347
350 ;;; Content
348 ;;; Content
351
349
352 (defun clean-audio ()
350 (defun clean-audio ()
353 (loop :for k :in (chain *object (keys *playing))
351 (loop :for k :in (chain *object (keys *playing))
354 :for v := (getprop *playing k)
352 :for v := (getprop *playing k)
355 :do (when (@ v ended)
353 :do (when (@ v ended)
356 (delete (@ *playing k)))))
354 (delete (@ *playing k)))))
357
355
358 (defun show-image (path)
356 (defun show-image (path)
359 (let ((img (get-frame :image)))
357 (let ((img (get-frame :image)))
360 (cond (path
358 (cond (path
361 (setf (@ img src) path)
359 (setf (@ img src) path)
362 (setf (@ img style display) "flex"))
360 (setf (@ img style display) "flex"))
363 (t
361 (t
364 (setf (@ img src) "")
362 (setf (@ img src) "")
365 (setf (@ img style display) "hidden")))))
363 (setf (@ img style display) "hidden")))))
366
364
367 (defun show-inline-images (frame-name images)
365 (defun show-inline-images (frame-name images)
368 (let ((frame (get-frame frame-name))
366 (let ((frame (get-frame frame-name))
369 (text ""))
367 (text ""))
370 (incf text "<div style='position:relative; display: inline-block'>")
368 (incf text "<div style='position:relative; display: inline-block'>")
371 (incf text (+ "<img src='" (@ images 0) "'>"))
369 (incf text (+ "<img src='" (@ images 0) "'>"))
372 (loop :for image :in (chain images (slice 1))
370 (loop :for image :in (chain images (slice 1))
373 :do (incf text
371 :do (incf text
374 (+ "<img style='position:absolute' src='" image "'>")))
372 (+ "<img style='position:absolute' src='" image "'>")))
375 (incf text "</div>")
373 (incf text "</div>")
376 (incf (inner-html frame) text)))
374 (incf (inner-html frame) text)))
377
375
378 (defun rgb-string (rgb)
376 (defun rgb-string (rgb)
379 (let ((red (ps::>> rgb 16))
377 (let ((red (ps::>> rgb 16))
380 (green (logand (ps::>> rgb 8) 255))
378 (green (logand (ps::>> rgb 8) 255))
381 (blue (logand rgb 255)))
379 (blue (logand rgb 255)))
382 (flet ((rgb-to-hex (comp)
380 (flet ((rgb-to-hex (comp)
383 (let ((hex (chain (*number comp) (to-string 16))))
381 (let ((hex (chain (*number comp) (to-string 16))))
384 (if (< (length hex) 2)
382 (if (< (length hex) 2)
385 (+ "0" hex)
383 (+ "0" hex)
386 hex))))
384 hex))))
387 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
385 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex blue)))))
388
386
389 (defun store-obj (key obj)
387 (defun store-obj (key obj)
390 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
388 (store-str key (btoa (encode-u-r-i-component (chain *j-s-o-n (stringify obj)))))
391 (void))
389 (void))
392 (defun store-str (key str)
390 (defun store-str (key str)
393 (chain local-storage (set-item (+ "qsp_" key) str))
391 (chain local-storage (set-item (+ "qsp_" key) str))
394 (void))
392 (void))
395
393
396 (defun load-obj (key)
394 (defun load-obj (key)
397 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
395 (chain *j-s-o-n (parse (encode-u-r-i-component (atob (load-str key))))))
398 (defun load-str (key)
396 (defun load-str (key)
399 (chain local-storage (get-item (+ "qsp_" key))))
397 (chain local-storage (get-item (+ "qsp_" key))))
400
398
401 ;;; Saves
399 ;;; Saves
402
400
403 (defun slot-savegame (slot comment)
401 (defun slot-savegame (slot comment)
404 (let ((saves (load-obj "saves")))
402 (let ((saves (load-obj "saves")))
405 (setf (@ saves slot) comment)
403 (setf (@ saves slot) comment)
406 (store-obj saves))
404 (store-obj saves))
407 (store-str slot (state-to-base64))
405 (store-str slot (state-to-base64))
408 (void))
406 (void))
409
407
410 (defun slot-loadgame (slot)
408 (defun slot-loadgame (slot)
411 (base64-to-state (load-str slot))
409 (base64-to-state (load-str slot))
412 (void))
410 (void))
413
411
414 (defun slot-deletegame (slot)
412 (defun slot-deletegame (slot)
415 (let ((saves (load-obj "saves")))
413 (let ((saves (load-obj "saves")))
416 (setf (@ saves slot) undefined)
414 (setf (@ saves slot) undefined)
417 (store-obj saves))
415 (store-obj saves))
418 (store-str slot undefined)
416 (store-str slot undefined)
419 (void))
417 (void))
420
418
421 (defun slot-listgames ()
419 (defun slot-listgames ()
422 (load-obj "saves"))
420 (load-obj "saves"))
423
421
424 (defun opengame ()
422 (defun opengame ()
425 (let ((element (chain document (create-element :input))))
423 (let ((element (chain document (create-element :input))))
426 (chain element (set-attribute :type :file))
424 (chain element (set-attribute :type :file))
427 (chain element (set-attribute :id :qsp-opengame))
425 (chain element (set-attribute :id :qsp-opengame))
428 (chain element (set-attribute :tabindex -1))
426 (chain element (set-attribute :tabindex -1))
429 (chain element (set-attribute "aria-hidden" t))
427 (chain element (set-attribute "aria-hidden" t))
430 (setf (@ element style display) :block)
428 (setf (@ element style display) :block)
431 (setf (@ element style visibility) :hidden)
429 (setf (@ element style visibility) :hidden)
432 (setf (@ element style position) :fixed)
430 (setf (@ element style position) :fixed)
433 (setf (@ element onchange)
431 (setf (@ element onchange)
434 (lambda (event)
432 (lambda (event)
435 (let* ((file (@ event target files 0))
433 (let* ((file (@ event target files 0))
436 (reader (new (*file-reader))))
434 (reader (new (*file-reader))))
437 (setf (@ reader onload)
435 (setf (@ reader onload)
438 (lambda (ev)
436 (lambda (ev)
439 (block nil
437 (block nil
440 (let ((target (@ ev current-target)))
438 (let ((target (@ ev current-target)))
441 (unless (@ target result)
439 (unless (@ target result)
442 (return))
440 (return))
443 (base64-to-state (@ target result))
441 (base64-to-state (@ target result))
444 (unstash-state)))))
442 (unstash-state)))))
445 (chain reader (read-as-text file)))))
443 (chain reader (read-as-text file)))))
446 (chain document body (append-child element))
444 (chain document body (append-child element))
447 (chain element (click))
445 (chain element (click))
448 (chain document body (remove-child element))))
446 (chain document body (remove-child element))))
449
447
450 (defun savegame ()
448 (defun savegame ()
451 (let ((element (chain document (create-element :a))))
449 (let ((element (chain document (create-element :a))))
452 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
450 (chain element (set-attribute :href (+ "data:text/plain;charset=utf-8," (state-to-base64))))
453 (chain element (set-attribute :download "savegame.sav"))
451 (chain element (set-attribute :download "savegame.sav"))
454 (setf (@ element style display) :none)
452 (setf (@ element style display) :none)
455 (chain document body (append-child element))
453 (chain document body (append-child element))
456 (chain element (click))
454 (chain element (click))
457 (chain document body (remove-child element))))
455 (chain document body (remove-child element))))
458
456
459 (defun stash-state (args)
457 (defun stash-state (args)
460 (call-serv-loc "$ONGSAVE")
458 (call-serv-loc "$ONGSAVE")
461 (setf *state-stash
459 (setf *state-stash
462 (chain *j-s-o-n (stringify
460 (chain *j-s-o-n (stringify
463 (create :vars *globals
461 (create :vars *globals
464 :objs *objs
462 :objs *objs
465 :loc-args args
463 :loc-args args
466 :msecs (- (chain *date (now)) *started-at)
464 :msecs (- (chain *date (now)) *started-at)
467 :timer-interval *timer-interval
465 :timer-interval *timer-interval
468 :main-html (inner-html
466 :main-html (inner-html
469 (get-frame :main))
467 (get-frame :main))
470 :stat-html (inner-html
468 :stat-html (inner-html
471 (get-frame :stat))
469 (get-frame :stat))
472 :next-location *current-location))))
470 :next-location *current-location))))
473 (void))
471 (void))
474
472
475 (defun unstash-state ()
473 (defun unstash-state ()
476 (let ((data (chain *j-s-o-n (parse *state-stash))))
474 (let ((data (chain *j-s-o-n (parse *state-stash))))
477 (clear-act)
475 (clear-act)
478 (setf *globals (@ data :vars))
476 (setf *globals (@ data :vars))
479 (loop :for k :in (chain *object (keys *globals))
477 (loop :for k :in (chain *object (keys *globals))
480 :do (chain *object (set-prototype-of (getprop *globals k)
478 :do (chain *object (set-prototype-of (getprop *globals k)
481 (@ *var prototype))))
479 (@ *var prototype))))
482 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
480 (setf *started-at (- (chain *date (now)) (@ data :msecs)))
483 (setf *objs (@ data :objs))
481 (setf *objs (@ data :objs))
484 (setf *current-location (@ data :next-location))
482 (setf *current-location (@ data :next-location))
485 (setf (inner-html (get-frame :main))
483 (setf (inner-html (get-frame :main))
486 (@ data :main-html))
484 (@ data :main-html))
487 (setf (inner-html (get-frame :stat))
485 (setf (inner-html (get-frame :stat))
488 (@ data :stat-html))
486 (@ data :stat-html))
489 (update-objs)
487 (update-objs)
490 (set-timer (@ data :timer-interval))
488 (set-timer (@ data :timer-interval))
491 (call-serv-loc "$ONGLOAD")
489 (call-serv-loc "$ONGLOAD")
492 (call-loc *current-location (@ data :loc-args))
490 (call-loc *current-location (@ data :loc-args))
493 (void)))
491 (void)))
494
492
495 (defun state-to-base64 ()
493 (defun state-to-base64 ()
496 (btoa (encode-u-r-i-component *state-stash)))
494 (btoa (encode-u-r-i-component *state-stash)))
497
495
498 (defun base64-to-state (data)
496 (defun base64-to-state (data)
499 (setf *state-stash (decode-u-r-i-component (atob data))))
497 (setf *state-stash (decode-u-r-i-component (atob data))))
500
498
501 ;;; Timers
499 ;;; Timers
502
500
503 (defun set-timer (interval)
501 (defun set-timer (interval)
504 (setf *timer-interval interval)
502 (setf *timer-interval interval)
505 (clear-interval *timer-obj)
503 (clear-interval *timer-obj)
506 (setf *timer-obj
504 (setf *timer-obj
507 (set-interval
505 (set-interval
508 (lambda ()
506 (lambda ()
509 (call-serv-loc "$COUNTER"))
507 (call-serv-loc "$COUNTER"))
510 interval)))
508 interval)))
511
509
512 ;;; Special variables
510 ;;; Special variables
513
511
514 (defvar serv-vars (create))
512 (defvar serv-vars (create))
515
513
516 (define-serv-var $backimage (path)
514 (define-serv-var $backimage (path)
517 (setf (@ (get-frame :main) style background-image) path))
515 (setf (@ (get-frame :main) style background-image) path))
518
516
519 (define-serv-var bcolor (color)
517 (define-serv-var bcolor (color)
520 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
518 (setf (@ (get-frame :all) style background-color) (rgb-string color)))
521
519
522 (define-serv-var fcolor (color)
520 (define-serv-var fcolor (color)
523 (setf (@ (get-frame :all) style color) (rgb-string color)))
521 (setf (@ (get-frame :all) style color) (rgb-string color)))
524
522
525 (define-serv-var lcolor (color)
523 (define-serv-var lcolor (color)
526 (setf (@ (get-frame :style) inner-text)
524 (setf (@ (get-frame :style) inner-text)
527 (+ "a { color: " (rgb-string color) ";}")))
525 (+ "a { color: " (rgb-string color) ";}")))
528
526
529 (define-serv-var fsize (size)
527 (define-serv-var fsize (size)
530 (setf (@ (get-frame :all) style font-size) size))
528 (setf (@ (get-frame :all) style font-size) size))
531
529
532 (define-serv-var $fname (font-name)
530 (define-serv-var $fname (font-name)
533 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
531 (setf (@ (get-frame :all) style font-family) (+ font-name ",serif")))
@@ -1,173 +1,170 b''
1
1
2 (in-package sugar-qsp.lib)
2 (in-package sugar-qsp.lib)
3
3
4 ;;;; Macros implementing some intrinsics where it makes sense
4 ;;;; Macros implementing some intrinsics where it makes sense
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
5 ;;;; E.g. an equivalent JS function exists, or it's a direct API call
6
6
7 ;;; 1loc
7 ;;; 1loc
8
8
9 ;;; 2var
9 ;;; 2var
10
10
11 (defpsmacro killvar (varname &optional index)
11 (defpsmacro killvar (varname &optional index)
12 `(api-call kill-var ,varname ,index))
12 `(api-call kill-var ,varname ,index))
13
13
14 (defpsmacro killall ()
14 (defpsmacro killall ()
15 `(api-call kill-all))
15 `(api-call kill-all))
16
16
17 ;;; 3expr
17 ;;; 3expr
18
18
19 (defpsmacro no (arg)
19 (defpsmacro no (arg)
20 `(- -1 ,arg))
20 `(- -1 ,arg))
21
21
22 ;;; 4code
22 ;;; 4code
23
23
24 (defpsmacro qspver ()
24 (defpsmacro qspver ()
25 "0.0.1")
25 "0.0.1")
26
26
27 (defpsmacro curloc ()
27 (defpsmacro curloc ()
28 `*current-location)
28 `*current-location)
29
29
30 (defpsmacro rnd ()
30 (defpsmacro rnd ()
31 `(funcall rand 1 1000))
31 `(funcall rand 1 1000))
32
32
33 (defpsmacro qspmax (&rest args)
33 (defpsmacro qspmax (&rest args)
34 (if (= 1 (length args))
34 (if (= 1 (length args))
35 `(*math.max.apply nil ,@args)
35 `(*math.max.apply nil ,@args)
36 `(*math.max ,@args)))
36 `(*math.max ,@args)))
37
37
38 (defpsmacro qspmin (&rest args)
38 (defpsmacro qspmin (&rest args)
39 (if (= 1 (length args))
39 (if (= 1 (length args))
40 `(*math.min.apply nil ,@args)
40 `(*math.min.apply nil ,@args)
41 `(*math.min ,@args)))
41 `(*math.min ,@args)))
42
42
43 ;;; 5arrays
43 ;;; 5arrays
44
44
45 (defpsmacro arrsize (name)
45 (defpsmacro arrsize (name)
46 `(api-call array-size ,name))
46 `(api-call array-size ,name))
47
47
48 ;;; 6str
48 ;;; 6str
49
49
50 (defpsmacro len (s)
50 (defpsmacro len (s)
51 `(length ,s))
51 `(length ,s))
52
52
53 (defpsmacro mid (s from &optional count)
53 (defpsmacro mid (s from &optional count)
54 `(chain ,s (substring ,from ,count)))
54 `(chain ,s (substring ,from ,count)))
55
55
56 (defpsmacro ucase (s)
56 (defpsmacro ucase (s)
57 `(chain ,s (to-upper-case)))
57 `(chain ,s (to-upper-case)))
58
58
59 (defpsmacro lcase (s)
59 (defpsmacro lcase (s)
60 `(chain ,s (to-lower-case)))
60 `(chain ,s (to-lower-case)))
61
61
62 (defpsmacro trim (s)
62 (defpsmacro trim (s)
63 `(chain ,s (trim)))
63 `(chain ,s (trim)))
64
64
65 (defpsmacro replace (s from to)
65 (defpsmacro replace (s from to)
66 `(chain ,s (replace ,from ,to)))
66 `(chain ,s (replace ,from ,to)))
67
67
68 (defpsmacro val (s)
68 (defpsmacro val (s)
69 `(parse-int ,s 10))
69 `(parse-int ,s 10))
70
70
71 (defpsmacro qspstr (n)
71 (defpsmacro qspstr (n)
72 `(chain ,n (to-string)))
72 `(chain ,n (to-string)))
73
73
74 ;;; 7if
74 ;;; 7if
75
75
76 ;;; 8sub
76 ;;; 8sub
77
77
78 ;;; 9loops
78 ;;; 9loops
79
79
80 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
80 ;; JUMP is in ps-macros.lisp (because it's a part of a huge kludge)
81
81
82 (defpsmacro exit ()
82 (defpsmacro exit ()
83 `(return-from nil (values)))
83 `(return-from nil (values)))
84
84
85 ;;; 10dynamic
85 ;;; 10dynamic
86
86
87 ;;; 11main
87 ;;; 11main
88
88
89 (defpsmacro desc (s)
89 (defpsmacro desc (s)
90 (declare (ignore s))
90 (declare (ignore s))
91 "")
91 "")
92
92
93 ;;; 12stat
93 ;;; 12stat
94
94
95 (defpsmacro showstat (enable)
95 (defpsmacro showstat (enable)
96 `(api-call enable-frame :stat ,enable))
96 `(api-call enable-frame :stat ,enable))
97
97
98 ;;; 13diag
98 ;;; 13diag
99
99
100 (defpsmacro msg (text)
100 (defpsmacro msg (text)
101 `(alert ,text))
101 `(alert ,text))
102
102
103 ;;; 14act
103 ;;; 14act
104
104
105 (defpsmacro curact ()
106 `*current-action)
107
108 (defpsmacro showacts (enable)
105 (defpsmacro showacts (enable)
109 `(api-call enable-frame :acts ,enable))
106 `(api-call enable-frame :acts ,enable))
110
107
111 (defpsmacro delact (&optional name)
108 (defpsmacro delact (&optional name)
112 (if name
109 (if name
113 `(api-call del-act ,name)
110 `(api-call del-act ,name)
114 `(api-call del-act)))
111 `(api-call del-act)))
115
112
116 (defpsmacro cla ()
113 (defpsmacro cla ()
117 `(api-call clear-act))
114 `(api-call clear-act))
118
115
119 ;;; 15objs
116 ;;; 15objs
120
117
121 (defpsmacro showobjs (enable)
118 (defpsmacro showobjs (enable)
122 `(api-call enable-frame :objs ,enable))
119 `(api-call enable-frame :objs ,enable))
123
120
124 (defpsmacro countobj ()
121 (defpsmacro countobj ()
125 `(length *objs))
122 `(length *objs))
126
123
127 (defpsmacro getobj (index)
124 (defpsmacro getobj (index)
128 `(or (elt *objs ,index) ""))
125 `(or (elt *objs ,index) ""))
129
126
130 ;;; 16menu
127 ;;; 16menu
131
128
132 ;;; 17sound
129 ;;; 17sound
133
130
134 (defpsmacro isplay (filename)
131 (defpsmacro isplay (filename)
135 `(funcall (@ playing includes) ,filename))
132 `(funcall (@ playing includes) ,filename))
136
133
137 ;;; 18img
134 ;;; 18img
138
135
139 (defpsmacro view (&optional path)
136 (defpsmacro view (&optional path)
140 `(api-call show-image ,path))
137 `(api-call show-image ,path))
141
138
142 (defpsmacro img (&rest images)
139 (defpsmacro img (&rest images)
143 `(api-call show-inline-images :stat (list ,@images)))
140 `(api-call show-inline-images :stat (list ,@images)))
144
141
145 (defpsmacro *img (&rest images)
142 (defpsmacro *img (&rest images)
146 `(api-call show-inline-images :main (list ,@images)))
143 `(api-call show-inline-images :main (list ,@images)))
147
144
148 ;;; 19input
145 ;;; 19input
149
146
150 (defpsmacro showinput (enable)
147 (defpsmacro showinput (enable)
151 `(api-call enable-frame :input ,enable))
148 `(api-call enable-frame :input ,enable))
152
149
153 ;;; 20time
150 ;;; 20time
154
151
155 (defpsmacro wait (msec)
152 (defpsmacro wait (msec)
156 `(await (api-call sleep ,msec)))
153 `(await (api-call sleep ,msec)))
157
154
158 (defpsmacro settimer (interval)
155 (defpsmacro settimer (interval)
159 `(api-call set-timer ,interval))
156 `(api-call set-timer ,interval))
160
157
161 ;;; 21local
158 ;;; 21local
162
159
163 ;;; 22for
160 ;;; 22for
164
161
165 ;;; misc
162 ;;; misc
166
163
167 (defpsmacro opengame (&optional filename)
164 (defpsmacro opengame (&optional filename)
168 (declare (ignore filename))
165 (declare (ignore filename))
169 `(api-call opengame))
166 `(api-call opengame))
170
167
171 (defpsmacro savegame (&optional filename)
168 (defpsmacro savegame (&optional filename)
172 (declare (ignore filename))
169 (declare (ignore filename))
173 `(api-call savegame))
170 `(api-call savegame))
@@ -1,321 +1,326 b''
1
1
2 (in-package sugar-qsp.lib)
2 (in-package sugar-qsp.lib)
3
3
4 ;;;; Functions and procedures defined by the QSP language.
4 ;;;; Functions and procedures defined by the QSP language.
5 ;;;; They can call api and deal with locations and other data directly.
5 ;;;; They can call api and deal with locations and other data directly.
6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
6 ;;;; Except vars. Use VAR and SET or GET-VAR and SET-VAR api calls.
7
7
8 ;;; 1loc
8 ;;; 1loc
9
9
10 (defun goto (target args)
10 (defun goto (target args)
11 (api:clear-text :main)
11 (api:clear-text :main)
12 (funcall xgoto target args)
12 (funcall xgoto target args)
13 (void))
13 (void))
14
14
15 (defun xgoto (target args)
15 (defun xgoto (target args)
16 (setf args (or args (list)))
16 (setf args (or args (list)))
17 (api:clear-act)
17 (api:clear-act)
18 (setf *current-location (chain target (to-upper-case)))
18 (setf *current-location (chain target (to-upper-case)))
19 (api:stash-state args)
19 (api:stash-state args)
20 (api:call-loc *current-location args)
20 (api:call-loc *current-location args)
21 (api:call-serv-loc "$ONNEWLOC")
21 (api:call-serv-loc "$ONNEWLOC")
22 (void))
22 (void))
23
23
24 ;;; 2var
24 ;;; 2var
25
25
26 ;;; 3expr
26 ;;; 3expr
27
27
28 (defun obj (name)
28 (defun obj (name)
29 (has name *objs))
29 (has name *objs))
30
30
31 (defun loc (name)
31 (defun loc (name)
32 (has name *locs))
32 (has name *locs))
33
33
34 ;;; 4code
34 ;;; 4code
35
35
36 (defun rand (a &optional (b 1))
36 (defun rand (a &optional (b 1))
37 (let ((min (min a b))
37 (let ((min (min a b))
38 (max (max a b)))
38 (max (max a b)))
39 (+ min (chain *math (random (- max min))))))
39 (+ min (chain *math (random (- max min))))))
40
40
41 ;;; 5arrays
41 ;;; 5arrays
42
42
43 (defun copyarr (to from start count)
43 (defun copyarr (to from start count)
44 (multiple-value-bind (to-name to-slot)
44 (multiple-value-bind (to-name to-slot)
45 (api:var-real-name to)
45 (api:var-real-name to)
46 (multiple-value-bind (from-name from-slot)
46 (multiple-value-bind (from-name from-slot)
47 (api:var-real-name from)
47 (api:var-real-name from)
48 (for ((i start))
48 (for ((i start))
49 ((< i (min (api:array-size from-name)
49 ((< i (min (api:array-size from-name)
50 (+ start count))))
50 (+ start count))))
51 ((incf i))
51 ((incf i))
52 (api:set-var to-name (+ start i) to-slot
52 (api:set-var to-name (+ start i) to-slot
53 (api:get-var from-name (+ start i) from-slot))))))
53 (api:get-var from-name (+ start i) from-slot))))))
54
54
55 (defun arrpos (name value &optional (start 0))
55 (defun arrpos (name value &optional (start 0))
56 (multiple-value-bind (real-name slot)
56 (multiple-value-bind (real-name slot)
57 (api:var-real-name name)
57 (api:var-real-name name)
58 (for ((i start)) ((< i (api:array-size name))) ((incf i))
58 (for ((i start)) ((< i (api:array-size name))) ((incf i))
59 (when (eq (api:get-var real-name i slot) value)
59 (when (eq (api:get-var real-name i slot) value)
60 (return-from arrpos i))))
60 (return-from arrpos i))))
61 -1)
61 -1)
62
62
63 (defun arrcomp (name pattern &optional (start 0))
63 (defun arrcomp (name pattern &optional (start 0))
64 (multiple-value-bind (real-name slot)
64 (multiple-value-bind (real-name slot)
65 (api:var-real-name name)
65 (api:var-real-name name)
66 (for ((i start)) ((< i (api:array-size name))) ((incf i))
66 (for ((i start)) ((< i (api:array-size name))) ((incf i))
67 (when (funcall (getprop (api:get-var real-name i slot) 'match) pattern)
67 (when (funcall (getprop (api:get-var real-name i slot) 'match) pattern)
68 (return-from arrcomp i))))
68 (return-from arrcomp i))))
69 -1)
69 -1)
70
70
71 ;;; 6str
71 ;;; 6str
72
72
73 (defun instr (s subs &optional (start 1))
73 (defun instr (s subs &optional (start 1))
74 (+ start (chain s (substring (- start 1)) (search subs))))
74 (+ start (chain s (substring (- start 1)) (search subs))))
75
75
76 (defun isnum (s)
76 (defun isnum (s)
77 (if (is-na-n s)
77 (if (is-na-n s)
78 0
78 0
79 -1))
79 -1))
80
80
81 (defun strcomp (s pattern)
81 (defun strcomp (s pattern)
82 (if (chain s (match pattern))
82 (if (chain s (match pattern))
83 -1
83 -1
84 0))
84 0))
85
85
86 (defun strfind (s pattern group)
86 (defun strfind (s pattern group)
87 (let* ((re (new (*reg-exp pattern)))
87 (let* ((re (new (*reg-exp pattern)))
88 (match (chain re (exec s))))
88 (match (chain re (exec s))))
89 (chain match (group group))))
89 (chain match (group group))))
90
90
91 (defun strpos (s pattern &optional (group 0))
91 (defun strpos (s pattern &optional (group 0))
92 (let* ((re (new (*reg-exp pattern)))
92 (let* ((re (new (*reg-exp pattern)))
93 (match (chain re (exec s)))
93 (match (chain re (exec s)))
94 (found (chain match (group group))))
94 (found (chain match (group group))))
95 (if found
95 (if found
96 (chain s (search found))
96 (chain s (search found))
97 0)))
97 0)))
98
98
99 ;;; 7if
99 ;;; 7if
100
100
101 ;; Has to be a function because it always evaluates all three of its
101 ;; Has to be a function because it always evaluates all three of its
102 ;; arguments
102 ;; arguments
103 (defun iif (cond-expr then-expr else-expr)
103 (defun iif (cond-expr then-expr else-expr)
104 (if cond-expr then-expr else-expr))
104 (if cond-expr then-expr else-expr))
105
105
106 ;;; 8sub
106 ;;; 8sub
107
107
108 (defun gosub (target &rest args)
108 (defun gosub (target &rest args)
109 (api:call-loc target args)
109 (api:call-loc target args)
110 (void))
110 (void))
111
111
112 (defun func (target &rest args)
112 (defun func (target &rest args)
113 (api:call-loc target args))
113 (api:call-loc target args))
114
114
115 ;;; 9loops
115 ;;; 9loops
116
116
117 ;;; 10dynamic
117 ;;; 10dynamic
118
118
119 (defun dynamic (block &rest args)
119 (defun dynamic (block &rest args)
120 (when (stringp block)
120 (when (stringp block)
121 (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC."))
121 (api:report-error "DYNAMIC can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNAMIC."))
122 (api:with-call-args args
122 (api:with-call-args args
123 (funcall block args))
123 (funcall block args))
124 (void))
124 (void))
125
125
126 (defun dyneval (block &rest args)
126 (defun dyneval (block &rest args)
127 (when (stringp block)
127 (when (stringp block)
128 (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL."))
128 (api:report-error "DYNEVAL can't evaluate arbitrary strings.\\nUse {braces} to create blocks for DYNEVAL."))
129 (api:with-call-args args
129 (api:with-call-args args
130 (funcall block args)))
130 (funcall block args)))
131
131
132 ;;; 11main
132 ;;; 11main
133
133
134 (defun main-p (s)
134 (defun main-p (s)
135 (api:add-text :main s)
135 (api:add-text :main s)
136 (void))
136 (void))
137
137
138 (defun main-pl (s)
138 (defun main-pl (s)
139 (api:add-text :main s)
139 (api:add-text :main s)
140 (api:newline :main)
140 (api:newline :main)
141 (void))
141 (void))
142
142
143 (defun main-nl (s)
143 (defun main-nl (s)
144 (api:newline :main)
144 (api:newline :main)
145 (api:add-text :main s)
145 (api:add-text :main s)
146 (void))
146 (void))
147
147
148 (defun maintxt (s)
148 (defun maintxt (s)
149 (api:get-text :main)
149 (api:get-text :main)
150 (void))
150 (void))
151
151
152 (defun desc (s)
152 (defun desc (s)
153 "")
153 "")
154
154
155 (defun main-clear ()
155 (defun main-clear ()
156 (api:clear-text :main)
156 (api:clear-text :main)
157 (void))
157 (void))
158
158
159 ;;; 12stat
159 ;;; 12stat
160
160
161 (defun stat-p (s)
161 (defun stat-p (s)
162 (api:add-text :stat s)
162 (api:add-text :stat s)
163 (void))
163 (void))
164
164
165 (defun stat-pl (s)
165 (defun stat-pl (s)
166 (api:add-text :stat s)
166 (api:add-text :stat s)
167 (api:newline :stat)
167 (api:newline :stat)
168 (void))
168 (void))
169
169
170 (defun stat-nl (s)
170 (defun stat-nl (s)
171 (api:newline :stat)
171 (api:newline :stat)
172 (api:add-text :stat s)
172 (api:add-text :stat s)
173 (void))
173 (void))
174
174
175 (defun stattxt (s)
175 (defun stattxt (s)
176 (api:get-text :stat)
176 (api:get-text :stat)
177 (void))
177 (void))
178
178
179 (defun stat-clear ()
179 (defun stat-clear ()
180 (api:clear-text :stat)
180 (api:clear-text :stat)
181 (void))
181 (void))
182
182
183 (defun cls ()
183 (defun cls ()
184 (stat-clear)
184 (stat-clear)
185 (main-clear)
185 (main-clear)
186 (cla)
186 (cla)
187 (cmdclear)
187 (cmdclear)
188 (void))
188 (void))
189
189
190 ;;; 13diag
190 ;;; 13diag
191
191
192 ;;; 14act
192 ;;; 14act
193
193
194 (defun selact ()
195 (loop :for (k v) :of *acts
196 :do (when (@ v :selected)
197 (return-from selact (@ v :name)))))
198
194 (defun curacts ()
199 (defun curacts ()
195 (let ((acts (api-call copy-obj *acts)))
200 (let ((acts (api-call copy-obj *acts)))
196 (lambda ()
201 (lambda ()
197 (setf *acts acts)
202 (setf *acts acts)
198 (void))))
203 (void))))
199
204
200 ;;; 15objs
205 ;;; 15objs
201
206
202 (defun addobj (name img)
207 (defun addobj (name img)
203 (setf img (or img ""))
208 (setf img (or img ""))
204 (setf (getprop *objs name)
209 (setf (getprop *objs name)
205 (create :name name :img img :selected nil))
210 (create :name name :img img :selected nil))
206 (api:update-objs)
211 (api:update-objs)
207 (api-call call-serv-loc "$ONOBJADD" name img)
212 (api-call call-serv-loc "$ONOBJADD" name img)
208 (void))
213 (void))
209
214
210 (defun delobj (name)
215 (defun delobj (name)
211 (delete (getprop *objs name))
216 (delete (getprop *objs name))
212 (api:update-objs)
217 (api:update-objs)
213 (api-call call-serv-loc "$ONOBJDEL" name)
218 (api-call call-serv-loc "$ONOBJDEL" name)
214 (void))
219 (void))
215
220
216 (defun killobj (&optional (num nil))
221 (defun killobj (&optional (num nil))
217 (if (eq nil num)
222 (if (eq nil num)
218 (setf *objs (create))
223 (setf *objs (create))
219 (delobj (elt (chain *object (keys *objs)) num)))
224 (delobj (elt (chain *object (keys *objs)) num)))
220 (api:update-objs)
225 (api:update-objs)
221 (void))
226 (void))
222
227
223 (defun selobj ()
228 (defun selobj ()
224 (loop :for (k v) :of *objs
229 (loop :for (k v) :of *objs
225 :do (when (@ v :selected)
230 :do (when (@ v :selected)
226 (return-from selobj (@ v :name)))))
231 (return-from selobj (@ v :name)))))
227
232
228 ;;; 16menu
233 ;;; 16menu
229
234
230 (defun menu (menu-name)
235 (defun menu (menu-name)
231 (let ((menu-data (list)))
236 (let ((menu-data (list)))
232 (loop :for item-obj :in (@ (api:get-array (api:var-real-name menu-name)) values)
237 (loop :for item-obj :in (@ (api:get-array (api:var-real-name menu-name)) values)
233 :for item := (@ item-obj :str)
238 :for item := (@ item-obj :str)
234 :do (cond ((string= item "")
239 :do (cond ((string= item "")
235 (break))
240 (break))
236 ((string= item "-:-")
241 ((string= item "-:-")
237 (chain menu-data (push :delimiter)))
242 (chain menu-data (push :delimiter)))
238 (t
243 (t
239 (let* ((tokens (chain item (split ":"))))
244 (let* ((tokens (chain item (split ":"))))
240 (when (= (length tokens) 2)
245 (when (= (length tokens) 2)
241 (chain tokens (push "")))
246 (chain tokens (push "")))
242 (let* ((text (chain tokens (splice 0 (- (length tokens) 2)) (join ":")))
247 (let* ((text (chain tokens (splice 0 (- (length tokens) 2)) (join ":")))
243 (loc (getprop tokens (- (length tokens) 2)))
248 (loc (getprop tokens (- (length tokens) 2)))
244 (icon (getprop tokens (- (length tokens) 1))))
249 (icon (getprop tokens (- (length tokens) 1))))
245 (chain menu-data
250 (chain menu-data
246 (push (create :text text
251 (push (create :text text
247 :loc loc
252 :loc loc
248 :icon icon))))))))
253 :icon icon))))))))
249 (api:menu menu-data)
254 (api:menu menu-data)
250 (void)))
255 (void)))
251
256
252 ;;; 17sound
257 ;;; 17sound
253
258
254 (defun play (filename &optional (volume 100))
259 (defun play (filename &optional (volume 100))
255 (let ((audio (new (*audio filename))))
260 (let ((audio (new (*audio filename))))
256 (setf (getprop *playing filename) audio)
261 (setf (getprop *playing filename) audio)
257 (setf (@ audio volume) (* volume 0.01))
262 (setf (@ audio volume) (* volume 0.01))
258 (chain audio (play))))
263 (chain audio (play))))
259
264
260 (defun close (filename)
265 (defun close (filename)
261 (funcall (getprop *playing filename) stop)
266 (funcall (getprop *playing filename) stop)
262 (delete (getprop *playing filename))
267 (delete (getprop *playing filename))
263 (void))
268 (void))
264
269
265 (defun closeall ()
270 (defun closeall ()
266 (loop :for k :in (chain *object (keys *playing))
271 (loop :for k :in (chain *object (keys *playing))
267 :for v := (getprop *playing k)
272 :for v := (getprop *playing k)
268 :do (funcall v stop))
273 :do (funcall v stop))
269 (setf *playing (create)))
274 (setf *playing (create)))
270
275
271 ;;; 18img
276 ;;; 18img
272
277
273 (defun refint ()
278 (defun refint ()
274 ;; "Force interface update" Uh... what exactly do we do here?
279 ;; "Force interface update" Uh... what exactly do we do here?
275 ;(api:report-error "REFINT is not supported")
280 ;(api:report-error "REFINT is not supported")
276 )
281 )
277
282
278 ;;; 19input
283 ;;; 19input
279
284
280 (defun usertxt ()
285 (defun usertxt ()
281 (let ((input (by-id "qsp-input")))
286 (let ((input (by-id "qsp-input")))
282 (@ input value)))
287 (@ input value)))
283
288
284 (defun cmdclear ()
289 (defun cmdclear ()
285 (let ((input (by-id "qsp-input")))
290 (let ((input (by-id "qsp-input")))
286 (setf (@ input value) "")))
291 (setf (@ input value) "")))
287
292
288 (defun input (text)
293 (defun input (text)
289 (chain window (prompt text)))
294 (chain window (prompt text)))
290
295
291 ;;; 20time
296 ;;; 20time
292
297
293 (defun msecscount ()
298 (defun msecscount ()
294 (- (chain *date (now)) *started-at))
299 (- (chain *date (now)) *started-at))
295
300
296 ;;; 21local
301 ;;; 21local
297
302
298 ;;; 22for
303 ;;; 22for
299
304
300 ;;; misc
305 ;;; misc
301
306
302 (defun rgb (red green blue)
307 (defun rgb (red green blue)
303 (+ (<< red 16)
308 (+ (<< red 16)
304 (<< green 8)
309 (<< green 8)
305 blue))
310 blue))
306
311
307 (defun openqst (name)
312 (defun openqst (name)
308 (api-call run-game name))
313 (api-call run-game name))
309
314
310 (defun addqst (name)
315 (defun addqst (name)
311 (let ((game (api-call filename-game name)))
316 (let ((game (api-call filename-game name)))
312 ;; Add the game's locations
317 ;; Add the game's locations
313 (chain *object (assign *locs
318 (chain *object (assign *locs
314 (getprop *games name)))))
319 (getprop *games name)))))
315
320
316 (defun killqst ()
321 (defun killqst ()
317 ;; Delete all locations not from the current main game
322 ;; Delete all locations not from the current main game
318 (loop :for (k v) :in *games
323 (loop :for (k v) :in *games
319 :do (unless (string= k *main-game)
324 :do (unless (string= k *main-game)
320 (delete (getprop *locs k)))))
325 (delete (getprop *locs k)))))
321
326
@@ -1,55 +1,54 b''
1
1
2 (in-package sugar-qsp.main)
2 (in-package sugar-qsp.main)
3
3
4 ;;; Game session state (saved in savegames)
4 ;;; Game session state (saved in savegames)
5 ;; Variables
5 ;; Variables
6 (var *globals (create))
6 (var *globals (create))
7 ;; Inventory (objects)
7 ;; Inventory (objects)
8 (var *objs (create))
8 (var *objs (create))
9 (var *current-location nil)
9 (var *current-location nil)
10 (var *current-action nil)
11 ;; Game time
10 ;; Game time
12 (var *started-at (chain *date (now)))
11 (var *started-at (chain *date (now)))
13 ;; Timers
12 ;; Timers
14 (var *timer-interval 500)
13 (var *timer-interval 500)
15 (var *timer-obj nil)
14 (var *timer-obj nil)
16 ;; Games
15 ;; Games
17 (var *loaded-games (list))
16 (var *loaded-games (list))
18
17
19 ;;; Transient state
18 ;;; Transient state
20 ;; ACTions
19 ;; ACTions
21 (var *acts (create))
20 (var *acts (create))
22 ;; Savegame data
21 ;; Savegame data
23 (var *state-stash (create))
22 (var *state-stash (create))
24 ;; List of audio files being played
23 ;; List of audio files being played
25 (var *playing (create))
24 (var *playing (create))
26 ;; Local variables stack (starts with an empty frame)
25 ;; Local variables stack (starts with an empty frame)
27 (var *locals (list))
26 (var *locals (list))
28 ;; Promise to continue running the game after menu
27 ;; Promise to continue running the game after menu
29 (var *menu-resume nil)
28 (var *menu-resume nil)
30
29
31 ;;; Game data
30 ;;; Game data
32 ;; Games (filename -> [locations])
31 ;; Games (filename -> [locations])
33 (var *games (list))
32 (var *games (list))
34 ;; The main (non library) game. Updated by openqst
33 ;; The main (non library) game. Updated by openqst
35 (var *main-game nil)
34 (var *main-game nil)
36 ;; Active locations
35 ;; Active locations
37 (var *locs (create))
36 (var *locs (create))
38
37
39 (setf (@ window onload)
38 (setf (@ window onload)
40 (lambda ()
39 (lambda ()
41 (#.(intern "INIT-DOM" "SUGAR-QSP.API"))
40 (#.(intern "INIT-DOM" "SUGAR-QSP.API"))
42 ;; For MSECCOUNT
41 ;; For MSECCOUNT
43 (setf *started-at (chain *date (now)))
42 (setf *started-at (chain *date (now)))
44 ;; For $COUNTER and SETTIMER
43 ;; For $COUNTER and SETTIMER
45 (#.(intern "SET-TIMER" "SUGAR-QSP.API")
44 (#.(intern "SET-TIMER" "SUGAR-QSP.API")
46 *timer-interval)
45 *timer-interval)
47 ;; Start the first game
46 ;; Start the first game
48 (#.(intern "RUN-GAME" "SUGAR-QSP.API")
47 (#.(intern "RUN-GAME" "SUGAR-QSP.API")
49 (chain *object (keys *games) 0))
48 (chain *object (keys *games) 0))
50 (values)))
49 (values)))
51
50
52 ;;; Some very common utilities (for both api and lib)
51 ;;; Some very common utilities (for both api and lib)
53
52
54 (defun by-id (id)
53 (defun by-id (id)
55 (chain document (get-element-by-id id)))
54 (chain document (get-element-by-id id)))
@@ -1,108 +1,108 b''
1
1
2 (in-package cl-user)
2 (in-package cl-user)
3
3
4 (defpackage :sugar-qsp.js)
4 (defpackage :sugar-qsp.js)
5
5
6 (defpackage :sugar-qsp.main
6 (defpackage :sugar-qsp.main
7 (:use :cl :ps :sugar-qsp.js)
7 (:use :cl :ps :sugar-qsp.js)
8 (:export #:api-call #:by-id
8 (:export #:api-call #:by-id
9 #:has
9 #:has
10
10
11 #:*globals #:*objs #:*current-location #:*current-action
11 #:*globals #:*objs #:*current-location
12 #:*started-at #:*timer-interval #:*timer-obj #:*loaded-games
12 #:*started-at #:*timer-interval #:*timer-obj #:*loaded-games
13
13
14 #:*acts #:*state-stash #:*playing #:*locals
14 #:*acts #:*state-stash #:*playing #:*locals
15
15
16 #:*games #:*main-game #:*locs #:*menu-resume
16 #:*games #:*main-game #:*locs #:*menu-resume
17 ))
17 ))
18
18
19 (defpackage :code-walker
19 (defpackage :code-walker
20 (:use :cl)
20 (:use :cl)
21 (:export #:deftransform
21 (:export #:deftransform
22 #:deftransform-stop
22 #:deftransform-stop
23 #:walk
23 #:walk
24 #:whole
24 #:whole
25 #:walk-continue))
25 #:walk-continue))
26
26
27 ;;; API functions
27 ;;; API functions
28 (defpackage :sugar-qsp.api
28 (defpackage :sugar-qsp.api
29 (:use :cl :ps :sugar-qsp.main :sugar-qsp.js)
29 (:use :cl :ps :sugar-qsp.main :sugar-qsp.js)
30 (:export #:with-frame #:with-call-args
30 (:export #:with-frame #:with-call-args
31 #:stash-state
31 #:stash-state
32
32
33 #:report-error #:sleep #:init-dom #:call-serv-loc #:*serv-vars*
33 #:report-error #:sleep #:init-dom #:call-serv-loc #:*serv-vars*
34 #:newline #:clear-id #:prepare-contents #:get-id #:set-id #:append-id
34 #:newline #:clear-id #:prepare-contents #:get-id #:set-id #:append-id
35 #:init-args #:get-result #:call-loc #:call-act
35 #:init-args #:get-result #:call-loc #:call-act
36 #:get-frame #:add-text #:get-text #:clear-text #:enable-frame
36 #:get-frame #:add-text #:get-text #:clear-text #:enable-frame
37 #:add-act #:del-act #:clear-act #:update-acts
37 #:add-act #:del-act #:clear-act #:update-acts
38 #:set-str-element #:set-any-element #:set-serv-var
38 #:set-str-element #:set-any-element #:set-serv-var
39 #:*var #:new-value #:index-num #:get #:set #:kill
39 #:*var #:new-value #:index-num #:get #:set #:kill
40 #:var-real-name #:ensure-var #:var-ref #:get-var #:set-var
40 #:var-real-name #:ensure-var #:var-ref #:get-var #:set-var
41 #:get-array #:set-array #:kill-var #:array-size
41 #:get-array #:set-array #:kill-var #:array-size
42 #:push-local-frame #:pop-local-frame #:current-local-frame #:new-local
42 #:push-local-frame #:pop-local-frame #:current-local-frame #:new-local
43 #:update-objs
43 #:update-objs
44 #:menu
44 #:menu
45 #:clean-audio
45 #:clean-audio
46 #:show-image
46 #:show-image
47 #:opengame #:savegame
47 #:opengame #:savegame
48 ))
48 ))
49
49
50 ;;; QSP library functions and macros
50 ;;; QSP library functions and macros
51 (defpackage :sugar-qsp.lib
51 (defpackage :sugar-qsp.lib
52 (:use :cl :ps :sugar-qsp.main :sugar-qsp.js)
52 (:use :cl :ps :sugar-qsp.main :sugar-qsp.js)
53 (:local-nicknames (#:api :sugar-qsp.api)
53 (:local-nicknames (#:api :sugar-qsp.api)
54 (#:walker :code-walker))
54 (#:walker :code-walker))
55 (:export #:str #:exec #:qspblock #:qspfor #:game #:location
55 (:export #:str #:exec #:qspblock #:qspfor #:game #:location
56 #:qspcond #:qspvar #:set #:local #:jump
56 #:qspcond #:qspvar #:set #:local #:jump
57
57
58 #:killvar #:killall
58 #:killvar #:killall
59 #:obj #:loc #:no
59 #:obj #:loc #:no
60 #:qspver #:curloc
60 #:qspver #:curloc
61 #:rnd #:qspmax #:qspmin
61 #:rnd #:qspmax #:qspmin
62 #:arrsize #:len
62 #:arrsize #:len
63 #:mid #:ucase #:lcase #:trim #:replace #:val #:qspstr
63 #:mid #:ucase #:lcase #:trim #:replace #:val #:qspstr
64 #:exit #:desc
64 #:exit #:desc
65 #:showstat #:msg
65 #:showstat #:msg
66 #:showacts #:delact #:cla
66 #:showacts #:delact #:cla
67 #:showobjs #:countobj #:getobj
67 #:showobjs #:countobj #:getobj
68 #:isplay
68 #:isplay
69 #:view
69 #:view
70 #:showinput
70 #:showinput
71 #:wait #:settimer
71 #:wait #:settimer
72 #:local
72 #:local
73 #:opengame #:savegame
73 #:opengame #:savegame
74
74
75 #:goto #:xgoto
75 #:goto #:xgoto
76 #:rand
76 #:rand
77 #:copyarr #:arrpos #:arrcomp
77 #:copyarr #:arrpos #:arrcomp
78 #:instr #:isnum #:strcomp #:strfind #:strpos
78 #:instr #:isnum #:strcomp #:strfind #:strpos
79 #:iif
79 #:iif
80 #:gosub #:func
80 #:gosub #:func
81 #:dynamic #:dyneval
81 #:dynamic #:dyneval
82 #:main-p #:main-pl #:main-nl #:maintxt #:desc #:main-clear
82 #:main-p #:main-pl #:main-nl #:maintxt #:desc #:main-clear
83 #:stat-p #:stat-pl #:stat-nl #:stattxt #:stat-clear #:cls
83 #:stat-p #:stat-pl #:stat-nl #:stattxt #:stat-clear #:cls
84 #:curacts
84 #:curacts
85 #:addobj #:delobj #:killobj
85 #:addobj #:delobj #:killobj
86 #:menu
86 #:menu
87 #:play #:close #:closeall
87 #:play #:close #:closeall
88 #:refint
88 #:refint
89 #:usertxt #:cmdclear #:input
89 #:usertxt #:cmdclear #:input
90 #:msecscount
90 #:msecscount
91 #:rgb
91 #:rgb
92 #:openqst #:addqst #:killqst
92 #:openqst #:addqst #:killqst
93 ))
93 ))
94
94
95 (setf (ps:ps-package-prefix "SUGAR-QSP.MAIN") "qsp_")
95 (setf (ps:ps-package-prefix "SUGAR-QSP.MAIN") "qsp_")
96 (setf (ps:ps-package-prefix "SUGAR-QSP.API") "qsp_api_")
96 (setf (ps:ps-package-prefix "SUGAR-QSP.API") "qsp_api_")
97 (setf (ps:ps-package-prefix "SUGAR-QSP.LIB") "qsp_lib_")
97 (setf (ps:ps-package-prefix "SUGAR-QSP.LIB") "qsp_lib_")
98
98
99 ;;; The compiler
99 ;;; The compiler
100 (defpackage :sugar-qsp
100 (defpackage :sugar-qsp
101 (:use :cl)
101 (:use :cl)
102 (:local-nicknames (#:p #:esrap)
102 (:local-nicknames (#:p #:esrap)
103 (#:lib :sugar-qsp.lib)
103 (#:lib :sugar-qsp.lib)
104 (#:api :sugar-qsp.api)
104 (#:api :sugar-qsp.api)
105 (#:main :sugar-qsp.main)
105 (#:main :sugar-qsp.main)
106 (#:walker :code-walker))
106 (#:walker :code-walker))
107 (:export #:parse-file #:entry-point))
107 (:export #:parse-file #:entry-point))
108
108
General Comments 0
You need to be logged in to leave comments. Login now