##// END OF EJS Templates
Multiple sources, multiple games, openqst/addqst/killqst
naryl -
r31:5d061177 default
parent child Browse files
Show More
@@ -1,5 +1,4 b''
1
1
2 * MENU with async/await
3 * Special locations
2 * Special locations
4 * Special variables
3 * Special variables
5 * CLI build for Linux
4 * CLI build for Linux
@@ -11,6 +10,7 b''
11 * Report JUMP with missing label (in tagbody)
10 * Report JUMP with missing label (in tagbody)
12
11
13 * Build Istreblenie
12 * Build Istreblenie
13 * Build Цветохимия
14 * Windows GUI (for the compiler)
14 * Windows GUI (for the compiler)
15 * Save-load game in slots
15 * Save-load game in slots
16 * Resizable frames
16 * Resizable frames
@@ -1,13 +1,11 b''
1 ql alexandria
1 ql alexandria
2 ql esrap
2 ql esrap
3 ql parenscript
3 ql parenscript
4 ql cl-uglify-js
5 ql flute
4 ql flute
6
5
7 ql cl-ppcre
6 ql cl-ppcre
8 ql anaphora
7 ql anaphora
9 ql named-readtables
8 ql named-readtables
10 ql parse-js
11 ql cl-unicode
9 ql cl-unicode
12 ql flexi-streams
10 ql flexi-streams
13 ql trivial-gray-streams
11 ql trivial-gray-streams
@@ -62,6 +62,19 b''
62 (when loc
62 (when loc
63 (funcall loc args))))))
63 (funcall loc args))))))
64
64
65 (defun filename-game (filename)
66 (let ((game-name (chain filename (match "(.*/)?([^.]+)(\\.[a-zA-Z]+)?") 2))))
67 (getprop (root games) game-name))
68
69 (defun run-game (name)
70 (let ((game (filename-game name)))
71 (setf (root main-game) name)
72 ;; Replace locations with the new game's
73 (setf (root locs) game)
74 (funcall (getprop game
75 (chain *object (keys game) 0))
76 (list))))
77
65 ;;; Misc
78 ;;; Misc
66
79
67 (defun newline (key)
80 (defun newline (key)
@@ -13,10 +13,11 b''
13 (void))
13 (void))
14
14
15 (defun xgoto (target args)
15 (defun xgoto (target args)
16 (setf args (or args (list)))
16 (api:clear-act)
17 (api:clear-act)
17 (setf (root current-location) (chain target (to-upper-case)))
18 (setf (root current-location) (chain target (to-upper-case)))
18 (api:stash-state args)
19 (api:stash-state args)
19 (api:call-loc (root current-location) (or args (list)))
20 (api:call-loc (root current-location) args)
20 (void))
21 (void))
21
22
22 ;;; 2var
23 ;;; 2var
@@ -292,11 +293,18 b''
292 hex))))
293 hex))))
293 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
294 (+ "#" (rgb-to-hex red) (rgb-to-hex green) (rgb-to-hex red))))
294
295
295 (defun openqst ()
296 (defun openqst (name)
296 (api:report-error "OPENQST is not supported."))
297 (api-call run-game name))
297
298
298 (defun addqst ()
299 (defun addqst (name)
299 (api:report-error "ADDQST is not supported. Bundle the library with the main game."))
300 (let ((game (api-call filename-game name)))
301 ;; Add the game's locations
302 (chain *object (assign (root locs)
303 (getprop (root games) name)))))
300
304
301 (defun killqst ()
305 (defun killqst ()
302 (api:report-error "KILLQST is not supported."))
306 ;; Delete all locations not from the current main game
307 (loop :for (k v) :in (root games)
308 :do (unless (string= k (root main-game))
309 (delete (getprop (root locs) k)))))
310
@@ -24,7 +24,7 b''
24 alert prompt
24 alert prompt
25 set-timeout set-interval clear-interval
25 set-timeout set-interval clear-interval
26 *promise *j-s-o-n
26 *promise *j-s-o-n
27 href parse
27 href parse match
28 set-prototype-of
28 set-prototype-of
29 body append-child remove-child
29 body append-child remove-child
30 add ; remove (is already in COMMON-LISP)
30 add ; remove (is already in COMMON-LISP)
@@ -11,8 +11,8 b''
11 (values))
11 (values))
12
12
13 (defun parse-opts (args)
13 (defun parse-opts (args)
14 (let ((mode :source)
14 (let ((mode :sources)
15 (data (list :source nil :target nil :js nil :css nil :body nil :compile nil :beautify nil)))
15 (data (list :sources nil :target nil :js nil :css nil :body nil :compile nil :beautify nil)))
16 (loop :for arg :in args
16 (loop :for arg :in args
17 :do (alexandria:switch (arg :test #'string=)
17 :do (alexandria:switch (arg :test #'string=)
18 ("-o" (setf mode :target))
18 ("-o" (setf mode :target))
@@ -22,9 +22,9 b''
22 ("-c" (setf (getf data :compile) t))
22 ("-c" (setf (getf data :compile) t))
23 ("--beautify" (setf (getf data :beautify) t))
23 ("--beautify" (setf (getf data :beautify) t))
24 (t (push arg (getf data mode)))))
24 (t (push arg (getf data mode)))))
25 (unless (= 1 (length (getf data :source)))
25 (unless (< 0 (length (getf data :sources)))
26 (print-usage)
26 (print-usage)
27 (report-error "There should be exactly one source"))
27 (report-error "There should be at least one source"))
28 (unless (> 1 (length (getf data :target)))
28 (unless (> 1 (length (getf data :target)))
29 (print-usage)
29 (print-usage)
30 (report-error "There should be no more than one target"))
30 (report-error "There should be no more than one target"))
@@ -33,12 +33,12 b''
33 (report-error "There should be no more than one body"))
33 (report-error "There should be no more than one body"))
34 (unless (getf data :target)
34 (unless (getf data :target)
35 (setf (getf data :target)
35 (setf (getf data :target)
36 (let* ((source (first (getf data :source)))
36 (let* ((sources (first (getf data :sources)))
37 (tokens (uiop:split-string source :separator "."))
37 (tokens (uiop:split-string sources :separator "."))
38 (target (format nil "~{~A~^.~}.html"
38 (target (format nil "~{~A~^.~}.html"
39 (butlast tokens))))
39 (butlast tokens))))
40 (list target))))
40 (list target))))
41 (list :source (first (getf data :source))
41 (list :sources (getf data :sources)
42 :target (first (getf data :target))
42 :target (first (getf data :target))
43 :js (getf data :js)
43 :js (getf data :js)
44 :css (getf data :css)
44 :css (getf data :css)
@@ -102,12 +102,25 b''
102 :stream out
102 :stream out
103 :pretty nil))))
103 :pretty nil))))
104
104
105 (defmethod initialize-instance ((compiler compiler) &key source ((:js js-files)) ((:css css-files)) ((:body body-file)) compile &allow-other-keys)
105 (defun filename-game (filename)
106 (let ((filename (alexandria:lastcar (uiop:split-string filename :separator "/"))))
107 (format nil "~{~A~^.~}" (butlast (uiop:split-string filename :separator ".")))))
108
109 (defmethod initialize-instance ((compiler compiler) &key sources ((:js js-files)) ((:css css-files)) ((:body body-file)) compile &allow-other-keys)
106 (call-next-method)
110 (call-next-method)
107 (with-slots (body css js)
111 (with-slots (body css js)
108 compiler
112 compiler
109 ;; Compile the game's JS
113 ;; Compile the game's JS
110 (push (list* 'progn (parse-file source)) js)
114 (dolist (source sources)
115 (let ((ps (parse-file source))
116 (game-name (filename-game source)))
117 (destructuring-bind (kw &rest locations)
118 ps
119 (unless (eq kw 'lib:game)
120 (report-error "Internal error!"))
121 (push
122 `(lib:game (,game-name) ,@locations)
123 js))))
111 ;; Does the user need us to do anything else
124 ;; Does the user need us to do anything else
112 (unless compile
125 (unless compile
113 ;; Read in body
126 ;; Read in body
@@ -129,7 +142,7 b''
129 (alexandria:write-string-into-file
142 (alexandria:write-string-into-file
130 (if (compile-only compiler)
143 (if (compile-only compiler)
131 ;; Just the JS
144 ;; Just the JS
132 (preprocess-js (js-sources compiler) (beautify compiler))
145 (js-sources compiler)
133 ;; All of it
146 ;; All of it
134 (html-sources compiler))
147 (html-sources compiler))
135 (target compiler) :if-exists :supersede))
148 (target compiler) :if-exists :supersede))
@@ -3,7 +3,7 b''
3
3
4 (setf (root)
4 (setf (root)
5 (create
5 (create
6 ;;; Game session state
6 ;;; Game session state (saved in savegames)
7 ;; Variables
7 ;; Variables
8 vars (create)
8 vars (create)
9 ;; Inventory (objects)
9 ;; Inventory (objects)
@@ -14,17 +14,25 b''
14 ;; Timers
14 ;; Timers
15 timer-interval 500
15 timer-interval 500
16 timer-obj nil
16 timer-obj nil
17 ;; Games
18 loaded-games (list)
19
17 ;;; Transient state
20 ;;; Transient state
21 ;; ACTions
22 acts (create)
18 ;; Savegame data
23 ;; Savegame data
19 state-stash (create)
24 state-stash (create)
20 ;; List of audio files being played
25 ;; List of audio files being played
21 playing (create)
26 playing (create)
22 ;; Local variables stack (starts with an empty frame)
27 ;; Local variables stack (starts with an empty frame)
23 locals (list)
28 locals (list)
29
24 ;;; Game data
30 ;;; Game data
25 ;; ACTions
31 ;; Games (filename -> [locations])
26 acts (create)
32 games (list)
27 ;; Locations
33 ;; The main (non library) game. Updated by openqst
34 main-game nil
35 ;; Active locations
28 locs (create)))
36 locs (create)))
29
37
30 ;; Launch the game from the first location
38 ;; Launch the game from the first location
@@ -36,9 +44,8 b''
36 ;; For $COUNTER and SETTIMER
44 ;; For $COUNTER and SETTIMER
37 (#.(intern "SET-TIMER" "SUGAR-QSP.API")
45 (#.(intern "SET-TIMER" "SUGAR-QSP.API")
38 (root timer-interval))
46 (root timer-interval))
39 ;; Start the first location
47 ;; Start the first game
40 (funcall (getprop (root locs)
48 (#.(intern "RUN-GAME" "SUGAR-QSP.API")
41 (chain *object (keys (root locs)) 0))
49 (chain *object (keys (root games)) 0))
42 (list))
43 (values)))
50 (values)))
44
51
@@ -10,7 +10,7 b''
10 #:vars #:objs #:current-location
10 #:vars #:objs #:current-location
11 #:started-at #:timer-interval #:timer-obj
11 #:started-at #:timer-interval #:timer-obj
12 #:state-stash #:playing #:locals
12 #:state-stash #:playing #:locals
13 #:acts #:locs))
13 #:acts #:locs #:games))
14
14
15 ;;; API functions
15 ;;; API functions
16 (defpackage :sugar-qsp.api
16 (defpackage :sugar-qsp.api
@@ -39,7 +39,7 b''
39 (defpackage :sugar-qsp.lib
39 (defpackage :sugar-qsp.lib
40 (:use :cl :ps :sugar-qsp.main :sugar-qsp.js)
40 (:use :cl :ps :sugar-qsp.main :sugar-qsp.js)
41 (:local-nicknames (#:api :sugar-qsp.api))
41 (:local-nicknames (#:api :sugar-qsp.api))
42 (:export #:str #:exec #:qspblock #:qspfor #:location
42 (:export #:str #:exec #:qspblock #:qspfor #:game #:location
43 #:qspcond #:qspvar #:set #:local #:jump
43 #:qspcond #:qspvar #:set #:local #:jump
44
44
45 #:killvar #:killall
45 #:killvar #:killall
@@ -176,7 +176,8 b''
176
176
177 (p:defrule sugar-qsp-grammar (and (* (or spaces #\newline))
177 (p:defrule sugar-qsp-grammar (and (* (or spaces #\newline))
178 (* location))
178 (* location))
179 (:function second))
179 (:lambda (list)
180 `(lib:game ,@(second list))))
180
181
181 (p:defrule location (and location-header block-body location-end)
182 (p:defrule location (and location-header block-body location-end)
182 (:destructure (header body end)
183 (:destructure (header body end)
@@ -29,11 +29,20 b''
29
29
30 ;;; 1loc
30 ;;; 1loc
31
31
32 (defpsmacro game ((name) &body body)
33 `(progn
34 (setf (root games ,name)
35 (create))
36 ,@(loop :for location :in body
37 :collect `(setf (root games ,name ,(caadr location))
38 ,location))))
39
32 (defpsmacro location ((name) &body body)
40 (defpsmacro location ((name) &body body)
33 `(setf (root locs ,name)
41 (declare (ignore name))
34 (async-lambda (args)
42 "Name is used by the game macro above"
35 (label-block ()
43 `(async-lambda (args)
36 ,@body))))
44 (label-block ()
45 ,@body)))
37
46
38 (defpsmacro goto% (target &rest args)
47 (defpsmacro goto% (target &rest args)
39 `(progn
48 `(progn
General Comments 0
You need to be logged in to leave comments. Login now