anchor.diff:                                :extra-armies extra-armies))
            (dolist (frontierkey terr-frontiers)
              (add-edge-between-vertexes frontiers key frontierkey))))
  -     (make-instance 'game :territories territories :frontiers frontiers))) 
  +     (make-instance 'game-map :territories territories :frontiers frontiers)))
   
     (:method ((path pathname) &key)
  -   (with-open-file (file path) (read-map file))) 
  +   (with-open-file (file path) (read-map file)))
   
     (:method ((path string) &key)
      (read-map
        (parse-namestring
          (if (probe-file path)
            path
  -         (format nil "~a.map" path)))))) 
  +         (format nil "~a.map" path))))))
   
  -(defun territory (game territory-key)
  -  (gethash territory-key (territories game)))
  +(defgeneric territory (container key)
  +  (:method ((container game-map) key)
  +   (gethash key (territories container)))
  +  (:method ((container game) key)
  +   (territory (game-map container) key)))
   
  -(defun player (game player-key)
  -  (gethash player-key (players game)))
  +(defmethod territories ((game game))
  +  (territories (game-map game)))
   
  -(defun territory-keys (game)
  -  (keys (territories game)))
  +(defmethod frontiers ((game game))
  +  (frontiers (game-map game)))
   
  -(defun player-keys (game)
  -  (keys (players game)))
  +(defgeneric player (game player-key)
  +  (:method ((game game) player-key)
  +   (gethash player-key (players game))))
   
  -(defun territories-connected-p (game origin-key destination-key)
  -  (let ((graph (frontiers game)))
  -    (vertices-share-edge-p
  -      (find-vertex graph origin-key)
  -      (find-vertex graph destination-key))))
  +(defgeneric territory-keys (game)
  +  (:method ((game game))
  +   (keys (territories game))))
   
  -(defun add-player (game name &optional (handle name))
  -  (setf (gethash handle (players game)) (make-instance 'player :name name)))
  +(defgeneric player-keys (game)
  +  (:method ((game game))
  +   (keys (players game))))
   
  -(defun initialize-territory (territory player)
  -  (setf (owner territory) player)
  -  (setf (armies territory) 1))
  +(defgeneric territories-connected-p (game origin-key destination-key)
  +  (:method ((game game) origin-key destination-key)
  +   (let ((graph (frontiers game)))
  +     (vertices-share-edge-p
  +       (find-vertex graph origin-key)
  +       (find-vertex graph destination-key)))))
   
  -(defun shuffle-territories (game)
  -  (unless (territory-keys game)
  -    (error "El juego debe tener territorios"))
  -  (unless (player-keys game)
  -    (error "El juego debe tener jugadores"))
  -  (let* ((territories (shuffle (territory-keys game)))
  -        (players (shuffle (player-keys game)))
  -        (share (floor (/ (length territories) (length players)))))
  -    (dolist (player players)
  -      (loop repeat share
  -            for territory = (first territories) do
  -            (initialize-territory (territory game territory) (player game player))
  -            (pop territories)))
  -    (loop while territories
  -          for territory = (first territories)
  -          for player = (first players) do
  -          (initialize-territory (territory game territory) (player game player))
  -          (pop players)
  -          (pop territories))))
  +(defgeneric add-player (game name)
  +  (:method ((game game) (name string))
  +   (setf (gethash name (players game)) (make-instance 'player :name name))))
   
  -(defgeneric move-armies (game from to amount &key))
  +(defgeneric shuffle-territories (game)
  +  (:method ((game game))
  +   (unless (territory-keys game)
  +     (error "El juego debe tener territorios"))
  +   (unless (player-keys game)
  +     (error "El juego debe tener jugadores"))
  +   (flet
  +     ((initialize-territory (territory player)
  +        (setf (owner (territory game territory)) (player game player))
  +        (setf (armies (territory game territory)) 1)))
  +     (let* ((territories (shuffle (territory-keys game)))
  +            (players (shuffle (player-keys game)))
  +            (share (floor (/ (length territories) (length players)))))
  +       (dolist (player players)
  +         (loop repeat share
  +               for territory = (first territories) do
  +               (initialize-territory territory player)
  +               (pop territories)))
  +       (loop while territories
  +         for territory = (first territories)
  +         for player = (first players) do
  +         (initialize-territory territory player)
  +         (pop players)
  +         (pop territories))))))
   
  -(defmethod move-armies (game origin-key destination-key amount &key)
  -  (let ((origin (territory game origin-key))
  -        (destination (territory game destination-key)))
  -    (unless (territories-connected-p game origin-key destination-key)
  -      (error "Los territorios deben estar conectados"))
  -    (unless (eq (owner origin) (owner destination))
  -      (error "Los territorios tienen que tener el mismo dueño"))
  -    (unless (> amount 0)
  -      (error "No se pueden mover 0 o menos ejércitos"))
  -    (unless (> (armies origin) amount)
  -      (error "No hay suficientes ejércitos")) 
  -    (decf (armies origin) amount) 
  -    (incf (armies destination) amount)))
  +(defgeneric move-armies (game from to amount &key)
  +  (:method ((game game) origin-key destination-key amount &key)
  +   (let ((origin (territory game origin-key))
  +         (destination (territory game destination-key)))
  +     (unless (territories-connected-p game origin-key destination-key)
  +       (error "Los territorios deben estar conectados"))
  +     (unless (eq (owner origin) (owner destination))
  +       (error "Los territorios tienen que tener el mismo dueño"))
  +     (unless (> amount 0)
  +       (error "No se pueden mover 0 o menos ejércitos"))
  +     (unless (> (armies origin) amount)
  +       (error "No hay suficientes ejércitos"))
  +     (decf (armies origin) amount)
  +     (incf (armies destination) amount))))
   
  -(defgeneric place-armies (game where amount &key))
  +(defgeneric place-armies (game where amount &key)
  +  (:method ((game game) territory-key amount &key)
  +   (let ((territory (territory game territory-key)))
  +     (unless (> amount 0)
  +       (error "No se pueden poner 0 o menos ejércitos"))
  +     (incf (armies territory) amount))))
   
  -(defmethod place-armies (game territory-key amount &key)
  -  (let ((territory (territory game territory-key)))
  -    (unless (> amount 0)
  -      (error "No se pueden poner 0 o menos ejércitos"))
  -    (incf (armies territory) amount)))
  +(defgeneric attack (game from to &key)
  +  (:method ((game game) origin-key destination-key &key)
  +   (symbol-macrolet
  +     ((origin (territory game origin-key))
  +      (destination (territory game destination-key))
  +      (attackers (armies origin))
  +      (defenders (armies destination)))
  +     (unless (territories-connected-p game origin-key destination-key)
  +       (error "Los territorios deben estar conectados"))
  +     (unless (> attackers 2)
  +       (error "No se puede atacar teniendo 2 o menos ejércitos"))
  +     (when (equal (owner destination) (owner origin))
  +       (error "Un jugador no se puede atacar a sí mismo"))
  +     (let ((decrement (1+ (min defenders (- attackers 2)))))
  +       (decf attackers (random decrement))
  +       (decf defenders (random decrement))
  +       (when (= defenders 0)
  +         (setf (owner destination) (owner origin))
  +         (move-armies game origin-key destination-key 1)))
  +     (eq (owner origin) (owner destination)))))
   
  -(defgeneric attack (game from to &key))
  +(defgeneric print-game (game)
  +  (:method ((game game))
  +   (format t "~&Jugadores:")
  +   (loop for v being the hash-values in (players game) do
  +         (format t "~&~t~a" (name v)))
  +   (format t "~&Territorios:")
  +   (loop for v being the hash-values in (territories game) do
  +         (format t "~&~a~&~tDueño:~t~a~&~tEjércitos:~a"
  +                 (name v)
  +                 (if (owner v) (name (owner v)) "Ninguno")
  +                 (armies v)))))
   
  -(defmethod attack (game origin-key destination-key &key)
  -  (symbol-macrolet
  -    ((origin (territory game origin-key))
  -     (destination (territory game destination-key))
  -     (attackers (armies origin))
  -     (defenders (armies destination)))
  -    (unless (territories-connected-p game origin-key destination-key)
  -      (error "Los territorios deben estar conectados"))
  -    (unless (> attackers 2)
  -      (error "No se puede atacar teniendo 2 o menos ejércitos"))
  -    (when (equal (owner destination) (owner origin))
  -      (error "Un jugador no se puede atacar a sí mismo"))
  -    (let ((decrement (1+ (min defenders (- attackers 2)))))
  -      (decf attackers (random decrement))
  -      (decf defenders (random decrement))
  -      (when (= defenders 0)
  -        (setf (owner destination) (owner origin))
  -        (move-armies game origin-key destination-key 1)))
  -    (eq (owner origin) (owner destination))))
  -
  -(defun print-game (game)
  -  (format t "~&Jugadores:")
  -  (loop for v being the hash-values in (players game) do
  -        (format t "~&~t~a" (name v)))
  -  (format t "~&Territorios:")
  -  (loop for v being the hash-values in (territories game) do
  -        (format t "~&~a~&~tDueño:~t~a~&~tEjércitos:~a"
  -                (name v)
  -                (if (owner v) (name (owner v)) "Ninguno")
  -                (armies v))))
  -
  
positive.code:    (owner nil a)
     (armies nil a)))
  
  (defclass* player ()
    ((name (error "Debe ingresar el nombre del jugador") ir)))
  
  (defclass* game ()
    ((territories (error "Debe especificar los territorios") ir)
     (frontiers (error "Debe especificar las fronteras") ir)
     (players (make-hash-table) r)))
  
  (defgeneric read-map (file &key)
  
negative.code:    (loop for m from (length list) downto 1
           for l = list then (remove v l :count 1)
           for v = (elt l (random m))
           collecting v))
  
  (defclass* territory ()
    ((name (error "Debe ingresar el nombre del territorio") ir)
  