Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
wyvern.jl 2.81 KiB
### 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...
###

"""
Beware the wyvern! This evolutionary cousin of the dragon may only have two
legs, but that doesn't make it any less dangerous...
"""
@species Wyvern begin
    popsize = 10
    fecundity = 0.02
    maxage = 365
    speed = 20
    vision = 50
    aggression = 0.2
    huntsuccess = 0.8

    @initialise(@habitat(@landcover() in (grass, soil, agriculture, builtup)), popsize=popsize)
    phase = "winter"

    """
    Wyverns are ferocious hunters, scouring the landscape for their favourite
    prey: wolpertingers...
    """
    @phase summer begin
        for a in @neighbours(@trait(speed))
            # check if a wolpertinger is in pouncing distance
            if a.traits["name"] == "Wolpertinger"
                move_agent!(animal, a.pos, model)
                if @rand() < @trait(huntsuccess)
                    @debug "$(animalid(animal)) killed $(animalid(a))."
                    kill_agent!(a, model)
                    @goto reproduce
                end
            elseif a.traits["name"] == "Wyvern" && @rand() < @trait(aggression)
                # wyverns also fight against each other if they get too close
                move_agent!(animal, a.pos, model)
                outcome = @rand()
                if outcome < 0.4
                    @debug "$(animalid(animal)) killed $(animalid(a)) in a fight."
                    kill_agent!(a, model)
                elseif outcome < 0.8
                    @kill 1.0 "wounds sustained in a fight"
                end
                @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 @neighbours(@trait(vision))
            if a.traits["name"] == "Wolpertinger"
                direction = get_direction(animal.pos, a.pos, model)
                break
            end
        end    
        for i in 1:@trait(speed)
            walk!(animal, direction, model; ifempty=false)
        end
        # reproduce every once in a blue moon
        @label reproduce
        (@rand() < @trait(fecundity)) && @reproduce
        # hibernate from November to March
        if monthday(model.date) == (11,1)
            @trait(phase) = "winter"
        end
        (@trait(age) == maxage) && @kill(1.0, "old age")
    end

    """
    Fortunately, wyverns hibernate in winter.
    """
    @phase winter begin
        # hibernate from November to March
        if monthday(model.date) == (3,1)
            @trait(phase) = "summer"
        end
    end
end