diff --git a/ATL/game-objects.atl b/ATL/game-objects.atl
index 5e29634..84553f3 100644
--- a/ATL/game-objects.atl
+++ b/ATL/game-objects.atl
@@ -5,6 +5,8 @@
 
 define-monster "Fury"
 	description "Hades' messengers, torturers, assassins. Beware!"
+	health 10
+	dexterity 10
 	strength 10
 	aggression 30
 	armour-class 3
@@ -12,6 +14,7 @@
 
 define-weapon "fire-whip"
 	description "A 10-foot long whip, blazing with magical fire"
+	type "whip"
 	damage 2
 
 define-item "Anaklusmos"
@@ -20,6 +23,7 @@
 
 define-weapon "Anaklusmos"
 	description "Riptide, a sword for heroes!"
+	type "sword"
 	damage 4
 
 define-npc "Hades"

diff --git a/ATL/game-objects.atl b/ATL/game-objects.atl
index 5e29634..84553f3 100644
--- a/ATL/game-objects.atl
+++ b/ATL/game-objects.atl
@@ -5,6 +5,8 @@
 
 define-monster "Fury"
 	description "Hades' messengers, torturers, assassins. Beware!"
+	health 10
+	dexterity 10
 	strength 10
 	aggression 30
 	armour-class 3
@@ -12,6 +14,7 @@
 
 define-weapon "fire-whip"
 	description "A 10-foot long whip, blazing with magical fire"
+	type "whip"
 	damage 2
 
 define-item "Anaklusmos"
@@ -20,6 +23,7 @@
 
 define-weapon "Anaklusmos"
 	description "Riptide, a sword for heroes!"
+	type "sword"
 	damage 4
 
 define-npc "Hades"
diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp
index 6fbcee5..080bc7e 100644
--- a/lisp/game-objects.lisp
+++ b/lisp/game-objects.lisp
@@ -31,6 +31,7 @@
 (defstruct monster
 	(name "")
 	(description "")
+	(health 0)
 	(strength 0)
 	(dexterity 0)
 	(aggression 0)
@@ -47,18 +48,16 @@
 (defstruct weapon
 	(name "")
 	(description "")
-	(ranged NIL)
+	(type "generic")
 	(damage 0))
 
 
 (defun set-object-attribute (game-object property value)
 	"Set the attribute 'property' of 'game-object' to 'value'"
 	;; Here follows Lisp magic :D      (that took ages to get right...)
-	;; [And half the magic is gone after being outsourced to build-symbol :-(]
-	;; I'm not sure how elegant it is to call (eval) explicitly, but in this
-	;; case I couldn't avoid it - I needed a mix between a macro and a function
+	;; XXX It's not elegant to call (eval) explicitly, but in this case I can't
+	;; find a way to avoid it - I needed a mix between a macro and a function
 	(let ((command (build-symbol (type-of game-object) "-" property)))
-		;; TODO This following section is rather ugly...
 		(eval `(if (or (null (,command ,game-object))
 					   (listp (,command ,game-object)))
 				   (setf (,command ,game-object)
@@ -70,11 +69,11 @@
 	;; Same comment applies as above
 	(let ((command (build-symbol (type-of game-object) "-" property)))
 		(eval `(if (listp (,command ,game-object))
-				   ;; FIXME This is going to give problems with multiple values
-				   ;; (but will that scenario ever take place?)
+				   ;; FIXME This gives problems with multiple values
 				   (setf (,command ,game-object)
 					   (remove-if #'(lambda (x) (equalp x ,value))
 						   (,command ,game-object)))
+				   ;; TODO set numbers to 0, strings to ""
 				   (setf (,command ,game-object) NIL)))))
 
 ;; XXX This function is probably superfluous, as all place objects are stored
@@ -83,3 +82,8 @@
 	(defun list-place-objects (object-type place)
 		"Get a list of the names of all the place's objects of this type."
 		(funcall list-function object-type place)))
+
+(defun monster-strikes-player (monster player)
+	"The monster attacks a player"
+	;;TODO
+	)

diff --git a/ATL/game-objects.atl b/ATL/game-objects.atl
index 5e29634..84553f3 100644
--- a/ATL/game-objects.atl
+++ b/ATL/game-objects.atl
@@ -5,6 +5,8 @@
 
 define-monster "Fury"
 	description "Hades' messengers, torturers, assassins. Beware!"
+	health 10
+	dexterity 10
 	strength 10
 	aggression 30
 	armour-class 3
@@ -12,6 +14,7 @@
 
 define-weapon "fire-whip"
 	description "A 10-foot long whip, blazing with magical fire"
+	type "whip"
 	damage 2
 
 define-item "Anaklusmos"
@@ -20,6 +23,7 @@
 
 define-weapon "Anaklusmos"
 	description "Riptide, a sword for heroes!"
+	type "sword"
 	damage 4
 
 define-npc "Hades"
diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp
index 6fbcee5..080bc7e 100644
--- a/lisp/game-objects.lisp
+++ b/lisp/game-objects.lisp
@@ -31,6 +31,7 @@
 (defstruct monster
 	(name "")
 	(description "")
+	(health 0)
 	(strength 0)
 	(dexterity 0)
 	(aggression 0)
@@ -47,18 +48,16 @@
 (defstruct weapon
 	(name "")
 	(description "")
-	(ranged NIL)
+	(type "generic")
 	(damage 0))
 
 
 (defun set-object-attribute (game-object property value)
 	"Set the attribute 'property' of 'game-object' to 'value'"
 	;; Here follows Lisp magic :D      (that took ages to get right...)
-	;; [And half the magic is gone after being outsourced to build-symbol :-(]
-	;; I'm not sure how elegant it is to call (eval) explicitly, but in this
-	;; case I couldn't avoid it - I needed a mix between a macro and a function
+	;; XXX It's not elegant to call (eval) explicitly, but in this case I can't
+	;; find a way to avoid it - I needed a mix between a macro and a function
 	(let ((command (build-symbol (type-of game-object) "-" property)))
-		;; TODO This following section is rather ugly...
 		(eval `(if (or (null (,command ,game-object))
 					   (listp (,command ,game-object)))
 				   (setf (,command ,game-object)
@@ -70,11 +69,11 @@
 	;; Same comment applies as above
 	(let ((command (build-symbol (type-of game-object) "-" property)))
 		(eval `(if (listp (,command ,game-object))
-				   ;; FIXME This is going to give problems with multiple values
-				   ;; (but will that scenario ever take place?)
+				   ;; FIXME This gives problems with multiple values
 				   (setf (,command ,game-object)
 					   (remove-if #'(lambda (x) (equalp x ,value))
 						   (,command ,game-object)))
+				   ;; TODO set numbers to 0, strings to ""
 				   (setf (,command ,game-object) NIL)))))
 
 ;; XXX This function is probably superfluous, as all place objects are stored
@@ -83,3 +82,8 @@
 	(defun list-place-objects (object-type place)
 		"Get a list of the names of all the place's objects of this type."
 		(funcall list-function object-type place)))
+
+(defun monster-strikes-player (monster player)
+	"The monster attacks a player"
+	;;TODO
+	)
diff --git a/lisp/player.lisp b/lisp/player.lisp
index b96302c..0cbe51b 100644
--- a/lisp/player.lisp
+++ b/lisp/player.lisp
@@ -21,12 +21,17 @@
 	(money 0)
 	(item NIL)
 	(weapon "")
+	(armour-class 0)
 	(place "")
 	(experience 0)
+	(level 0)
 	(max-health 50)
 	(health 50)
 	(game-admin NIL))
 
+;; How many XP are needed to level up?
+;; XXX Make this configurable in ATL?
+(defvar *level-experience* 100)
 
 (defstruct race
 	(name "")
@@ -50,3 +55,15 @@
 	(defun list-player-objects (object-type player)
 		"Get a list of the names of all the player's objects of this type."
 		(funcall list-function object-type player)))
+
+(defun change-player-health (player amount)
+	"Change the player's health points"
+	(incf (player-health player) amount)
+	(when (> 1 (player-health player))
+		(error "You died!"))) ;; TODO adjust this (especially for multiplayer)
+
+(defun add-player-experience (player amount)
+	"The player gains experience points"
+	(incf (player-experience player) amount)
+	(when (zerop (rem (player-experience player) *level-experience*))
+		(incf (player-level player) player)))

diff --git a/ATL/game-objects.atl b/ATL/game-objects.atl
index 5e29634..84553f3 100644
--- a/ATL/game-objects.atl
+++ b/ATL/game-objects.atl
@@ -5,6 +5,8 @@
 
 define-monster "Fury"
 	description "Hades' messengers, torturers, assassins. Beware!"
+	health 10
+	dexterity 10
 	strength 10
 	aggression 30
 	armour-class 3
@@ -12,6 +14,7 @@
 
 define-weapon "fire-whip"
 	description "A 10-foot long whip, blazing with magical fire"
+	type "whip"
 	damage 2
 
 define-item "Anaklusmos"
@@ -20,6 +23,7 @@
 
 define-weapon "Anaklusmos"
 	description "Riptide, a sword for heroes!"
+	type "sword"
 	damage 4
 
 define-npc "Hades"
diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp
index 6fbcee5..080bc7e 100644
--- a/lisp/game-objects.lisp
+++ b/lisp/game-objects.lisp
@@ -31,6 +31,7 @@
 (defstruct monster
 	(name "")
 	(description "")
+	(health 0)
 	(strength 0)
 	(dexterity 0)
 	(aggression 0)
@@ -47,18 +48,16 @@
 (defstruct weapon
 	(name "")
 	(description "")
-	(ranged NIL)
+	(type "generic")
 	(damage 0))
 
 
 (defun set-object-attribute (game-object property value)
 	"Set the attribute 'property' of 'game-object' to 'value'"
 	;; Here follows Lisp magic :D      (that took ages to get right...)
-	;; [And half the magic is gone after being outsourced to build-symbol :-(]
-	;; I'm not sure how elegant it is to call (eval) explicitly, but in this
-	;; case I couldn't avoid it - I needed a mix between a macro and a function
+	;; XXX It's not elegant to call (eval) explicitly, but in this case I can't
+	;; find a way to avoid it - I needed a mix between a macro and a function
 	(let ((command (build-symbol (type-of game-object) "-" property)))
-		;; TODO This following section is rather ugly...
 		(eval `(if (or (null (,command ,game-object))
 					   (listp (,command ,game-object)))
 				   (setf (,command ,game-object)
@@ -70,11 +69,11 @@
 	;; Same comment applies as above
 	(let ((command (build-symbol (type-of game-object) "-" property)))
 		(eval `(if (listp (,command ,game-object))
-				   ;; FIXME This is going to give problems with multiple values
-				   ;; (but will that scenario ever take place?)
+				   ;; FIXME This gives problems with multiple values
 				   (setf (,command ,game-object)
 					   (remove-if #'(lambda (x) (equalp x ,value))
 						   (,command ,game-object)))
+				   ;; TODO set numbers to 0, strings to ""
 				   (setf (,command ,game-object) NIL)))))
 
 ;; XXX This function is probably superfluous, as all place objects are stored
@@ -83,3 +82,8 @@
 	(defun list-place-objects (object-type place)
 		"Get a list of the names of all the place's objects of this type."
 		(funcall list-function object-type place)))
+
+(defun monster-strikes-player (monster player)
+	"The monster attacks a player"
+	;;TODO
+	)
diff --git a/lisp/player.lisp b/lisp/player.lisp
index b96302c..0cbe51b 100644
--- a/lisp/player.lisp
+++ b/lisp/player.lisp
@@ -21,12 +21,17 @@
 	(money 0)
 	(item NIL)
 	(weapon "")
+	(armour-class 0)
 	(place "")
 	(experience 0)
+	(level 0)
 	(max-health 50)
 	(health 50)
 	(game-admin NIL))
 
+;; How many XP are needed to level up?
+;; XXX Make this configurable in ATL?
+(defvar *level-experience* 100)
 
 (defstruct race
 	(name "")
@@ -50,3 +55,15 @@
 	(defun list-player-objects (object-type player)
 		"Get a list of the names of all the player's objects of this type."
 		(funcall list-function object-type player)))
+
+(defun change-player-health (player amount)
+	"Change the player's health points"
+	(incf (player-health player) amount)
+	(when (> 1 (player-health player))
+		(error "You died!"))) ;; TODO adjust this (especially for multiplayer)
+
+(defun add-player-experience (player amount)
+	"The player gains experience points"
+	(incf (player-experience player) amount)
+	(when (zerop (rem (player-experience player) *level-experience*))
+		(incf (player-level player) player)))
diff --git a/lisp/ui.lisp b/lisp/ui.lisp
index e5abbbf..0fafe21 100644
--- a/lisp/ui.lisp
+++ b/lisp/ui.lisp
@@ -111,13 +111,12 @@
 ;;; Here follow the functions that define the in-game commands.
 ;;;
 
-
 ;; A list of all in-game commands. Each new command must be registered here.
 (defvar *commands*
 	'(help place player
 		 goto pickup drop
 		 talk trade
-		 equip fight shoot
+		 equip attack
 		 about save clear))
 
 ;;; The following commands don't take any arguments except for a player
@@ -137,8 +136,7 @@
 pickup <item>    -  Pick up an item lying around
 drop <item>      -  Drop the item
 equip <weapon>   -  Equip this item as your weapon
-shoot <monster>  -  Take a shot at a monster
-fight <monster>  -  Fight a monster
+attack <monster> -  Fight a monster
 save <game-file> -  Save the game to file")
 	(format t "~A" help-text))
 
@@ -168,6 +166,7 @@
 			(player-constitution p) tab (player-dexterity p))
 		(format t "~&=====")
 		(format t "~&Weapon: ~A" (player-weapon p))
+		;; XXX This will need adjusting for large item numbers
 		(format t "~&Items: ~A" (string-from-list (player-item p)))
 		(format t "~&=====")
 		(format t "~&Max health: ~A~ACurrent health: ~A"
@@ -187,7 +186,8 @@
 			((and last-save (not game-file)) (setf game-file last-save))
 			((not (or last-save game-file))
 				(format t "~&Where do you want to save the game?")
-				(input-string game-file)))
+				(input-string game-file)
+				(setf last-save game-file)))
 		(when (y-or-n-p "Save game to ~A?" game-file)
 			(save-world game-file)
 			(format t "~&Game saved."))))
@@ -338,10 +338,55 @@
 			(format t "~&You have equipped: ~A" new-weapon))
 		(format t "~&Sorry, this item is not available as a weapon!")))
 
-(defun fight (player &optional opponent)
-	"The player enters combat"
+(defun attack (player &optional opponent)
+	"The player launches an attack at a monster"
 	(unless opponent
 		(format t "~&Please specify an opponent!")
-		(return-from fight))
-	;; TODO
-	)
+		(return-from attack))
+	(unless (member opponent
+				(list-place-objects 'monster (player-place player))
+				:test #'equalp)
+		(format t "~&This monster is not here!")
+		(return-from attack))
+	(let* ((monster (get-game-object 'monster opponent))
+			  (m-str (monster-strength monster))
+			  (m-dex (monster-dexterity monster))
+			  (m-ac (monster-armour-class monster))
+			  (m-weapon (get-game-object 'weapon (monster-weapon monster)))
+			  (p-str (player-strength player))
+			  (p-dex (player-dexterity player))
+			  (p-ac (player-armour-class player))
+			  (p-weapon (if (not (equalp (player-weapon player) "")) ;lbyl
+							(get-game-object 'weapon (player-weapon player))
+							(make-weapon :name "Fists" :damage 0)))
+			  (damage 0))
+		(if (> (+ (random 10) p-dex) (+ (random 10) m-dex))
+			(setf damage (calculate-damage p-str p-weapon m-dex m-ac))
+			(setf damage (- 0 (calculate-damage m-str m-weapon p-dex p-ac))))
+		;(break)
+		(cond ((plusp damage)
+				  (decf (monster-health monster) damage)
+				  (format t "~&You hit! ~A points damage." damage)
+				  (when (> 1 (monster-health monster))
+					  (let ((experience (round (average m-str m-dex))))
+						  (break)
+						  (remove-object-attribute (player-place player)
+							  'monster monster)
+						  (break)
+						  (add-player-experience player experience)
+						  (format t "~&You killed the monster!")
+						  (format t "~A points experience." experience))))
+			((minusp damage)
+				(change-player-health player (- 0 damage))
+				(format t "~&You missed. The monster hit!")
+				(format t "~A points damage." damage))
+			(t (format t "~&You missed. The monster missed.")))))
+
+(defun calculate-damage (att-str att-weapon def-dex def-ac)
+	"A private function to calculate the damage caused by an attack"
+	(let ((damage 0))
+		(incf damage (random att-str))
+		(incf damage (weapon-damage att-weapon))
+		(decf damage (random def-dex))
+		(decf damage def-ac)
+		(if (minusp damage) 0 damage)))

diff --git a/ATL/game-objects.atl b/ATL/game-objects.atl
index 5e29634..84553f3 100644
--- a/ATL/game-objects.atl
+++ b/ATL/game-objects.atl
@@ -5,6 +5,8 @@
 
 define-monster "Fury"
 	description "Hades' messengers, torturers, assassins. Beware!"
+	health 10
+	dexterity 10
 	strength 10
 	aggression 30
 	armour-class 3
@@ -12,6 +14,7 @@
 
 define-weapon "fire-whip"
 	description "A 10-foot long whip, blazing with magical fire"
+	type "whip"
 	damage 2
 
 define-item "Anaklusmos"
@@ -20,6 +23,7 @@
 
 define-weapon "Anaklusmos"
 	description "Riptide, a sword for heroes!"
+	type "sword"
 	damage 4
 
 define-npc "Hades"
diff --git a/lisp/game-objects.lisp b/lisp/game-objects.lisp
index 6fbcee5..080bc7e 100644
--- a/lisp/game-objects.lisp
+++ b/lisp/game-objects.lisp
@@ -31,6 +31,7 @@
 (defstruct monster
 	(name "")
 	(description "")
+	(health 0)
 	(strength 0)
 	(dexterity 0)
 	(aggression 0)
@@ -47,18 +48,16 @@
 (defstruct weapon
 	(name "")
 	(description "")
-	(ranged NIL)
+	(type "generic")
 	(damage 0))
 
 
 (defun set-object-attribute (game-object property value)
 	"Set the attribute 'property' of 'game-object' to 'value'"
 	;; Here follows Lisp magic :D      (that took ages to get right...)
-	;; [And half the magic is gone after being outsourced to build-symbol :-(]
-	;; I'm not sure how elegant it is to call (eval) explicitly, but in this
-	;; case I couldn't avoid it - I needed a mix between a macro and a function
+	;; XXX It's not elegant to call (eval) explicitly, but in this case I can't
+	;; find a way to avoid it - I needed a mix between a macro and a function
 	(let ((command (build-symbol (type-of game-object) "-" property)))
-		;; TODO This following section is rather ugly...
 		(eval `(if (or (null (,command ,game-object))
 					   (listp (,command ,game-object)))
 				   (setf (,command ,game-object)
@@ -70,11 +69,11 @@
 	;; Same comment applies as above
 	(let ((command (build-symbol (type-of game-object) "-" property)))
 		(eval `(if (listp (,command ,game-object))
-				   ;; FIXME This is going to give problems with multiple values
-				   ;; (but will that scenario ever take place?)
+				   ;; FIXME This gives problems with multiple values
 				   (setf (,command ,game-object)
 					   (remove-if #'(lambda (x) (equalp x ,value))
 						   (,command ,game-object)))
+				   ;; TODO set numbers to 0, strings to ""
 				   (setf (,command ,game-object) NIL)))))
 
 ;; XXX This function is probably superfluous, as all place objects are stored
@@ -83,3 +82,8 @@
 	(defun list-place-objects (object-type place)
 		"Get a list of the names of all the place's objects of this type."
 		(funcall list-function object-type place)))
+
+(defun monster-strikes-player (monster player)
+	"The monster attacks a player"
+	;;TODO
+	)
diff --git a/lisp/player.lisp b/lisp/player.lisp
index b96302c..0cbe51b 100644
--- a/lisp/player.lisp
+++ b/lisp/player.lisp
@@ -21,12 +21,17 @@
 	(money 0)
 	(item NIL)
 	(weapon "")
+	(armour-class 0)
 	(place "")
 	(experience 0)
+	(level 0)
 	(max-health 50)
 	(health 50)
 	(game-admin NIL))
 
+;; How many XP are needed to level up?
+;; XXX Make this configurable in ATL?
+(defvar *level-experience* 100)
 
 (defstruct race
 	(name "")
@@ -50,3 +55,15 @@
 	(defun list-player-objects (object-type player)
 		"Get a list of the names of all the player's objects of this type."
 		(funcall list-function object-type player)))
+
+(defun change-player-health (player amount)
+	"Change the player's health points"
+	(incf (player-health player) amount)
+	(when (> 1 (player-health player))
+		(error "You died!"))) ;; TODO adjust this (especially for multiplayer)
+
+(defun add-player-experience (player amount)
+	"The player gains experience points"
+	(incf (player-experience player) amount)
+	(when (zerop (rem (player-experience player) *level-experience*))
+		(incf (player-level player) player)))
diff --git a/lisp/ui.lisp b/lisp/ui.lisp
index e5abbbf..0fafe21 100644
--- a/lisp/ui.lisp
+++ b/lisp/ui.lisp
@@ -111,13 +111,12 @@
 ;;; Here follow the functions that define the in-game commands.
 ;;;
 
-
 ;; A list of all in-game commands. Each new command must be registered here.
 (defvar *commands*
 	'(help place player
 		 goto pickup drop
 		 talk trade
-		 equip fight shoot
+		 equip attack
 		 about save clear))
 
 ;;; The following commands don't take any arguments except for a player
@@ -137,8 +136,7 @@
 pickup <item>    -  Pick up an item lying around
 drop <item>      -  Drop the item
 equip <weapon>   -  Equip this item as your weapon
-shoot <monster>  -  Take a shot at a monster
-fight <monster>  -  Fight a monster
+attack <monster> -  Fight a monster
 save <game-file> -  Save the game to file")
 	(format t "~A" help-text))
 
@@ -168,6 +166,7 @@
 			(player-constitution p) tab (player-dexterity p))
 		(format t "~&=====")
 		(format t "~&Weapon: ~A" (player-weapon p))
+		;; XXX This will need adjusting for large item numbers
 		(format t "~&Items: ~A" (string-from-list (player-item p)))
 		(format t "~&=====")
 		(format t "~&Max health: ~A~ACurrent health: ~A"
@@ -187,7 +186,8 @@
 			((and last-save (not game-file)) (setf game-file last-save))
 			((not (or last-save game-file))
 				(format t "~&Where do you want to save the game?")
-				(input-string game-file)))
+				(input-string game-file)
+				(setf last-save game-file)))
 		(when (y-or-n-p "Save game to ~A?" game-file)
 			(save-world game-file)
 			(format t "~&Game saved."))))
@@ -338,10 +338,55 @@
 			(format t "~&You have equipped: ~A" new-weapon))
 		(format t "~&Sorry, this item is not available as a weapon!")))
 
-(defun fight (player &optional opponent)
-	"The player enters combat"
+(defun attack (player &optional opponent)
+	"The player launches an attack at a monster"
 	(unless opponent
 		(format t "~&Please specify an opponent!")
-		(return-from fight))
-	;; TODO
-	)
+		(return-from attack))
+	(unless (member opponent
+				(list-place-objects 'monster (player-place player))
+				:test #'equalp)
+		(format t "~&This monster is not here!")
+		(return-from attack))
+	(let* ((monster (get-game-object 'monster opponent))
+			  (m-str (monster-strength monster))
+			  (m-dex (monster-dexterity monster))
+			  (m-ac (monster-armour-class monster))
+			  (m-weapon (get-game-object 'weapon (monster-weapon monster)))
+			  (p-str (player-strength player))
+			  (p-dex (player-dexterity player))
+			  (p-ac (player-armour-class player))
+			  (p-weapon (if (not (equalp (player-weapon player) "")) ;lbyl
+							(get-game-object 'weapon (player-weapon player))
+							(make-weapon :name "Fists" :damage 0)))
+			  (damage 0))
+		(if (> (+ (random 10) p-dex) (+ (random 10) m-dex))
+			(setf damage (calculate-damage p-str p-weapon m-dex m-ac))
+			(setf damage (- 0 (calculate-damage m-str m-weapon p-dex p-ac))))
+		;(break)
+		(cond ((plusp damage)
+				  (decf (monster-health monster) damage)
+				  (format t "~&You hit! ~A points damage." damage)
+				  (when (> 1 (monster-health monster))
+					  (let ((experience (round (average m-str m-dex))))
+						  (break)
+						  (remove-object-attribute (player-place player)
+							  'monster monster)
+						  (break)
+						  (add-player-experience player experience)
+						  (format t "~&You killed the monster!")
+						  (format t "~A points experience." experience))))
+			((minusp damage)
+				(change-player-health player (- 0 damage))
+				(format t "~&You missed. The monster hit!")
+				(format t "~A points damage." damage))
+			(t (format t "~&You missed. The monster missed.")))))
+
+(defun calculate-damage (att-str att-weapon def-dex def-ac)
+	"A private function to calculate the damage caused by an attack"
+	(let ((damage 0))
+		(incf damage (random att-str))
+		(incf damage (weapon-damage att-weapon))
+		(decf damage (random def-dex))
+		(decf damage def-ac)
+		(if (minusp damage) 0 damage)))
diff --git a/lisp/util.lisp b/lisp/util.lisp
index 4437124..3ad8306 100644
--- a/lisp/util.lisp
+++ b/lisp/util.lisp
@@ -106,6 +106,10 @@
 	;; Perhaps not very clean, but it works
 	(eval `(,function-name ,@args)))
 
+(defun average (&rest numbers)
+	"Compute the average of the given numbers"
+	(/ (reduce #'+ numbers) (length numbers)))
+
 (defun keys (assoc-list)
 	"Return a list of the keys in an association list"
 	(if (null assoc-list) NIL
@@ -145,6 +149,10 @@
 		(dotimes (i (length char-list) s)
 			(setf (aref s i) (nth i char-list)))))
 
+(defun trim-whitespace (s)
+	"Trim off spaces and tabs before and after string s"
+	(string-trim '(#\space #\tab) s))
+
 (defun to-string (x)
 	"Whatever x is, convert it into a string"
 	(cond ((stringp x) x)
@@ -182,6 +190,16 @@
 	(dolist (line (load-text-file file-name))
 		(unless (null line) (format t "~%~A" line))))
 
+(defun write-to-file (text filename &optional (append NIL))
+	"Write text (a string or list of strings) to the specified file"
+	(let ((text-list (if (listp text) text (list text)))
+			 (f (if append
+					(open filename :direction :output :if-exists :append)
+					(open filename :direction :output))))
+		(dolist (line text-list)
+			(format f "~&~A~&" line))
+		(close f)))
+
 (defun build-symbol (&rest components)
 	"Concatenate the passed components into a single symbol"
 	(read-from-string (string-from-list components "")))