You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Create a macro `@ecosystem` that should be able to define a world given a list of statements `@add # $species ${optional:sex}`
9
+
```julia
10
+
world =@ecosystembegin
11
+
@add10 Sheep Female # adds 10 female sheep
12
+
@add2 Sheep Male # adds 2 male sheep
13
+
@add100 Grass # adds 100 pieces of grass
14
+
@add3 Wolf # adds 5 wolf with random sex
15
+
end
16
+
```
17
+
As this is not a small task let's break it into 3 steps
18
+
1. Define method `default_config(::Type{T})` for each `T` in `Grass, Wolf,...`, which returns a tuple of default parameters for that particular agent.
19
+
2. Define method `_add_agents(max_id, count::Int, species::Type{<:Species})` and `_add_agents(max_id, count::Int, species::Type{<:AnimalSpecies}, sex::Type{<:Sex})` that return an array of `count` agents of species `species` with `id` going from `max_id+1` to `max_id+count`. Default parameters should be constructed with `default_config`.
20
+
3. Define the underlying function `_ecosystem(ex)`, which parses the block expression and creates a piece of code that constructs the world.
21
+
22
+
!!! info "`Type{T}` type"
23
+
Some hints about this signature, which we have not yet introduced.
24
+
25
+
You can test the macro (more precisely the `_ecosystem` function) with the following expression
26
+
```julia
27
+
ex = :(begin
28
+
@add10 Sheep Female
29
+
@add2 Sheep Male
30
+
@add100 Grass
31
+
@add3 Wolf
32
+
end)
33
+
genex =_ecosystem(ex)
34
+
world =eval(genex)
35
+
```
36
+
37
+
```@raw html
38
+
</div></div>
39
+
<details class = "solution-body" hidden>
40
+
<summary class = "solution-header">Solution:</summary><p>
There are at least two ways how we can make our life simpler when using our `Ecosystem` and `EcosystemCore` pkgs. Firstly, recall that in order to test our simulation we always had to write something like this:
228
+
```julia
229
+
functioncreate_world()
230
+
n_grass =500
231
+
regrowth_time =17.0
232
+
233
+
n_sheep =100
234
+
Δenergy_sheep =5.0
235
+
sheep_reproduce =0.5
236
+
sheep_foodprob =0.4
237
+
238
+
n_wolves =8
239
+
Δenergy_wolf =17.0
240
+
wolf_reproduce =0.03
241
+
wolf_foodprob =0.02
242
+
243
+
gs = [Grass(id, regrowth_time) for id in1:n_grass];
244
+
ss = [Sheep(id, 2*Δenergy_sheep, Δenergy_sheep, sheep_reproduce, sheep_foodprob) for id in n_grass+1:n_grass+n_sheep];
245
+
ws = [Wolf(id, 2*Δenergy_wolf, Δenergy_wolf, wolf_reproduce, wolf_foodprob) for id in n_grass+n_sheep+1:n_grass+n_sheep+n_wolves];
246
+
World(vcat(gs, ss, ws))
247
+
end
248
+
world =create_world();
249
+
```
250
+
which includes the tedious process of defining the agent counts, their parameters and last but not least the unique id manipulation. As part of the [HW](@ref hw07) for this lecture you will be tasked to define a simple DSL, which can be used to define a world in a few lines.
251
+
252
+
Secondly, the definition of a new `Animal` or `Plant`, that did not have any special behavior currently requires quite a bit of repetitive code. For example defining a new plant type `Broccoli` goes as follows
In order to make these relation clearer we will create two macros, which can be called at one place to construct all the relations.
269
+
228
270
### New Animal/Plant definition
271
+
Our goal is to be able to define new plants and animal species, while having a clear idea about their relations. For this we have proposed the following macros/syntax:
Unfortunately the current version of `Ecosystem` and `EcosystemCore`, already contains some definitions of species such as `Sheep`, `Wolf` and `Mushroom`, which would collide with the new definition thus there exists a modified version of those pkgs. **TODO LINK IT**
287
+
288
+
We can test the current definition with the following code that constructs "eating matrix"
Syntax `Grass => 0.5ΔE` indicates defines the behavior of the `eat!` function, where the coefficient is used as a multiplier for the energy balance, in other words the `Rabbit` should get only `0.5` of energy for a piece of `Grass`.
340
+
341
+
Define first helper functions `_plant` and `_animal` to inspect the respective macro's output. This is indispensable, as we are defining new types/constants and thus we would otherwise encountered errors during repeated evaluation (though only if the type signature changed).
342
+
343
+
**HINTS**:
344
+
- use `QuoteNode` in the show function
345
+
- sdfsdf
346
+
347
+
```@raw html
348
+
</div></div>
349
+
<details class = "solution-body">
350
+
<summary class = "solution-header">Solution:</summary><p>
351
+
```
352
+
353
+
```julia
354
+
355
+
ex = :(begin
356
+
name => Broccoli
357
+
icon => 🥦
358
+
end)
359
+
360
+
macroplant(ex)
361
+
return_plant(ex)
362
+
end
363
+
364
+
function_plant(ex)
365
+
cfg =Dict{Symbol, Symbol}()
366
+
for arg in ex.args
367
+
if~(arg isa LineNumberNode) && arg.head ==:call&& arg.args[1] == :(=>)
0 commit comments