/
predator_prey.jl
156 lines (144 loc) · 3.89 KB
/
predator_prey.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
export Sheep, Wolf, Grass
mutable struct Sheep <: AbstractAgent
id::Int
pos::Tuple{Int,Int}
energy::Float64
reproduction_prob::Float64
Δenergy::Float64
end
mutable struct Wolf <: AbstractAgent
id::Int
pos::Tuple{Int,Int}
energy::Float64
reproduction_prob::Float64
Δenergy::Float64
end
mutable struct Grass <: AbstractAgent
id::Int
pos::Tuple{Int,Int}
fully_grown::Bool
regrowth_time::Int
countdown::Int
end
"""
``` julia
predator_prey(;
n_sheep = 100,
n_wolves = 50,
dims = (20, 20),
regrowth_time = 30,
Δenergy_sheep = 4,
Δenergy_wolf = 20,
sheep_reproduce = 0.04,
wolf_reproduce = 0.05,
)
```
Same as in [Model of predator-prey dynamics](@ref).
To access the `Sheep`, `Wolf` and `Grass` types, simply call
``` julia
using Agents.Models: Sheep, Wolf, Grass
```
"""
function predator_prey(;
n_sheep = 100,
n_wolves = 50,
dims = (20, 20),
regrowth_time = 30,
Δenergy_sheep = 4,
Δenergy_wolf = 20,
sheep_reproduce = 0.04,
wolf_reproduce = 0.05,
)
space = GridSpace(dims, moore = true)
model =
ABM(Union{Sheep,Wolf,Grass}, space, scheduler = by_type(true, true), warn = false)
id = 0
for _ in 1:n_sheep
id += 1
energy = rand(1:(Δenergy_sheep * 2)) - 1
## Note that we must instantiate agents before adding them in a mixed-ABM
## to confirm their type.
sheep = Sheep(id, (0, 0), energy, sheep_reproduce, Δenergy_sheep)
add_agent!(sheep, model)
end
for _ in 1:n_wolves
id += 1
energy = rand(1:(Δenergy_wolf * 2)) - 1
wolf = Wolf(id, (0, 0), energy, wolf_reproduce, Δenergy_wolf)
add_agent!(wolf, model)
end
for p in positions(model)
id += 1
fully_grown = rand(Bool)
countdown = fully_grown ? regrowth_time : rand(1:regrowth_time) - 1
grass = Grass(id, (0, 0), fully_grown, regrowth_time, countdown)
add_agent!(grass, p, model)
end
return model, predator_prey_agent_step!, dummystep
end
function predator_prey_agent_step!(sheep::Sheep, model)
move!(sheep, model)
sheep.energy -= 1
agents = [model[a] for a in agents_in_pos(sheep.pos, model)]
dinner = filter!(x -> isa(x, Grass), agents)
eat!(sheep, dinner, model)
if sheep.energy < 0
kill_agent!(sheep, model)
return
end
if rand() <= sheep.reproduction_prob
reproduce!(sheep, model)
end
end
function predator_prey_agent_step!(wolf::Wolf, model)
move!(wolf, model)
wolf.energy -= 1
agents = [model[a] for a in agents_in_pos(wolf.pos, model)]
dinner = filter!(x -> isa(x, Sheep), agents)
eat!(wolf, dinner, model)
if wolf.energy < 0
kill_agent!(wolf, model)
return
end
if rand() <= wolf.reproduction_prob
reproduce!(wolf, model)
end
end
function predator_prey_agent_step!(grass::Grass, model)
if !grass.fully_grown
if grass.countdown <= 0
grass.fully_grown = true
grass.countdown = grass.regrowth_time
else
grass.countdown -= 1
end
end
end
function move!(agent, model)
neighbors = nearby_positions(agent, model)
position = rand(collect(neighbors))
move_agent!(agent, position, model)
end
function eat!(sheep::Sheep, grass_array, model)
isempty(grass_array) && return
grass = grass_array[1]
if grass.fully_grown
sheep.energy += sheep.Δenergy
grass.fully_grown = false
end
end
function eat!(wolf::Wolf, sheep, model)
if !isempty(sheep)
dinner = rand(sheep)
kill_agent!(dinner, model)
wolf.energy += wolf.Δenergy
end
end
function reproduce!(agent, model)
agent.energy /= 2
id = nextid(model)
A = typeof(agent)
offspring = A(id, agent.pos, agent.energy, agent.reproduction_prob, agent.Δenergy)
add_agent_pos!(offspring, model)
return
end