From 8c09236e497d174fa7629731e5b09befe92f0fb4 Mon Sep 17 00:00:00 2001
From: Daniel Vedder <daniel.vedder@idiv.de>
Date: Mon, 28 Nov 2022 19:46:10 +0100
Subject: [PATCH] Added the Wyvern

Yes, this is another test species - I want to trial a simple
Lotka-Volterra model.
---
 src/Persephone.jl    |  1 +
 src/nature/wyvern.jl | 70 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)
 create mode 100644 src/nature/wyvern.jl

diff --git a/src/Persephone.jl b/src/Persephone.jl
index 8c0262d..ad1fd4f 100644
--- a/src/Persephone.jl
+++ b/src/Persephone.jl
@@ -43,6 +43,7 @@ include("farm/farm.jl")
 include("crop/crops.jl")
 include("nature/nature.jl")
 include("nature/wolpertinger.jl")
+include("nature/wyvern.jl")
 include("core/simulation.jl")
 
 end
diff --git a/src/nature/wyvern.jl b/src/nature/wyvern.jl
new file mode 100644
index 0000000..99698c5
--- /dev/null
+++ b/src/nature/wyvern.jl
@@ -0,0 +1,70 @@
+### Persephone - a socio-economic-ecological model of European agricultural landscapes.
+###
+### This file holds the code for the Wyvern (https://en.wikipedia.org/wiki/Wyvern).
+### NOT FOR ACTUAL USE! This is of course only a test species ;-)
+### Thankfully, wyverns are not a species we have to manage for...
+###
+
+"""
+    initwyvern!(model)
+
+Initialise a population of Wyverns in pairs locations around the landscape.
+"""
+function initwyvern!(model::AgentBasedModel)
+    species = getspecies("Wyvern")
+    x, y = size(model.landscape)
+    for i in 1:species.traits["initpop"]
+        add_agent!(Animal, model, species, hermaphrodite, 0, species.traits["birthenergy"])
+    end
+    @debug "$(species.traits["initpop"]) wyverns are now lying in wait in the landscape."
+end
+
+"""
+    updatewyvern!(animal, model)
+
+Wyverns are ferocious hunters, scouring the landscape for their favourite
+prey: wolpertingers...
+"""
+function updatewyvern!(w::Animal, model::AgentBasedModel)
+    # check if a wolpertinger is in pouncing distance
+    for a in nearby_agents(w, model, trait(w, "speed"))
+        (a.species.name != "Wolpertinger") && continue
+        move_agent!(w, a.pos, model)
+        w.energy -= trait(w, "pounceenergy")
+        if rand() < trait(w, "huntsuccess")
+            @debug "Wyvern $(w.id) killed wolpertinger $(a.id)."
+            w.energy += Int(round(a.energy/2))
+            kill_agent!(a, model)
+            @goto reproduce
+        end
+    end
+    # check if a wolpertinger is in seeing distance, or walk in a random direction
+    direction = Tuple(rand([-1,1], 2))
+    for a in nearby_agents(w, model, trait(w, "vision"))
+        if a.species.name == "Wolpertinger"
+            direction = get_direction(w.pos, a.pos, model)
+            break
+        end
+    end    
+    for i in 1:trait(w, "speed")
+        walk!(w, direction, model; ifempty=false)
+        w.energy -= 1
+    end
+    # reproduce every once in a blue moon
+    @label reproduce
+    if rand() < 0.01
+        @debug "Wyvern $(w.id) has reproduced."
+        add_agent!(w.pos, Animal, model, getspecies("Wyvern"),
+                   hermaphrodite, 0, trait(w, "birthenergy"))
+    end
+end
+
+newspecies("Wyvern",
+           initwyvern!,
+           updatewyvern!,
+           Dict("initpop"=>100,
+                "birthenergy"=>1000,
+                "speed"=>10,
+                "vision"=>50,
+                "pounceenergy"=>20,
+                "huntsuccess"=>0.3))
-- 
GitLab