Skip to content
Snippets Groups Projects
Commit e668f4ee authored by xo30xoqa's avatar xo30xoqa
Browse files

Wrote skylark nesting phase

parent 99fafcf3
Branches
Tags
No related merge requests found
......@@ -69,10 +69,14 @@ export
@killother,
@reproduce,
@migrate,
@occupy,
@isoccupied,
@vacate,
@habitat,
@landcover,
@cropname,
@cropheight,
@cropcover,
@directionto,
@distanceto,
@distancetoedge,
......
......@@ -199,3 +199,16 @@ function cropheight(pos::Tuple{Int64,Int64}, model::SimulationModel)
ismissing(model.landscape[pos...].fieldid) ? nothing :
model.farmplots[model.landscape[pos...].fieldid].height
end
"""
cropcover(model, position)
Return the percentage ground cover of the crop at this position, or nothing if there is no crop
here (utility wrapper).
"""
function cropcover(pos::Tuple{Int64,Int64}, model::SimulationModel)
#FIXME LAItotal != ground cover?
ismissing(model.landscape[pos...].fieldid) ? nothing :
model.farmplots[model.landscape[pos...].fieldid].LAItotal
end
......@@ -348,7 +348,7 @@ end
"""
@cropheight
Return the height of the crop at this position, or 0 if there is no crop here.
Return the height of the crop at this position, or nothing if there is no crop here.
This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
......@@ -356,6 +356,17 @@ macro cropheight()
:(cropheight($(esc(:pos)), $(esc(:model))))
end
"""
@cropcover
Return the percentage ground cover of the crop at this position, or nothing if there is no crop
here. This is a utility wrapper that can only be used nested within [`@phase`](@ref)
or [`@habitat`](@ref).
"""
macro cropcover()
:(cropcover($(esc(:pos)), $(esc(:model))))
end
"""
@directionto
......@@ -468,6 +479,7 @@ used nested within [`@phase`](@ref).
macro walk(args...)
#XXX add `ifempty` keyword?
:(walk!($(esc(:self)), $(esc(:model)), $(map(esc, args)...)))
#FIXME MethodError: no method matching walk!(::Persefone.Skylark, ::AgricultureModel, ::Tuple{UnitRange{Int64}, UnitRange{Int64}}) -> due to map(esc())?
end
#TODO add own walking functions that respect habitat descriptors
......
......@@ -31,8 +31,8 @@ At the moment, this implementation is still in development.
"""
@species Skylark begin
# species parameters
const movementrange = 500m #XXX arbitrary
const visionrange = 200m #XXX arbitrary
const movementrange::Length = 500m #XXX arbitrary
const visionrange::Length = 200m #XXX arbitrary
const eggtime::Int64 = 11 # days from laying to hatching
const nestlingtime::UnitRange{Int64} = 7:11 # days from hatching to leaving nest
......@@ -55,7 +55,7 @@ At the moment, this implementation is still in development.
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
const breedingdelay::Int64 = 18 # days after hatching before starting a new brood
const breedingdelay::Int64 = 18 # days after hatching before starting a new brood #XXX ??
const nestingend::Int64 = July # last month of nesting
# individual variables
......@@ -74,7 +74,7 @@ end
#TODO respect habitat when moving
"""
As a non-breeding adult, move around with other individuals and check for migration.
Non-breeding adults move around with other individuals and check for migration.
"""
@phase Skylark nonbreeding begin
# flocking behaviour - follow a random neighbour or move randomly
......@@ -91,27 +91,45 @@ As a non-breeding adult, move around with other individuals and check for migrat
@kill(self.migrationmortality, "migration")
returndate = Date(year(model.date)+1, arrive[1], arrive[2])
self.sex == male ?
@setphase(territory-search) :
@setphase(mate-search)
@setphase(territorysearch) :
@setphase(matesearch)
@migrate(returndate)
end
end
@phase Skylark territory-search begin
#TODO move around, searching for a suitable area to establish a territory
"""
Males returning from migration move around to look for suitable habitats to establish a territory.
"""
@phase Skylark territorysearch begin
#TODO
#TODO Standorttreue
# If we've found a territory, or the breeding season is over, move to the next phase
if !isempty(self.territory)
@setphase(occupation)
elseif month(model.date) > nestingend
elseif month(model.date) > self.nestingend
@setphase(nonbreeding)
else
@walk("random", self.movementrange)
#FIXME MethodError: no method matching walk!(::Persefone.Skylark, ::AgricultureModel, ::Tuple{UnitRange{Int64}, UnitRange{Int64}})
end
end
@phase Skylark mate-search begin
"""
Once a male has found a territory, he remains in it until the breeding season is over,
adjusting it to new conditions when and as necessary.
"""
@phase Skylark occupation begin
#move to a random location in the territory
@move(@rand(self.territory))
#TODO adjust territory as needed
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
# look for a mate among the neighbouring birds, or move randomly
for n in @neighbours(self.visionrange)
......@@ -124,10 +142,7 @@ end
end
#@debug("$(animalid(self)) didn't find a mate.")
if self.mate != -1
mon, day = monthday(model.date)
nest = ((mon == self.nestingbegin[1] && day >= self.nestingbegin[2]
&& @chance(0.1)) || (mon > self.nestingbegin[1])) #XXX magic number
nest && @setphase(breeding)
@setphase(nesting)
elseif month(model.date) > self.nestingend # stop trying to find a mate if it's too late
@setphase(nonbreeding)
else
......@@ -135,25 +150,60 @@ end
end
end
@phase Skylark occupation begin
#move to a random location in the territory
@move(@rand(self.territory))
#TODO adjust territory as needed
"""
Females that have found a partner build a nest and lay eggs in a suitable location.
"""
@phase Skylark nesting begin
if model.date < Date(year(model.date), self.nestingbegin...)
# wait for nesting to begin, moving around in the territory
@move(@rand(@animal(self.mate).territory))
elseif isempty(nest)
# choose site, build nest & lay eggs
for pos in @shuffle!(deepcopy(@animal(self.mate).territory))
#TODO is this condition correct? -> needs validation!
if (@landcover() == grass || @landcover() == soil ||
(@landcover() == agriculture &&
(self.nestingheight[1] <= @cropheight() <= self.nestingheight[2]) &&
(self.nestingcover[1] <= @cropcover() <= self.nestingcover[2])))
@move(pos)
self.nest = pos
self.clutch = @rand(self.eggsperclutch)
timer = self.nestbuildingtime + self.clutch # time to build + 1 day per egg laid
if month(model.date) == self.nestingbegin[1]
# the first nest takes twice as long to build
#XXX this may affect the first two nests
timer += self.nestbuildingtime
end
break
end
end
isempty(nest) && @warn("$(animalid(self)) didn't find a nesting location.")
elseif timer == 0
@debug("$(animalid(self)) has laid $(self.clutch) eggs.")
@setphase(breeding)
else
self.timer -= 1
end
# tillage and harvest destroys the nest
@respond(tillage, nest = ())
@respond(harvesting, nest = ())
end
"""
Females that have laid eggs take care of their chicks, restarting the nesting process once the
chicks are independent or in case of brood loss.
"""
@phase Skylark breeding begin
if isempty(nest)
#TODO choose site, build nest & lay eggs
elseif clutch > 0
#TODO wait for eggs to hatch & chicks to mature, checking for mortality
#TODO wait for eggs to hatch & chicks to mature, checking for mortality
# restart breeding cycle if there is time
if clutch == 0 && month(model.date) <= self.nestingend
@setphase(nesting) #TODO breeding delay?
elseif month(model.date) > self.nestingend
#TODO restart cycle, if time
@setphase(nonbreeding)
end
end
## SUPPORTING FUNCTIONS
"""
......@@ -215,8 +265,8 @@ should currently be on migration. Also sets other individual-specific variables.
returndate = Date(year(model.date), arrive[1], arrive[2])
model.date != @param(core.startdate) && (returndate += Year(1))
self.sex == male ?
@setphase(territory-search) :
@setphase(mate-search)
@setphase(territorysearch) :
@setphase(matesearch)
@migrate(returndate)
end
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment