(defpackage :verb-lib\r
(:use :common-lisp :if-lib :if-basic-lib)\r
(:export :attack :take :teleport :examine \r
- :go-to \r
+ :go-to :pass\r
:take :put-in :put-on :drop :receive\r
:wear :strip :enter :climb :drink :eat\r
:rub :turn :switch-on :switch-off\r
- :fill :empty :extract :let-go)\r
- (:shadow :listen :fill)\r
+ :fill :empty :extract :let-go :open :close\r
+ :lock :unlock :unlock-open)\r
+ (:shadow :listen :fill :open :close)\r
(:shadowing-import-from :if-lib :room))\r
\r
(in-package :verb-lib)\r
\r
(verb "empty" '(:noun -> empty))\r
\r
+(verb "open" \r
+ '(:noun -> open)\r
+ '(:noun "with" :held -> unlock-open))\r
\r
+(verb "close" '(:noun -> close))\r
+(verb "shut" \r
+ '(:noun -> close)\r
+ '("off" :noun -> switch-off)\r
+ '(:noun "off" -> switch-off))\r
+\r
+(verb "lock"\r
+ '(:noun "with" :held -> lock))\r
+(verb "unlock"\r
+ '(:noun "with" :held -> unlock))\r
+ \r
\r
(defaction attack (obj) "Violence is not the answer.")\r
\r
\r
(defaction go-to (dir)\r
(let ((destination (read-property *location* (property dir))))\r
- (if destination (go-to-room destination)\r
+ (if destination (exec go-to-dispatch (destination))\r
(if (provides *location* 'cant-go) \r
(read-property *location* 'cant-go)\r
"You can't go here."))))\r
\r
-;; (defaction go-n () (run-action 'go-to dir-n))\r
-;; (defaction go-ne () (run-action 'go-to dir-ne))\r
-;; (defaction go-e () (run-action 'go-to dir-e))\r
-;; (defaction go-se () (run-action 'go-to dir-se))\r
-;; (defaction go-s () (run-action 'go-to dir-s))\r
-;; (defaction go-sw () (run-action 'go-to dir-sw))\r
-;; (defaction go-w () (run-action 'go-to dir-w))\r
-;; (defaction go-nw () (run-action 'go-to dir-nw))\r
-;; (defaction go-u () (run-action 'go-to dir-u))\r
-;; (defaction go-d () (run-action 'go-to dir-d))\r
-;; (defaction go-in () (run-action 'go-to dir-in))\r
-;; (defaction go-out () (run-action 'go-to dir-out))\r
+(defgeneric go-to-dispatch (dest)\r
+ (:documentation "Dispatches between different kinds of goable objects"))\r
+\r
+(defmethod go-to-dispatch ((dest room))\r
+ (go-to-room dest))\r
+\r
+(defmethod go-to-dispatch ((dest door))\r
+ (unless (has dest :door) (return-from go-to-dispatch (call-next-method)))\r
+ (if (has dest :closed) (format nil "~a is closed." (the-name dest))\r
+ (run-action 'pass *args*)))\r
+\r
+(defaction pass (obj)\r
+ "Something's wrong happened.")\r
+\r
+(defmethod pass ((obj door))\r
+ (go-to-dispatch (read-property obj 'destination))\r
+ (run-action-after obj))\r
\r
(defun inventory ()\r
(sprint "You are carrying: ~a." (list-contents *player*))\r
"This action achieves nothing.")\r
\r
(defaction turn (what)\r
- "That's fixed in place")\r
+ "That's fixed in place.")\r
\r
(defmethod turn ((item item))\r
(if (has item :item)\r
(defmethod let-go ((host container) (item item))\r
(move item (parent host))\r
(run-action-after host))\r
+\r
+(defaction open (obj)\r
+ "You cannot open this.")\r
+\r
+(defmethod open ((obj predoor))\r
+ (unless (and (or (has obj :container) (has obj :door)) (has obj :openable))\r
+ (return-from open (call-next-method))) \r
+ (if (has obj :closed)\r
+ (if (hasnt obj :locked)\r
+ (progn \r
+ (give obj :~closed)\r
+ (when (run-action-after obj)\r
+ (format nil "You open ~a." (the-name obj))))\r
+ "It's locked.")\r
+ (format nil "~a is already open." (the-name obj))))\r
+\r
+(defaction close (obj)\r
+ "You cannot close this.")\r
+\r
+(defmethod close ((obj predoor))\r
+ (unless (and (or (has obj :container) (has obj :door)) (has obj :openable))\r
+ (return-from close (call-next-method)))\r
+ (if (hasnt obj :closed)\r
+ (progn \r
+ (give obj :closed)\r
+ (when (run-action-after obj)\r
+ (format nil "You close ~a." (the-name obj))))\r
+ (format nil "~a is already closed." (the-name obj))))\r
+\r
+(defaction lock (obj key)\r
+ "Not lockable.")\r
+\r
+(defmethod lock ((obj predoor) (key item))\r
+ (unless (and (or (has obj :container) (has obj :door)) \r
+ (has obj :openable)\r
+ (has obj :lockable))\r
+ (return-from lock (call-next-method)))\r
+ (if (has obj :locked) \r
+ (format nil "~a is already locked." (the-name obj))\r
+ (if (hasnt obj :closed)\r
+ (format nil "~a is not closed." (the-name obj))\r
+ (if (with-keys obj key)\r
+ (progn\r
+ (give obj :locked)\r
+ (when (run-action-after obj)\r
+ (format nil "You lock ~a." (the-name obj))))\r
+ (format nil "You cannot lock ~a with ~a."\r
+ (the-name obj) (the-name key))))))\r
+\r
+(defaction unlock (obj key)\r
+ "There is nothing to unlock.")\r
+\r
+(defmethod unlock ((obj predoor) (key item))\r
+ (unless (and (or (has obj :container) (has obj :door)) \r
+ (has obj :openable)\r
+ (has obj :lockable))\r
+ (return-from unlock (call-next-method)))\r
+ (if (hasnt obj :locked) \r
+ (format nil "~a is already unlocked." (the-name obj))\r
+ (if (hasnt obj :closed)\r
+ (format nil "~a is not closed." (the-name obj))\r
+ (if (with-keys obj key)\r
+ (progn\r
+ (give obj :~locked)\r
+ (when (run-action-after obj)\r
+ (format nil "You unlock ~a." (the-name obj))))\r
+ (format nil "You cannot unlock ~a with ~a."\r
+ (the-name obj) (the-name key))))))\r
+\r
+(defaction unlock-open (obj key)\r
+ "You cannot open this.")\r
+\r
+(defmethod unlock-open ((obj predoor) (key item))\r
+ (unless (and (or (has obj :container) (has obj :door)) \r
+ (has obj :openable))\r
+ (return-from unlock-open (call-next-method)))\r
+ (and (run-action 'unlock *args*)\r
+ (run-action 'open obj)))\r