From: david
Subject: oo adventure game
Date: 
Message-ID: <0c07b913-af5c-4d85-9cd1-9cb94bf68d59@u8g2000yqn.googlegroups.com>
hello! i attempt to write an adventure simulation with clos.
here is my code so far. please criticize and review my code.

(defclass thing ()
  ((name :accessor name
	 :initarg :name)
   (location :accessor location :initform nil)))

(defmethod print-object ((x thing) stream)
  (format stream "~A" (name x)))

(defclass container (thing)
  ((description :accessor description)
   (contents :accessor contents :initform nil)))

(defclass person (container)
  ((contents :accessor inventory)
   (hp   :accessor hp :initform 10)
   (weapon :accessor weapon)
   (strength :accessor strength :initform 10)))

(defun put-in-container (what where)
  (when (location what)
    (setf (contents (location what)) (delete what (contents (location
what)))))
  (setf (location what) nil)
  (pushnew what (contents where))
  (setf (location what) where))

From: Pascal J. Bourguignon
Subject: Re: oo adventure game
Date: 
Message-ID: <87ljq3iig7.fsf@galatea.local>
david <······@gmail.com> writes:

> hello! i attempt to write an adventure simulation with clos.
> here is my code so far. please criticize and review my code.
>
> (defclass thing ()
>   ((name :accessor name
> 	 :initarg :name)
>    (location :accessor location :initform nil)))
>
> (defmethod print-object ((x thing) stream)
>   (format stream "~A" (name x)))

So (make-instance 'thing) is valid,
but (print (make-instance 'thing)) will break.

If you are not prepared to test for unbound slots everywhere they're
referenced, then do provide an :initform !

Otherwise you could define a initialize-instance method and signal an
error for a missing name.


> (defun put-in-container (what where)
>   (when (location what)
>     (setf (contents (location what)) (delete what (contents (location
> what)))))
>   (setf (location what) nil)
>   (pushnew what (contents where))
>   (setf (location what) where))

In OO, the object should be able to change of location itself, and a
container should be able to add or remove contents from itself.

And there's no need to set the location to nil just to assign it to
where later.

(defgeneric remove-item (container item)    
 (:method ((self null) (item t)) self)
 (:method ((self container) (item thing))
   (setf (contents self) (delete item (contents item)))
   self))

(defgeneric add-item (container item)    
 (:method ((self null) (item t)) self)
 (:method ((self container) (item thing))
   (pushnew item (contents self))
   self))

(defmethod move-to ((self thing) (where container))
  (remove-item (location self) self)
  (setf (location self) (add-item where item))
  self)

-- 
__Pascal Bourguignon__
From: david
Subject: Re: oo adventure game
Date: 
Message-ID: <e159b7f5-8464-4260-8f08-9c825a5160aa@k8g2000yqn.googlegroups.com>
On Apr 14, 6:27 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:

> > (defclass thing ()
> >   ((name :accessor name
> >     :initarg :name)
> >    (location :accessor location :initform nil)))
>
> > (defmethod print-object ((x thing) stream)
> >   (format stream "~A" (name x)))
>
> So (make-instance 'thing) is valid,
> but (print (make-instance 'thing)) will break.

CL-USER> (let ((rock (make-instance 'thing :name "rock")))
	   (print rock))

rock
rock

do you mean the printing twice? otherwise, i do not understand
From: Pascal J. Bourguignon
Subject: Re: oo adventure game
Date: 
Message-ID: <87hc0ri104.fsf@galatea.local>
david <······@gmail.com> writes:

> On Apr 14, 6:27�am, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>> > (defclass thing ()
>> > � ((name :accessor name
>> > � � :initarg :name)
>> > � �(location :accessor location :initform nil)))
>>
>> > (defmethod print-object ((x thing) stream)
>> > � (format stream "~A" (name x)))
>>
>> So (make-instance 'thing) is valid,
>> but (print (make-instance 'thing)) will break.
>
> CL-USER> (let ((rock (make-instance 'thing :name "rock")))
> 	   (print rock))
>
> rock
> rock
>
> do you mean the printing twice? otherwise, i do not understand

I wrote the forms to test, you didn't test them.  Why?  

Do you just want to be mean to me for nothing or is the font you use
to read my article unreadable?


(prog1 :success (make-instance 'thing))
(prog1 :success (print (make-instance 'thing)))


C/USER[14]> (prog1 :success (make-instance 'thing))
:SUCCESS
C/USER[15]> (prog1 :success (print (make-instance 'thing)))



*** - SLOT-VALUE: The slot NAME of
*** - SLOT-VALUE: The slot NAME of
*** - SLOT-VALUE: The slot NAME of
*** - Unprintable error message
The following restarts are available:
*** - Unprintable error message
The following restarts are available:
*** - Unprintable error message
The following restarts are available:
*** - Unprintable error message
The following restarts are available:
*** - Unprintable error message
...


-- 
__Pascal Bourguignon__
From: david
Subject: Re: oo adventure game
Date: 
Message-ID: <02af1ab9-c015-44e7-abe6-76fce3dfea3b@v19g2000yqn.googlegroups.com>
On Apr 14, 12:44 pm, ····@informatimago.com (Pascal J. Bourguignon)
wrote:

> >> So (make-instance 'thing) is valid,
> >> but (print (make-instance 'thing)) will break.
>
> > CL-USER> (let ((rock (make-instance 'thing :name "rock")))
> >       (print rock))
>
> > rock
> > rock
>
> > do you mean the printing twice? otherwise, i do not understand
>
> I wrote the forms to test, you didn't test them.  Why?  
>
> Do you just want to be mean to me for nothing or is the font you use
> to read my article unreadable?

i tried to test them. (make-instance 'thing) make slime hang with
pipelined request.
; pipelined request... (swank:listener-eval "

i have been reading on defgeneric and :method but i can't run this
code either.

; SLIME 2009-02-27;; Compiling file /home/david/game.lisp ...
WARNING in #:|38 41 (DEFMETHOD MOVE-TO (# #) ...)-7-1-1| in lines
38..41 :
ITEM is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
;; Wrote file /home/david/game.fas
The following special variables were not defined:
 ITEM
0 errors, 1 warning

there was no defgeneric in the clos examples i studied.
i don't get the error message you did. i understand
In OO, the object should be able to change of location itself, and a
container should be able to add or remove contents from itself.

i still don't understand what is wrong with my print-object.
i do not try to be mean. i am just thick-headed noob:)
From: Pascal J. Bourguignon
Subject: Re: oo adventure game
Date: 
Message-ID: <874owqj2ym.fsf@galatea.local>
david <······@gmail.com> writes:

> On Apr 14, 12:44�pm, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>> >> So (make-instance 'thing) is valid,
>> >> but (print (make-instance 'thing)) will break.
>>
>> > CL-USER> (let ((rock (make-instance 'thing :name "rock")))
>> > � � � (print rock))
>>
>> > rock
>> > rock
>>
>> > do you mean the printing twice? otherwise, i do not understand
>>
>> I wrote the forms to test, you didn't test them. �Why? �
>>
>> Do you just want to be mean to me for nothing or is the font you use
>> to read my article unreadable?
>
> i tried to test them. (make-instance 'thing) make slime hang with
> pipelined request.
> ; pipelined request... (swank:listener-eval "

Remember, you are using a REPL, which includes a PRINT function,
therefore you didn't test my form, but my form wrapped in a PRINT!

To test them I provided in the previous message the forms to
evalate. You didn't quote them, here are they again:

(prog1 :success (make-instance 'thing))
(prog1 :success (print (make-instance 'thing)))


> i have been reading on defgeneric and :method but i can't run this
> code either.
>
> ; SLIME 2009-02-27;; Compiling file /home/david/game.lisp ...
> WARNING in #:|38 41 (DEFMETHOD MOVE-TO (# #) ...)-7-1-1| in lines
> 38..41 :
> ITEM is neither declared nor bound,
> it will be treated as if it were declared SPECIAL.
> ;; Wrote file /home/david/game.fas
> The following special variables were not defined:
>  ITEM
> 0 errors, 1 warning

Yes, there's was bug in MOVE-TO.  You have to learn to debug.   Find
the bug and correct it!  It should be easy to do, if you try to
understand what it does.  Then you'll know what to put instead of the
free variable ITEM in MOVE-TO.


> there was no defgeneric in the clos examples i studied.

Normally, when you define a method, you should before define the
generic function.  the defgeneric form allows to define some methods
at the same time.  So

(defgeneric remove-item (container item)    
 (:method ((self null) (item t)) self)
 (:method ((self container) (item thing))
   (setf (contents self) (delete item (contents item)))
   self))

is a shortcut for:

(defgeneric remove-item (container item))

(defmethod ((self null) (item t))
    self)

(defmethod ((self container) (item thing))
   (setf (contents self) (delete item (contents item)))
   self)



> i don't get the error message you did. i understand

Try the PROG1 forms given above. 


> In OO, the object should be able to change of location itself, and a
> container should be able to add or remove contents from itself.

Yes.


> i still don't understand what is wrong with my print-object.

It calls (name x) when the slot accessed by the accessor NAME might be
unbound.  (make-instance 'thing) creates an object with an unbound slot.


> i do not try to be mean. i am just thick-headed noob:)

I know, I didn't really mean it ;-)

-- 
__Pascal Bourguignon__
From: david
Subject: Re: oo adventure game
Date: 
Message-ID: <02bf76fb-a741-44e4-afab-522f895ee1db@g19g2000yql.googlegroups.com>
thanks, now i understand. i add an :initform
and get

CL-USER> (prog1 :success (print (make-instance 'thing)))

#<THING #x2047559E>
:SUCCESS

(defclass thing ()
  ((name :accessor name
	 :initarg :name :initform "unnamed thing")
   (location :accessor location :initform nil)))

i was going to write functions to make instances:

(defun make-thing (name)
  (make-instance 'thing :name name))

because i thought to add lots more slots to my classes,
and i wanted to read the rooms, persons, etc from a
file.

i will debug move-to. thanks for teaching me.
-david
From: Pascal J. Bourguignon
Subject: Re: oo adventure game
Date: 
Message-ID: <87zleigzbq.fsf@galatea.local>
david <······@gmail.com> writes:

> thanks, now i understand. i add an :initform
> and get
>
> CL-USER> (prog1 :success (print (make-instance 'thing)))
>
> #<THING #x2047559E>
> :SUCCESS
>
> (defclass thing ()
>   ((name :accessor name
> 	 :initarg :name :initform "unnamed thing")
>    (location :accessor location :initform nil)))

Good.

-- 
__Pascal Bourguignon__
From: david
Subject: Re: oo adventure game
Date: 
Message-ID: <8fcc5674-0a27-4cd6-9c9a-428c2d4b69eb@v15g2000yqn.googlegroups.com>
On Apr 14, 6:27 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:

> (defgeneric remove-item (container item)    
>  (:method ((self null) (item t)) self)
>  (:method ((self container) (item thing))
>    (setf (contents self) (delete item (contents item)))
>    self))
>
> (defgeneric add-item (container item)    
>  (:method ((self null) (item t)) self)
>  (:method ((self container) (item thing))
>    (pushnew item (contents self))
>    self))
>
> (defmethod move-to ((self thing) (where container))
>   (remove-item (location self) self)
>   (setf (location self) (add-item where self))
>   self)
>
> --
> __Pascal Bourguignon__

i have made move-to to work correctly. i have questions about
your methods. haha. anyway in this code:

(:method ((self null) (item t)) self)

we make a specializer for null containers. why do we do this?
also, how does lisp know that self is the container and not the item?
i have read in hyperspec for hours. which is always informative.
but rarely on what i was trying to look up.
From: Pascal J. Bourguignon
Subject: Re: oo adventure game
Date: 
Message-ID: <87k55mgvbe.fsf@galatea.local>
david <······@gmail.com> writes:

> On Apr 14, 6:27�am, ····@informatimago.com (Pascal J. Bourguignon)
> wrote:
>
>> (defgeneric remove-item (container item) � �
>> �(:method ((self null) (item t)) self)
>> �(:method ((self container) (item thing))
>> � �(setf (contents self) (delete item (contents item)))
>> � �self))
>>
>> (defgeneric add-item (container item) � �
>> �(:method ((self null) (item t)) self)
>> �(:method ((self container) (item thing))
>> � �(pushnew item (contents self))
>> � �self))
>>
>> (defmethod move-to ((self thing) (where container))
>> � (remove-item (location self) self)
>> � (setf (location self) (add-item where self))
>> � self)
>>
>> --
>> __Pascal Bourguignon__
>
> i have made move-to to work correctly. i have questions about
> your methods. haha. anyway in this code:
>
> (:method ((self null) (item t)) self)
>
> we make a specializer for null containers. why do we do this?

This is to avoid having to test for null locations explicitely.

When I write (remove-item (location self) self), since (location self)
can be NIL, this case is handled by the method remove-item defined on
the NULL class (which contains only the NIL object).

Here is another example:

(defgeneric length* (object)
   (:method ((object null)) 0)
   (:method ((object cons)) (1+ (length* (cdr object)))))


C/USER[25]> (dolist (test '( () (a) (a b c) (a b . c)))
              (print `(length* ,test))
              (princ " --> ")
              (prin1 (length* test)))
(LENGTH* NIL)  --> 0
(LENGTH* (A))  --> 1
(LENGTH* (A B C))  --> 3
(LENGTH* (A B . C))  --> 
*** - NO-APPLICABLE-METHOD: When calling #<STANDARD-GENERIC-FUNCTION LENGTH*>
      with arguments (C), no method is applicable.
The following restarts are available:
RETRY          :R1      try calling LENGTH* again
RETURN         :R2      specify return values
ABORT          :R3      Abort main loop
C/Break 1 USER[26]> (defmethod length* ((object t))
                      (warn "Computing the length* of a dotted list ending in ~S" object) 
                       1/2)
WARNING: The generic function #<STANDARD-GENERIC-FUNCTION LENGTH*> is being
         modified, but has already been called.
#1=#<STANDARD-METHOD (#2=#<BUILT-IN-CLASS T>)>
C/Break 1 USER[26]> :r1
WARNING: Computing the length* of a dotted list ending in C
5/2
NIL
C/USER[27]> 


> also, how does lisp know that self is the container and not the item?

By the order of the parameters.  Notice that in the case of 
(:method ((self null) (item t)) self)
the 'container', self, is actually NIL.


> i have read in hyperspec for hours. which is always informative.
> but rarely on what i was trying to look up.

You may try some of the documents referenced in:
http://www.cliki.net/Online%20Tutorial


-- 
__Pascal Bourguignon__
From: david
Subject: Re: oo adventure game
Date: 
Message-ID: <5b3dc1b5-591d-40be-b889-656553cc3c3a@b16g2000yqb.googlegroups.com>
On Apr 15, 3:44 am, ····@informatimago.com (Pascal J. Bourguignon)
wrote:

> __Pascal Bourguignon__

thank you, that is crystal clear now.
From: Timofei Shatrov
Subject: Re: oo adventure game
Date: 
Message-ID: <49ef0241.1630083315@news.motzarella.org>
On Tue, 14 Apr 2009 03:03:58 -0700 (PDT), david <······@gmail.com> tried to
confuse everyone with this message:

>hello! i attempt to write an adventure simulation with clos.
>here is my code so far. please criticize and review my code.

This reminded me of my project called LIFP [1] that I was doing a while ago. It
was an attempt to make an interactive fiction library in Common Lisp similar to
Inform 6 [2].

This is what typical code in it looked like (this is an unfinished version of
Adventure):

http://common-lisp.net/project/lifp/darcs/lifp/EXAMPLES/advent.lisp

(compare to: http://www.inform-fiction.org/examples/Advent/Advent.inf)

Of course the library itself was extremely hairy.

------
[1]:http://common-lisp.net/project/lifp/
[2]: http://en.wikipedia.org/wiki/Inform

-- 
|Don't believe this - you're not worthless              ,gr---------.ru
|It's us against millions and we can't take them all... |  ue     il   |
|But we can take them on!                               |     @ma      |
|                       (A Wilhelm Scream - The Rip)    |______________|
From: david
Subject: Re: oo adventure game
Date: 
Message-ID: <f58dc663-af28-4c7b-bfd3-4611689e3f94@r37g2000yqn.googlegroups.com>
On Apr 22, 6:57 am, ····@mail.ru (Timofei Shatrov) wrote:
> On Tue, 14 Apr 2009 03:03:58 -0700 (PDT), david <······@gmail.com> tried to
> confuse everyone with this message:
>
> >hello! i attempt to write an adventure simulation with clos.
> >here is my code so far. please criticize and review my code.
>
> This reminded me of my project called LIFP [1] that I was doing a while ago.

thanks. i have already downloaded your program. i haven't got
ltk installed yet, but its on my to-do list.