(use-modules (mudsync)
(mudsync parser)
- (8sync systems actors)
+ (8sync actors)
(8sync agenda)
(oop goops)
(ice-9 control)
(append readable-commands
thing-commands))
-(define readable-actions
- (build-actions
- (cmd-read (wrap-apply readable-cmd-read))))
-
-(define readable-actions*
- (append readable-actions
- thing-actions*))
-
(define-class <readable> (<thing>)
(read-text #:init-value "All it says is: \"Blah blah blah.\""
#:init-keyword #:read-text)
(commands
#:init-value readable-commands*)
- (message-handler
- #:init-value
- (simple-dispatcher readable-actions*)))
+ (actions #:allocation #:each-subclass
+ #:init-value (build-actions
+ (cmd-read readable-cmd-read))))
(define (readable-cmd-read actor message)
(<- actor (message-from message) 'tell
;;; Lobby
;;; -----
-(define-mhandler (npc-chat-randomly actor message)
+(define (npc-chat-randomly actor message . _)
(define text-to-send
(format #f "~a says: \"~a\"\n"
(slot-ref actor 'name)
(list
(direct-command "chat" 'cmd-chat)
(direct-command "talk" 'cmd-chat)))
-(define chat-actions
- (build-actions
- (cmd-chat (wrap-apply npc-chat-randomly))))
(define hotel-owner-grumps
'("Eight sinks! Eight sinks! And I couldn't unwind them..."
#:init-keyword #:catchphrases)
(commands
#:init-value chat-commands)
- (message-handler
- #:init-value
- (simple-dispatcher (append gameobj-actions chat-actions))))
+ (actions #:allocation #:each-subclass
+ #:init-value
+ (build-actions
+ (cmd-chat npc-chat-randomly))))
(define random-bricabrac
'("a creepy porcelain doll"
#:init-value
(list
(prep-direct-command "sign" 'cmd-sign-form
- '("as"))))
- (message-handler
- #:init-value
- (simple-dispatcher
- (append
- (build-actions
- (cmd-sign-form (wrap-apply sign-cmd-sign-in)))
- gameobj-actions))))
+ '("as"))))
+ (actions #:allocation #:each-subclass
+ #:init-value (build-actions
+ (cmd-sign-form sign-cmd-sign-in))))
(define name-sre
(and (irregex-match name-sre name)
(not (member name forbidden-words))))
-(define-mhandler (sign-cmd-sign-in actor message direct-obj indir-obj)
+(define* (sign-cmd-sign-in actor message
+ #:key direct-obj indir-obj preposition)
(define old-name
- (message-ref
- (<-wait actor (message-from message) 'get-name)
- 'val))
+ (msg-val (<-wait actor (message-from message) 'get-name)))
(define name indir-obj)
(if (valid-name? indir-obj)
(begin
- (<-wait actor (message-from message) 'set-name!
- #:val name)
+ (<-wait actor (message-from message) 'set-name! name)
(<- actor (slot-ref actor 'loc) 'tell-room
#:text (format #f "~a signs the form!\n~a is now known as ~a\n"
old-name old-name name)))
(append summoning-bell-commands
thing-commands*))
-(define summoning-bell-actions
- (build-actions
- (cmd-ring (wrap-apply summoning-bell-cmd-ring))))
-(define summoning-bell-actions*
- (append summoning-bell-actions
- thing-actions*))
-
(define-class <summoning-bell> (<thing>)
(summons #:init-keyword #:summons)
(commands
#:init-value summoning-bell-commands*)
- (message-handler
- #:init-value
- (simple-dispatcher summoning-bell-actions*)))
-
-(define-mhandler (summoning-bell-cmd-ring bell message)
+ (actions #:allocation #:each-subclass
+ #:init-value (build-actions
+ (cmd-ring summoning-bell-cmd-ring))))
+
+(define* (summoning-bell-cmd-ring bell message . _)
+ ;; Call back to actor who invoked this message handler
+ ;; and find out their name. We'll call *their* get-name message
+ ;; handler... meanwhile, this procedure suspends until we get
+ ;; their response.
(define who-rang
- (message-ref
- (<-wait bell (message-from message) 'get-name)
- 'val))
+ (msg-val (<-wait bell (message-from message) 'get-name)))
+
+ ;; Now we'll invoke the "tell" message handler on the player
+ ;; who rang us, displaying this text on their screen.
+ ;; This one just uses <- instead of <-wait, since we don't
+ ;; care when it's delivered; we're not following up on it.
(<- bell (message-from message) 'tell
#:text "*ring ring!* You ring the bell!\n")
+ ;; We also want everyone else in the room to "hear" the bell,
+ ;; but they get a different message since they aren't the ones
+ ;; ringing it. Notice here's where we make use of the invoker's
+ ;; name as extracted and assigned to the who-rang variable.
+ ;; Notice how we send this message to our "location", which
+ ;; forwards it to the rest of the occupants in the room.
(<- bell (gameobj-loc bell) 'tell-room
#:text
(format #f "*ring ring!* ~a rings the bell!\n"
who-rang)
#:exclude (message-from message))
-
+ ;; Now we perform the primary task of the bell, which is to summon
+ ;; the "clerk" character to the room. (This is configurable,
+ ;; so we dynamically look up their address.)
(<- bell (dyn-ref bell (slot-ref bell 'summons)) 'be-summoned
#:who-summoned (message-from message)))
+(define prefect-quotes
+ '("I'm a frood who really knows where my towel is!"
+ "On no account allow a Vogon to read poetry at you."
+ "Time is an illusion, lunchtime doubly so!"
+ "How can you have money if none of you produces anything?"
+ "On no account allow Arthur to request tea on this ship."))
+
(define lobby
(lol
('room:lobby
"Chris Webber" ; heh, did you rtfc? or was it so obvious?
"hotel proprietor" "proprietor")
#:catchphrases hotel-owner-grumps)
- ;; NPC: desk clerk (comes when you ring the s)
- ;; impatient teenager, only stays around for a few minutes
- ;; complaining, then leaves.
-
;; Object: Sign
('thing:lobby:sign
<readable> 'room:lobby
('thing:cuddles-plushie
<thing> 'room:playroom
#:name "a cuddles plushie"
- #:goes-by '("plushie" "cuddles plushie")
+ #:goes-by '("plushie" "cuddles plushie" "cuddles")
#:takeable #t
#:desc " A warm and fuzzy cuddles plushie! It's a cuddlefish!")))
#:init-value
(list
(direct-command "sit" 'cmd-sit-furniture)))
- (message-handler
- #:init-value
- (simple-dispatcher
- (append
- (build-actions
- (cmd-sit-furniture (wrap-apply furniture-cmd-sit)))
- gameobj-actions))))
+ (actions #:allocation #:each-subclass
+ #:init-value (build-actions
+ (cmd-sit-furniture furniture-cmd-sit))))
-(define-mhandler (furniture-cmd-sit actor message direct-obj)
+(define* (furniture-cmd-sit actor message #:key direct-obj)
(define player-name
- (message-ref
- (<-wait actor (message-from message) 'get-name)
- 'val))
+ (msg-val (<-wait actor (message-from message) 'get-name)))
(<- actor (message-from message) 'tell
#:text (format #f "You ~a ~a.\n"
(slot-ref actor 'sit-phrase)
#:sit-phrase "hop on"
#:sit-phrase-third-person "hops onto"
#:sit-name "the bar stool")
+ ('npc:ford-prefect
+ <chatty-npc> 'room:smoking-parlor
+ #:name "Ford Prefect"
+ #:desc "Just some guy, you know?"
+ #:goes-by '("Ford Prefect" "ford prefect"
+ "frood" "prefect" "ford")
+ #:catchphrases prefect-quotes)
;; TODO: Cigar dispenser
(direct-command "talk" 'cmd-chat)
(direct-command "chat" 'cmd-chat)
(direct-command "ask" 'cmd-ask-incomplete)
- (prep-direct-command "ask" 'cmd-ask-about)))
+ (prep-direct-command "ask" 'cmd-ask-about)
+ (direct-command "dismiss" 'cmd-dismiss)))
(define clerk-commands*
(append clerk-commands thing-commands*))
-(define clerk-actions
- (build-actions
- (init (wrap-apply clerk-act-init))
- (cmd-chat (wrap-apply clerk-cmd-chat))
- (cmd-ask-incomplete (wrap-apply clerk-cmd-ask-incomplete))
- (cmd-ask-about (wrap-apply clerk-cmd-ask))
- (update-loop (wrap-apply clerk-act-update-loop))
- (be-summoned (wrap-apply clerk-act-be-summoned))))
-(define clerk-actions* (append clerk-actions
- thing-actions*))
-
(define-class <desk-clerk> (<thing>)
;; The desk clerk has three states:
;; - on-duty: Arrived, and waiting for instructions (and losing patience
(state #:init-value 'slacking)
(commands #:init-value clerk-commands*)
(patience #:init-value 0)
- (message-handler
- #:init-value
- (simple-dispatcher clerk-actions*)))
-
-(define-mhandler (clerk-act-init clerk message)
+ (actions #:allocation #:each-subclass
+ #:init-value (build-actions
+ (init clerk-act-init)
+ (cmd-chat clerk-cmd-chat)
+ (cmd-ask-incomplete clerk-cmd-ask-incomplete)
+ (cmd-ask-about clerk-cmd-ask)
+ (cmd-dismiss clerk-cmd-dismiss)
+ (update-loop clerk-act-update-loop)
+ (be-summoned clerk-act-be-summoned))))
+
+(define (clerk-act-init clerk message)
;; call the gameobj main init method
(gameobj-act-init clerk message)
;; start our main loop
energy particle physicist. But ya gotta pay the bills, especially
with tuition at where it is..."))
-(define-mhandler (clerk-cmd-chat clerk message)
+(define* (clerk-cmd-chat clerk message #:key direct-obj)
(match (slot-ref clerk 'state)
('on-duty
(<- clerk (message-from message) 'tell
(random-choice clerk-slacking-complaints)
"\"\n")))))
-(define-mhandler (clerk-cmd-ask-incomplete clerk message)
+(define (clerk-cmd-ask-incomplete clerk message)
(<- clerk (message-from message) 'tell
#:text "The clerk says, \"Ask about what?\"\n"))
(define clerk-doesnt-know-text
"The clerk apologizes and says she doesn't know about that topic.\n")
-(define-mhandler (clerk-cmd-ask clerk message indir-obj)
+(define* (clerk-cmd-ask clerk message #:key indir-obj
+ #:allow-other-keys)
(match (slot-ref clerk 'state)
('on-duty
(match (assoc (pk 'indir indir-obj) clerk-help-topics)
(<- clerk (message-from message) 'tell
#:text "The clerk says, \"Sorry, I'm on my break.\"\n"))))
-(define-mhandler (clerk-act-be-summoned clerk message who-summoned)
+(define* (clerk-act-be-summoned clerk message #:key who-summoned)
(match (slot-ref clerk 'state)
('on-duty
(<- clerk who-summoned 'tell
You can ask me about the following:
" clerk-knows-about ".\"\n")))))
+(define* (clerk-cmd-dismiss clerk message . _)
+ (define player-name
+ (msg-val (<-wait clerk (message-from message) 'get-name)))
+ (match (slot-ref clerk 'state)
+ ('on-duty
+ (<- clerk (gameobj-loc clerk) 'tell-room
+ #:text
+ (format #f "\"Thanks ~a!\" says the clerk. \"I have somewhere I need to be.\"
+The clerk leaves the room in a hurry.\n"
+ player-name)
+ #:exclude (actor-id clerk))
+ (gameobj-set-loc! clerk (dyn-ref clerk 'room:break-room))
+ (slot-set! clerk 'state 'slacking)
+ (<- clerk (gameobj-loc clerk) 'tell-room
+ #:text clerk-return-to-slacking-text
+ #:exclude (actor-id clerk)))
+ ('slacking
+ (<- clerk (message-from message) 'tell
+ #:text "The clerk sternly asks you to not be so dismissive.\n"))))
+
(define clerk-slacking-texts
'("The clerk takes a long drag on her cigarette.\n"
"The clerk scrolls through text messages on her phone.\n"
(define clerk-return-to-slacking-text
"The desk clerk enters and slams the door behind her.\n")
-(define-mhandler (clerk-act-update-loop clerk message)
+
+(define (clerk-act-update-loop clerk message)
(define (tell-room text)
(<- clerk (gameobj-loc clerk) 'tell-room
- #:text text))
- (define (loop return)
- (define (stop-if-destructed)
- (if (slot-ref clerk 'destructed)
- (return #f)))
- (match (slot-ref clerk 'state)
- ('slacking
- (tell-room (random-choice clerk-slacking-texts))
- (8sleep (+ (random 10) 10))
- (stop-if-destructed)
- (loop return))
- ('on-duty
- (if (> (slot-ref clerk 'patience) 0)
- ;; Keep working but lose patience gradually
- (begin
- (tell-room (random-choice clerk-working-impatience-texts))
- (slot-set! clerk 'patience (- (slot-ref clerk 'patience)
- (+ (random 2) 1)))
- (8sleep (+ (random 25) 20))
- (stop-if-destructed)
- (loop return))
- ;; Back to slacking
- (begin
- (tell-room clerk-slack-excuse-text)
- ;; back bto the break room
- (gameobj-set-loc! clerk (pk 'break-room (dyn-ref clerk 'room:break-room)))
- (tell-room clerk-return-to-slacking-text)
- ;; annnnnd back to slacking
- (slot-set! clerk 'state 'slacking)
- (8sleep (+ (random 30) 15))
- (stop-if-destructed)
- (loop return))))))
- (call/ec loop))
+ #:text text
+ #:exclude (actor-id clerk)))
+ (define (loop-if-not-destructed)
+ (if (not (slot-ref clerk 'destructed))
+ ;; This iterates by "recursing" on itself by calling itself
+ ;; (as the message handler) again. It used to be that we had to do
+ ;; this, because there was a bug where a loop which yielded like this
+ ;; would keep growing the stack due to some parameter goofiness.
+ ;; That's no longer true, but there's an added advantage to this
+ ;; route: it's much more live hackable. If we change the definition
+ ;; of this method, the character will act differently on the next
+ ;; "tick" of the loop.
+ (<- clerk (actor-id clerk) 'update-loop)))
+ (match (slot-ref clerk 'state)
+ ('slacking
+ (tell-room (random-choice clerk-slacking-texts))
+ (8sleep (+ (random 10) 10))
+ (loop-if-not-destructed))
+ ('on-duty
+ (if (> (slot-ref clerk 'patience) 0)
+ ;; Keep working but lose patience gradually
+ (begin
+ (tell-room (random-choice clerk-working-impatience-texts))
+ (slot-set! clerk 'patience (- (slot-ref clerk 'patience)
+ (+ (random 2) 1)))
+ (8sleep (+ (random 25) 20))
+ (loop-if-not-destructed))
+ ;; Back to slacking
+ (begin
+ (tell-room clerk-slack-excuse-text)
+ ;; back bto the break room
+ (gameobj-set-loc! clerk (pk 'break-room (dyn-ref clerk 'room:break-room)))
+ (tell-room clerk-return-to-slacking-text)
+ ;; annnnnd back to slacking
+ (slot-set! clerk 'state 'slacking)
+ (8sleep (+ (random 30) 15))
+ (loop-if-not-destructed))))))
+
(define break-room
(lol