Homework 3

In this homework we will implement a function find_food and practice the use of closures. The solution of lab 3 can be found here. You can use this file and add the code that you write for the homework to it.

How to submit?

Put all your code (including your or the provided solution of lab 2) in a script named hw.jl. Zip only this file (not its parent folder) and upload it to BRUTE.

Agents looking for food


Implement a method find_food(a::Animal, w::World) returns one randomly chosen agent from all w.agents that can be eaten by a or nothing if no food could be found. This means that if e.g. the animal is a Wolf you have to return one random Sheep, etc.

Hint: You can write a general find_food method for all animals and move the parts that are specific to the concrete animal types to a separate function. E.g. you could define a function eats(::Animal{Wolf}, ::Animal{Sheep}) = true, etc.

You can check your solution with the public test:

julia> sheep = Sheep(1,pf=1.0)🐑♂ #1 E=4.0 ΔE=0.2 pr=0.8 pf=1.0
julia> world = World([Grass(2), sheep])Main.World{Main.Agent} 🌿 #2 100% grown 🐑♂ #1 E=4.0 ΔE=0.2 pr=0.8 pf=1.0
julia> find_food(sheep, world) isa Plant{Grass}true

Callbacks & Closures


Implement a function every_nth(f::Function,n::Int) that takes an inner function f and uses a closure to construct an outer function g that only calls f every nth call to g. For example, if n=3 the inner function f be called at the 3rd, 6th, 9th ... call to g (not at the 1st, 2nd, 4th, 5th, 7th... call).

Hint: You can use splatting via ... to pass on an unknown number of arguments from the outer to the inner function.

You can use every_nth to log (or save) the agent count only every couple of steps of your simulation. Using every_nth will look like this:

julia> w = World([Sheep(1), Grass(2), Wolf(3)])
       # `@info agent_count(w)` is executed only every 3rd call to logcb(w)Main.World{Main.Agent}
  🌿  #2 50% grown
  🐺♀ #3 E=10.0 ΔE=8.0 pr=0.1 pf=0.2
  🐑♀ #1 E=4.0 ΔE=0.2 pr=0.8 pf=0.6
julia> logcb = every_nth(w->(@info agent_count(w)), 3);
julia> logcb(w); # x->(@info agent_count(w)) is not called
julia> logcb(w); # x->(@info agent_count(w)) is not called
julia> logcb(w); # x->(@info agent_count(w)) *is* called[ Info: Dict(:Wolf => 1.0, :Grass => 0.5, :Sheep => 1.0)