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

Wrote skylark nesting phase

parent 99fafcf3
No related branches found
No related tags found
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.
Finish editing this message first!
Please register or to comment