diff --git a/Project.toml b/Project.toml
index 10e11cc5f83ee4dca77654ae4817288137df499d..7ed919c23cd1e7263a9b8ee27ecf4c985995b394 100644
--- a/Project.toml
+++ b/Project.toml
@@ -1,7 +1,7 @@
 name = "Persefone"
 uuid = "039acd1d-2a07-4b33-b082-83a1ff0fd136"
 authors = ["Daniel Vedder <daniel.vedder@idiv.de>"]
-version = "0.3.6"
+version = "0.4.0"
 
 [deps]
 Agents = "46ada45e-f475-11e8-01d0-f70cc89e6671"
diff --git a/src/Persefone.jl b/src/Persefone.jl
index e02955ff3b27961baa22986d16a3c25f11287eac..cc6fef76642118c4b4c8c2b33fb756f8aa1992e2 100644
--- a/src/Persefone.jl
+++ b/src/Persefone.jl
@@ -110,7 +110,7 @@ include("nature/ecologicaldata.jl")
 # for f in readdir("nature/species", join=true)
 #     endswith(f, ".jl") && include(f)
 # end
-#include("nature/species/skylark.jl")
+include("nature/species/skylark.jl")
 include("nature/species/wolpertinger.jl")
 include("nature/species/wyvern.jl")
 
diff --git a/src/nature/nature.jl b/src/nature/nature.jl
index b9e96ee85b2ac4c335e0ced081ae1d444ae55869..4fca51f3ded4ee9dd79429a8dfea10d54dfe5739 100644
--- a/src/nature/nature.jl
+++ b/src/nature/nature.jl
@@ -95,7 +95,7 @@ Run processes that affect all animals.
 function updatenature!(model::AgentBasedModel)
     # The migrant pool is sorted by date of return, so we can simply look at the top
     # of the stack to check whether any animals are returning today.
-    while !isempty(model.migrants) && model.migrants[1].second == model.date
+    while !isempty(model.migrants) && model.migrants[1].second <= model.date
         add_agent_pos!(model.migrants[1].first, model)
         @debug "$(animalid(model.migrants[1].first)) has returned."
         deleteat!(model.migrants, 1)
diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl
index 98d71935b57d9e2ab79c1b0653cdbc13aa26807f..5b0a2e82cab5360c61a1737f6c77c50b38c11322 100644
--- a/src/nature/species/skylark.jl
+++ b/src/nature/species/skylark.jl
@@ -25,7 +25,7 @@ At the moment, this implementation is still in development.
     migrationdates = ()
 
     habitats = @habitat((@landcover() == grass || 
-                         (@landcover() == agriculture && @croptype() != maize)) &&
+                         (@landcover() == agriculture && @cropname() != "maize")) &&
                         @distanceto(forest) > 5)
     
     @initialise(habitats, pairs=true, initfunction=initskylark)
@@ -69,13 +69,18 @@ Initialise a skylark individual. Selects migration dates and checks if the
 bird should currently be on migration.
 """
 function initskylark(animal::Animal, model::AgentBasedModel)
+    @debug "Added $(animalid(animal)) at $(animal.pos)"
     animal.migrationdates = migrationdates(animal, model)
     leave = animal.migrationdates[1]
     arrive = animal.migrationdates[2]
     m, d = monthday(model.date)
     migrate = (((m < arrive[1]) || (m == arrive[1] && d < arrive[2])) ||
                ((m > leave[1]) || (m == leave[1] && d >= leave[2])))
-    migrate && @migrate(Date(year(model.date)+year(1), arrive[1], arrive[2]))
+    if migrate
+        returndate = Date(year(model.date), arrive[1], arrive[2])
+        model.date != @param(core.startdate) && (returndate += Year(1))
+        @migrate(returndate)
+    end
     #TODO other stuff?
 end
 
@@ -90,7 +95,7 @@ function migrationdates(skylark::Animal, model::AgentBasedModel)
     minarrive = skylark.sex == male ? (2, 15) : (3, 1)
     deltaleave = @rand(0:45) #XXX ought to be normally distributed
     deltaarrive = @rand(0:15) #XXX ought to be normally distributed
-    leave = monthday(Date(2000, minleave[1], minleave[2]) + Day(deltaleave))
-    arrive = monthday(Date(2000, minarrive[1], minarrive[2]) + Day(deltaarrive))
+    leave = monthday(Date(2001, minleave[1], minleave[2]) + Day(deltaleave))
+    arrive = monthday(Date(2001, minarrive[1], minarrive[2]) + Day(deltaarrive))
     (leave, arrive)
 end
diff --git a/test/io_tests.jl b/test/io_tests.jl
index aa45dd2dc483b78b9fee327eab0ac51652394d19..734ee7844566ddf2eb6cc01cd421204d9d253084 100644
--- a/test/io_tests.jl
+++ b/test/io_tests.jl
@@ -67,6 +67,8 @@ end
 @testset "Model object serialization" begin
     model = inittestmodel()
     Ps.createdatadir(@param(core.outdir), true)
+    originalenddate = @param(core.enddate)
+    @param(core.enddate) = Date(year(model.date), 2, 5)
     @test_logs((:debug, "Saved model object to results_testsuite/test.dat."),
                min_level=Logging.Debug, match_mode=:any,
                savemodelobject(model, "test"))
@@ -75,11 +77,12 @@ end
     @test model.date == model2.date
     @test model.settings == model2.settings
     @test length(model.agents) == length(model2.agents)
-    simulate!(model)
-    simulate!(model2)
+    simulate!(Ps.withtestlogger(model))
+    simulate!(Ps.withtestlogger(model2))
     @test model.date == model2.date
     @test length(model.agents) == length(model2.agents)
     rm(@param(core.outdir), force=true, recursive=true)
+    @param(core.enddate) = originalenddate
 end
 
 @testset "Output visualisation" begin
diff --git a/test/landscape_tests.jl b/test/landscape_tests.jl
index aaf1f8e4628538c16601e2fdc20bdc67f18bbe8a..3a29f872a27dea2af4b5c60b662692dbd1caeae3 100644
--- a/test/landscape_tests.jl
+++ b/test/landscape_tests.jl
@@ -42,7 +42,8 @@ end
 
 @testset "Landscape functions" begin
     model = inittestmodel()
-    @test Ps.distanceto((2,3), model, Ps.forest) == 0
+    @test Ps.distanceto((2,3), model, Ps.agriculture) == 0
+    @test Ps.distanceto((2,3), model, Ps.forest) == 2
     @test Ps.distanceto((2,3), model, Ps.grass) == 2
     @test Ps.distanceto((2,3), model, Ps.water) == 4
     @test Ps.distanceto((2,3), model, Ps.soil) == Inf
diff --git a/test/nature_tests.jl b/test/nature_tests.jl
index 1d6276b05a591bd374d4e18e2464182f9fcdb765..dddbb64ada3a88773f37efcdafbfab46e518a577 100644
--- a/test/nature_tests.jl
+++ b/test/nature_tests.jl
@@ -39,7 +39,7 @@ end
     species::Dict{String,Any} = Dict("name"=>spec)
     # create a set of initialisation functions
     initfun1 = Ps.initrandompopulation(10)
-    initfun2 = Ps.initrandompopulation(6*6*3, asexual=true)
+    initfun2 = Ps.initrandompopulation(8*8*3, asexual=true)
     initfun3 = Ps.initpopulation(@habitat(@landcover() == Ps.grass), pairs=true)
     initfun4 = Ps.initpopulation(@habitat(@landcover() == Ps.water &&
                                           @countanimals(species="test_animal", radius=0) < 5),
@@ -48,12 +48,12 @@ end
     @test_logs (:info, "Initialised 10 $(spec)s.") initfun1(species, model)
     @test all(a -> a.sex in (Ps.male, Ps.female), allagents(model))
     genocide!(model)
-    @test_logs (:info, "Initialised 108 $(spec)s.") initfun2(species, model)
+    @test_logs (:info, "Initialised 192 $(spec)s.") initfun2(species, model)
     @test Ps.countanimals((1,1), model, species=spec, radius=0) ==
         Ps.countanimals((6,6), model, species=spec, radius=0) == 3
     @test all(a -> a.sex == Ps.hermaphrodite, allagents(model))
     genocide!(model)
-    @test_logs (:info, "Initialised 16 $(spec)s.") initfun3(species, model)
+    @test_logs (:info, "Initialised 36 $(spec)s.") initfun3(species, model)
     @test Ps.countanimals((2,2), model, species=spec, radius=2) ==
         Ps.countanimals((5,3), model, species=spec, radius=1) == 0
     @test Ps.countanimals((5,5), model, species=spec, radius=0) ==
@@ -192,3 +192,30 @@ end
     #TODO
                                   
 end
+
+@testset "Skylark submodel" begin
+    # set up a modified test landscape
+    model = inittestmodel()
+    model.landscape[3,7] = Pixel(Ps.forest, missing, [])
+    species = Ps.Skylark(model)
+    # test migration
+    @test_logs((:info, "Initialised 2 Skylarks."),
+               (:debug, "Skylark 1 has migrated."),
+               (:debug, "Skylark 2 has migrated."),
+               min_level=Logging.Debug, match_mode=:any,
+               species["initialise!"](species, Ps.withtestlogger(model)))    
+    @test nagents(model) == 0
+    @test length(model.migrants) == 2
+    @test model.migrants[1].first.sex != model.migrants[2].first.sex
+    for a in model.migrants
+        leave, arrive = a.first.migrationdates
+        @test leave[1] in (9, 10) || (leave[1] == 11 && leave[2] <= 15)
+        @test (arrive[1] == 2 && arrive[2] >= 15) || (arrive[1] == 3 && arrive[2] <= 15)
+    end
+    model.date = Date(year(model.date), 3, 17)
+    @test_logs((:debug, "Skylark 1 has returned."),
+               (:debug, "Skylark 2 has returned."),
+               min_level=Logging.Debug, match_mode=:any,
+               Ps.updatenature!(Ps.withtestlogger(model)))
+    #TODO
+end
diff --git a/test/runtests.jl b/test/runtests.jl
index 78d32931d147e946905dfd86d639bf908cc6c397..4636903dfea5c7034e079cbae9f42b5eec5c95fc 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -58,20 +58,25 @@ end
 """
     smalltestlandscape()
 
-Create a 6x6 landscape with three land cover types for testing:
+Create a 8x8 landscape with five land cover types for testing:
 
-    F F F F F F
-    F F F F F F
-    F F F F F F
-    F F F F F W
-    F F G G G G
-    F F G G G G
+    A A A A A A A A
+    A A A A A A A A
+    A A A A A A A A
+    A A A A A W A A
+    F F G G G G G G
+    F F G G G G G G
+    F F G G G G G G
+    B B B B B B B B
 """
 function smalltestlandscape()
-    landscape = Matrix{Pixel}(undef, 6, 6)
-    for x in 1:6
-        for y in 1:6
-            (x in (1:2) || y in (1:4)) ? lc = Ps.forest : lc = Ps.grass
+    landscape = Matrix{Pixel}(undef, 8, 8)
+    for x in 1:8
+        for y in 1:8
+            (y in (1:4)) ? lc = Ps.agriculture :
+                (x in (1:2)) ? lc = Ps.forest :
+                (y == 8) ? lc = Ps.builtup :
+                lc = Ps.grass
             landscape[x,y] = Pixel(lc, missing, [])
         end
     end