From fc239eaaa3fb14d60adf3afa9bdb0ee7035680d7 Mon Sep 17 00:00:00 2001 From: Daniel Vedder <daniel.vedder@idiv.de> Date: Mon, 5 Aug 2024 15:14:06 +0200 Subject: [PATCH] Bug fixes in the skylark model --- src/nature/individuals.jl | 10 +++++++--- src/nature/populations.jl | 2 +- src/nature/species/skylark.jl | 17 ++++++++--------- src/world/landscape.jl | 2 +- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/nature/individuals.jl b/src/nature/individuals.jl index 8ba9098..934d219 100644 --- a/src/nature/individuals.jl +++ b/src/nature/individuals.jl @@ -76,14 +76,18 @@ end """ occupy!(animal, model, position) -Add the given location to the animal's territory. +Add the given location to the animal's territory. Returns `true` if successful +(i.e. if the location was not already occupied by a conspecific), `false` if not. """ function occupy!(animal::Animal, model::SimulationModel, position::Tuple{Int64,Int64}) if isoccupied(model, speciesof(animal), position) #XXX should this be an error? @warn "Position $position is already occupied by a $(speciesof(animal))." animal + return false + else + push!(animal.territory, position) + push!(model.landscape[position...].territories, animalid(animal)) + return true end - push!(animal.territory, position) - push!(model.landscape[position...].territories, animal.id) end """ diff --git a/src/nature/populations.jl b/src/nature/populations.jl index f3c7bed..a31a840 100644 --- a/src/nature/populations.jl +++ b/src/nature/populations.jl @@ -146,7 +146,7 @@ Test whether this location is part of the territory of an animal of the given sp """ function isoccupied(model::SimulationModel, species::String, position::Tuple{Int64,Int64}) for id in model.landscape[position...].territories - (speciesof(model.animals[id]) == species) && return true + occursin(species, id) && return true end return false end diff --git a/src/nature/species/skylark.jl b/src/nature/species/skylark.jl index 87ac542..dfd8f2f 100644 --- a/src/nature/species/skylark.jl +++ b/src/nature/species/skylark.jl @@ -77,6 +77,7 @@ 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 end @@ -140,8 +141,7 @@ adjusting it to new conditions when and as necessary. @move(@rand(self.territory)) if model.date > self.nestingend # once the breeding season is over and all the young have left the nest, stop breeding - #FIXME under which conditions would @animal(self.mate) == nothing? - if self.mate == -1 || !isnothing(@animal(self.mate)) || @animal(self.mate).clutch == 0 + if self.mate == -1 || isnothing(@animal(self.mate)) || @animal(self.mate).clutch == 0 @setphase(nonbreeding) end end @@ -162,8 +162,8 @@ Females returning from migration move around to look for a suitable partner with @setphase(nesting) return else - self.mate = -1 @animal(self.mate).mate = -1 + self.mate = -1 end else self.mate = -1 @@ -279,7 +279,7 @@ If it is, return the list of coordinates that make up the new territory, else re function findterritory(skylark::Skylark, model::SimulationModel) effectivesize::Area = 0m² # the usable size of the territory, weighted by habitat quality territory::Vector{Tuple{Int64,Int64}} = [] - msize = size(model.landscape) + width, height = size(model.landscape) radius = 0 constrained = false # Inspect the landscape in concentric circles around the individual until enough pixels have @@ -304,7 +304,7 @@ function findterritory(skylark::Skylark, model::SimulationModel) end #FIXME some duplicates remain? for c in coords # ...then inspect them - (c[1] <= 0 || c[2] <= 0 || c[1] > msize[1] || c[2] > msize[2]) && continue + (c[1] <= 0 || c[2] <= 0 || c[1] > width || c[2] > height) && continue (isoccupied(model, "Skylark", c)) && continue push!(territory, c) quality = foragequality(skylark, model, c) @@ -347,10 +347,9 @@ function allowsnesting(skylark::Skylark, model::SimulationModel, pos::Tuple{Int6 (@landcover() == grass || (@landcover() == agriculture && (skylark.nestingheight[1] <= @cropheight() <= skylark.nestingheight[2]) && - (skylark.nestingcover[1] <= @cropcover() <= skylark.nestingcover[2]))) #&& - #FIXME if we add the distance requirement, females don't find a nesting spot? - #(@distanceto(forest) < skylark.mindistancetoedge) && - #(@distanceto(builtup) < skylark.mindistancetoedge) + (skylark.nestingcover[1] <= @cropcover() <= skylark.nestingcover[2])) && + (@distanceto(forest) < skylark.mindistancetoedge) && + (@distanceto(builtup) < skylark.mindistancetoedge)) end """ diff --git a/src/world/landscape.jl b/src/world/landscape.jl index b6fc167..762ea8b 100644 --- a/src/world/landscape.jl +++ b/src/world/landscape.jl @@ -22,7 +22,7 @@ mutable struct Pixel fieldid::Union{Missing,Int64} # ID of the farmplot (if any) at this position events::Vector{Management} # management events that have been applied to this pixel animals::Vector{Int64} # IDs of animals currently at this position - territories::Vector{Int64} # IDs of animals that claim this pixel as part of their territory + territories::Vector{String} # IDs of animals that claim this pixel as part of their territory end Pixel(landcover::LandCover, fieldid::Union{Missing,Int64}) = -- GitLab