diff --git a/creatur.cabal b/creatur.cabal
--- a/creatur.cabal
+++ b/creatur.cabal
@@ -1,5 +1,5 @@
 Name:              creatur
-Version:           5.0.1
+Version:           5.2.0
 Stability:         experimental
 Synopsis:          Framework for artificial life experiments.
 Description:       A software framework for automating experiments
@@ -52,10 +52,11 @@
                     ALife.Creatur.Genetics.Code,
                     ALife.Creatur.Genetics.BRGCBool,
                     ALife.Creatur.Genetics.BRGCWord8,
+                    ALife.Creatur.Genetics.BRGCWord16,
                     ALife.Creatur.Genetics.Diploid,
                     ALife.Creatur.Genetics.Recombination,
-                    ALife.Creatur.Genetics.Reproduction.Asexual,
                     ALife.Creatur.Genetics.Reproduction.Sexual,
+                    ALife.Creatur.Genetics.Reproduction.SimplifiedSexual,
                     ALife.Creatur.Logger,
                     ALife.Creatur.Universe,
                     ALife.Creatur.Task,
@@ -112,4 +113,5 @@
                     ALife.Creatur.Genetics.DiploidQC,
                     ALife.Creatur.Genetics.BRGCBoolQC
                     ALife.Creatur.Genetics.BRGCWord8QC
+                    ALife.Creatur.Genetics.BRGCWord16QC
                     ALife.Creatur.Genetics.RecombinationQC
diff --git a/src/ALife/Creatur/Genetics/Analysis.hs b/src/ALife/Creatur/Genetics/Analysis.hs
--- a/src/ALife/Creatur/Genetics/Analysis.hs
+++ b/src/ALife/Creatur/Genetics/Analysis.hs
@@ -21,7 +21,7 @@
 import GHC.Generics
 
 class Analysable g where
-  -- | Writes a gene to a sequence.
+  -- | Analyses a genetic sequence.
   analyse :: g -> String
 
   default analyse :: (Generic g, GAnalysable (Rep g)) => g -> String
diff --git a/src/ALife/Creatur/Genetics/BRGCWord16.hs b/src/ALife/Creatur/Genetics/BRGCWord16.hs
new file mode 100644
--- /dev/null
+++ b/src/ALife/Creatur/Genetics/BRGCWord16.hs
@@ -0,0 +1,287 @@
+------------------------------------------------------------------------
+-- |
+-- Module      :  ALife.Creatur.Genetics.BRGCWord16
+-- Copyright   :  (c) Amy de Buitléir 2013
+-- License     :  BSD-style
+-- Maintainer  :  amy@nualeargais.ie
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- Utilities for working with genes that are encoded as a sequence of
+-- 16-bit words, using a Binary Reflected Gray Code (BRGC).
+--
+-- A Gray code maps values to codes in a way that guarantees that the
+-- codes for two consecutive values will differ by only one bit. This
+-- feature can be useful in evolutionary programming because the genes
+-- resulting from a crossover operation are likely to be similar to
+-- the inputs. This helps to ensure that offspring are similar to
+-- their parents, as any radical changes from one generation to the
+-- next are the result of mutation alone.
+--
+------------------------------------------------------------------------
+{-# LANGUAGE TypeFamilies, FlexibleContexts, FlexibleInstances,
+    DefaultSignatures, DeriveGeneric, TypeOperators #-}
+module ALife.Creatur.Genetics.BRGCWord16
+  (
+    Genetic(..),
+    Sequence,
+    Writer,
+    write,
+    runWriter,
+    Reader,
+    read,
+    runReader,
+    copy,
+    consumed,
+    DiploidSequence,
+    DiploidReader,
+    readAndExpress,
+    runDiploidReader,
+    getAndExpress,
+    getAndExpressWithDefault,
+    copy2,
+    consumed2,
+    putRawWord16,
+    getRawWord16,
+    putRawWord16s,
+    getRawWord16s
+  ) where
+
+import Prelude hiding (read)
+import ALife.Creatur.Genetics.Diploid (Diploid, express)
+import ALife.Creatur.Util (fromEither)
+import Codec.Gray (integralToGray, grayToIntegral)
+import Control.Applicative ((<$>), (<*>))
+import Control.Monad.State.Lazy (StateT, runState, execState, evalState)
+import qualified Control.Monad.State.Lazy as S (put, get, gets)
+import Data.Char (ord, chr)
+import Data.Functor.Identity (Identity)
+import Data.Word (Word8, Word16)
+import GHC.Generics
+
+type Sequence = [Word16]
+
+type Writer = StateT Sequence Identity
+
+write :: Genetic x => x -> Sequence
+write x = execState (put x) []
+
+runWriter :: Writer () -> Sequence
+runWriter w = execState w []
+
+type Reader = StateT (Sequence, Int) Identity
+
+read :: Genetic g => Sequence -> Either [String] g
+read s = evalState get (s, 0)
+
+runReader :: Reader g -> Sequence -> g
+runReader r s = evalState r (s, 0)
+
+-- | Return the entire genome.
+copy :: Reader Sequence
+copy = S.gets fst
+
+-- | Return the portion of the genome that has been read.
+consumed :: Reader Sequence
+consumed = do
+  (xs, i) <- S.get
+  return $ take i xs
+
+-- | A class representing anything which is represented in, and
+--   determined by, an agent's genome.
+--   This might include traits, parameters, "organs" (components of
+--   agents), or even entire agents.
+--   Instances of this class can be thought of as genes, i.e.,
+--   instructions for building an agent.
+class Genetic g where
+  -- | Writes a gene to a sequence.
+  put :: g -> Writer ()
+
+  default put :: (Generic g, GGenetic (Rep g)) => g -> Writer ()
+  put = gput . from
+
+  -- | Reads the next gene in a sequence.
+  get :: Reader (Either [String] g)
+
+  default get :: (Generic g, GGenetic (Rep g)) => Reader (Either [String] g)
+  get = do
+    a <- gget
+    return $ fmap to a
+
+  getWithDefault :: g -> Reader g
+  getWithDefault d = fmap (fromEither d) get
+
+class GGenetic f where
+  gput :: f a -> Writer ()
+  gget :: Reader (Either [String] (f a))
+
+-- | Unit: used for constructors without arguments
+instance GGenetic U1 where
+  gput U1 = return ()
+  gget = return (Right U1)
+
+-- | Constants, additional parameters and recursion of kind *
+instance (GGenetic a, GGenetic b) => GGenetic (a :*: b) where
+  gput (a :*: b) = gput a >> gput b
+  gget = do
+    a <- gget
+    b <- gget
+    return $ (:*:) <$> a <*> b
+
+-- | Meta-information (constructor names, etc.)
+instance (GGenetic a, GGenetic b) => GGenetic (a :+: b) where
+  gput (L1 x) = putRawWord16 0 >> gput x
+  gput (R1 x) = putRawWord16 1 >> gput x
+  gget = do
+    a <- getRawWord16
+    case a of
+      Right x -> do
+        if even x -- Only care about the last bit
+          then fmap (fmap L1) gget
+          else fmap (fmap R1) gget
+      Left s -> return $ Left s
+
+-- | Sums: encode choice between constructors
+instance (GGenetic a) => GGenetic (M1 i c a) where
+  gput (M1 x) = gput x
+  gget = fmap (fmap M1) gget
+
+-- | Products: encode multiple arguments to constructors
+instance (Genetic a) => GGenetic (K1 i a) where
+  gput (K1 x) = put x
+  gget = do
+    a <- get
+    return $ fmap K1 a
+
+--
+-- Instances
+--
+
+instance Genetic Bool where
+  put False = putRawWord16 0
+  put True  = putRawWord16 1
+  get = fmap (fmap word16ToBool) getRawWord16
+
+word16ToBool :: Word16 -> Bool
+word16ToBool x = if even x then False else True
+
+instance Genetic Char where
+  put = putRawWord16 . fromIntegral . ord
+  get = fmap (fmap (chr . fromIntegral)) getRawWord16
+
+instance Genetic Word8 where
+  put x = put (fromIntegral x :: Word16)
+  get = do
+    x <- get :: Reader (Either [String] Word16)
+    return $ fmap fromIntegral x
+
+instance Genetic Word16 where
+  put = putRawWord16 . integralToGray
+  get = fmap (fmap grayToIntegral) getRawWord16
+
+instance (Genetic a) => Genetic [a]
+
+instance (Genetic a) => Genetic (Maybe a)
+
+instance (Genetic a, Genetic b) => Genetic (a, b)
+
+instance (Genetic a, Genetic b) => Genetic (Either a b)
+
+
+--
+-- Utilities
+--
+
+-- | Write a Word16 value to the genome without encoding it
+putRawWord16 :: Word16 -> Writer ()
+putRawWord16 x = do
+  xs <- S.get
+  S.put (xs ++ [x])
+
+-- | Read a Word16 value from the genome without decoding it
+getRawWord16 :: Reader (Either [String] Word16)
+getRawWord16 = do
+  (xs, i) <- S.get
+  let xs' = drop i xs
+  if null xs'
+     then return $ Left ["End of sequence"]
+     else do
+       let x = head xs'
+       S.put (xs, i+1)
+       return $ Right x
+
+-- | Write a raw sequence of Word16 values to the genome
+putRawWord16s :: [Word16] -> Writer ()
+putRawWord16s ys = do
+  xs <- S.get
+  S.put (xs ++ ys)
+
+-- | Read a raw sequence of Word16 values from the genome
+getRawWord16s :: Int -> Reader (Either [String] [Word16])
+getRawWord16s n =
+  if n == 0
+    then return $ Right []
+    else do
+      (xs, i) <- S.get
+      let xs' = drop i xs
+      if null xs' || length xs' < n
+        then return $ Left ["End of genes"]
+        else do
+          let ys = take n xs'
+          S.put (xs, i+n)
+          return $ Right ys
+
+--
+-- Diploid genes
+--
+
+type DiploidSequence = (Sequence, Sequence)
+
+type DiploidReader = StateT ((Sequence, Int), (Sequence, Int)) Identity
+
+readAndExpress :: (Genetic g, Diploid g) => DiploidSequence -> Either [String] g
+readAndExpress (s1, s2) = evalState getAndExpress ((s1, 0), (s2, 0))
+
+runDiploidReader :: DiploidReader g -> DiploidSequence -> g
+runDiploidReader r (s1, s2) = evalState r ((s1, 0), (s2, 0))
+
+-- | Return the entire genome.
+copy2 :: DiploidReader DiploidSequence
+copy2 = do
+  (ra, rb) <- S.get
+  let as = evalState copy ra
+  let bs = evalState copy rb
+  return (as, bs)
+
+-- | Return the portion of the genome that has been read.
+consumed2 :: DiploidReader DiploidSequence
+consumed2 = do
+  (ra, rb) <- S.get
+  let as = evalState consumed ra
+  let bs = evalState consumed rb
+  return (as, bs)
+
+-- | Read the next pair of genes from twin sequences of genetic
+--   information, and return the resulting gene (after taking
+--   into account any dominance relationship) and the remaining
+--   (unread) portion of the two nucleotide strands.
+getAndExpress :: (Genetic g, Diploid g) => DiploidReader (Either [String] g)
+getAndExpress = do
+  (sa, sb) <- S.get
+  let (a, sa') = runState get sa
+  let (b, sb') = runState get sb
+  S.put (sa', sb')
+  return $ expressEither a b
+
+getAndExpressWithDefault :: (Genetic g, Diploid g) => g -> DiploidReader g
+getAndExpressWithDefault d = fmap (fromEither d) getAndExpress
+
+expressEither
+  :: Diploid g
+    => Either [String] g -> Either [String] g
+      -> Either [String] g
+expressEither (Right a) (Right b) = Right (express a b)
+expressEither (Right a) (Left _)  = Right a
+expressEither (Left _)  (Right b) = Right b
+expressEither (Left xs) (Left ys) =
+  Left $ (map ("sequence 1: " ++) xs) ++ (map ("sequence 2: " ++) ys)
diff --git a/src/ALife/Creatur/Genetics/Reproduction/Asexual.hs b/src/ALife/Creatur/Genetics/Reproduction/Asexual.hs
deleted file mode 100644
--- a/src/ALife/Creatur/Genetics/Reproduction/Asexual.hs
+++ /dev/null
@@ -1,66 +0,0 @@
-------------------------------------------------------------------------
--- |
--- Module      :  ALife.Creatur.Genetics.Reproduction.Asexual
--- Copyright   :  (c) Amy de Buitléir 2012-2013
--- License     :  BSD-style
--- Maintainer  :  amy@nualeargais.ie
--- Stability   :  experimental
--- Portability :  portable
---
--- A reproduction method for artificial lifeforms where:
---
--- * Each agent has a /single/ strand of genetic information.
---
--- * Each child has two parents.
---
--- * Each parent contributes approximately half of its genetic
---   information to the offspring.
---
-------------------------------------------------------------------------
-{-# LANGUAGE TypeFamilies #-}
-module ALife.Creatur.Genetics.Reproduction.Asexual
-  (
-    Reproductive(..)
-  ) where
-
-import ALife.Creatur (AgentId)
-import Control.Monad.Random (Rand, RandomGen)
-
--- | A species that reproduces, transmitting genetic information to
---   its offspring. Minimal complete definition: all except @mate@.
-class Reproductive a where
-
-  -- | A sequence of hereditary information for an agent.
-  type Base a
-
-  -- | Recombines the genetic information from two parents, creating
-  --   genetic information for potential offspring.
-  --
-  --   Typically this involves the following steps:
-  --
-  --   1. Recombine the two strands of genetic information (one from
-  --      each parent) to obtain two new strands.
-  --
-  --   1. Discard one strand, and return the remaining one.
-  recombine :: RandomGen r => a -> a -> Rand r (Base a)
-
-  -- | Builds an agent based on the genome provided, if it is possible
-  --   to do so.
-  build :: AgentId -> Base a -> Either [String] a
-
-  -- | @'makeOffspring' (parent1, parent2) name@ uses the genetic
-  --   information from @parent1@ and @parent2@ to produce a child with
-  --   the agent ID @name@. The default implementation:
-  --
-  --   1. Calls @'recombine'@ to create a genome for the child.
-  --
-  --   2. Calls @'build'@ to construct a child with this genome.
-  makeOffspring
-    :: RandomGen r
-      => a -> a -> AgentId -> Rand r (Either [String] a)
-  makeOffspring a b name = do
-    g <- recombine a b
-    return $ build name g
-
-
-
diff --git a/src/ALife/Creatur/Genetics/Reproduction/Sexual.hs b/src/ALife/Creatur/Genetics/Reproduction/Sexual.hs
--- a/src/ALife/Creatur/Genetics/Reproduction/Sexual.hs
+++ b/src/ALife/Creatur/Genetics/Reproduction/Sexual.hs
@@ -32,18 +32,18 @@
 
   -- | A sequence of hereditary information for an agent.
   --   The type signature for the agent's genome is 
-  --   (Base a, Base a).
-  type Base a
+  --   (Strand a, Strand a).
+  type Strand a
 
   -- | From the /two/ strands of the genetic information from this 
   --   agent, creates a /single/ strand that will contribute to the
   --   child's genome. 
   --   (This is analogous to creating either a single sperm or ova.)
-  produceGamete :: RandomGen r => a -> Rand r (Base a)
+  produceGamete :: RandomGen r => a -> Rand r (Strand a)
 
   -- | Builds an agent based on the genome provided, if it is possible
   --   to do so.
-  build :: AgentId -> (Base a, Base a) -> Either [String] a
+  build :: AgentId -> (Strand a, Strand a) -> Either [String] a
 
   -- | @'makeOffspring' (parent1, parent2) name@ uses the genetic
   --   information from @parent1@ and @parent2@ to produce a child with
diff --git a/src/ALife/Creatur/Genetics/Reproduction/SimplifiedSexual.hs b/src/ALife/Creatur/Genetics/Reproduction/SimplifiedSexual.hs
new file mode 100644
--- /dev/null
+++ b/src/ALife/Creatur/Genetics/Reproduction/SimplifiedSexual.hs
@@ -0,0 +1,66 @@
+------------------------------------------------------------------------
+-- |
+-- Module      :  ALife.Creatur.Genetics.Reproduction.SimplifiedSexual
+-- Copyright   :  (c) Amy de Buitléir 2012-2013
+-- License     :  BSD-style
+-- Maintainer  :  amy@nualeargais.ie
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- A reproduction method for artificial lifeforms where:
+--
+-- * Each agent has a /single/ strand of genetic information.
+--
+-- * Each child has two parents.
+--
+-- * Each parent contributes approximately half of its genetic
+--   information to the offspring.
+--
+------------------------------------------------------------------------
+{-# LANGUAGE TypeFamilies #-}
+module ALife.Creatur.Genetics.Reproduction.SimplifiedSexual
+  (
+    Reproductive(..)
+  ) where
+
+import ALife.Creatur (AgentId)
+import Control.Monad.Random (Rand, RandomGen)
+
+-- | A species that reproduces, transmitting genetic information to
+--   its offspring. Minimal complete definition: all except @mate@.
+class Reproductive a where
+
+  -- | A sequence of hereditary information for an agent.
+  type Strand a
+
+  -- | Recombines the genetic information from two parents, creating
+  --   genetic information for potential offspring.
+  --
+  --   Typically this involves the following steps:
+  --
+  --   1. Recombine the two strands of genetic information (one from
+  --      each parent) to obtain two new strands.
+  --
+  --   1. Discard one strand, and return the remaining one.
+  recombine :: RandomGen r => a -> a -> Rand r (Strand a)
+
+  -- | Builds an agent based on the genome provided, if it is possible
+  --   to do so.
+  build :: AgentId -> Strand a -> Either [String] a
+
+  -- | @'makeOffspring' (parent1, parent2) name@ uses the genetic
+  --   information from @parent1@ and @parent2@ to produce a child with
+  --   the agent ID @name@. The default implementation:
+  --
+  --   1. Calls @'recombine'@ to create a genome for the child.
+  --
+  --   2. Calls @'build'@ to construct a child with this genome.
+  makeOffspring
+    :: RandomGen r
+      => a -> a -> AgentId -> Rand r (Either [String] a)
+  makeOffspring a b name = do
+    g <- recombine a b
+    return $ build name g
+
+
+
diff --git a/test/ALife/Creatur/Genetics/BRGCWord16QC.hs b/test/ALife/Creatur/Genetics/BRGCWord16QC.hs
new file mode 100644
--- /dev/null
+++ b/test/ALife/Creatur/Genetics/BRGCWord16QC.hs
@@ -0,0 +1,73 @@
+------------------------------------------------------------------------
+-- |
+-- Module      :  ALife.Creatur.Genetics.BRGCWord16QC
+-- Copyright   :  (c) Amy de Buitléir 2013
+-- License     :  BSD-style
+-- Maintainer  :  amy@nualeargais.ie
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- QuickCheck tests.
+--
+------------------------------------------------------------------------
+{-# LANGUAGE DeriveGeneric, FlexibleInstances #-}
+module ALife.Creatur.Genetics.BRGCWord16QC
+  (
+    test
+  ) where
+
+import Prelude hiding (read)
+import ALife.Creatur.Genetics.BRGCWord16
+import ALife.Creatur.Genetics.Analysis (Analysable)
+import Control.Applicative ((<$>), (<*>))
+import Data.Word (Word8, Word16)
+import GHC.Generics (Generic)
+import Test.Framework as TF (Test, testGroup)
+import Test.Framework.Providers.QuickCheck2 (testProperty)
+import Test.QuickCheck (Arbitrary, Gen, Property, arbitrary, choose,
+  oneof, property, sized, vectorOf)
+
+prop_round_trippable :: (Eq g, Genetic g) => g -> Property
+prop_round_trippable g = property $ g' == Right g
+  where x = write g
+        g' = read x
+
+data TestStructure = A | B Bool | C Word16 | D Word8 Char | E [TestStructure]
+  deriving (Show, Eq, Generic)
+
+instance Genetic TestStructure
+instance Analysable TestStructure
+
+sizedArbTestStructure :: Int -> Gen TestStructure
+sizedArbTestStructure 0 =
+  oneof [ return A, B <$> arbitrary, C <$> arbitrary,
+          D <$> arbitrary <*> arbitrary]
+sizedArbTestStructure n = do
+  k <- choose (0,min 8 (n-1))
+  oneof [
+          return A,
+          B <$> arbitrary,
+          C <$> arbitrary,
+          D <$> arbitrary <*> arbitrary,
+          E <$> vectorOf k (sizedArbTestStructure (n-1))
+        ]
+  
+instance Arbitrary TestStructure where
+  arbitrary = sized sizedArbTestStructure
+
+test :: Test
+test = testGroup "ALife.Creatur.Genetics.BRGCWord16QC"
+  [
+    testProperty "prop_round_trippable - Bool"
+      (prop_round_trippable :: Bool -> Property),
+    testProperty "prop_round_trippable - Char"
+      (prop_round_trippable :: Char -> Property),
+    testProperty "prop_round_trippable - Word8"
+      (prop_round_trippable :: Word8 -> Property),
+    testProperty "prop_round_trippable - Word16"
+      (prop_round_trippable :: Word16 -> Property),
+    testProperty "prop_round_trippable - TestStructure"
+      (prop_round_trippable :: TestStructure -> Property)
+  ]
+
+
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -22,6 +22,7 @@
 import ALife.Creatur.Genetics.RecombinationQC (test)
 import ALife.Creatur.Genetics.BRGCBoolQC (test)
 import ALife.Creatur.Genetics.BRGCWord8QC (test)
+import ALife.Creatur.Genetics.BRGCWord16QC (test)
 
 import Test.Framework as TF (defaultMain, Test)
 
@@ -37,7 +38,8 @@
     ALife.Creatur.Genetics.DiploidQC.test,
     ALife.Creatur.Genetics.RecombinationQC.test,
     ALife.Creatur.Genetics.BRGCBoolQC.test,
-    ALife.Creatur.Genetics.BRGCWord8QC.test
+    ALife.Creatur.Genetics.BRGCWord8QC.test,
+    ALife.Creatur.Genetics.BRGCWord16QC.test
   ]
 
 main :: IO ()
