diff --git a/biomes.lisp b/biomes.lisp
index 65fd733..0c1ad51 100644
--- a/biomes.lisp
+++ b/biomes.lisp
@@ -12,7 +12,7 @@
 (defstruct biome
 	(name "")
 	(ground "")
-	(occupants '()) ;an alist of possible occupants and their probabilities
+	(features '()) ;an alist of possible features and their 1/p probabilities
 	(char #\.) ;default map display character
 	(col ':white)) ;default map display colour
 
@@ -37,28 +37,30 @@
 	:name "grassland"
 	:ground "tall elephant grass"
 	:char #\; :col ':yellow
-	:occupants '((acacia 5) (boulder 1))) ;TODO
+	:features '((acacia 20) (boulder 100))) ;TODO
 
 (new-biome 'forest
 	:name "forest"
 	:ground "leaf litter and small shrubs"
 	:char #\. :col ':green
-	:occupants '((miombo 20) (acacia 10))) ;TODO
+	:features '((miombo 5) (acacia 10))) ;TODO
 
 (new-biome 'stream
 	:name "stream"
 	:ground "shallow flowing water"
 	:char #\~ :col ':blue
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'swamp
 	:name "swamp"
 	:ground "short sedge grass growing on boggy black soil"
 	:char #\w :col ':green
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'hill
 	:name "hill"
 	:ground "hard, stony soil"
 	:char #\m :col ':white
-	:occupants '((boulder 15))) ;TODO
+	:features '((boulder 7))) ;TODO
+
+;;TODO desert

diff --git a/biomes.lisp b/biomes.lisp
index 65fd733..0c1ad51 100644
--- a/biomes.lisp
+++ b/biomes.lisp
@@ -12,7 +12,7 @@
 (defstruct biome
 	(name "")
 	(ground "")
-	(occupants '()) ;an alist of possible occupants and their probabilities
+	(features '()) ;an alist of possible features and their 1/p probabilities
 	(char #\.) ;default map display character
 	(col ':white)) ;default map display colour
 
@@ -37,28 +37,30 @@
 	:name "grassland"
 	:ground "tall elephant grass"
 	:char #\; :col ':yellow
-	:occupants '((acacia 5) (boulder 1))) ;TODO
+	:features '((acacia 20) (boulder 100))) ;TODO
 
 (new-biome 'forest
 	:name "forest"
 	:ground "leaf litter and small shrubs"
 	:char #\. :col ':green
-	:occupants '((miombo 20) (acacia 10))) ;TODO
+	:features '((miombo 5) (acacia 10))) ;TODO
 
 (new-biome 'stream
 	:name "stream"
 	:ground "shallow flowing water"
 	:char #\~ :col ':blue
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'swamp
 	:name "swamp"
 	:ground "short sedge grass growing on boggy black soil"
 	:char #\w :col ':green
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'hill
 	:name "hill"
 	:ground "hard, stony soil"
 	:char #\m :col ':white
-	:occupants '((boulder 15))) ;TODO
+	:features '((boulder 7))) ;TODO
+
+;;TODO desert
diff --git a/items.lisp b/items.lisp
index ee75e07..b9291cb 100644
--- a/items.lisp
+++ b/items.lisp
@@ -15,6 +15,7 @@
 		(cassoc symbol-name item-list))
 
 	(defun get-item (symbol-name)
+		;;FIXME copy-item doesn't work with CLOS
 		(copy-item (get-item-type symbol-name))))
 
 (defmacro new-item (type name &body body)
@@ -54,19 +55,24 @@
 	:name "acacia"
 	:description "A tall acacia tree, spreading its branches wide."
 	:destroy-with '(wood)
-	:drops '(wood) :weight 2000)
+	:drops '(wood) :weight 2000
+	:char #\T :color :green)
 
 (new-item 'feature 'miombo
 	:name "miombo"
 	:description "A small, crooked miombo tree."
 	:destroy-with '(wood)
-	:drops '(wood) :weight 500)
+	:drops '(wood) :weight 500
+	:char #\Y :color :green)
 
 (new-item 'feature 'boulder
 	:name "boulder"
 	:description "A huge lump of grey basalt, sticking out of the ground."
 	:destroy-with '(stone)
-	:drops '(stone) :weight 5000)
+	:drops '(stone) :weight 5000
+	:char #\8 :color :gray)
+
+;;TODO termite hill, palm, baobab, cactus, pond
 
 ;;; TOOL ITEMS
 

diff --git a/biomes.lisp b/biomes.lisp
index 65fd733..0c1ad51 100644
--- a/biomes.lisp
+++ b/biomes.lisp
@@ -12,7 +12,7 @@
 (defstruct biome
 	(name "")
 	(ground "")
-	(occupants '()) ;an alist of possible occupants and their probabilities
+	(features '()) ;an alist of possible features and their 1/p probabilities
 	(char #\.) ;default map display character
 	(col ':white)) ;default map display colour
 
@@ -37,28 +37,30 @@
 	:name "grassland"
 	:ground "tall elephant grass"
 	:char #\; :col ':yellow
-	:occupants '((acacia 5) (boulder 1))) ;TODO
+	:features '((acacia 20) (boulder 100))) ;TODO
 
 (new-biome 'forest
 	:name "forest"
 	:ground "leaf litter and small shrubs"
 	:char #\. :col ':green
-	:occupants '((miombo 20) (acacia 10))) ;TODO
+	:features '((miombo 5) (acacia 10))) ;TODO
 
 (new-biome 'stream
 	:name "stream"
 	:ground "shallow flowing water"
 	:char #\~ :col ':blue
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'swamp
 	:name "swamp"
 	:ground "short sedge grass growing on boggy black soil"
 	:char #\w :col ':green
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'hill
 	:name "hill"
 	:ground "hard, stony soil"
 	:char #\m :col ':white
-	:occupants '((boulder 15))) ;TODO
+	:features '((boulder 7))) ;TODO
+
+;;TODO desert
diff --git a/items.lisp b/items.lisp
index ee75e07..b9291cb 100644
--- a/items.lisp
+++ b/items.lisp
@@ -15,6 +15,7 @@
 		(cassoc symbol-name item-list))
 
 	(defun get-item (symbol-name)
+		;;FIXME copy-item doesn't work with CLOS
 		(copy-item (get-item-type symbol-name))))
 
 (defmacro new-item (type name &body body)
@@ -54,19 +55,24 @@
 	:name "acacia"
 	:description "A tall acacia tree, spreading its branches wide."
 	:destroy-with '(wood)
-	:drops '(wood) :weight 2000)
+	:drops '(wood) :weight 2000
+	:char #\T :color :green)
 
 (new-item 'feature 'miombo
 	:name "miombo"
 	:description "A small, crooked miombo tree."
 	:destroy-with '(wood)
-	:drops '(wood) :weight 500)
+	:drops '(wood) :weight 500
+	:char #\Y :color :green)
 
 (new-item 'feature 'boulder
 	:name "boulder"
 	:description "A huge lump of grey basalt, sticking out of the ground."
 	:destroy-with '(stone)
-	:drops '(stone) :weight 5000)
+	:drops '(stone) :weight 5000
+	:char #\8 :color :gray)
+
+;;TODO termite hill, palm, baobab, cactus, pond
 
 ;;; TOOL ITEMS
 
diff --git a/terranostra.lisp b/terranostra.lisp
index 075a37f..e4857d3 100644
--- a/terranostra.lisp
+++ b/terranostra.lisp
@@ -1,7 +1,7 @@
 ;;;;
 ;;;; Terra Nostra is a Minecraft-like survival game for the commandline.
 ;;;;
-;;;; This is the main program file.
+;;;; This is the main program file with the user interface.
 ;;;;
 ;;;; (c) 2018 Daniel Vedder, MIT license
 ;;;;
@@ -73,16 +73,22 @@
 			(dotimes (w (- (floor (/ (.width win) 2)) 1))
 				(let ((p (coord (+ w x0 1) (+ h y0 1))))
 					(if (null p) (add-char win #\space)
-						;;TODO draw features
 						(if (and (= (first (patch-pos p)) (first me))
 								(= (second (patch-pos p)) (second me)))
 							(progn (setf (.color-pair win) '(:white :black))
 								(add-char win #\X))
-							(progn
-								(setf (.color-pair win)
-									(list (biome-col (patch-biome p)) :black))
-								(add-char win
-									(biome-char (patch-biome p))))))
+							(if (patch-occupant p)
+								(progn ;FIXME throws an error
+									(setf (.color-pair win)
+										(list (.color (patch-occupant p))
+											:black))
+									(add-char win (.char (patch-occupant p))))
+								(progn
+									(setf (.color-pair win)
+										(list (biome-col (patch-biome p))
+											:black))
+									(add-char win
+										(biome-char (patch-biome p)))))))
 					(add-char win #\space)))
 			(setf (.cursor-position win) (list (+ h 1) 1)))
 		(refresh win)))

diff --git a/biomes.lisp b/biomes.lisp
index 65fd733..0c1ad51 100644
--- a/biomes.lisp
+++ b/biomes.lisp
@@ -12,7 +12,7 @@
 (defstruct biome
 	(name "")
 	(ground "")
-	(occupants '()) ;an alist of possible occupants and their probabilities
+	(features '()) ;an alist of possible features and their 1/p probabilities
 	(char #\.) ;default map display character
 	(col ':white)) ;default map display colour
 
@@ -37,28 +37,30 @@
 	:name "grassland"
 	:ground "tall elephant grass"
 	:char #\; :col ':yellow
-	:occupants '((acacia 5) (boulder 1))) ;TODO
+	:features '((acacia 20) (boulder 100))) ;TODO
 
 (new-biome 'forest
 	:name "forest"
 	:ground "leaf litter and small shrubs"
 	:char #\. :col ':green
-	:occupants '((miombo 20) (acacia 10))) ;TODO
+	:features '((miombo 5) (acacia 10))) ;TODO
 
 (new-biome 'stream
 	:name "stream"
 	:ground "shallow flowing water"
 	:char #\~ :col ':blue
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'swamp
 	:name "swamp"
 	:ground "short sedge grass growing on boggy black soil"
 	:char #\w :col ':green
-	:occupants '()) ;TODO
+	:features '()) ;TODO
 
 (new-biome 'hill
 	:name "hill"
 	:ground "hard, stony soil"
 	:char #\m :col ':white
-	:occupants '((boulder 15))) ;TODO
+	:features '((boulder 7))) ;TODO
+
+;;TODO desert
diff --git a/items.lisp b/items.lisp
index ee75e07..b9291cb 100644
--- a/items.lisp
+++ b/items.lisp
@@ -15,6 +15,7 @@
 		(cassoc symbol-name item-list))
 
 	(defun get-item (symbol-name)
+		;;FIXME copy-item doesn't work with CLOS
 		(copy-item (get-item-type symbol-name))))
 
 (defmacro new-item (type name &body body)
@@ -54,19 +55,24 @@
 	:name "acacia"
 	:description "A tall acacia tree, spreading its branches wide."
 	:destroy-with '(wood)
-	:drops '(wood) :weight 2000)
+	:drops '(wood) :weight 2000
+	:char #\T :color :green)
 
 (new-item 'feature 'miombo
 	:name "miombo"
 	:description "A small, crooked miombo tree."
 	:destroy-with '(wood)
-	:drops '(wood) :weight 500)
+	:drops '(wood) :weight 500
+	:char #\Y :color :green)
 
 (new-item 'feature 'boulder
 	:name "boulder"
 	:description "A huge lump of grey basalt, sticking out of the ground."
 	:destroy-with '(stone)
-	:drops '(stone) :weight 5000)
+	:drops '(stone) :weight 5000
+	:char #\8 :color :gray)
+
+;;TODO termite hill, palm, baobab, cactus, pond
 
 ;;; TOOL ITEMS
 
diff --git a/terranostra.lisp b/terranostra.lisp
index 075a37f..e4857d3 100644
--- a/terranostra.lisp
+++ b/terranostra.lisp
@@ -1,7 +1,7 @@
 ;;;;
 ;;;; Terra Nostra is a Minecraft-like survival game for the commandline.
 ;;;;
-;;;; This is the main program file.
+;;;; This is the main program file with the user interface.
 ;;;;
 ;;;; (c) 2018 Daniel Vedder, MIT license
 ;;;;
@@ -73,16 +73,22 @@
 			(dotimes (w (- (floor (/ (.width win) 2)) 1))
 				(let ((p (coord (+ w x0 1) (+ h y0 1))))
 					(if (null p) (add-char win #\space)
-						;;TODO draw features
 						(if (and (= (first (patch-pos p)) (first me))
 								(= (second (patch-pos p)) (second me)))
 							(progn (setf (.color-pair win) '(:white :black))
 								(add-char win #\X))
-							(progn
-								(setf (.color-pair win)
-									(list (biome-col (patch-biome p)) :black))
-								(add-char win
-									(biome-char (patch-biome p))))))
+							(if (patch-occupant p)
+								(progn ;FIXME throws an error
+									(setf (.color-pair win)
+										(list (.color (patch-occupant p))
+											:black))
+									(add-char win (.char (patch-occupant p))))
+								(progn
+									(setf (.color-pair win)
+										(list (biome-col (patch-biome p))
+											:black))
+									(add-char win
+										(biome-char (patch-biome p)))))))
 					(add-char win #\space)))
 			(setf (.cursor-position win) (list (+ h 1) 1)))
 		(refresh win)))
diff --git a/world.lisp b/world.lisp
index bb4e9c4..2102747 100644
--- a/world.lisp
+++ b/world.lisp
@@ -122,8 +122,15 @@
 	(with-open-file (tf file-name :direction :output)
 		(print-topography tf)))
 
+(defun get-patch-feature (patch)
+	"Find a random feature (or none) to occupy this patch."
+	(let ((flist (biome-features (patch-biome patch))))
+		(dolist (f flist NIL)
+			(when (chancep (second f))
+				(return-from get-patch-feature (first f))))))
+
 (defun generate-biomes (size-factor world)
-	;;XXX The maps this produces don't look as expected, but for
+	;;XXX The maps this produces don't look quite as expected, but for
 	;; current purposes they are good enough
 	(debugging "~&Generating biomes") ;debug
 	(let* ((world-size (length world)) (seeds NIL)
@@ -142,9 +149,10 @@
 		;;For each patch, calculate the closest seed and set to that biome
 		(dotimes (x world-size)
 			(dotimes (y world-size)
-				(let ((b (third (closest-coords (list x y) seeds T))))
-					(setf (patch-biome (coord x y world))
-						(get-biome b)))))))
+				(let ((p (coord x y world))
+						 (b (third (closest-coords (list x y) seeds T))))
+					(setf (patch-biome p) (get-biome b))
+					(setf (patch-occupant p) (get-patch-feature p)))))))
 	
 (defun generate-stream (x0 y0 world)
 	(debugging "~&Generating a stream, starting at ~S/~S" x0 y0) ;debug
@@ -153,20 +161,8 @@
 			 (patch (coord x0 y0 world) (neighbour patch dir world)))
 		((or (null patch) (eq (patch-biome patch) (get-biome 'stream))))
 		(setf (patch-biome patch) (get-biome 'stream))))
-	
-(defun generate-stream-broad (x0 y0 world &optional (broad NIL))
-	(debugging "~&Generating a stream, starting at ~S/~S" x0 y0) ;debug
-	;;FIXME adjacent needs a second one if going diagonally
-	(do* ((dir (random-elt *directions*)
-			  (if (probabilityp 75) dir (next-dir dir (random-elt '(T NIL)))))
-			 (patch (coord x0 y0 world) (neighbour patch dir world))
-			 (adjacent (when patch (neighbour patch (if (diagonalp dir) (next-dir dir) (orth-dir dir)) world))
-				 (when patch (neighbour patch (if (diagonalp dir) (next-dir dir) (orth-dir dir)) world))))
-		((or (null patch) (eq (patch-biome patch) (get-biome 'stream))))
-		(setf (patch-biome patch) (get-biome 'stream))
-		(when (and broad adjacent)
-			(debugging "~&~S~%~S" (patch-pos patch) (patch-pos adjacent))
-			(setf (patch-biome adjacent) (get-biome 'stream)))))
+
+;;TODO create animal herds
 
 (defun create-world (size)
 	(let ((world (init-matrix size)))