From 61505db66bccc1f685a6292c4cd59aca43d0c701 Mon Sep 17 00:00:00 2001 From: Daniel Vedder <daniel.vedder@idiv.de> Date: Tue, 6 Aug 2024 10:13:43 +0200 Subject: [PATCH] Non-breeding skylarks only look once for a neighbour to follow --- src/nature/species/skylark.jl | 53 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl index dfd8f2f..cced022 100644 --- a/src/nature/species/skylark.jl +++ b/src/nature/species/skylark.jl @@ -36,27 +36,25 @@ Ecology and Evolution, 12(1), e8461. https://doi.org/10.1002/ece3.8461 """ @species Skylark begin - # species parameters - const movementrange::Length = 500m #XXX arbitrary - const visionrange::Length = 200m #XXX arbitrary - + ## SPECIES PARAMETERS + + # juveniles const eggtime::Int64 = 11 # days from laying to hatching const nestlingtime::Int64 = 9 # days from hatching to leaving nest const fledglingtime::Int64 = 21 # days from leaving the nest to independence - #XXX predation mortality should be habitat-dependent const eggpredationmortality::Float64 = 0.03 # per-day egg mortality from predation const nestlingpredationmortality::Float64 = 0.03 # per-day nestling mortality from predation const fledglingpredationmortality::Float64 = 0.01 # per-day fledgling mortality from predation const firstyearmortality::Float64 = 0.38 # total mortality in the first year after independence - # skylarks migrate from autumn to early spring, with the females leaving earlier - # and arriving later than the males + # migration const migrationdeparture::Tuple{AnnualDate,AnnualDate} = ((September, 15), (November, 1)) const migrationarrival::Tuple{AnnualDate,AnnualDate} = ((February, 15), (March, 1)) const migrationdelayfemales::Day = Day(15) const migrationmortality::Float64 = 0.33 # chance of dying during the winter + # habitat requirements const minimumterritory = 5000m² # size of territory under ideal conditions const mindistancetoedge = 60m # minimum distance of habitat to vertical structures const maxforageheight = 50cm # maximum preferred vegetation height for foraging @@ -64,20 +62,26 @@ 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 + # breeding const matefaithfulness = 0.5 # chance of a female retaining her previous partner const nestingbegin::Tuple{AnnualDate,AnnualDate} = ((April, 10), (April, 20)) # 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 const nestingend::AnnualDate = (August, 15) # end of the nesting period - - # individual variables + + # mating / non-breeding + const movementrange::Length = 500m #XXX arbitrary + const visionrange::Length = 200m #XXX arbitrary + const flockingdistance::Length = 30m #XXX arbitrary + + ## INDIVIDUAL VARIABLES timer::Int64 = 0 # a counter that can be used for different purposes firstnest::AnnualDate = (April, 15) # is redefined by each individual in @create(Skylark) migrationdates::Tuple = () # is defined by each individual in @create(Skylark) mate::Int64 = -1 # the agent ID of the mate (-1 if none) nest::Tuple = () # coordinates of current nest clutch::Int64 = 0 # number and life stage of offspring in current clutch - #following::Int64 = -1 # ID of the individual being followed in the non-breeding phase + following::Int64 = -1 # ID of the individual being followed in the non-breeding phase end @@ -89,26 +93,27 @@ end Non-breeding adults move around with other individuals and check for migration. """ @phase Skylark nonbreeding begin - #FIXME searching for neighbours is *the* performance bottleneck!! - # Two options: - # (a) ignore flocking, simply move randomly (scientifically OK, doesn't look as good) - # (b) select a random neighbour once, then keep following that individual - - # flocking behaviour - follow a random neighbour or move randomly - neighbours = () - #neighbours = @neighbours(self.visionrange) #XXX check for the closest neighbour(s)? - isempty(neighbours) ? - @walk("random", self.movementrange) : - @follow(@rand(neighbours), 30m) #XXX magic number # check if the bird migrates - arrive, depart = self.migrationdates - if model.date >= depart + if model.date >= self.migrationdates[2] @kill(self.migrationmortality, "migration") self.sex == male ? @setphase(territorysearch) : @setphase(matesearch) - @migrate(arrive) + @migrate(self.migrationdates[1]) + return + end + # flocking behaviour - follow a neighbour or move randomly + self.following > 0 && isnothing(@animal(self.following)) && (self.following = -1) + if self.following == -1 + neighbours = @neighbours(self.visionrange) + if isempty(neighbours) + @walk("random", self.movementrange) + return + else + self.following = @rand(neighbours).id + end end + @follow(@animal(self.following), self.flockingdistance) end """ -- GitLab