diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl index fd366abce096f32624e59b06446c93bc68e081b5..606ebc478ecad982421ba6d38cdbbd0218251cb0 100644 --- a/src/nature/species/skylark.jl +++ b/src/nature/species/skylark.jl @@ -52,7 +52,8 @@ At the moment, this implementation is still in development. const maxforagecover = 0.7 # maximum preferred vegetation cover for foraging const nestingheight = (15cm, 25cm) # min and max preferred vegetation height for nesting const nestingcover = (0.2, 0.5) # min and max preferred vegetation cover for nesting - + + const matefaithfulness = 0.5 # chance of a female retaining her previous partner const nestingbegin::Tuple{Int64,Int64} = (April, 10) # begin nesting in the middle of April const nestbuildingtime::UnitRange{Int64} = 4:5 # 4-5 days needed to build a nest (doubled for first nest) const eggsperclutch::UnitRange{Int64} = 2:5 # eggs laid per clutch @@ -85,16 +86,13 @@ Non-breeding adults move around with other individuals and check for migration. @follow(@rand(neighbours), 30m) #XXX magic number # check if the bird migrates leave, arrive = self.migrationdates - month, day = monthday(model.date) - migrate = (((month < arrive[1]) || (month == arrive[1] && day < arrive[2])) || - ((month > leave[1]) || (month == leave[1] && day >= leave[2]))) - if migrate + if leave <= model.date < arrive @kill(self.migrationmortality, "migration") - returndate = Date(year(model.date)+1, arrive[1], arrive[2]) self.sex == male ? @setphase(territorysearch) : @setphase(matesearch) - @migrate(returndate) + @migrate(arrive) + self.migrationdates = self.migrationdates .+ Year(1) end end @@ -136,22 +134,35 @@ end Females returning from migration move around to look for a suitable partner with a territory. """ @phase Skylark matesearch begin - #TODO move around, looking for a male with an established territory - #TODO teilweise Partnertreue - + if self.mate != -1 # if the female already had a partner last year... + if isalive(@animal(self.mate)) + if @chance(self.matefaithfulness) + # ...check if he is still alive and the female wants to stay with him + #XXX is mate-faithfulness decided by the female when she returns, + # or by the male taking whichever female comes to him first? + @debug "$(animalid(self)) and $(animalid(n)) have mated again." + @setphase(nesting) + return + else + self.mate = -1 + @animal(self.mate).mate = -1 + end + else + self.mate = -1 + end + end # look for a mate among the neighbouring birds, or move randomly for n in @neighbours(self.visionrange) if n.sex == male && n.mate == -1 && n.phase == occupation - self.mate = n.id + self.mate = n.id #XXX may be the old partner again by chance n.mate = self.id + @setphase(nesting) @debug "$(animalid(self)) and $(animalid(n)) have mated." - break + return end end #@debug("$(animalid(self)) didn't find a mate.") - if self.mate != -1 - @setphase(nesting) - elseif month(model.date) > self.nestingend # stop trying to find a mate if it's too late + if month(model.date) > self.nestingend # stop trying to find a mate if it's too late @setphase(nonbreeding) else @walk("random", self.movementrange) @@ -225,8 +236,8 @@ function migrationdates(skylark::Skylark, model::SimulationModel) minarrive = skylark.sex == male ? (February, 15) : (March, 1) deltaleave = @rand(0:45) #XXX ought to be normally distributed deltaarrive = @rand(0:15) #XXX ought to be normally distributed - leave = monthday(Date(2001, minleave[1], minleave[2]) + Day(deltaleave)) - arrive = monthday(Date(2001, minarrive[1], minarrive[2]) + Day(deltaarrive)) + leave = Date(year(model.date), minleave[1], minleave[2]) + Day(deltaleave)) + arrive = Date(year(model.date)+1, minarrive[1], minarrive[2]) + Day(deltaarrive)) (leave, arrive) end @@ -266,13 +277,11 @@ function findterritory(skylark::Skylark, model::SimulationModel) for c in coords # ...then inspect them (c[1] <= 0 || c[2] <= 0 || c[1] > msize[1] || c[2] > msize[2]) && continue (isoccupied(model, "Skylark", c)) && continue + push!(territory, c) quality = foragequality(skylark, model, c) + effectivesize += @param(world.mapresolution)^2*quality + (quality > 0) && (constrained = false) #XXX check for nesting habitats? - if quality > 0 - constrained = false - push!(territory, c) - effectivesize += @param(world.mapresolution)^2*quality - end end radius +=1 end @@ -329,18 +338,14 @@ should currently be on migration. Also sets other individual-specific variables. """ @create Skylark begin @debug "Added $(animalid(self)) at $(self.pos)" - self.migrationdates = migrationdates(self, model) #XXX should be dynamic + self.migrationdates = migrationdates(self, model) .- Year(1) #XXX should be dynamic leave, arrive = self.migrationdates - mon, day = monthday(model.date) - migrate = (((mon < arrive[1]) || (mon == arrive[1] && day < arrive[2])) || - ((mon > leave[1]) || (mon == leave[1] && day >= leave[2]))) - if migrate - returndate = Date(year(model.date), arrive[1], arrive[2]) - model.date != @param(core.startdate) && (returndate += Year(1)) + if leave <= model.date < arrive self.sex == male ? @setphase(territorysearch) : @setphase(matesearch) - @migrate(returndate) + @migrate(arrive) + self.migrationdates = self.migrationdates .+ Year(1)) end end