Port to the remove-define-mhandler 8sync branch
[mudsync.git] / mudsync / gameobj.scm
index ec95e2c9f6278fe57ba840affc0cc7d3a10d9b7d..8b1040fbcaee86df2aab20369c0ecd6db7486f79 100644 (file)
@@ -24,6 +24,7 @@
   #:use-module (8sync systems actors)
   #:use-module (8sync agenda)
   #:use-module (srfi srfi-1)
   #:use-module (8sync systems actors)
   #:use-module (8sync agenda)
   #:use-module (srfi srfi-1)
+  #:use-module (ice-9 format)
   #:use-module (ice-9 match)
   #:use-module (oop goops)
   #:export (<gameobj>
   #:use-module (ice-9 match)
   #:use-module (oop goops)
   #:export (<gameobj>
             gameobj-loc
             gameobj-gm
 
             gameobj-loc
             gameobj-gm
 
+            gameobj-act-init
+            gameobj-set-loc!
             gameobj-occupants
             gameobj-actions
             gameobj-self-destruct
 
             gameobj-occupants
             gameobj-actions
             gameobj-self-destruct
 
+            slot-ref-maybe-runcheck
+            val-or-run
+
             dyn-ref))
 
 ;;; Gameobj
             dyn-ref))
 
 ;;; Gameobj
 ;;; Actions supported by all gameobj
 (define gameobj-actions
   (build-actions
 ;;; Actions supported by all gameobj
 (define gameobj-actions
   (build-actions
-   (init (wrap-apply gameobj-init))
+   (init (wrap-apply gameobj-act-init))
+   ;; Commands for co-occupants
    (get-commands (wrap-apply gameobj-get-commands))
    (get-commands (wrap-apply gameobj-get-commands))
+   ;; Commands for participants in a room
    (get-container-commands (wrap-apply gameobj-get-container-commands))
    (get-container-commands (wrap-apply gameobj-get-container-commands))
+   ;; Commands for inventory items, etc (occupants of the gameobj commanding)
+   (get-contained-commands (wrap-apply gameobj-get-contained-commands))
    (get-occupants (wrap-apply gameobj-get-occupants))
    (add-occupant! (wrap-apply gameobj-add-occupant!))
    (remove-occupant! (wrap-apply gameobj-remove-occupant!))
    (get-occupants (wrap-apply gameobj-get-occupants))
    (add-occupant! (wrap-apply gameobj-add-occupant!))
    (remove-occupant! (wrap-apply gameobj-remove-occupant!))
+   (get-loc (wrap-apply gameobj-act-get-loc))
    (set-loc! (wrap-apply gameobj-act-set-loc!))
    (get-name (wrap-apply gameobj-get-name))
    (set-name! (wrap-apply gameobj-act-set-name!))
    (set-loc! (wrap-apply gameobj-act-set-loc!))
    (get-name (wrap-apply gameobj-get-name))
    (set-name! (wrap-apply gameobj-act-set-name!))
 
   ;; Commands we can handle by being something's container
   (container-commands #:init-value '())
 
   ;; Commands we can handle by being something's container
   (container-commands #:init-value '())
+
+  ;; Commands we can handle by being contained by something else
+  (contained-commands #:init-value '())
+
   (message-handler
    #:init-value
    (simple-dispatcher gameobj-actions))
   (message-handler
    #:init-value
    (simple-dispatcher gameobj-actions))
   ;; @@: Would be preferable to be using generic methods for this...
   ;;   Hopefully we can port this to Guile 2.2 soon...
   (visible-to-player?
   ;; @@: Would be preferable to be using generic methods for this...
   ;;   Hopefully we can port this to Guile 2.2 soon...
   (visible-to-player?
-   #:init-value (wrap-apply gameobj-visible-to-player?)))
+   #:init-value (wrap-apply gameobj-visible-to-player?))
+
+  ;; Set this on self-destruct
+  ;; (checked by some "long running" game routines)
+  (destructed #:init-value #f))
 
 
 ;;; gameobj message handlers
 
 
 ;;; gameobj message handlers
 ;; Kind of a useful utility, maybe?
 (define (simple-slot-getter slot)
   (lambda (actor message)
 ;; Kind of a useful utility, maybe?
 (define (simple-slot-getter slot)
   (lambda (actor message)
-    (reply-message actor message
+    (<-reply actor message
                    #:val (slot-ref actor slot))))
 
                    #:val (slot-ref actor slot))))
 
-
-(define (gameobj-replace-step-occupants actor replace-reply)
-  (define occupants
-    (message-ref replace-reply 'occupants #f))
+(define (gameobj-replace-step-occupants actor occupants)
   ;; Snarf all the occupants!
   (display "replacing occupant\n")
   (when occupants
   ;; Snarf all the occupants!
   (display "replacing occupant\n")
   (when occupants
 (define gameobj-replace-steps*
   (list gameobj-replace-step-occupants))
 
 (define gameobj-replace-steps*
   (list gameobj-replace-step-occupants))
 
-(define (run-replacement actor message replace-steps)
-  (define replaces (message-ref message 'replace #f))
+(define (run-replacement actor replaces replace-steps)
   (when replaces
   (when replaces
-    (let ((replace-reply
-           (<-wait actor replaces 'assist-replace)))
+    (msg-receive (_ #:key occupants)
+        (<-wait actor replaces 'assist-replace)
       (for-each
        (lambda (replace-step)
       (for-each
        (lambda (replace-step)
-         (replace-step actor replace-reply))
+         (replace-step actor occupants))
        replace-steps))))
 
        replace-steps))))
 
-;; @@: This could be kind of a messy way of doing gameobj-init
+;; @@: This could be kind of a messy way of doing gameobj-act-init
 ;;   stuff.  If only we had generic methods :(
 ;;   stuff.  If only we had generic methods :(
-(define-mhandler (gameobj-init actor message)
+(define* (gameobj-act-init actor message #:key replace)
   "Your most basic game object init procedure.
 Assists in its replacement of occupants if necessary and nothing else."
   "Your most basic game object init procedure.
 Assists in its replacement of occupants if necessary and nothing else."
-  (display "gameobj init!\n")
-  (run-replacement actor message gameobj-replace-steps*))
+  (run-replacement actor replace gameobj-replace-steps*))
 
 (define (gameobj-goes-by gameobj)
   "Find the name we go by.  Defaults to #:name if nothing else provided."
 
 (define (gameobj-goes-by gameobj)
   "Find the name we go by.  Defaults to #:name if nothing else provided."
@@ -172,7 +186,7 @@ Assists in its replacement of occupants if necessary and nothing else."
              verb))
    commands))
 
              verb))
    commands))
 
-(define-mhandler (gameobj-get-commands actor message verb)
+(define* (gameobj-get-commands actor message #:key verb)
   "Get commands a co-occupant of the room might execute for VERB"
   (define filtered-commands
     (filter-commands (val-or-run (slot-ref actor 'commands))
   "Get commands a co-occupant of the room might execute for VERB"
   (define filtered-commands
     (filter-commands (val-or-run (slot-ref actor 'commands))
@@ -181,19 +195,28 @@ Assists in its replacement of occupants if necessary and nothing else."
            #:commands filtered-commands
            #:goes-by (gameobj-goes-by actor)))
 
            #:commands filtered-commands
            #:goes-by (gameobj-goes-by actor)))
 
-(define-mhandler (gameobj-get-container-commands actor message verb)
+(define* (gameobj-get-container-commands actor message #:key verb)
   "Get commands as the container / room of message's sender"
   (define filtered-commands
     (filter-commands (val-or-run (slot-ref actor 'container-commands))
                      verb))
   (<-reply actor message #:commands filtered-commands))
 
   "Get commands as the container / room of message's sender"
   (define filtered-commands
     (filter-commands (val-or-run (slot-ref actor 'container-commands))
                      verb))
   (<-reply actor message #:commands filtered-commands))
 
-(define-mhandler (gameobj-add-occupant! actor message who)
+(define* (gameobj-get-contained-commands actor message #:key verb)
+  "Get commands as being contained (eg inventory) of commanding gameobj"
+  (define filtered-commands
+    (filter-commands (val-or-run (slot-ref actor 'contained-commands))
+                     verb))
+  (<-reply actor message
+           #:commands filtered-commands
+           #:goes-by (gameobj-goes-by actor)))
+
+(define* (gameobj-add-occupant! actor message #:key who)
   "Add an actor to our list of present occupants"
   (hash-set! (slot-ref actor 'occupants)
              who #t))
 
   "Add an actor to our list of present occupants"
   (hash-set! (slot-ref actor 'occupants)
              who #t))
 
-(define-mhandler (gameobj-remove-occupant! actor message who)
+(define* (gameobj-remove-occupant! actor message #:key who)
   "Remove an occupant from the room."
   (hash-remove! (slot-ref actor 'occupants) who))
 
   "Remove an occupant from the room."
   (hash-remove! (slot-ref actor 'occupants) who))
 
@@ -217,39 +240,51 @@ Assists in its replacement of occupants if necessary and nothing else."
    '()
    (slot-ref gameobj 'occupants)))
 
    '()
    (slot-ref gameobj 'occupants)))
 
-(define-mhandler (gameobj-get-occupants actor message)
+(define* (gameobj-get-occupants actor message #:key exclude)
   "Get all present occupants of the room."
   "Get all present occupants of the room."
-  (define exclude (message-ref message 'exclude #f))
   (define occupants
     (gameobj-occupants actor #:exclude exclude))
 
   (<-reply actor message
            #:occupants occupants))
 
   (define occupants
     (gameobj-occupants actor #:exclude exclude))
 
   (<-reply actor message
            #:occupants occupants))
 
+(define (gameobj-act-get-loc actor message)
+  (<-reply actor message
+           #:val (slot-ref actor 'loc)))
+
 (define (gameobj-set-loc! gameobj loc)
   "Set the location of this object."
   (define old-loc (gameobj-loc gameobj))
   (format #t "DEBUG: Location set to ~s for ~s\n"
           loc (actor-id-actor gameobj))
 
 (define (gameobj-set-loc! gameobj loc)
   "Set the location of this object."
   (define old-loc (gameobj-loc gameobj))
   (format #t "DEBUG: Location set to ~s for ~s\n"
           loc (actor-id-actor gameobj))
 
-  (slot-set! gameobj 'loc loc)
-  ;; Change registation of where we currently are
-  (if loc
-      (<-wait gameobj loc 'add-occupant! #:who (actor-id gameobj)))
-  (if old-loc
-      (<-wait gameobj old-loc 'remove-occupant! #:who (actor-id gameobj))))
+  (when (not (equal? old-loc loc))
+    (slot-set! gameobj 'loc loc)
+    ;; Change registation of where we currently are
+    (if old-loc
+        (<-wait gameobj old-loc 'remove-occupant! #:who (actor-id gameobj)))
+    (if loc
+        (<-wait gameobj loc 'add-occupant! #:who (actor-id gameobj)))))
 
 ;; @@: Should it really be #:id ?  Maybe #:loc-id or #:loc?
 
 ;; @@: Should it really be #:id ?  Maybe #:loc-id or #:loc?
-(define-mhandler (gameobj-act-set-loc! actor message loc)
+(define* (gameobj-act-set-loc! actor message #:key loc)
   "Action routine to set the location."
   (gameobj-set-loc! actor loc))
 
   "Action routine to set the location."
   (gameobj-set-loc! actor loc))
 
+(define (slot-ref-maybe-runcheck gameobj slot whos-asking)
+  "Do a slot-ref on gameobj, evaluating it including ourselves
+and whos-asking, and see if we should just return it or run it."
+  (match (slot-ref gameobj slot)
+    ((? procedure? slot-val-proc)
+     (slot-val-proc gameobj whos-asking))
+    (anything-else anything-else)))
+
 (define gameobj-get-name (simple-slot-getter 'name))
 
 (define gameobj-get-name (simple-slot-getter 'name))
 
-(define-mhandler (gameobj-act-set-name! actor message val)
+(define* (gameobj-act-set-name! actor message #:key val)
   (slot-set! actor 'name val))
 
   (slot-set! actor 'name val))
 
-(define-mhandler (gameobj-get-desc actor message whos-looking)
+(define* (gameobj-get-desc actor message #:key whos-looking)
   (define desc-text
     (match (slot-ref actor 'desc)
       ((? procedure? desc-proc)
   (define desc-text
     (match (slot-ref actor 'desc)
       ((? procedure? desc-proc)
@@ -262,7 +297,7 @@ Assists in its replacement of occupants if necessary and nothing else."
 By default, this is whether or not the generally-visible flag is set."
   (slot-ref gameobj 'generally-visible))
 
 By default, this is whether or not the generally-visible flag is set."
   (slot-ref gameobj 'generally-visible))
 
-(define-mhandler (gameobj-visible-name actor message whos-looking)
+(define* (gameobj-visible-name actor message #:key whos-looking)
   ;; Are we visible?
   (define we-are-visible
     ((slot-ref actor 'visible-to-player?) actor whos-looking))
   ;; Are we visible?
   (define we-are-visible
     ((slot-ref actor 'visible-to-player?) actor whos-looking))
@@ -283,10 +318,11 @@ By default, this is whether or not the generally-visible flag is set."
   "General gameobj self destruction routine"
   ;; Unregister from being in any particular room
   (gameobj-set-loc! gameobj #f)
   "General gameobj self destruction routine"
   ;; Unregister from being in any particular room
   (gameobj-set-loc! gameobj #f)
+  (slot-set! gameobj 'destructed #t)
   ;; Boom!
   (self-destruct gameobj))
 
   ;; Boom!
   (self-destruct gameobj))
 
-(define-mhandler (gameobj-act-self-destruct gameobj message)
+(define (gameobj-act-self-destruct gameobj message)
   "Action routine for self destruction"
   (gameobj-self-destruct gameobj))
 
   "Action routine for self destruction"
   (gameobj-self-destruct gameobj))
 
@@ -320,11 +356,11 @@ By default, this is whether or not the generally-visible flag is set."
   (match special-symbol
     ;; if it's a symbol, look it up dynamically
     ((? symbol? _)
   (match special-symbol
     ;; if it's a symbol, look it up dynamically
     ((? symbol? _)
-     (message-ref
-      (<-wait gameobj (slot-ref gameobj 'gm) 'lookup-special
-              #:symbol special-symbol)
-      'val))
+     (msg-receive (_ #:key val)
+         (<-wait gameobj (slot-ref gameobj 'gm) 'lookup-special
+                 #:symbol special-symbol)
+       val))
     ;; if it's false, return nothing
     ;; if it's false, return nothing
-    ((#f #f))
+    (#f #f)
     ;; otherwise it's probably an address, return it as-is
     (_ special-symbol)))
     ;; otherwise it's probably an address, return it as-is
     (_ special-symbol)))