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

Wrote the `nearby_animals()` functions

parent c9d982f1
Branches
Tags
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
variables:
- `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).
- `pos` gives the animal's current position as a coordinate tuple.
- `model` a reference to the model world (an object of type `AgentBasedModel`).
This allows access to `model.date` (the current simulation date) and
`model.landscape` (a two-dimensional array of pixels containing geographic
information).
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:
`@trait(phase) = "newphase"`.
......@@ -140,7 +141,12 @@ To transition an individual to another phase, simply redefine its phase variable
macro phase(name, body)
#XXX make this documentable?
#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
"""
......@@ -201,9 +207,15 @@ macro reproduce(args...)
:(reproduce!(animal, model, $(args...)))
end
#XXX add a macro @f to call a function with animal and model as first parameters?
# e.g. @f(nearby_agents, distance)
# -> rather create wrapper macros
"""
@neighbours(radius)
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
......@@ -236,11 +248,7 @@ circumvented by directly creating an equivalent function.
macro habitat(body)
quote
function($(esc(:pos)), $(esc(:model)))
if $(esc(body))
return true
else
return false
end
($(esc(body))) ? return true : return false
end
end
end
......@@ -249,7 +257,7 @@ end
@landcover
Returns the local landcover. This is a utility wrapper that can only be used
nested within `@habitat`.
nested within `@phase` or `@habitat`.
"""
macro landcover()
:(landcover($(esc(:pos)), $(esc(:model))))
......@@ -259,7 +267,7 @@ end
@croptype
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()
:(croptype($(esc(:pos)), $(esc(:model))))
......@@ -269,27 +277,27 @@ end
@cropheight
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()
:(cropheight($(esc(:pos)), $(esc(:model))))
end
"""
@distanceto(habitattype)
@distanceto(habitat)
Calculate the distance to the closest habitat of the specified type.
This is a utility wrapper that can only be used nested within `@habitat`.
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 `@phase` or `@habitat`.
"""
macro distanceto(habitattype)
:(distanceto($(esc(:pos)), $(esc(:model)), $habitattype))
macro distanceto(habitat)
:(distanceto($(esc(:pos)), $(esc(:model)), $habitat))
end
"""
@distancetoedge
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()
:(distancetoedge($(esc(:pos)), $(esc(:model))))
......@@ -299,7 +307,7 @@ end
@countanimals(speciesname)
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)
#XXX this also counts the enquiring agent
......
......@@ -60,14 +60,35 @@ function kill!(animal::Animal, model::AgentBasedModel, probability::Float64=1.0,
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
for a in nearby_ids(pos, model, 0)
typeof(model[a]) == Animal && model[a].traits.name == speciesname && (n += 1)
for a in nearby_animals(pos, model, radius)
model[a].traits.name == speciesname && (n += 1)
end
return n
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment