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 >>