anchor.diff:       (setf (gethash ,(string name) *ajax-funcs*)
              (defun ,name ,lambda-list ,@body))))
   
  -(defajax add-message (msg)
  -  (add-user-message (session-value 'username) msg)
  +(defajax add-action (action dialogue)
  +  (add-user-action (session-value 'username) action dialogue)
     (update-chat))
   
  +(defun render-user-action (user-action)
  +  (let ((action (user-action-action user-action))
  +        (dialogue (user-action-dialogue user-action)))
  +    (<:div :class "user-entry"
  +      (if (and (not (emptyp action)) (emptyp dialogue))
  +          (<:li :class "action"
  +               (<:ah action))
  +          (progn
  +            (<:li :class "character"
  +                 (<:ah (user-action-user user-action)))
  +            (unless (emptyp action)
  +              (<:li :class "parenthetical"
  +                   (<:ah "(" action ")")))
  +            (<:li :class "dialogue"
  +                 (<:ah
  +                  (if (emptyp dialogue)
  +                      "..."
  +                      dialogue))))))))
  +
   (defajax update-chat ()
  -  (prog1
  -      (with-yaclml-output-to-string
  -        (mapc (lambda (message)
  -                (<:p (<:ai (user-message-message message) " ("(user-message-user message)")")))
  -              (get-recent-messages (session-value 'last-message-id))))
  -    (setf (session-value 'last-message-id) *max-message-id*)))
  +  (prog1 (with-yaclml-output-to-string
  +           (mapc #'render-user-action
  +                 (get-recent-actions (session-value 'last-action-id))))
  +    (setf (session-value 'last-action-id) *max-action-id*)))
  
positive.code:     (<:html
       (<:head
        (<:title "Hello!")
        (<:script :src "http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" :type "text/javascript")
        (<:script :type "text/javascript" (<:ai "
  function callback(data) {
  
negative.code: ;; TODO for today:
  ;; * Add another input field, 'action'.
  ;; * When someone logs in, draw a screenplay-style scene heading.
  ;; * Render each entry as screenplay-style Action/Dialogue for the user that spoke.
  
  (defvar *server* nil)
  (defparameter *current-story* nil)
  (defvar *users* nil)
  (defvar *max-action-id* 0)
  
  (defstruct user-action id user timestamp action dialogue)
  
  (defun add-user-action (user action dialogue &optional (timestamp (get-universal-time))
                           &aux (id (incf *max-action-id*)))
    (push (make-user-action :id id :user user :timestamp timestamp :action action :dialogue dialogue)
          *current-story*)
    id)
  
  (defun get-recent-actions (last-action-id)
    (member (1+ last-action-id) (reverse *current-story*) :key #'user-action-id))
  
  (defun session-cleanup (session)
    (let ((username (session-value 'username session)))
  