anchor.diff:      This software is in Public Domain.
       You're free to do with it as you please.")
     (:use "COMMON-LISP")
  -  (:export  "MAIN")
  -  );;COM.INFORMATIMAGO.COMMON-LISP.PUZZLE
  +  (:export  "MAIN"))
   (in-package "COM.INFORMATIMAGO.COMMON-LISP.PUZZLE")
  -
   
   (defclass square ()
     ;; What? A class for a mere integer?  No. We just leave to the reader
     ;; the pleasure to implement an picture-square subclass that would
     ;; display a picture part like on the real puzzle games.
  -  ((label :accessor label  :initform 0 :initarg :label :type integer)));;square
  +  ((label :accessor label  :initform 0 :initarg :label :type integer)))
  +
  +(defmethod print-object ((self square) stream)
  +  (prin1 (label self) stream)
  +  self)
  +
   
   
   (defclass puzzle ()
     ((size   :accessor size   :initform 4 :initarg :size :type (integer 2))
      (places :accessor places :initform nil
  -           :type (simple-array (or null square) (* *)))
  -   (empty  :accessor empty  :initform nil :type cons)));;puzzle
  +           :type (or null (simple-array (or null square) (* *))))
  +   (empty  :accessor empty  :initform nil :type list)))
   
   
   (defgeneric get-coordinates  (puzzle relative-move))
  
positive.code:     (destructuring-bind (ex . ey) (empty self)
        (psetf (aref (places self) x y)   (aref (places self) ex ey)
               (aref (places self) ex ey) (aref (places self) x y))
        (setf (empty self) (cons x y)))));;move-square
  
  
  (defmethod play ((self puzzle))
    (loop
     (tagbody
      :loop
      (format t "~&----------------------------------------~%")
       (format t "~A" self)
       (format t "square to move: ")
       (let ((input (let ((*package*
                           (find-package "COM.INFORMATIMAGO.COMMON-LISP.PUZZLE")))
                      ;; To be able to read mere symbols (instead of keywords).
                      (read)))
             (movable (get-movable-list self))
             square x y)
         (typecase input
           (integer
            (let ((m (member input movable
                             :key (lambda (x) (label (second x))) :test (function =))))
              (if m
                (progn
                  (setf square (second (car m)))
                  (multiple-value-setq (x y)
                      (get-coordinates self (first (car m)))))
                (progn
                  (format t "Cannot move square ~D.~%" input)
                  (go :loop)))))
           (symbol
            (handler-case
                (progn
                  (multiple-value-setq (x y)
                      (get-coordinates
                       self (case input
                              ((:l :left l left)   :l)
  
negative.code:     (format out "~&")
      (loop with size = (size self)
            for i from 0 below size do
              (loop for j from 0 below size do
                (if (aref (places self) i j)
                    (format out " ~VD " width (label (aref (places self) i j)))
                    (format out " ~VA " width "")))
              (format out "~%")))
    (format out "~%")
    self)
  
  
  (defmethod get-coordinates ((self puzzle) relative-move)
  