Let's try our new command:
  (weld 'chain 'bucket)
  ==> (you cannot weld like that -)
Oops... we don't have a bucket or chain, do we? ...and there's no welding machine around... oh well...
Now let's create a command for dunking the chain and bucket in the well:
  (setq bucket-filled nil)

  (defun dunk (subject object)
    (cond ((and (eq location 'garden)
                (eq subject 'bucket)
                (eq object 'well)
                (have 'bucket)
                chain-welded)
           (setq bucket-filled 't) '(the bucket is now full of water))
          (t '(you cannot dunk like that -))))
Now if you paid attention, you probably noticed that this command looks a lot like the weld command... Both commands need to check the location, subject, and object, but they're different enough that we can't combine the similarities into a single function. Too bad...
...but since this is Lisp, we can do more than just write functions, we can cast SPELs! Let's create the following SPEL:
  (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 cannot ,',command like that -)))))
Notice how ridiculously complex this SPEL is - It has more quotes, backquotes, commas and other weird symbols than you can shake a list at. More than that, it is a SPEL that actually casts another SPEL! Even experienced Lisp programmers would have to put some thought into creating a monstrosity like this (and in fact they would consider this SPEL to be inelegant and would go through some extra esoteric steps to make it better-behaved that we won't worry about here...)
<< begin < previous - next > end >>