container.scm 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. ;;; Mudsync --- Live hackable MUD
  2. ;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
  3. ;;;
  4. ;;; This file is part of Mudsync.
  5. ;;;
  6. ;;; Mudsync is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or
  9. ;;; (at your option) any later version.
  10. ;;;
  11. ;;; Mudsync is distributed in the hope that it will be useful, but
  12. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. ;;; General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with Mudsync. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Containers
  19. ;;; ==========
  20. ;;;
  21. ;;; While all gameobjs are containers, some gameobjs are more
  22. ;;; containers than others.
  23. (define-module (mudsync container)
  24. #:use-module (8sync)
  25. #:use-module (oop goops)
  26. #:use-module (mudsync gameobj)
  27. #:use-module (mudsync utils)
  28. #:use-module (ice-9 control)
  29. #:export (<container>
  30. cmd-take-from cmd-put-in))
  31. (define-actor <container> (<gameobj>)
  32. ((cmd-take-from cmd-take-from)
  33. (cmd-put-in cmd-put-in))
  34. ;; Can be a boolean or a procedure accepting
  35. ;; (gameobj whos-acting take-what)
  36. (take-from-me? #:init-value #t
  37. #:init-keyword #:take-from-me?)
  38. ;; Can be a boolean or a procedure accepting
  39. ;; (gameobj whos-acting put-what)
  40. (put-in-me? #:init-value #t
  41. #:init-keyword #:put-in-me?))
  42. ;; @@: Moving this to a container subclass/mixin could allow a lot more
  43. ;; customization of take out / put in phrases
  44. (define* (cmd-take-from gameobj message
  45. #:key direct-obj indir-obj preposition
  46. (player (message-from message)))
  47. (define player-name
  48. (mbody-val (<-wait player 'get-name)))
  49. (define player-loc
  50. (mbody-val (<-wait player 'get-loc)))
  51. (define our-name (slot-ref gameobj 'name))
  52. ;; We need to check if we even have such a thing
  53. (define this-thing
  54. (call/ec
  55. (lambda (return)
  56. (for-each (lambda (occupant)
  57. (define goes-by (mbody-val (<-wait occupant 'goes-by)))
  58. (when (ci-member direct-obj goes-by)
  59. (return occupant)))
  60. (gameobj-occupants gameobj))
  61. ;; nothing found
  62. #f)))
  63. (define (this-thing-name)
  64. (mbody-val (<-wait this-thing 'get-name)))
  65. (define (should-take-from-me)
  66. (and this-thing
  67. (slot-ref-maybe-runcheck gameobj 'take-from-me? player this-thing)))
  68. (define (default-objection)
  69. `("Unfortunately, it doesn't seem like you can take "
  70. ,(this-thing-name) " " ,preposition " " ,our-name "."))
  71. (define (this-thing-objection)
  72. (mbody-receive (_ taken-ok? #:key why-not) ; does the object object to being removed?
  73. (<-wait this-thing 'ok-to-be-taken-from? player) ; @@ no need to supply from where
  74. (and (not taken-ok?)
  75. ;; Either give the specified reason, or give a boilerplate one
  76. (or why-not
  77. (default-objection)))))
  78. (cond
  79. ;; Unfortunately this does leak information about what is contained
  80. ;; by us. Maybe not what's wanted in all circumstances.
  81. ((not this-thing)
  82. (<- player 'tell
  83. #:text `("You don't see any such " ,direct-obj " to take "
  84. ,preposition " " ,our-name ".")))
  85. ;; A particular objection to taking this thing.
  86. ;; We should allow customizing the reason here, which could be
  87. ;; provided by the 'ok-to-be-taken-from? slot.
  88. ((not (should-take-from-me))
  89. (<- player 'tell
  90. #:text (default-objection)))
  91. ;; the thing we wsant to take itself has objected...
  92. ((this-thing-objection) =>
  93. (lambda (objection)
  94. (<- player 'tell
  95. #:text objection)))
  96. ;; looks like we can take it
  97. (else
  98. ;; Wait to announce to the player just in case settting the location
  99. ;; errors out or something. Maybe it's overthinking things, I dunno.
  100. (<-wait this-thing 'set-loc! #:loc player)
  101. (<- player 'tell
  102. #:text `("You take " ,(this-thing-name) " from "
  103. ,our-name "."))
  104. (<- player-loc 'tell-room
  105. #:text `(,player-name " takes " ,(this-thing-name) " from "
  106. ,our-name ".")
  107. #:exclude player))))
  108. (define* (cmd-put-in gameobj message
  109. #:key direct-obj indir-obj preposition
  110. (player (message-from message)))
  111. (define player-name
  112. (mbody-val (<-wait player 'get-name)))
  113. (define player-loc
  114. (mbody-val (<-wait player 'get-loc)))
  115. (define our-name (slot-ref gameobj 'name))
  116. ;; We need to check if we even have such a thing
  117. (define this-thing
  118. (call/ec
  119. (lambda (return)
  120. (for-each (lambda (occupant)
  121. (define goes-by (mbody-val (<-wait occupant 'goes-by)))
  122. (when (ci-member direct-obj goes-by)
  123. (return occupant)))
  124. (mbody-val (<-wait player 'get-occupants)))
  125. ;; nothing found
  126. #f)))
  127. (define (this-thing-name)
  128. (mbody-val (<-wait this-thing 'get-name)))
  129. (define (should-put-in-me)
  130. (and this-thing
  131. (slot-ref-maybe-runcheck gameobj 'put-in-me? player this-thing)))
  132. (define (default-objection)
  133. `("As much as you'd like to, it doesn't seem like you can put "
  134. ,(this-thing-name) " " ,preposition " " ,our-name "."))
  135. (define (this-thing-objection)
  136. (mbody-receive (_ put-in-ok? #:key why-not) ; does the object object to being moved?
  137. (<-wait this-thing 'ok-to-be-put-in? player (actor-id gameobj))
  138. (and (not put-in-ok?)
  139. ;; Either give the specified reason, or give a boilerplate one
  140. (or why-not (default-objection)))))
  141. (cond
  142. ;; Is it not there, or maybe we won't allow it to be taken?
  143. ((not this-thing)
  144. (<- player 'tell
  145. #:text `("You don't seem to have any such " ,direct-obj " to put "
  146. ,preposition " " ,our-name ".")))
  147. ((or (not (should-put-in-me)))
  148. (<- player 'tell
  149. #:text (default-objection)))
  150. ;; the thing we wsant to take itself has objected...
  151. ((this-thing-objection) =>
  152. (lambda (objection)
  153. (<- player 'tell
  154. #:text objection)))
  155. ;; looks like we can take it
  156. (else
  157. ;; Wait to announce to the player just in case settting the location
  158. ;; errors out or something. Maybe it's overthinking things, I dunno.
  159. (<-wait this-thing 'set-loc! #:loc (actor-id gameobj))
  160. (<- player 'tell
  161. #:text `("You put " ,(this-thing-name) " " ,preposition " "
  162. ,our-name "."))
  163. (<- player-loc 'tell-room
  164. #:text `(,player-name " puts " ,(this-thing-name) " " ,preposition " "
  165. ,our-name ".")
  166. #:exclude player))))