move some logic into their own funcs(move,eat,reproduce)
parent
0165c839cd
commit
f0bfe3cb87
|
|
@ -46,17 +46,63 @@
|
|||
# example, we could have only one type and one additional filed to separate them.
|
||||
# Nevertheless, for the sake of example, we will use two different types.)
|
||||
using Agents, Random
|
||||
|
||||
using CairoMakie
|
||||
@agent struct Sheep(GridAgent{2})
|
||||
energy::Float64
|
||||
reproduction_prob::Float64
|
||||
Δenergy::Float64
|
||||
#perception::Int32
|
||||
#speed::Float64
|
||||
#endurance::Float64
|
||||
end
|
||||
function move!(sheep::Sheep,model)
|
||||
randomwalk!(sheep, model)
|
||||
sheep.energy -= 1
|
||||
end
|
||||
function eat!(sheep::Sheep, model)
|
||||
if model.fully_grown[sheep.pos...]
|
||||
sheep.energy += sheep.Δenergy
|
||||
model.fully_grown[sheep.pos...] = false
|
||||
end
|
||||
return
|
||||
end
|
||||
function reproduce!(sheep::Sheep, model)
|
||||
if rand(abmrng(model)) ≤ sheep.reproduction_prob
|
||||
sheep.energy /= 2
|
||||
replicate!(sheep, model)
|
||||
end
|
||||
end
|
||||
|
||||
@agent struct Wolf(GridAgent{2})
|
||||
energy::Float64
|
||||
reproduction_prob::Float64
|
||||
Δenergy::Float64
|
||||
#perception::Int32
|
||||
#speed::Float64
|
||||
#endurance::Float64
|
||||
end
|
||||
function move!(wolf::Wolf,model)
|
||||
randomwalk!(wolf, model; ifempty=false)
|
||||
wolf.energy -= 1
|
||||
end
|
||||
function eat!(wolf::Wolf, model)
|
||||
dinner = first_sheep_in_position(wolf.pos, model)
|
||||
if !isnothing(dinner)
|
||||
remove_agent!(dinner, model)
|
||||
wolf.energy += wolf.Δenergy
|
||||
end
|
||||
end
|
||||
function reproduce!(wolf::Wolf, model)
|
||||
if rand(abmrng(model)) ≤ wolf.reproduction_prob
|
||||
wolf.energy /= 2
|
||||
replicate!(wolf, model)
|
||||
end
|
||||
end
|
||||
|
||||
function first_sheep_in_position(pos, model)
|
||||
ids = ids_in_position(pos, model)
|
||||
j = findfirst(id -> model[id] isa Sheep, ids)
|
||||
isnothing(j) ? nothing : model[ids[j]]::Sheep
|
||||
end
|
||||
|
||||
# The function `initialize_model` returns a new model containing sheep, wolves, and grass
|
||||
|
|
@ -119,56 +165,23 @@ end
|
|||
# Notice how the function `sheepwolf_step!`, which is our `agent_step!`,
|
||||
# is dispatched to the appropriate agent type via Julia's Multiple Dispatch system.
|
||||
function sheepwolf_step!(sheep::Sheep, model)
|
||||
randomwalk!(sheep, model)
|
||||
sheep.energy -= 1
|
||||
move!(sheep, model)
|
||||
if sheep.energy < 0
|
||||
remove_agent!(sheep, model)
|
||||
return
|
||||
end
|
||||
eat!(sheep, model)
|
||||
if rand(abmrng(model)) ≤ sheep.reproduction_prob
|
||||
sheep.energy /= 2
|
||||
replicate!(sheep, model)
|
||||
end
|
||||
reproduce!(sheep, model)
|
||||
end
|
||||
|
||||
function sheepwolf_step!(wolf::Wolf, model)
|
||||
randomwalk!(wolf, model; ifempty=false)
|
||||
wolf.energy -= 1
|
||||
move!(wolf, model)
|
||||
if wolf.energy < 0
|
||||
remove_agent!(wolf, model)
|
||||
return
|
||||
end
|
||||
## If there is any sheep on this grid cell, it's dinner time!
|
||||
dinner = first_sheep_in_position(wolf.pos, model)
|
||||
!isnothing(dinner) && eat!(wolf, dinner, model)
|
||||
if rand(abmrng(model)) ≤ wolf.reproduction_prob
|
||||
wolf.energy /= 2
|
||||
replicate!(wolf, model)
|
||||
end
|
||||
end
|
||||
|
||||
function first_sheep_in_position(pos, model)
|
||||
ids = ids_in_position(pos, model)
|
||||
j = findfirst(id -> model[id] isa Sheep, ids)
|
||||
isnothing(j) ? nothing : model[ids[j]]::Sheep
|
||||
end
|
||||
|
||||
# Sheep and wolves have separate `eat!` functions. If a sheep eats grass, it will acquire
|
||||
# additional energy and the grass will not be available for consumption until regrowth time
|
||||
# has elapsed. If a wolf eats a sheep, the sheep dies and the wolf acquires more energy.
|
||||
function eat!(sheep::Sheep, model)
|
||||
if model.fully_grown[sheep.pos...]
|
||||
sheep.energy += sheep.Δenergy
|
||||
model.fully_grown[sheep.pos...] = false
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function eat!(wolf::Wolf, sheep::Sheep, model)
|
||||
remove_agent!(sheep, model)
|
||||
wolf.energy += wolf.Δenergy
|
||||
return
|
||||
eat!(wolf, model)
|
||||
reproduce!(wolf, model)
|
||||
end
|
||||
|
||||
# The behavior of grass function differently. If it is fully grown, it is consumable.
|
||||
|
|
@ -187,6 +200,7 @@ function grass_step!(model)
|
|||
end
|
||||
end
|
||||
|
||||
function run()
|
||||
sheepwolfgrass = initialize_model()
|
||||
|
||||
# ## Running the model
|
||||
|
|
@ -194,7 +208,6 @@ sheepwolfgrass = initialize_model()
|
|||
# We will run the model for 500 steps and record the number of sheep, wolves and consumable
|
||||
# grass patches after each step. First: initialize the model.
|
||||
|
||||
using CairoMakie
|
||||
CairoMakie.activate!() # hide
|
||||
|
||||
# To view our starting population, we can build an overview plot using [`abmplot`](@ref).
|
||||
|
|
@ -292,3 +305,5 @@ abmvideo(
|
|||
# <source src="../sheepwolf.mp4" type="video/mp4">
|
||||
# </video>
|
||||
# ```
|
||||
end
|
||||
run()
|
||||
|
|
|
|||
Loading…
Reference in New Issue