X-Git-Url: https://jxself.org/git/?p=mudsync.git;a=blobdiff_plain;f=mudsync%2Fplayer.scm;h=78d9a01574efbed2f113f8e9f18fbd1d1e53cf63;hp=bf19a16a6b0e1a0a4716f70333cddaec2a757b8e;hb=f22e3b3e60031ebb8ef6260692bf8c03dcce1c60;hpb=4738c5ae39e26b65cdba3bec005bfe034c4ea2c2 diff --git a/mudsync/player.scm b/mudsync/player.scm index bf19a16..78d9a01 100644 --- a/mudsync/player.scm +++ b/mudsync/player.scm @@ -21,99 +21,116 @@ #:use-module (mudsync gameobj) #:use-module (mudsync game-master) #:use-module (mudsync parser) - #:use-module (8sync systems actors) + #:use-module (8sync actors) #:use-module (8sync agenda) + #:use-module (8sync rmeta-slot) #:use-module (ice-9 control) #:use-module (ice-9 format) #:use-module (ice-9 match) #:use-module (oop goops) #:use-module (srfi srfi-1) #:use-module (srfi srfi-9) - #:export ( - player-self-commands)) + #:export ()) ;;; Players ;;; ======= -(define player-actions - (build-actions - (init (wrap-apply player-init!)) - (handle-input (wrap-apply player-handle-input)) - (tell (wrap-apply player-tell)) - ;; @@: We really need to unify / make sensible this look stuff - (look-room (wrap-apply player-look-room)))) - -(define player-actions* - (append player-actions - gameobj-actions)) - -(define player-dispatcher - (simple-dispatcher player-actions*)) - (define-class () (username #:init-keyword #:username - #:accessor player-username) - ;; Connection id - (client #:accessor player-client) + #:getter player-username) - (self-commands - #:init-value '() - #:accessor player-self-commands) + (self-commands #:allocation #:each-subclass + #:init-thunk + (build-commands + (("inventory" "inv" "i") ((empty-command cmd-inventory))) + ("help" ((empty-command cmd-help))))) - (message-handler - #:init-value - ;; @@: We're gonna need action inheritance real awful soon, huh? - (wrap-apply player-dispatcher))) + (actions #:allocation #:each-subclass + #:init-thunk + (build-actions + (init player-init) + (handle-input player-handle-input) + (tell player-tell) + (disconnect-self-destruct player-disconnect-self-destruct) + (cmd-inventory player-cmd-inventory) + (cmd-help player-cmd-help)))) ;;; player message handlers -(define-mhandler (player-init! player message) - (player-look-around player)) +(define (player-init player message) + ;; Look around the room we're in + (<- (gameobj-loc player) 'look-room)) -(define-mhandler (player-handle-input player message input) +(define* (player-handle-input player message #:key input) (define split-input (split-verb-and-rest input)) - (define input-verb (pk 'input-verb (car split-input))) - (define input-rest (pk 'input-rest (cdr split-input))) + (define input-verb (car split-input)) + (define input-rest (cdr split-input)) (define command-candidates - (pk 'candidates - (player-gather-command-handlers player input-verb))) + (player-gather-command-handlers player input-verb)) (define winner - (pk 'winner (find-command-winner command-candidates input-rest))) + (find-command-winner command-candidates input-rest)) (match winner ((cmd-action winner-id message-args) - (apply send-message player (pk 'winner-id winner-id) (pk 'cmd-action cmd-action) (pk 'message-args message-args))) + (apply <- winner-id cmd-action message-args)) (#f - (<- player (gameobj-gm player) 'write-home - #:text "Huh?\n")))) + (<- (gameobj-gm player) 'write-home + #:text "Sorry, I didn't understand that? (type \"help\" for common commands)\n")))) -(define-mhandler (player-tell player message text) - (<- player (gameobj-gm player) 'write-home +(define* (player-tell player message #:key text) + (<- (gameobj-gm player) 'write-home #:text text)) -(define-mhandler (player-look-room player message) - (player-look-around player)) - - -;;; player methods - -(define (player-look-around player) - (define room-name - (message-ref - (<-wait player (gameobj-loc player) 'get-name) - 'val)) - (define room-desc - (message-ref - (<-wait player (gameobj-loc player) 'get-desc) - 'val)) - (define message-text - (format #f "**~a**\n~a\n" room-name room-desc)) - - (<- player (gameobj-gm player) 'write-home #:text message-text)) +(define (player-disconnect-self-destruct player message) + "Action routine for being told to disconnect and self destruct." + (define loc (gameobj-loc player)) + (when loc + (<- loc 'tell-room + #:exclude (actor-id player) + #:text (format #f "~a disappears in a puff of entropy!\n" + (slot-ref player 'name)))) + (gameobj-self-destruct player)) + +(define (player-cmd-inventory player message) + "Display the inventory for the player" + (define inv-names + (map + (lambda (inv-item) + (mbody-val (<-wait inv-item 'get-name))) + (gameobj-occupants player))) + (define text-to-show + (if (eq? inv-names '()) + "You aren't carrying anything.\n" + `((p "You are carrying:") + (ul ,(map (lambda (item-name) + `(li ,item-name)) + inv-names))))) + (<- (actor-id player) 'tell #:text text-to-show)) + +(define (player-cmd-help player message) + (<- (actor-id player) 'tell + #:text '((strong "** Mudsync Help **")(br) + (p "You're playing Mudsync, a multiplayer text-adventure. " + "Type different commands to interact with your surroundings " + "and other players.") + (p "Some common commands:" + (ul (li (strong "say ") " -- " + "Chat with other players in the same room. " + "(Also aliased to the " (b "\"") " character.)") + (li (strong "look") " -- " + "Look around the room you're in.") + (li (strong "look [at] ") " -- " + "Examine a particular object.") + (li (strong "go ") " -- " + "Move to another room in direction."))) + (p "Different objects can be interacted with in different ways. " + "For example, if there's a bell in the same room as you, " + "you might try typing " (em "ring bell") + " and see what happens.")))) ;;; Command handling @@ -131,21 +148,25 @@ #:player-id (actor-id player))))) ;; Ask the room for its commands - (define room-commands + (define room-dom-commands + ;; TODO: Map room id and sort + (mbody-receive (_ #:key commands) + (<-wait player-loc 'get-container-dom-commands + #:verb verb) + commands)) + + (define room-sub-commands ;; TODO: Map room id and sort - (message-ref - (<-wait player player-loc - 'get-container-commands - #:verb verb) - 'commands)) + (mbody-receive (_ #:key commands) + (<-wait player-loc 'get-container-sub-commands + #:verb verb) + commands)) ;; All the co-occupants of the room (not including ourself) (define co-occupants (remove (lambda (x) (equal? x (actor-id player))) - (message-ref - (<-wait player player-loc 'get-occupants) - 'occupants))) + (mbody-val (<-wait player-loc 'get-occupants)))) ;; @@: There's a race condition here if someone leaves the room ;; during this, heh... @@ -154,31 +175,51 @@ ;; Get all the co-occupants' commands (define co-occupant-commands - ;; TODO: Switch this to a fold. Ignore a result if it - ;; returns false for in the command response - (map - (lambda (co-occupant) - (let ((result (<-wait player co-occupant 'get-commands - #:verb verb))) - (list - (message-ref result 'commands) - (message-ref result 'goes-by) - co-occupant))) + (fold + (lambda (co-occupant prev) + (mbody-receive (_ #:key commands goes-by) + (<-wait co-occupant 'get-commands + #:verb verb) + (append + (map (lambda (command) + (list command goes-by co-occupant)) + commands) + prev))) + '() co-occupants)) ;; Append our own command handlers (define our-commands - (player-self-commands player)) - - ;; TODO: Append our inventory's relevant command handlers + (class-rmeta-ref (class-of player) 'self-commands verb + #:dflt '())) + + ;; Append our inventory's relevant command handlers + (define inv-items + (gameobj-occupants player)) + (define inv-item-commands + (fold + (lambda (inv-item prev) + (mbody-receive (_ #:key commands goes-by) + (<-wait inv-item 'get-contained-commands + #:verb verb) + (append + (map (lambda (command) + (list command goes-by inv-item)) + commands) + prev))) + '() + inv-items)) ;; Now return a big ol sorted list of ((actor-id . command)) (append - (sort-commands-append-actor (pk 'room-commands room-commands) + (sort-commands-append-actor room-dom-commands player-loc '()) ; room doesn't go by anything (sort-commands-multi-actors co-occupant-commands) (sort-commands-append-actor our-commands - (actor-id player) '()))) ; nor does player + (actor-id player) '()) ; nor does player + (sort-commands-multi-actors inv-item-commands) + (sort-commands-append-actor room-sub-commands + player-loc '()))) (define (sort-commands-append-actor commands actor-id goes-by) (sort-commands-multi-actors @@ -188,14 +229,14 @@ (sort actors-and-commands (lambda (x y) - (> (command-priority (car (pk 'x x))) - (command-priority (car (pk 'y y))))))) + (> (command-priority (car x)) + (command-priority (car y)))))) (define (find-command-winner sorted-candidates line) "Find a command winner from a sorted list of candidates" ;; A cache of results from matchers we've already seen - ;; TODO: fill this in + ;; TODO: fill in this cache. This is a *critical* optimization! (define matcher-cache '()) (call/ec (lambda (return) @@ -211,7 +252,7 @@ actor-goes-by matched)) ; matched is kwargs if truthy (return (list (command-action command) - (pk 'earlier-actor-id actor-id) matched)) + actor-id matched)) #f)))) sorted-candidates) #f)))