diff --git a/src/Persephone.jl b/src/Persephone.jl index cdf484f3934e77924a28060ef3e6e0b5bae415a3..58c1b36094283ae0dc0bbb780f9283a8f1da44cf 100644 --- a/src/Persephone.jl +++ b/src/Persephone.jl @@ -60,6 +60,7 @@ export @distancetoedge, @countanimals, @rand, + @shuffle!, #functions simulate, simulate!, diff --git a/src/core/input.jl b/src/core/input.jl index d9507386315b6e33262568ed80772d7eef339125..7b396058f02292a653c7d6abefd7fc55b04a3239 100644 --- a/src/core/input.jl +++ b/src/core/input.jl @@ -7,7 +7,7 @@ ## (https://github.com/CCTB-Ecomods/gemm/blob/master/src/input.jl) """ -The file that stores all default parameters. +The file that stores all default parameters: `src/parameters.toml` """ const PARAMFILE = joinpath(pkgdir(Persephone), "src/parameters.toml") ## (DO NOT CHANGE THIS VALUE! Instead, specify simulation-specific configuration files @@ -19,11 +19,11 @@ const PARAMFILE = joinpath(pkgdir(Persephone), "src/parameters.toml") Return a configuration parameter from the global settings. The argument should be in the form `<domain>.<parameter>`, for example `@param(core.outdir)`. Possible values for -<domain> are `core`, `nature`, `farm`, or `crop`. For a full +`<domain>` are `core`, `nature`, `farm`, or `crop`. For a full list of parameters, see `src/parameters.toml`. -Note that this macro only works in a context where the `model` -object is available. +Note: this macro only works in a context where the `model` +object is available! """ macro param(domainparam) domain = String(domainparam.args[1]) @@ -112,6 +112,28 @@ function flattenTOML(tomldict) flatdict end +""" + @rand(args...) + +Return a random number or element from the sample, using the model RNG. +This is a utility wrapper that can only be used a context where the +`model` object is available. +""" +macro rand(args...) + :($(esc(:rand))($(esc(:model)).rng, $(map(esc, args)...))) +end + +""" + @shuffle!(collection) + +Shuffle the given collection in place, using the model RNG. +This is a utility wrapper that can only be used a context where the +`model` object is available. +""" +macro shuffle!(collection) + :($(esc(:shuffle!))($(esc(:model)).rng, $(esc(collection)))) +end + """ parsecommandline() diff --git a/src/nature/nature.jl b/src/nature/nature.jl index a02f984c68f959c3040b337a4198de4aca0ee556..97885d0c95e68412f7cb1ec83225a822597f6366 100644 --- a/src/nature/nature.jl +++ b/src/nature/nature.jl @@ -375,17 +375,6 @@ macro countanimals(args...) :(countanimals($(esc(:pos)), $(esc(:model)); $(map(esc, args)...))) end -""" - @rand(args...) - -Return a random number or element from the sample, using the model RNG. -This is a utility wrapper that can only be used nested within `@phase` or `@habitat` -(or in other contexts where the `model` object is available). -""" -macro rand(args...) - :($(esc(:rand))($(esc(:model)).rng, $(map(esc, args)...))) -end - ##TODO @chance macro: @chance(0.5) => rand(model.rng) < 0.5 ##TODO add movement macros diff --git a/src/nature/populations.jl b/src/nature/populations.jl index a76008898b6fc116ca017883001bc0378cecb62b..4e213e34fd457ae460c0e704d9be18d796f9675e 100644 --- a/src/nature/populations.jl +++ b/src/nature/populations.jl @@ -40,15 +40,15 @@ function initpopulation(habitatdescriptor::Function; phase::Union{String,Nothing (!isnothing(phase)) && (species["phase"] = phase) width, height = size(model.landscape) while n == 0 || n < popsize - for x in shuffle!(model.rng, Vector(1:width)) - for y in shuffle!(model.rng, Vector(1:height)) + for x in @shuffle!(Vector(1:width)) + for y in @shuffle!(Vector(1:height)) if habitatdescriptor((x,y), model) if pairs add_agent!((x,y), Animal, model, deepcopy(species), female, 0) add_agent!((x,y), Animal, model, deepcopy(species), male, 0) n += 2 else - sex = asexual ? hermaphrodite : rand(model.rng, [male, female]) + sex = asexual ? hermaphrodite : @rand([male, female]) add_agent!((x,y), Animal, model, deepcopy(species), sex, 0) n += 1 end @@ -88,7 +88,7 @@ Produce one or more offspring for the given animal at its current location. """ function reproduce!(animal::Animal, model::AgentBasedModel, n::Int64=1) for i in 1:n - sex = (animal.sex == hermaphrodite) ? hermaphrodite : rand(model.rng, [male, female]) + sex = (animal.sex == hermaphrodite) ? hermaphrodite : @rand([male, female]) # We need to generate a fresh species dict here species = @eval $(Symbol(animal.traits["name"]))($model) add_agent!(animal.pos, Animal, model, species, sex, 0) @@ -103,7 +103,7 @@ Kill this animal, optionally with a given percentage probability. Returns true if the animal dies, false if not. """ function kill!(animal::Animal, model::AgentBasedModel, probability::Float64=1.0, cause::String="") - if rand(model.rng) < probability + if @rand() < probability postfix = isempty(cause) ? "." : " from $cause." @debug "$(animalid(animal)) has died$(postfix)" kill_agent!(animal, model)