anchor.diff:  
   Should return true beginning on the day of their 13th birthday."
     (>= (player-age player) 13))
  -(defun collect-setters-for-class (class info)
  -  "GIven a  CLASS name symbol, where  INFO is a property  list suitable for
  -MAKE-INSTANCE CLASS, collect the values  from the list where the keyword
  -matches  the first  initarg name  for a  slot, and  the value  following
  -matches the type specification for it, as well.
  -
  -Returns an alist where  each car is a writer function  for the slot, and
  -each cdr, a new value."
  -  (loop with not-found = 'not-found
  -     for slot in (closer-mop:class-slots (find-class class))
  -     for initarg = (first (closer-mop:slot-definition-initargs slot))
  -     for writer = (or (first (closer-mop:slot-definition-writers slot))
  -                      (first (closer-mop:slot-definition-writers slot)))
  -     for type = (or (closer-mop:slot-definition-type slot) t)
  -     for new-value = (getf info initarg not-found)
  -     when (not (eql new-value not-found))
  -     do (assert (typep new-value type) (new-value)
  -                "Cannot store ~s in slot ~s (type ~s) of class ~s"
  -                new-value type (closer-mop:slot-definition-name slot)
  -                type class)
  -     collect (cons writer new-value)))
  +
  +;; (defun class-slot-writers (class)
  +;;   "Enumerate the first writer (if any) for any slot on CLASS that has one."
  +;;   (loop with not-found = 'not-found
  +;;      for slot in (closer-mop:class-slots (find-class class))
  +;;      for writers = (closer-mop:slot-definition-writers slot) 
  +;;      when writers
  +;;      collect (cons slot (first writers))))
  +
  +;; (eval-when (:compile-toplevel :execute)
  +;;   (dolist (class '(player))
  +;;     (dolist (writer (class-slot-writers class))
  +;;       (add-method 
  +;;        (closer-mop:method-generic-function writer)
  +;;        (make-method 
  +;;         )))))
  +
   
   (defun update-player-info (player-id info)
     "GIven  property  list  INFO,  find  the record  for  player  with  ID
  
positive.code:   (declare (ignore info))
    (user-id<-registration registrar id))
  
  
  (defun find-player-by-id (id)
    "Retrieve the player object represented by ID."
    (check-type id (unsigned-byte 128))
    (error 'unimplemented))
  
  (defun ensure-player (player)
    "Ensure  that  PLAYER   is  a  PLAYER  object.   Coërces  integers  or
  
negative.code: 
  ;;; Creatures, Players.
  
  ;; (defmodel creature-controller
  ;;   (:inflate registered-at #'datetime-to-timestamp) 
  ;;   id 
  ;;   registered-at)
  
  ;; (defclass creature-controller ()
  ;;   ((creature :type (or creature (unsigned-byte 128) null)
  ;;              :accessor creature-controller-creature 
  ;;              :initarg :creature
  ;;              :documentation "If this controller is currently controlling
  ;;              a creature, this is a reference to that creature; either an
  ;;              ID, or the creature object."))
  ;;   (:documentation "A base class used for any entity (eg, player) who can
  ;;  control a character in the game in some way."))
  
  (datafly:defmodel player
    "A  structure representing  a  player  who is  a  human  being in  the
   real world.
  
  Structure slots:
  
  @itemize  @item ID  
  
  A 128-bit  unique identifier  for this player,  used internally.  We are
  generating these using v4-UUID's, at  least for now, although other than
  being a positive  integer, I would not recommend  making any assumptions
  about their internal format.
  
  @item EMAIL
  
  The primary  e-mail address  associated with  this player.  The player's
  contact  methods list  may have  alternate  addresses, and  there is  no
  guarantee that  this “primary” address is  as good as, much  less better
  than, any of them.  This value may be used for  display only, but before
  actually  sending mail,  visit the  contact  methods list  and find  the
  actual best address.
  
  This may also be NIL.
  
  @item GIVEN-NAME
  
  The player's given name (usually, first  name) if one is known. This may
  be NIL.
  
  @item SURNAME
  
  The  player's surname  (family  name, or  last name)  if  one is  known.
  This may be NIL.
  
  @item FULL-NAME
  
  The player's  full name, formatted as  they like it. This  might include
  honorifics or titles;  there is no safe way to  convery between this and
  the given name and surname.
  
  @item DATE-OF-BIRTH
  
  The player's date of birth, if it is known.
  
  @item AGE
  
  The  player's age,  if it  is known.  Note that  the reader  method will
  compute the age from the date-of-birth when one is present.
  
  For sanity-checking purposes only, the age  is clamped to 0…130. This is
  mostly to detect the not-uncommon  data-entry error of someone supplying
  a  two-digit year-of-birth  that  is later  interpreted  as their  being
  1,900+ years old.
  
  @end itemize"
    (id (binary<-uuid (uuid:make-v4-uuid))
        :type (unsigned-byte 128))
    (email nil :type (or string null))
    (given-name nil :type (or string null))
    (surname nil :type (or string null))
    (full-name nil :type (or string null))
    (date-of-birth nil :type (or local-time:date null))
    (age nil :type (or (real 0 (130)) null))) 
  
  (defun legal-age (date-of-birth &optional (reference-date (local-time:now)))
    "The age of  a person born on DATE-OF-BIRTH, as  of REFERENCE-DATE (or
  right  now).  This uses  the  legal  definition  that the  person's  age
  increments at  the midnight of their  date of birth each  year, with the
  date 29 February treated as 1 March on non-leap-years.
  
  The time  zone used for  this computation  is the not  defined, however,
  yielding  rather  irregular  behaviour   depending  on  time  zones  and
  