Rename call of start-agenda to run-agenda
[mudsync.git] / mudsync / player.scm
index 63af65e77a8f84071f5780cfd486f6a5fb183717..e3ae2ba8ffcee53cea6cef848d72216e5a74fbc4 100644 (file)
@@ -21,7 +21,7 @@
   #: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 (ice-9 control)
   #:use-module (ice-9 format)
 ;;; Players
 ;;; =======
 
-(define player-actions
-  (build-actions
-   (init (wrap-apply player-init!))
-   (handle-input (wrap-apply player-handle-input))))
-
-(define player-actions*
-  (append player-actions
-          gameobj-actions))
-
-(define player-dispatcher
-  (simple-dispatcher player-actions*))
+(define player-self-commands
+  (list
+   (empty-command "inventory" 'cmd-inventory)
+   ;; aliases...
+   ;; @@: Should use an "alias" system for common aliases?
+   (empty-command "inv" 'cmd-inventory)
+   (empty-command "i" 'cmd-inventory)))
 
 (define-class <player> (<gameobj>)
   (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 #:init-value player-self-commands)
 
-  (message-handler
-   #:init-value
-   ;; @@: We're gonna need action inheritance real awful soon, huh?
-   (wrap-apply player-dispatcher)))
+  (actions #:allocation #:each-subclass
+           #:init-value
+           (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))))
 
 
 ;;; 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
+  (<- player (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 <- player winner-id cmd-action message-args))
     (#f
      (<- player (gameobj-gm player) 'write-home
          #:text "Huh?\n"))))
 
-
-;;; 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-tell player message #:key text)
+  (<- player (gameobj-gm player) 'write-home
+      #:text 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
+    (<- player 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)
+       (msg-val (<-wait player inv-item 'get-name)))
+     (gameobj-occupants player)))
+  (define text-to-show
+    (if (eq? inv-names '())
+        "You aren't carrying anything.\n"
+        (apply string-append
+               "You are carrying:\n"
+               (map (lambda (item-name)
+                      (string-append "  * " item-name "\n"))
+                    inv-names))))
+  (<- player (actor-id player) 'tell #:text text-to-show))
 
 
 ;;; Command handling
   ;; Ask the room for its commands
   (define room-commands
     ;; TODO: Map room id and sort
-    (message-ref
-     (<-wait player player-loc
+    (msg-receive (_ #:key commands)
+        (<-wait player player-loc
              'get-container-commands
              #:verb verb)
-     'commands))
+      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)))
+     (msg-receive (_ #:key occupants)
+         (<-wait player player-loc 'get-occupants)
+       occupants)))
 
   ;; @@: There's a race condition here if someone leaves the room
   ;;   during this, heh...
 
   ;; 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)
+       (msg-receive (_ #:key commands goes-by)
+           (<-wait player 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
+    (filter
+     (lambda (cmd)
+       (equal? (command-verbs cmd) verb))
+     (val-or-run
+      (slot-ref player 'self-commands))))
+
+  ;; Append our inventory's relevant command handlers
+  (define inv-items
+    (gameobj-occupants player))
+  (define inv-item-commands
+    (fold
+     (lambda (inv-item prev)
+       (msg-receive (_ #:key commands goes-by)
+           (<-wait player 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-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)))
 
 (define (sort-commands-append-actor commands actor-id goes-by)
   (sort-commands-multi-actors
   (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)
                            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)))