On Oct 2, 2005, at 8:35 AM, Jim Menard wrote: > Boy, was this fun. My solution, RADS, is at > <http://www.io.com/~jimm/rubyquiz/quiz49/>. That is beyond awesome! I've been reading the PAWS source thinking of porting it, but you have a very interesting start here. My solution is below. Again, I took the direct approach of a line for line translation. So, in my code you will see the Lisp, followed by my Ruby translation. It was interesting making lines like: > walk east work in irb. It even came out cleaner than the Lisp version of "(walk east)". Enjoy. James Edward Gray II (setf *objects* '(whiskey-bottle bucket frog chain)) ### ^ Lisp >>> Ruby v ### $objects = %w{whiskey_bottle bucket frog chain} (setf *map* '((living-room (you are in the living-room of a wizards house. there is a wizard snoring loudly on the couch.) (west door garden) (upstairs stairway attic)) (garden (you are in a beautiful garden. there is a well in front of you.) (east door living-room)) (attic (you are in the attic of the wizards house. there is a giant welding torch in the corner.) (downstairs stairway living-room)))) ### ^ Lisp >>> Ruby v ### $map = { "living_room" => [ "You are in the living_room of a wizard's house. There is a wizard snoring loudly on the couch.", %w{west door garden}, %w{upstairs stairway attic} ], "garden" => [ "You are in a beautiful garden. There is a well in front of you.", %w{east door living_room} ], "attic" => [ "You are in the attic of the wizard's house. There is a giant welding torch in the corner.", %w{downstairs stairway living_room} ] } (setf *object-locations* '((whiskey-bottle living-room) (bucket living-room) (chain garden) (frog garden))) ### ^ Lisp >>> Ruby v ### $object_locations = { "whiskey_bottle" => "living_room", "bucket" => "living_room", "chain" => "garden", "frog" => "garden" } (setf *location* 'living-room) ### ^ Lisp >>> Ruby v ### $location = "living_room" (defun describe-location (location map) (second (assoc location map))) ### ^ Lisp >>> Ruby v ### def describe_location( location, map ) map[location].first end (describe-location 'living-room *map*) ### ^ Lisp >>> Ruby v ### describe_location "living_room", $map (defun describe-path (path) `(there is a ,(second path) going ,(first path) from here.)) ### ^ Lisp >>> Ruby v ### def describe_path( path ) "There is a #{path[1]} going #{path[0]} from here." end (describe-path '(west door garden)) ### ^ Lisp >>> Ruby v ### describe_path %w{west door garden} (defun describe-paths (location map) (apply #'append (mapcar #'describe-path (cddr (assoc location map))))) ### ^ Lisp >>> Ruby v ### def describe_paths( location, map ) map[location][1..-1].map { |p| describe_path(p) }.join(" ") end (describe-paths 'living-room *map*) ### ^ Lisp >>> Ruby v ### describe_paths "living_room", $map (defun is-at (obj loc obj-loc) (eq (second (assoc obj obj-loc)) loc)) ### ^ Lisp >>> Ruby v ### def is_at?( object, location, object_locations ) location == object_locations[object] end (is-at 'whiskey-bottle 'living-room *object-locations*) ### ^ Lisp >>> Ruby v ### is_at? "whiskey_bottle", "living_room", $object_locations (defun describe-floor (loc objs obj-loc) (apply #'append (mapcar (lambda (x) `(you see a ,x on the floor.)) (remove-if-not (lambda (x) (is-at x loc obj-loc)) objs)))) ### ^ Lisp >>> Ruby v ### def describe_floor( location, object_locations ) object_locations.select { |obj, loc| loc == location }.map do | obj, loc| "You see a #{obj} on the floor." end.join(" ") end (describe-floor 'living-room *objects* *object-locations*) ### ^ Lisp >>> Ruby v ### describe_floor "living_room", $object_locations (defun look () (append (describe-location *location* *map*) (describe-paths *location* *map*) (describe-floor *location* *objects* *object-locations*))) ### ^ Lisp >>> Ruby v ### def look [ describe_location($location, $map), describe_paths($location, $map), describe_floor($location, $object_locations) ].join(" ").strip end (look) ### ^ Lisp >>> Ruby v ### look (defun walk-direction (direction) (let ((next (assoc direction (cddr (assoc *location* *map*))))) (cond (next (setf *location* (third next)) (look)) (t '(you cant go that way.))))) ### ^ Lisp >>> Ruby v ### def walk_direction( direction ) if to = $map[$location][1..-1].assoc(direction) $location = to.last look else "You can't go that way." end end (walk-direction 'west) ### ^ Lisp >>> Ruby v ### walk_direction "west" (defmacro defspel (&rest rest) `(defmacro ,@rest)) ### ^ Lisp >>> Ruby v ### $stringify = %w{west east upstairs downstairs} def method_missing( method, *args, &block ) if $stringify.include? method.to_s method.to_s else "I don't know the word '#{method}'." end end (defspel walk (direction) `(walk-direction ',direction) ### ^ Lisp >>> Ruby v ### alias walk walk_direction (walk east) ### ^ Lisp >>> Ruby v ### walk east (defun pickup-object (object) (cond ((is-at object *location* *object-locations*) (push (list object 'body) *object-locations*) `(you are now carrying the ,object)) (t '(you cannot get that.)))) ### ^ Lisp >>> Ruby v ### def pickup_object( object ) if is_at? object, $location, $object_locations $object_locations[object] = "body" "You are now carrying #{object}." else "You cannot get that." end end (defspel pickup (object) `(pickup-object ',object)) ### ^ Lisp >>> Ruby v ### $stringify.push(*$objects) alias pickup pickup_object (pickup whiskey-bottle) ### ^ Lisp >>> Ruby v ### pickup whiskey_bottle (defun inventory () (remove-if-not (lambda (x) (is-at x 'body *object-locations*)) *objects*)) ### ^ Lisp >>> Ruby v ### def inventory $objects.select { |obj| $object_locations[obj] == "body" } end (defun have (object) (member object (inventory))) ### ^ Lisp >>> Ruby v ### def have?( object ) inventory.include? object end (setf *chain-welded* nil) ### ^ Lisp >>> Ruby v ### $chain_welded = nil (defun weld (subject object) (cond ((and (eq *location* 'attic) (eq subject 'chain) (eq object 'bucket) (have 'chain) (have 'bucket) (not *chain-welded*)) (setf *chain-welded* 't) '(the chain is now securely welded to the bucket.)) (t '(you cannot weld like that.)))) ### ^ Lisp >>> Ruby v ### def weld( *objects ) if $location == "attic" and not $chain_welded and objects.all? { |obj| have? obj } and objects.sort == %w{bucket chain} $chain_welded = true "The chain is now securely welded to the bucket." else "You cannot weld like that." end end (weld 'chain 'bucket) ### ^ Lisp >>> Ruby v ### weld "chain", "bucket" (setf *bucket-filled* nil) ### ^ Lisp >>> Ruby v ### $bucket_filled = nil (defun dunk (subject object) (cond ((and (eq *location* 'garden) (eq subject 'bucket) (eq object 'well) (have 'bucket) *chain-welded*) (setf *bucket-filled* 't) '(the bucket is now full of water)) (t '(you cannot dunk like that.)))) ### ^ Lisp >>> Ruby v ### def dunk( *objects ) if $location == "garden" and $chain_welded and objects.sort == %w {bucket well} $bucket_filled = true "The bucket is now full of water." else "You cannot dunk like that." end end (defspel game-action (command subj obj place &rest rest) `(defspel ,command (subject object) `(cond ((and (eq *location* ',',place) (eq ',subject ',',subj) (eq ',object ',',obj) (have ',',subj)) ,@',rest) (t '(i cant ,',command like that.))))) ### ^ Lisp >>> Ruby v ### def game_action( action, subject, object, location, &block ) $stringify << object unless $stringify.include? object self.class.send(:define_method, action) do |sub, obj| begin if $location == location and subject == sub and object == obj and have?(subject) block[sub, obj] else raise end rescue "You can't #{action} like that." end end end (game-action weld chain bucket attic (cond ((and (have 'bucket) (setf *chain-welded* 't)) '(the chain is now securely welded to the bucket.)) (t '(you do not have a bucket.)))) ### ^ Lisp >>> Ruby v ### game_action(*%w{weld chain bucket attic}) do |subject, object| have?(object) or raise $chain_welded = true "The chain is now securely welded to the bucket." end (weld chain bucket) ### ^ Lisp >>> Ruby v ### weld chain, bucket (game-action dunk bucket well garden (cond (*chain-welded* (setf *bucket-filled* 't) '(the bucket is now full of water)) (t '(the water level is too low to reach.)))) ### ^ Lisp >>> Ruby v ### game_action(*%w{dunk bucket well garden}) do |subject, object| $chain_welded or raise $bucket_filled = true "The bucket is now full of water." end (game-action splash bucket wizard living-room (cond ((not *bucket-filled*) '(the bucket has nothing in it.)) ((have 'frog) '(the wizard awakens and sees that you stole his frog. he is so upset he banishes you to the netherworlds- you lose! the end.)) (t '(the wizard awakens from his slumber and greets you warmly. he hands you the magic low-carb donut- you win! the end.)))) ### ^ Lisp >>> Ruby v ### game_action(*%w{splash bucket wizard living_room}) do |subject, object| $bucket_filled or raise if have? "frog" "The wizard awakens and sees that you stole his frog. " + "He is so upset he banishes you to the netherworlds--you lose! The end." else "The wizard awakens from his slumber and greets you warmly. " + "He hands you the magic low-carb donut--you win! The end." end end