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

Added parent field to animals

parent fb3407cc
Branches
Tags
No related merge requests found
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
## An enum used to assign a sex to each animal ## An enum used to assign a sex to each animal
@enum Sex hermaphrodite male female @enum Sex hermaphrodite male female
#XXX hermaphrodite probably is not needed and its implementation is iffy
""" """
Animal Animal
...@@ -24,13 +25,15 @@ i.e. the trait `phase` can be accessed and modified with `animal.phase`.) ...@@ -24,13 +25,15 @@ i.e. the trait `phase` can be accessed and modified with `animal.phase`.)
#XXX add `phase` and `species` (rather than `name`) directly to the struct? #XXX add `phase` and `species` (rather than `name`) directly to the struct?
traits::Dict{String,Any} traits::Dict{String,Any}
energy::Union{EnergyBudget,Nothing} # DEB is optional energy::Union{EnergyBudget,Nothing} # DEB is optional
parents::Tuple{Int64,Int64} #XXX two parents for hermaphrodites?
sex::Sex sex::Sex
age::Int age::Int
end end
# DEB is optional # DEB is optional
Animal(id::Int64, pos::Tuple{Int64,Int64}, traits::Dict{String,Any}, Animal(id::Int64, pos::Tuple{Int64,Int64}, traits::Dict{String,Any},
sex::Sex, age::Int) = Animal(id, pos, traits, nothing, sex, age) parents::Tuple{Int64,Int64}, sex::Sex, age::Int) =
Animal(id, pos, traits, nothing, parents, sex, age)
# Overloading the `getproperty` and `setproperty!` methods for `Animal` allows # Overloading the `getproperty` and `setproperty!` methods for `Animal` allows
# us to write `animal.property` instead of `animal.traits["property"]`. # us to write `animal.property` instead of `animal.traits["property"]`.
......
...@@ -20,8 +20,10 @@ This can be used to create the `initialise!` variable in a species definition bl ...@@ -20,8 +20,10 @@ This can be used to create the `initialise!` variable in a species definition bl
- `popsize` determines the number of individuals that will be created. If this is zero or - `popsize` determines the number of individuals that will be created. If this is zero or
negative, one individual will be created in every suitable location in the landscape. negative, one individual will be created in every suitable location in the landscape.
If `popsize` is greater than the number of suitable locations, multiple individuals If `popsize` is greater than the number of suitable locations, multiple individuals
will be created in one place. (Maximum population density can be set in the habitat will be created in one place.
descriptor using the [`@countanimals`](@ref) macro.)
- `popdensity`: if this is greater than zero, the chance of creating an individual (or
pair of individuals) at a suitable location is 1/popdensity.
- If `pairs` is true, a male and a female individual will be created in each selected - If `pairs` is true, a male and a female individual will be created in each selected
location, otherwise, only one individual will be created at a time. location, otherwise, only one individual will be created at a time.
...@@ -35,8 +37,8 @@ This can be used to create the `initialise!` variable in a species definition bl ...@@ -35,8 +37,8 @@ This can be used to create the `initialise!` variable in a species definition bl
individual has been created and placed. individual has been created and placed.
""" """
function initpopulation(habitatdescriptor::Function; phase::Union{String,Nothing}=nothing, function initpopulation(habitatdescriptor::Function; phase::Union{String,Nothing}=nothing,
popsize::Int64=-1, pairs::Bool=false, asexual::Bool=false, popsize::Int64=-1, popdensity::Int64=-1, pairs::Bool=false,
initfunction::Function=(a,m)->nothing) asexual::Bool=false, initfunction::Function=(a,m)->nothing)
#TODO add a constructor function for the individual? #TODO add a constructor function for the individual?
function(species::Dict{String,Any}, model::AgentBasedModel) function(species::Dict{String,Any}, model::AgentBasedModel)
n = 0 n = 0
...@@ -47,18 +49,20 @@ function initpopulation(habitatdescriptor::Function; phase::Union{String,Nothing ...@@ -47,18 +49,20 @@ function initpopulation(habitatdescriptor::Function; phase::Union{String,Nothing
while n == 0 || n < popsize while n == 0 || n < popsize
for x in @shuffle!(Vector(1:width)) for x in @shuffle!(Vector(1:width))
for y in @shuffle!(Vector(1:height)) for y in @shuffle!(Vector(1:height))
if habitatdescriptor((x,y), model) if habitatdescriptor((x,y), model) &&
(popdensity <= 0 || @chance(1/popdensity)) #XXX what if pd==0?
if pairs if pairs
a1 = add_agent!((x,y), Animal, model, a1 = add_agent!((x,y), Animal, model, deepcopy(species),
deepcopy(species), female, 0) (-1,-1), female, 0)
a2 = add_agent!((x,y), Animal, model, a2 = add_agent!((x,y), Animal, model, deepcopy(species),
deepcopy(species), male, 0) (-1, -1), male, 0)
initfunction(a1, model) initfunction(a1, model)
initfunction(a2, model) initfunction(a2, model)
n += 2 n += 2
else else
sex = asexual ? hermaphrodite : @rand([male, female]) sex = asexual ? hermaphrodite : @rand([male, female])
a = add_agent!((x,y),Animal,model,deepcopy(species),sex,0) a = add_agent!((x,y), Animal, model, deepcopy(species),
(-1, -1), sex,0)
initfunction(a, model) initfunction(a, model)
n += 1 n += 1
end end
...@@ -92,16 +96,18 @@ end ...@@ -92,16 +96,18 @@ end
#XXX initpopulation based on known occurences in real-life? #XXX initpopulation based on known occurences in real-life?
""" """
reproduce!(animal, model, n=1) reproduce!(animal, model, mate, n=1)
Produce one or more offspring for the given animal at its current location. Produce one or more offspring for the given animal at its current location.
The `mate` argument gives the ID of the reproductive partner.
""" """
function reproduce!(animal::Animal, model::AgentBasedModel, n::Int64=1) function reproduce!(animal::Animal, model::AgentBasedModel, mate::Int64, n::Int64=1)
(animal.sex == male) && @warn "Male $(animalid(animal)) is reproducing."
for i in 1:n for i in 1:n
sex = (animal.sex == hermaphrodite) ? hermaphrodite : @rand([male, female]) sex = (animal.sex == hermaphrodite) ? hermaphrodite : @rand([male, female])
# We need to generate a fresh species dict here # We need to generate a fresh species dict here
species = @eval $(Symbol(animal.traits["name"]))($model) species = @eval $(Symbol(animal.traits["name"]))($model)
add_agent!(animal.pos, Animal, model, species, sex, 0) add_agent!(animal.pos, Animal, model, species, (animal.id, mate), sex, 0)
end end
@debug "$(animalid(animal)) has reproduced." @debug "$(animalid(animal)) has reproduced."
end end
......
...@@ -31,7 +31,7 @@ of a deer. ...@@ -31,7 +31,7 @@ of a deer.
if @rand() < @trait(fecundity) && if @rand() < @trait(fecundity) &&
@countanimals(species="Wolpertinger") < @trait(crowding) @countanimals(species="Wolpertinger") < @trait(crowding)
@reproduce @reproduce(-1)
end end
@kill @trait(mortality) @kill @trait(mortality)
......
...@@ -61,7 +61,7 @@ legs, but that doesn't make it any less dangerous... ...@@ -61,7 +61,7 @@ legs, but that doesn't make it any less dangerous...
end end
# reproduce every once in a blue moon # reproduce every once in a blue moon
@label reproduce @label reproduce
(@rand() < @trait(fecundity)) && @reproduce (@rand() < @trait(fecundity)) && @reproduce(-1)
# hibernate from November to March # hibernate from November to March
if monthday(model.date) == (11,1) if monthday(model.date) == (11,1)
@trait(phase) = "winter" @trait(phase) = "winter"
......
...@@ -21,9 +21,9 @@ startdate = 2022-01-01 ...@@ -21,9 +21,9 @@ startdate = 2022-01-01
enddate = 2022-12-31 enddate = 2022-12-31
[world] [world]
landcovermap = "data/regions/jena/landcover.tif" # location of the landcover map landcovermap = "data/regions/jena-small/landcover.tif" # location of the landcover map
farmfieldsmap = "data/regions/jena/fields.tif" # location of the field geometry map farmfieldsmap = "data/regions/jena-small/fields.tif" # location of the field geometry map
weatherfile = "data/regions/jena/weather.csv" # location of the weather data file weatherfile = "data/regions/jena-small/weather.csv" # location of the weather data file
[farm] [farm]
farmmodel = "FieldManager" # which version of the farm model to use (not yet implemented) farmmodel = "FieldManager" # which version of the farm model to use (not yet implemented)
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
### This file manages the landscape maps that underlie the model. ### This file manages the landscape maps that underlie the model.
### ###
## IMPORTANT: do not change the order of this enum, or initlandscape() will break!
"The land cover classes encoded in the Mundialis Sentinel data." "The land cover classes encoded in the Mundialis Sentinel data."
@enum LandCover nodata forest grass water builtup soil agriculture @enum LandCover nodata forest grass water builtup soil agriculture
## Do not change the order of this enum, or initlandscape() will break!
"The types of landscape event that can be simulated" "The types of landscape event that can be simulated"
@enum EventType tillage sowing fertiliser pesticide harvesting @enum EventType tillage sowing fertiliser pesticide harvesting
...@@ -160,6 +160,7 @@ Calculate the distance from the given location to the closest habitat of the spe ...@@ -160,6 +160,7 @@ Calculate the distance from the given location to the closest habitat of the spe
Caution: can be computationally expensive! Caution: can be computationally expensive!
""" """
function distanceto(pos::Tuple{Int64,Int64}, model::AgentBasedModel, habitattype::LandCover) function distanceto(pos::Tuple{Int64,Int64}, model::AgentBasedModel, habitattype::LandCover)
#XXX allow testing for multiple habitat types?
# can't use @habitat here because nature.jl is loaded later than this file # can't use @habitat here because nature.jl is loaded later than this file
distanceto(pos, model, function(p,m) landcover(p,m) == habitattype end) distanceto(pos, model, function(p,m) landcover(p,m) == habitattype end)
end end
......
...@@ -83,7 +83,7 @@ end ...@@ -83,7 +83,7 @@ end
@debug "Animal: $animal" @debug "Animal: $animal"
if @trait(sex) == Persefone.female && @countanimals() < 3 && if @trait(sex) == Persefone.female && @countanimals() < 3 &&
@trait(age) >= @trait(ageofmaturity) && @landcover() == Persefone.water @trait(age) >= @trait(ageofmaturity) && @landcover() == Persefone.water
@reproduce() @reproduce(-1)
end end
end end
@phase drought begin @phase drought begin
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment