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

Added @here and nagents(), fixed farmplot() and directionto()

parent 45a68207
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,15 @@ mutable struct AgricultureModel <: SimulationModel
events::Vector{FarmEvent}
end
"""
nagents(model)
Return the total number of agents in a model object.
"""
function nagents(model::AgricultureModel)
length(model.animals)+length(model.farmers)+length(model.farmplots)
end
"""
stepagent!(agent, model)
......
......@@ -124,7 +124,7 @@ is explicitly defined by the user in the species definition block.
"""
macro phase(species, phase, body)
quote
Core.@__doc__ function $(esc(phase))($(esc(:self))::$(species),
Core.@__doc__ function $(esc(phase))($(esc(:self))::$(esc(species)),
$(esc(:model))::SimulationModel)
$(esc(:pos)) = $(esc(:self)).pos # needed for landscape macros
$(esc(body))
......@@ -145,7 +145,6 @@ can thus use all macros available in [`@phase`](@ref).
"""
macro create(species, body)
quote
#XXX species are created/referenced as Persefone.<speciesname>, is this relevant?
Core.@__doc__ function $(esc(:create!))($(esc(:self))::$(esc(species)),
$(esc(:model))::SimulationModel)
$(esc(:pos)) = $(esc(:self)).pos # needed for landscape macros
......@@ -176,10 +175,21 @@ macro isalive(id)
:(isalive($(esc(id)), $(esc(:model))))
end
"""
@here()
Return the landscape pixel of this animal's current location.
This can only be used nested within [`@phase`](@ref).
"""
macro here()
:($(esc(:model)).landscape[$(esc(:self)).pos...])
end
"""
@setphase(newphase)
Switch this animal over to a different phase. This can only be used nested within [`@phase`](@ref).
Switch this animal over to a different phase.
This can only be used nested within [`@phase`](@ref).
"""
macro setphase(newphase)
:($(esc(:self)).phase = $(newphase))
......
......@@ -116,11 +116,8 @@ end
Return the farm plot at this position, or nothing if there is none (utility wrapper).
"""
function farmplot(pos::Tuple{Int64,Int64}, model::SimulationModel)
if ismissing(model.landscape[pos...].fieldid)
nothing
else
model[model.landscape[pos...].fieldid]
end
id = model.landscape[pos...].fieldid
ismissing(id) ? nothing : model.farmplots[id]
end
"""
......@@ -131,19 +128,22 @@ habitat descriptor function. Returns a coordinate tuple (target - position), or
if no matching habitat is found. Caution: can be computationally expensive!
"""
function directionto(pos::Tuple{Int64,Int64}, model::SimulationModel, habitatdescriptor::Function)
#TODO test
#XXX split this up into a findnearest() and a directionto() function?
# search in expanding rectangles around the origin
(habitatdescriptor(pos, model)) && (return (0,0))
dist = 1
width, height = size(model.landscape)
while dist <= width || dist <= height
while dist <= width || dist <= height #XXX is there a quicker method?
# check the upper and lower bounds of the enclosing rectangle
y1 = pos[2] - dist
y2 = pos[2] + dist
minx = maximum((pos[1]-dist, 1))
maxx = minimum((pos[1]+dist, width))
#XXX alternately, we could check individually whether y1 and y2 are in bounds, and loop
# over x for each separately (not sure if that is quicker, but it may be)
for x in minx:maxx
(y1 > 0 && habitatdescriptor((x,y1), model)) && (return (x, y1))
(y2 <= height && habitatdescriptor((x,y2), model)) && (return (x, y2))
(y1 > 0 && habitatdescriptor((x,y1), model)) && (return (x, y1).-pos)
(y2 <= height && habitatdescriptor((x,y2), model)) && (return (x, y2).-pos)
end
# check the left and right bounds of the enclosing rectangle
x1 = pos[1] - dist
......@@ -151,14 +151,26 @@ function directionto(pos::Tuple{Int64,Int64}, model::SimulationModel, habitatdes
miny = maximum((pos[2]-dist+1, 1))
maxy = minimum((pos[2]+dist-1, height))
for y in miny:maxy
(x1 > 0 && habitatdescriptor((x1,y), model)) && (return (x1,y))
(x2 <= width && habitatdescriptor((x2,y), model)) && (return (x2,y))
(x1 > 0 && habitatdescriptor((x1,y), model)) && (return (x1,y).-pos)
(x2 <= width && habitatdescriptor((x2,y), model)) && (return (x2,y).-pos)
end
dist += 1
end
return nothing
end
"""
directionto(pos, model, habitattype)
Calculate the direction from the given location to the closest habitat of the specified type.
Returns a coordinate tuple (target - position), or nothing if no matching habitat is found.
Caution: can be computationally expensive!
"""
function directionto(pos::Tuple{Int64,Int64}, model::SimulationModel, habitattype::LandCover)
# can't use @habitat here because macros.jl is loaded later than this file
directionto(pos, model, function(p,m) landcover(p,m) == habitattype end)
end
"""
distanceto(pos, model, habitatdescriptor)
......@@ -166,10 +178,9 @@ Calculate the distance from the given location to the closest location matching
habitat descriptor function. Caution: can be computationally expensive!
"""
function distanceto(pos::Tuple{Int64,Int64}, model::SimulationModel, habitatdescriptor::Function)
#TODO test
target = directionto(pos, model, habitatdescriptor)
isnothing(target) && return Inf
return maximum(abs.(target.-pos))
return maximum(abs.(target))
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