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

Wrote the `nearby_animals()` functions

parent c9d982f1
No related branches found
No related tags found
No related merge requests found
...@@ -126,13 +126,14 @@ animal is in the relevant phase. When it is called, it has access to the followi ...@@ -126,13 +126,14 @@ animal is in the relevant phase. When it is called, it has access to the followi
variables: variables:
- `animal` a reference to the animal itself. This provides access to `animal.age`, - `animal` a reference to the animal itself. This provides access to `animal.age`,
`animal.sex`, and `animal.traits` (a dict that gives access to all species parameters). `animal.sex`, and `animal.traits` (a dict that gives access to all species parameters).
- `pos` gives the animal's current position as a coordinate tuple.
- `model` a reference to the model world (an object of type `AgentBasedModel`). - `model` a reference to the model world (an object of type `AgentBasedModel`).
This allows access to `model.date` (the current simulation date) and This allows access to `model.date` (the current simulation date) and
`model.landscape` (a two-dimensional array of pixels containing geographic `model.landscape` (a two-dimensional array of pixels containing geographic
information). information).
Several utility macros can be used within the body of `@phase` as a short-hand for Several utility macros can be used within the body of `@phase` as a short-hand for
common expressions: `@respond`, `@trait`, `@here`, `@kill`, `@reproduce`. common expressions: `@respond`, `@trait`, `@here`, `@kill`, `@reproduce`, `@neighbours`.
To transition an individual to another phase, simply redefine its phase variable: To transition an individual to another phase, simply redefine its phase variable:
`@trait(phase) = "newphase"`. `@trait(phase) = "newphase"`.
...@@ -140,7 +141,12 @@ To transition an individual to another phase, simply redefine its phase variable ...@@ -140,7 +141,12 @@ To transition an individual to another phase, simply redefine its phase variable
macro phase(name, body) macro phase(name, body)
#XXX make this documentable? #XXX make this documentable?
#FIXME Somehow, errors in the phase body are not shown? #FIXME Somehow, errors in the phase body are not shown?
:($(esc(name)) = function(animal::Animal, model::AgentBasedModel) $body end) quote
$(esc(name)) = function(animal::Animal, model::AgentBasedModel)
$(esc(:pos)) = animal.pos
$body
end
end
end end
""" """
...@@ -201,9 +207,15 @@ macro reproduce(args...) ...@@ -201,9 +207,15 @@ macro reproduce(args...)
:(reproduce!(animal, model, $(args...))) :(reproduce!(animal, model, $(args...)))
end end
#XXX add a macro @f to call a function with animal and model as first parameters? """
# e.g. @f(nearby_agents, distance) @neighbours(radius)
# -> rather create wrapper macros
Return an iterator over all animals in the given radius around this animal, excluding itself.
This can only be used nested within `@phase`.
"""
macro neighbours(radius)
:(nearby_animals(animal, model, $radius))
end
""" """
@habitat @habitat
...@@ -236,11 +248,7 @@ circumvented by directly creating an equivalent function. ...@@ -236,11 +248,7 @@ circumvented by directly creating an equivalent function.
macro habitat(body) macro habitat(body)
quote quote
function($(esc(:pos)), $(esc(:model))) function($(esc(:pos)), $(esc(:model)))
if $(esc(body)) ($(esc(body))) ? return true : return false
return true
else
return false
end
end end
end end
end end
...@@ -249,7 +257,7 @@ end ...@@ -249,7 +257,7 @@ end
@landcover @landcover
Returns the local landcover. This is a utility wrapper that can only be used Returns the local landcover. This is a utility wrapper that can only be used
nested within `@habitat`. nested within `@phase` or `@habitat`.
""" """
macro landcover() macro landcover()
:(landcover($(esc(:pos)), $(esc(:model)))) :(landcover($(esc(:pos)), $(esc(:model))))
...@@ -259,7 +267,7 @@ end ...@@ -259,7 +267,7 @@ end
@croptype @croptype
Return the local croptype, or nothing if there is no crop here. Return the local croptype, or nothing if there is no crop here.
This is a utility wrapper that can only be used nested within `@habitat`. This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
""" """
macro croptype() macro croptype()
:(croptype($(esc(:pos)), $(esc(:model)))) :(croptype($(esc(:pos)), $(esc(:model))))
...@@ -269,27 +277,27 @@ end ...@@ -269,27 +277,27 @@ end
@cropheight @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 0 if there is no crop here.
This is a utility wrapper that can only be used nested within `@habitat`. This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
""" """
macro cropheight() macro cropheight()
:(cropheight($(esc(:pos)), $(esc(:model)))) :(cropheight($(esc(:pos)), $(esc(:model))))
end end
""" """
@distanceto(habitattype) @distanceto(habitat)
Calculate the distance to the closest habitat of the specified type. Calculate the distance to the closest habitat of the specified type or descriptor.
This is a utility wrapper that can only be used nested within `@habitat`. This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
""" """
macro distanceto(habitattype) macro distanceto(habitat)
:(distanceto($(esc(:pos)), $(esc(:model)), $habitattype)) :(distanceto($(esc(:pos)), $(esc(:model)), $habitat))
end end
""" """
@distancetoedge @distancetoedge
Calculate the distance to the closest neighbouring habitat. Calculate the distance to the closest neighbouring habitat.
This is a utility wrapper that can only be used nested within `@habitat`. This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
""" """
macro distancetoedge() macro distancetoedge()
:(distancetoedge($(esc(:pos)), $(esc(:model)))) :(distancetoedge($(esc(:pos)), $(esc(:model))))
...@@ -299,7 +307,7 @@ end ...@@ -299,7 +307,7 @@ end
@countanimals(speciesname) @countanimals(speciesname)
Count the number of animals of the given species in this location. Count the number of animals of the given species in this location.
This is a utility wrapper that can only be used nested within `@habitat`. This is a utility wrapper that can only be used nested within `@phase` or `@habitat`.
""" """
macro countanimals(speciesname) macro countanimals(speciesname)
#XXX this also counts the enquiring agent #XXX this also counts the enquiring agent
......
...@@ -60,14 +60,35 @@ function kill!(animal::Animal, model::AgentBasedModel, probability::Float64=1.0, ...@@ -60,14 +60,35 @@ function kill!(animal::Animal, model::AgentBasedModel, probability::Float64=1.0,
end end
""" """
countanimals(model, pos, speciesname) nearby_animals(pos, model, radius)
Count the number of animals of the given species in this location. Return an iterator over all animals in the given radius around this position.
""" """
macro countanimals(model::AgentBasedModel, pos::Tuple{Int64,Int64}, speciesname::String) function nearby_animals(pos::Tuple{Int64,Int64}, model::AgentBasedModel, radius::Int64)
neighbours = (model[id] for id in nearby_ids(pos, model, radius))
Iterators.filter(a -> typeof(a) == Animal, neighbours)
end
"""
nearby_animals(animal, model, radius)
Return an iterator over all animals in the given radius around this animal, excluding itself.
"""
function nearby_animals(animal::Animal, model::AgentBasedModel, radius::Int64)
neighbours = (model[id] for id in nearby_ids(animal.pos, model, radius))
Iterators.filter(a -> typeof(a) == Animal && a.id != animal.id, neighbours)
end
"""
countanimals(pos, model, speciesname, radius=0)
Count the number of animals of the given species in this location (optionally supplying a radius).
"""
function countanimals(pos::Tuple{Int64,Int64}, model::AgentBasedModel,
speciesname::String, radius::Int64=0)
n = 0 n = 0
for a in nearby_ids(pos, model, 0) for a in nearby_animals(pos, model, radius)
typeof(model[a]) == Animal && model[a].traits.name == speciesname && (n += 1) model[a].traits.name == speciesname && (n += 1)
end end
return n return n
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