globals [
  setting-up?                         ; Used to suppress new-bat messages when setting up
  cached-largest-value                ; Cached value of the largest sharing this tick, for performance
  parent-who                          ; identity of the parent cached to use during reproduciton
  child-who                           ; identity of the child cached to use during reproduction
  daughter-age                        ; age of the daughter cached to use when determining if her mother is "feeding for two"
  hunting-order                       ; serial order of how many bats have hunted before you, used to represent food pressures for overcrowding
  seasonal-average                    ; the average food per season (set by a slider) modified by the seasonal offset
  season-day                          ; which day within the "season" (half a year) you're in
  season-word                         ; whether it's the low or high season
  plural                              ; when the message log mentions some quantity of something, this is "s" if that quantity is more than 1 and otherwise null
  share-value                         ; value of a trade of food that was made
  potential-donor                     ; agent that the potential recipient is asking for a trade
  donor-who                           ; who number of the (potential) donor when evaluating a trade
  recipient-who                       ; who number of the (potential) recipient when evaluating a trade
  donor-food                          ; food in the (potential) donors stomach when evaluating a trade
  donor-threshold                     ; the (potential) donors sharing threshold when evaluating a trade
  incoming-sharing                    ; the all-time contributions from the potential recipient to the potential donor when evaluating a trade
  outgoing-sharing                    ; the all-time contributions from the potential recipient to the potential donor when evaluating a trade
  modifier                            ; how much individual circumstances (motherhood, trust, annoyance) change the potential donors mind about this trade
  recombination-sharing-threshold     ; when reproducing, sharing threshold of one adult who's not your mother
  recombination-charity-to-mothers    ; when reproducing, charity to mothers of one adult who's not your mother
  recombination-trust-coefficient     ; when reproducing, trust coefficient of one adult who's not your mother
  recombination-annoyance-coefficient ; when reproducing, annoyance coefficient of one adult who's not your mother
  birth-count                         ; Number of births
  immigration-count                   ; Number of immigrations
  natural-death-count                 ; Number of natural deaths
  starvation-count                    ; Number of starvations
]

bats-own [
  food                                ; How much food is in the bats stomach currently
  pregnant?                           ; Whether the bat is currently pregnant
  pregnancy-days                      ; How many days the bat has been pregnant
  next-potential-pregnancy            ; How old you can be before your next pregnancy
  has-dependant?                      ; Whether this bat has a living daughter who can't feed themselves
  age                                 ; How old (in ticks) the bat is
  death-age                           ; How old (in ticks) the bat will be when they die naturally if they haven't already starved
  sharing-threshold                   ; How much more food than consumption this bat wants to have before it will share with strangers.
  charity-to-mothers                  ; How much a bat will lower it's sharing threshold for a bat with a non-hunting child.
  trust-coefficient                   ; How much this bats sharing threshold will be lowered for each unit of food is currently owes the other bat in a trade
  annoyance-coefficient               ; How much this bats sharing threshold will be raised for each unit of food the other bat in a trade currently owes it
  personal-consumption                ; How much this bat consumes each night (always either consumption-value or consumption-value + reproduction-cost)
  personal-threshold                  ; This bats threshold for a stranger bat (always personal-consumption + sharing-threshold)
  begging-tonight?                    ; Whether a bat is begging for food tonight because it's starving
  willing-to-give-tonight?            ; Whether a bat would be willing to give food to a stranger tonight
  willing-to-give-to-mothers-tonight? ; Whether a bat would be willing to give food to a stranger mother tonight
]

breed [ bats bat ]
directed-link-breed [ sharings sharing ]
sharings-own [ value cooperation-value ]
directed-link-breed [ mothers mother ]

to setup
  clear-all
  set setting-up? true ;; suppress message for bats joining roost during inital setup
  repeat starting-roost-count [ spawn-new-bat ]
  set setting-up? false
  ;; Reset counts
  set cached-largest-value 0
  set birth-count 0
  set immigration-count 0
  set starvation-count 0
  set natural-death-count 0
  reset-ticks
end

to go
  start-tick
  hunt
  become-pregnant
  share
  consume
  reproduce
  grow-older
  immigrate
  tick
end

to start-tick ;; clear out per-tick variables, update season, and post start-of-tick message if messages are enabled
  set hunting-order 0 ;; order changes each hunt, so clear previous queue
  ask sharings with [ value = 0 ] [ die ] ;; Any value-0 sharings were just created to protect from inifite loops, and aren't real sharings
  if any? sharings
  [
    set cached-largest-value max [ value ] of sharings ;; cache once a tick, for performance
    ask sharings [ set color scale-color blue value 0 cached-largest-value ] ;; scale so bluer = higher value, to make the viz more useful
  ]

  ask bats [ set has-dependant? false ] ;; we have to recheck this each tick

  if any? mothers
  [
    ask mothers
    [
      ask end2 [ set daughter-age age ] ;; end2 of mother links are daughters
      if daughter-age > age-until-independence  [ ask end1 [ set has-dependant? true ] ]
    ]
  ]

  ;; Season is a sine function with a period of year-length. At the peak, it raises the average food for each bat by season-length; at the trough, lowers it by the same.
  let season-int ticks mod year-length  ;; first, get an integer representation of where in the season we are...
  let season-proportion season-int / year-length ;; then, divide it by year length to bound it between 0 and 1...
  let season-degree season-proportion * 360 ;; next, multiply it by 360 to make it a value in degrees...
  set seasonal-average food-average + season-difference * sin ( season-degree ) ;; finally, take the sine of it and add that term to the food-average
  if messages-to-display != "No Messages" ;; write the tick and indicate where we are in the season
    [
    let season-length year-length / 2 ;; We divide a year into "high" and low" seasons depending on whether the sine output is positive or negative.
    ifelse season-int < season-length [ set season-word "high" set season-day season-int + 1] [ set season-word "low" set season-day ( season-int - ( season-length - 1 ) ) ]
    let season-change season-length - season-day + 1
    ifelse season-change = 1 [ set plural "" ] [ set plural "s" ]
    output-print ("") ;; pad with spaces for new tick announcements
    output-print ( word "--Tick " ticks " begins.--" )
    output-print ( word "It is day " season-day " of the " season-word " season." )
    output-print ( word "Season will change in " season-change " day" plural "." )
    output-print ("")]
end

to hunt ;; Bats get more food
 ask bats with [ age >= age-until-independence ] ;; all bats old enough to hunt
 [
    let ordered-average seasonal-average + ( hunting-order * order-penalty ) ;; The seasonal average is lowered by one order penalty for each bat in front of you
    let meal floor min list ( random-normal ordered-average food-standard-deviation ) ( stomach-size - food )  ;; each bat gets food according to food distrubtion, or just enough to be full
    if messages-to-display = "All Messages"
    [
      ifelse meal = 1 [ set plural "" ] [ set plural "s" ]
      output-print ( word "Bat " who " (" food " food) got " meal " more unit" plural " of food." ) ]
    set food food + meal
    set hunting-order hunting-order + 1
  ]
end

to become-pregnant ;; Bats who can pay the reproduction cost have a chance to get pregnant
  ask bats with [ pregnant? = false and food >= ( consumption-cost + reproduction-cost ) and age >= next-potential-pregnancy ] ;; If you can feed a child, don't have one, are sexually mature, and it's been long enough since last baby...
    [
      if random-float 1 < ( pregnancy-chance / 100 ) ;; you have a pregnancy-chance% chance to become pregnant
      [
        set pregnant? true
        set pregnancy-days 0
        if messages-to-display != "No Messages" [ output-print ( word "Bat " who " is now pregnant. " ) ]
        set personal-consumption consumption-cost + reproduction-cost
        set personal-threshold personal-threshold + reproduction-cost
    ]
  ]
end

to share ;; Bats may share food with each other
  ask bats [ check-sharing-status ] ;; find out who will starve tonight and who is willing to share

  ;; family subphase - first, mothers and daughters look out for each other
  ask mothers [ feed-family ]

  ;; cooperation subphase - check all existing links first, in decending order of priority
  ask sharings [ set cooperation-value value ] ;; clone off the value for just this sharing value
  while [ any? sharings with [ cooperation-value > 0 ] ] ;; loop over all sharings...
  [
    ask max-one-of sharings [ cooperation-value ]  ;; in decending order of value...
    [
      set cooperation-value 0 ;; delete cloned value, so we don't evaluate this link again
      if [begging-tonight?] of end1 = true ;; if the donor bat of this link wants to call in the debt tonight...
      [
        set potential-donor end2
        ask end1 [ beg-for-food ] ;; See if they'll go for it
      ]
    ]
  ]

  ;; mother begging subphase - hungry bats ask bats who are willing to donate to stranger mothers
  while [ any? bats with [ willing-to-give-to-mothers-tonight? = true ] and any? bats with [ begging-tonight? = true and has-dependant? = true ] ] ;; while some bats are hungry and others are willing to share with strangers...
  [
    ask one-of bats with [ begging-tonight? = true and has-dependant? = true ] ;; one bat who will die tonight without food...
    [
      set potential-donor one-of other bats with [ willing-to-give-to-mothers-tonight? = true and sharing-neighbor? myself = false and mother-neighbor? myself = false ] ;; asks a bat it has no relation with
      ifelse potential-donor != nobody [ beg-for-food ] [ set begging-tonight? false ] ;; go for a trade if anyone is willing; otherwise, don't bother trying to beg again
    ]
  ]

  ;; non-mother begging phase - hungry bats ask bats who are willing to donate to strangers in general
  while [ any? bats with [ willing-to-give-tonight? = true ] and any? bats with [ begging-tonight? = true ] ] ;; while some bats are hungry and others are willing to share with strangers...
  [
    ask one-of bats with [ begging-tonight? = true ] ;; one bat who will die tonight without food...
    [
      set potential-donor one-of other bats with [ willing-to-give-tonight? = true and sharing-neighbor? myself = false and mother-neighbor? myself = false ] ;; asks a bat it has no relation with
      ifelse potential-donor != nobody [ beg-for-food ] [ set begging-tonight? false ] ;; go for a trade if anyone is willing; otherwise, don't bother trying to beg again
    ]
 ]
end

to consume ;; Bats need to spend food or die
  ask bats
  [
    if pregnant? = true and food < personal-consumption ;; if you will starve keeping the fetus...
    [
      set pregnant? false ;; lose fetus
      set pregnancy-days 0
      set food food + ( pregnancy-days * reproduction-cost * absorption-efficiency ) ;; gain some of the invested energy back
      set food max list food stomach-size ;; but no more than you can hold in your stomach
      set personal-consumption personal-consumption - reproduction-cost
      set personal-threshold personal-threshold - reproduction-cost
      if messages-to-display != "No Messages" [ output-print ( word "Bat " who " was forced to absorb her fetus." ) ]
    ]
    ifelse food < personal-consumption ;; starve if you don't have enough food
    [ set starvation-count starvation-count + 1
        if messages-to-display != "No Messages" [ output-print ( word "Bat " who " starved to death." ) ]
        ask my-sharings [ die ]
        ask my-mothers [ die ]
        die
    ]
    [ set food food - personal-consumption ] ;; otherwise, just eat
  ]
end


to reproduce ;; Bats who have been pregnant for long enough have babies
  ask bats with [ pregnant? = true ]
  [
    set pregnancy-days pregnancy-days + 1
    if pregnancy-days >= reproduction-time ;; If you've been pregnant long enough...
    [  set pregnant? false
       set pregnancy-days 0
       set parent-who who
       set next-potential-pregnancy age + time-between-pregnancies
       set personal-consumption personal-consumption - reproduction-cost ;; reset consumption BEFORE you have the baby, so it gets the correct, non-pregnant ones
       set personal-threshold personal-threshold - reproduction-cost
       set birth-count birth-count + 1
       hatch-bats 1
       [
        setxy random-xcor random-ycor
        set color one-of base-colors
        set child-who who
        set food 0
        set age 0
        set next-potential-pregnancy age-until-sexual-maturity
        set death-age floor random-normal lifespan-average lifespan-standard-deviation
        if messages-to-display != "No Messages" [ output-print ( word "Bat " parent-who " gave birth to bat " who "." ) ]
        if psuedo-recombination? = true [ psuedo-recombinate ] ;; If optional psuedo recombination is turned on, run it
        mutate ;; Baby may differ slightly from mom
        set personal-threshold sharing-threshold + consumption-cost ;; sharing threshold may have changed, so update personal threshold
       ]
       create-mother-to bat child-who [ set color yellow ] ;; create a mother-daughter link - these bats will preferentially share
    ]
  ]
end

to grow-older ;; Bats grow older and maybe die of old age
  ask bats
  [
    set age age + 1
    if age >= death-age ;; Death function gave each bat a pre-determined lifespan on creation
    [ set natural-death-count natural-death-count + 1
      if messages-to-display != "No Messages" [ output-print ( word "Bat " who " died naturally." ) ]
      ask my-sharings [ die ]
      ask my-mothers [ die ]
      die ]
  ]
end

to immigrate ;; Stranger bats with no relation to the roost might join in
  if random-float 1 < ( immigration-chance / 100 ) [ spawn-new-bat set immigration-count immigration-count + 1 ]
end

to check-sharing-status ;; Determine whether a bat needs food tonight to live, and whether a bat is willing to donate to strangers.
  ifelse food < personal-consumption [ set begging-tonight? true ] [ set begging-tonight? false ] ;; figure out who will starve to death tonight and who won't
  ifelse food > personal-threshold [ set willing-to-give-tonight? true ] [ set willing-to-give-tonight? false ] ;; figure out who might be willing to give to strangers and who won't
  ifelse food > max list personal-consumption ( personal-threshold - charity-to-mothers ) [ set willing-to-give-to-mothers-tonight? true ] [ set willing-to-give-to-mothers-tonight? false ] ;; figure out who might be willing to give to stranger mothers and who won't
end

to feed-family ;; Special sharing function only for mothers and daughters
  if [ begging-tonight? ] of end2 = true ;; if the child is going to starve...
  [
    ask end2 [ set share-value personal-consumption - food ] ;; share-value has the hunger of the daughter
    ask end1 [ set share-value min list share-value food ] ;; mom makes sure her daughter is fed, even if she has to starve
    if share-value > 0 [ ask end1 [ set food food - share-value ] ask end2 [ set food food + share-value ] ]
  ]

  if [ begging-tonight? ] of end1 = true ;; if mom is going to starve...
  [
    ask end1 [ set share-value personal-consumption - food ] ;; share-value has the hunger of the mother
    ask end2 [ set share-value min list share-value food - personal-consumption ] ;; daughter won't go hungry for mom, but she'll share everything extra, ignoring threshold
    if share-value > 0 [ ask end2 [ set food food - share-value ] ask end1 [ set food food + share-value ] ]
  ]
    ask both-ends [ check-sharing-status ] ;; re-validate if either one is begging and/or willing to share tonight
end

to beg-for-food ;; This function is called by the potential recipient when potential-donor has another bat stored in it.
  set recipient-who who
  ask potential-donor
  [
    set donor-food food
    set donor-who who
    calculate-donor-modifier ;; donor figures out how much they'd change your personal threshold for this bat
    set donor-threshold max list ( personal-threshold + modifier ) ( personal-consumption ) ;; but their personal threshold is always at least as much as they need to live
  ]
  set share-value floor min list ( donor-food - donor-threshold ) ( ( donor-food - food ) / 2 ) ;; share until donor is unwilling to share more, or unitl sharing would make them equal
  set share-value max list share-value 0 ;; turn negative share values to 0 so function below can be simplier
  if messages-to-display = "All Messages" [ output-print ( word "Bat " who " (" food " food) asks bat " donor-who " (" donor-food " food) for food. " ) ]
  ifelse share-value > 0
  [
    if messages-to-display = "All Messages"
    [
      ifelse share-value = 1 [ set plural "" ] [ set plural "s" ]
      output-print ( word "She shares " share-value " unit" plural " of food. " ) ]
    ]
  [
    if messages-to-display = "All Messages" [ output-print ( word "She refuses.") ]
  ]
ask potential-donor [ update-sharing-link ] ;; update link even if no sharing happened to protect from infinite loops. This value-0 sharings are deleted each start-tick
end


to calculate-donor-modifier ;; Called by a bat being asked to donate blood, with the potential recipient's who number stored in recipient-who
  set outgoing-sharing 0 ;; baseline if the donor has never given to the recipient before
  set incoming-sharing 0 ;; baseline if the recipient has never given to the donor before
  if sharing who recipient-who != nobody [ ask sharing who recipient-who [ set outgoing-sharing value ] ]
  if sharing recipient-who who != nobody [ ask sharing recipient-who who [ set incoming-sharing value ] ]
  let net-sharing outgoing-sharing - incoming-sharing
  set modifier ( incoming-sharing * trust-coefficient * -1 ) ;; if the recipient has given food before, the donor will be more generous than baseline (smaller modifier = more giving)
  if net-sharing > 0 [ set modifier modifier + ( net-sharing * annoyance-coefficient ) ] ;; if the recipient currently owes the donor, they'll be less generous than baseline
  if any? mothers with [ end1 = recipient-who and [age] of end2 < age-until-independence ]  [ set modifier modifier - charity-to-mothers ] ;; if the recipient has a dependent, increase by charity to mothers
  set modifier floor modifier
end


to update-sharing-link ;; after a trade of food occurs, store off the value of it
  if out-sharing-neighbor? bat recipient-who = false [ create-sharing-to bat recipient-who [ set value 0  ] ] ;; create a sharing link if none exists
  ask sharing who recipient-who
  [
    ask end1 [ set food food - share-value ]
    ask end2 [ set food food + share-value ]
    set value value + share-value
    ask both-ends [ check-sharing-status ]
  ]
end

to psuedo-recombinate
  ;; we don't have true sexual reproduction, because we're not modeling males.
  ;; instead, we'll just average mom with one other adult, as long as there is one
  ;; This is a hack, but an acceptable one, since males have just as many of moms genes as females
  if any? bats with [ age >= age-until-sexual-maturity and who != parent-who ]
  [
    ask one-of bats with [ age >= age-until-sexual-maturity and who != parent-who ]
    [
      set recombination-sharing-threshold sharing-threshold
      set recombination-charity-to-mothers charity-to-mothers
      set recombination-trust-coefficient trust-coefficient
      set recombination-annoyance-coefficient annoyance-coefficient
    ]
    set sharing-threshold floor mean list recombination-sharing-threshold sharing-threshold
    set charity-to-mothers floor mean list recombination-charity-to-mothers charity-to-mothers
    set trust-coefficient mean list recombination-trust-coefficient trust-coefficient
    set annoyance-coefficient mean list recombination-annoyance-coefficient annoyance-coefficient
  ]
end

to mutate ;; change the genetic traits slightly
  set sharing-threshold  sharing-threshold + ( ( random 5 ) - 2 ) ;; increases or decreases sharing threshold by up to 2
  set charity-to-mothers charity-to-mothers + ( ( random 5 ) - 2 ) ;; increases or decreases charity to mothers by up to 2
  set trust-coefficient trust-coefficient + ( ( random-float .1 ) - .05 ) ;;  increases or decreases trust coefficient by up to .05
  set annoyance-coefficient annoyance-coefficient + ( ( random-float .1 ) - .05 ) ;;  increases or decreases annoyance coefficient by up to .05
end

to spawn-new-bat ;; used for initial bat population and immigration
  create-bats 1
  [
  setxy random-xcor random-ycor
  set food random 50
  set pregnant? false
  set next-potential-pregnancy age-until-sexual-maturity ;; bats can have their first child when they're sexually mature
  set age age-until-independence + random ( ( lifespan-average - age-until-independence ) / 3 ) ;; new bats are adults who have lived up to one-third of the average adult lifespan
  set death-age 0
  while [ death-age <= age ] [ set death-age floor random-normal lifespan-average lifespan-standard-deviation ] ;; if a bat lives this long, they'll die of natural causes
  set sharing-threshold random 20
  set personal-threshold sharing-threshold + consumption-cost
  set personal-consumption consumption-cost
  set trust-coefficient random-float .5
  set annoyance-coefficient random-float .5
  set charity-to-mothers random 20
  if setting-up? = false and messages-to-display != "No Messages" [ output-print ( word "Bat " who " has joined the roost." ) ]
  ]
end

; Copyright 2017 Collin Lysford
; See Info tab for full copyright and license.
@#$#@#$#@
GRAPHICS-WINDOW
215
10
643
439
-1
-1
12.73
1
10
1
1
1
0
0
0
1
-16
16
-16
16
0
0
1
ticks
30.0

BUTTON
5
10
73
43
NIL
setup
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

BUTTON
142
10
205
43
NIL
go
T
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

OUTPUT
926
10
1313
601
11

PLOT
650
10
912
160
Mean Sharing Threshold
tick
NIL
0.0
10.0
0.0
20.0
true
false
"" ""
PENS
"default" 1.0 0 -16777216 true "" "plot mean [sharing-threshold] of bats"

PLOT
650
340
913
503
Mean Trust Coefficient
tick
NIL
0.0
10.0
0.0
0.5
true
false
"" ""
PENS
"default" 1.0 0 -16777216 true "" "plot mean [ trust-coefficient ] of bats"

PLOT
650
510
915
681
Mean Annoyance Coefficient
tick
NIL
0.0
10.0
0.0
0.5
true
false
"" ""
PENS
"default" 1.0 0 -16777216 true "" "plot mean [ annoyance-coefficient ] of bats"

MONITOR
123
54
207
99
Immigrations
immigration-count
17
1
11

MONITOR
6
54
120
99
Births
birth-count
17
1
11

SLIDER
5
150
210
183
starting-roost-count
starting-roost-count
5
100
45.0
5
1
bats
HORIZONTAL

SLIDER
5
185
210
218
stomach-size
stomach-size
10
300
120.0
5
1
units
HORIZONTAL

SLIDER
5
220
210
253
consumption-cost
consumption-cost
10
100
50.0
10
1
units
HORIZONTAL

SLIDER
5
255
210
288
reproduction-cost
reproduction-cost
0
20
10.0
1
1
units
HORIZONTAL

SLIDER
5
290
210
323
reproduction-time
reproduction-time
1
30
19.0
1
1
ticks
HORIZONTAL

SLIDER
5
325
210
358
absorption-efficiency
absorption-efficiency
0
1
0.2
.1
1
NIL
HORIZONTAL

SLIDER
5
435
210
468
lifespan-average
lifespan-average
50
1000
450.0
50
1
ticks
HORIZONTAL

SLIDER
5
750
210
783
immigration-chance
immigration-chance
0
20
3.0
1
1
%/tick
HORIZONTAL

MONITOR
124
102
207
147
Natural Deaths
natural-death-count
17
1
11

MONITOR
7
102
121
147
Deaths by Starvation
starvation-count
17
1
11

SLIDER
5
580
210
613
food-average
food-average
10
150
75.0
5
1
units/night
HORIZONTAL

SLIDER
5
615
210
648
food-standard-deviation
food-standard-deviation
0
20
6.0
2
1
units
HORIZONTAL

CHOOSER
929
605
1116
650
messages-to-display
messages-to-display
"Major Events Only" "All Messages" "No Messages"
0

SLIDER
5
540
210
573
age-until-sexual-maturity
age-until-sexual-maturity
2
50
30.0
2
1
ticks
HORIZONTAL

PLOT
293
499
557
649
Count of Bats
tick
bats
0.0
10.0
0.0
10.0
true
false
"" ""
PENS
"default" 1.0 0 -16777216 true "" "plot count bats"
"pen-1" 1.0 0 -13345367 true "" "plot starting-roost-count"

SLIDER
5
505
210
538
age-until-independence
age-until-independence
0
20
12.0
1
1
ticks
HORIZONTAL

SLIDER
5
470
210
503
lifespan-standard-deviation
lifespan-standard-deviation
0
100
40.0
10
1
ticks
HORIZONTAL

SLIDER
5
680
210
713
season-difference
season-difference
0
20
10.0
1
1
units at peak
HORIZONTAL

SLIDER
5
715
210
748
year-length
year-length
2
50
36.0
2
1
ticks
HORIZONTAL

PLOT
650
165
910
335
Mean Charity to Mothers
tick
NIL
0.0
10.0
0.0
20.0
true
false
"" ""
PENS
"default" 1.0 0 -16777216 true "" "plot mean [ charity-to-mothers ] of bats"

TEXTBOX
254
444
624
485
Blue links represent lifetime food sharing from one bat to another.\nThe more blue, the more food was shared.\nYellow links are mother to daughter.
11
0.0
1

TEXTBOX
933
661
1357
772
\"Major Events\" include births, deaths, pregnancies, fetal absorptions, \nand immigrations. \"All Messages\" shows hunting and trading events as well. \nNote that showing all messages makes the model significantly slower.\nIf you want to read all messages for a developed bat colony, first let the colony develop without displaying messages, then pause and enable all messages.
11
0.0
1

SLIDER
5
650
210
683
order-penalty
order-penalty
-2
0
-0.4
.1
1
units/preceding bat
HORIZONTAL

TEXTBOX
235
745
565
801
We don't model males, but you can enable psuedo recombination if you want daughters (otherwise clones of their mothers) to average their traits with one other adult before mutating. This reduces variation over time.
11
0.0
1

TEXTBOX
655
695
915
776
These are the values that vary between individuals. The purpose of the model is to observe their change over time given various parameter configurations.
11
0.0
1

SLIDER
5
360
210
393
time-between-pregnancies
time-between-pregnancies
0
40
18.0
2
1
ticks
HORIZONTAL

SLIDER
5
395
210
428
pregnancy-chance
pregnancy-chance
1
100
10.0
1
1
%
HORIZONTAL

SWITCH
235
705
417
738
psuedo-recombination?
psuedo-recombination?
1
1
-1000

@#$#@#$#@
## WHAT IS IT?
This model examines the phenomena of blood sharing in bats. It has [been observed](http://rspb.royalsocietypublishing.org/content/282/1819/20152524) that female vampire bats will share blood with non-kin in order to increase the chance of donations when they themselves are having hard times. In essence, the diminishing marginal utility of food creates opportunity for nominally "equal" trades of food over time to benefit both parties. Testing this in vivo is logistically limited to small populations of captive bats, and it cannot examine the genetic drift over time. As such, this model will do what is experimentally difficult in real life and look at a small roost of bats over a large number of generations. By modeling genetic inheritance, we can see what level of altruism is optimal given various configurations of population size, food abundance, and rate of immigration from non-related bats.

## HOW IT WORKS
The bat population goes through seven distinct phases each tick.

###1. Hunting Phase
Each bat that is at least age-until-independence old gets a normally distributed value of food. The mean and standard deviation of this normal distribution are set by food-average and food-standard-deviation, respectively.
However, the mean is also modified in two other ways:

* For each bat that has hunted before this bat this phase, the mean is lowered by order-penalty. This represents overcrowding of the environment. Note that the order in which bats hunt is randomized each night.
* A sine function with period year-length is evaluated for the value of the tick modulo year-length, divided by the year length and multiplied by 360 to turn to degrees. The output of this function (which ranges from -1 to 1) is multiplied by season-difference and added to the mean. We term the ticks where this is positive the "high season", and the ticks where this is negative the "low season". 

###2. Pregnancy Phase
Each bat who:

* Is not pregnant
* Has at least consumption-cost + reproduction-cost of food
* Is at least age-until-sexual-maturity old
* Had their last child, if any, at least time-between-pregnancies ago

Has a pregnancy-chance percent chance to become pregnant. When a bat becomes pregnant, their consumption is increased by reproduction-cost. Since their sharing threshold is "How much more food than consumption do I want before I start sharing?", their sharing threshold increases by the same amount.

###3. Sharing Phase
The sharing phase is divided into four sub-phases:

####Family sub-phase
If a daughter bat would starve tonight, her mother will give her food until she runs out or her daughter will no longer starve tonight.

If a mother would starve tonight, her daughter will give her food until either the mother will no longer starve tonight or the daughter would starve if she gave away any more food.

####Cooperation sub-phase
If a bat who has donated to another bat before would starve tonight, they ask each bat they've donated to (in descending order of how much they've given that bat over time) for food. The potential donor decides whether to help them based on this criteria:

* Start with your personal threshold (your current consumption cost plus your sharing-threshold)
* For each unit of food this bat has ever shared with you, lower the threshold by your trust coefficient
* For each unit of food this bat currently OWES you (ie, for each unit your value to them is greater than their value to you), raise the threshold by your annoyance coefficient
* If the bat asking for food has a child who can't feed themselves, decrease your threshold by your charity-to-mothers

The potential donor shares food until they have this modified threshold worth of food, or until they and the bat asking for food have the same amount of food.

####Mother begging sub-phase
As the cooperation sub-phase, but instead, bats with children who can't feed themselves and who will starve tonight ask bats they have NEVER interacted with for food. To make the code run faster, we pre-cache whether any bat would bother sharing with a strange mother (since trust and annoyance don't factor in to this, this is static per bat.)

####Non-mother begging sub-phase
As the mother begging sub-phase, but with non-mothers.

###4. Consumption Phase

Mothers that will die tonight first reabsorb their fetus. This lowers their personal consumption back to baseline, and refunds food equal to the invested food (reproduction cost times days of pregnancy) times the absorption efficiency.

Then, each bat pays their personal consumption worth of food and dies if they can't.

###5. Reproduction Phase

Each bat that has been pregnant for reproduction-time has a daughter. If psuedo-recombination is turned off, daughters start as exact clones of their mother. If psuedo-recombination is turned on, their genetic traits are averaged with another living bat. In either case, the daughters genetic traits are then further mutated. The sharing threshold and charity to mothers has a 20% chance to decrease by 2, decrease by 1, stay the same, increase by 1, or increase by 2. The trust and annoyance coefficients are increased or decreased randomly by up to .05.

###6. Aging phase

Each living bat has their age increased by 1. If they reach their death-age, they die. The death-age was randomly chosen for each bat when they were created by a normal distribution with mean lifespan-average and standard deviation lifespan-standard-deviation.

###7. Immigration phase

There is an immigration-chance percent chance that one new bat is randomly added to the roost. This bat is generated with the same code that generated bats on setup, instead of being based on any existing living bat.

## HOW TO USE IT

### To setup

Each slider controls a certain aspect of the model. Refer to the Sliders Section for more information on the function of each variable.

Once all the sliders are set to the desired levels, click SETUP to start the model.

### To run

To observe the tick-by-tick interactions of the bat colony, set "messages-to-display" to "All Messages", hit "Go", and read along in the output box.

If you want to observe the long term trending of the genetic traits (sharing threshold, charity to mothers, trust coefficient, and annoyance coefficient), "All Messages" slows the model down too much. Set it to "Major Events Only" or "No Messages", then run the model on the fastest setting to develop the bat colony through many generations. 

If you want to read messages corresponding to a developed bat colony, you can always let the model run for a while on "No Messages", then turn on "All Messages" later.

### Buttons

The SETUP button initializes the model.

The GO button runs the simulation until the cell dies.

### Switches

psuedo-recombination? - If this is on, daughters will average their genetic traits with one other living adult before mutating. This will significantly reduce variation in the gene pool. 

### Choosers

messages-to-display? - Has three options:

* No Messages: Writes nothing to the output window.
* Major Events Only: Writes tick changes with seasonal updates, births, deaths, pregnancies, fetal absorptions, and immigrations to the output window.
* All Messages: Writes everything Major Events does to the output window, but also shows how much food each bat gets during the hunting phase, and every request and response during the sharing phase. This slows the model down significantly.

### Sliders

starting-roost-count: Sets the number of starting bats. Since the food related parameters dictate the population that can be maintained, this doesn't have too much impact on the models output. However, the Count of Bats plot has a line relating to the starting roost count, so picking one that's about the median value of what the environment can maintain will make it easier to read the Count of Bats plot.

stomach-size: How much food a bat can have at once.

consumption-cost: How much food a bat needs each tick to survive.

reproduction-cost: How much MORE food a bat needs if she's pregnant.

absorption-efficiency: How much of the invested food a bat gets back if she's forced to reabsorb her fetus because she would otherwise starve to death.

time-between-pregnancies: How long after having a daughter a bat can get pregnant again.

pregnancy-chance: The chance a bat will get pregnant each night she isn't pregnant, has enough food to pay the additional reproduction cost, is sexually mature, and has waited sufficiently long since her last pregnancy.

lifespan-average: The mean of the normal function that dictates how long a bat will live if they don't starve to death.

lifespan-standard-deviation: The standard deviation of the normal function that dictates how long a bat will live if they don't starve to death.

age-until-independence: How long after being born a bat is able to hunt.

age-until-sexual-maturity: How long after being born a bat can become pregnant.

food-average: The mean of the normal function that dictates how much food a bat will get each night.

food-standard-deviation: The standard deviation of the normal function that dictates how much food a bat will get each night.

order-penalty: How much less food a bat will get each night for each bat that has hunted already this night. 

season-difference: How much seasonal change impacts the availability of food. The seasons are modeled by a sine function. This corresponds to how much food is added or subtracted from the average when the sine function returns 1 or -1, respectively.

year-length: The period of the seasonal sine function.

immigration-chance: The percentage chance each tick for a new bat to immigrate to the roost.


### Plots

Count of Bats - Shows the number of living bats each tick. Also includes the starting roost count (in blue) as a reference.

Mean Sharing Threshold - Shows the mean sharing threshold of all living bats each tick.

Mean Charity to Mothers - Shows the mean charity to mothers of all living bats each tick.

Mean Trust Coefficient - Shows the mean trust coefficient of all living bats each tick.

Mean Annoyance Coefficient  - Shows the mean annoyance coefficient of all living bats each tick.


## THINGS TO NOTICE

Notice the sinusoidal pattern of the bat count that comes as a result of the seasonal difference and the order penalty. This is the ideal for natural selection, since it creates variation and then limits the survivors to the best adapted ones.

Notice the proportion of mother-daughter links to general sharing links as the model evolves.

## THINGS TO TRY

Increase the stomach size and watch what happens to the mean sharing threshold. Vampire bat altruism is heavily incentived by their small stomachs meaning that "it could be me in two days" - with large stomachs, greed is a much more successful strategy, because it's actually possible to hoard a significant amount of blood.

Other than that, you can try to do what I failed to do and find a parameter set where the "best" bats tend to die natural deaths. No matter what parameter set I explored, very few bats tend to die of natural causes in this model - this means that random chance is having a lot of impact and a large chunk of the fluctuation of the traits is just noise. Ideally, there's a parameter set where the "best adapted" bats live out their full lives. This model would have been much more interesting if I could have the defaults produce that result. (This could be a consequence of my food function - unfortunately, I couldn't find much research on how bat feedings scale with population, so I took a best guess.)

## EXTENDING THE MODEL

Since vampire bats tend to live in female-only roosts and thus only share blood with females, I made all children daughters and didn't model male bats. It might be interesting to try to make this a truly genetic model by researching how the male interacts with the roost. It's a harder problem than it sounds because the males exploits are "off-screen" with regards to the model, so the male rate of genetic change needs to be kept in sync somehow.

There's also the interesting possibility that this model is "doomed to fail" because kin-only altruism would be the ideal if you could get away with it, and vampire bat altruism is simply because bats don't have the memories to remember their trading history and who is and isn't kin. In essence, my model may be pre-supposing a level of sophistication bats don't actually possess, which explains why it diverges from what's observed in nature. It would be a relatively easy mutation to change this model to have no historical memory and no special handling of kin relations, and see what level of altruism the population stabilizes on.

## NETLOGO FEATURES

The season related code in start-tick shows how to model sinusoidal changes in the environment when the length of the period is determined by a user parameter.

The "cooperation phase" of share has a useful design pattern to "ask in order". It involves caching the value you want to sort on, then, while any one of those values is greater than zero, asking an agent with a maximal value for that cached variable and setting the cached value to 0 during the ask.

## HOW TO CITE

If you mention this model or the NetLogo software in a publication, we ask that you include the citation below.

Please cite the NetLogo software as:

* Wilensky, U. (1999). NetLogo. http://ccl.northwestern.edu/netlogo/. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.

## COPYRIGHT AND LICENSE
 
model developed by Collin Lysford in 2017
@#$#@#$#@
default
true
0
Polygon -7500403 true true 150 5 40 250 150 205 260 250

airplane
true
0
Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15

arrow
true
0
Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150

box
false
0
Polygon -7500403 true true 150 285 285 225 285 75 150 135
Polygon -7500403 true true 150 135 15 75 150 15 285 75
Polygon -7500403 true true 15 75 15 225 150 285 150 135
Line -16777216 false 150 285 150 135
Line -16777216 false 150 135 15 75
Line -16777216 false 150 135 285 75

bug
true
0
Circle -7500403 true true 96 182 108
Circle -7500403 true true 110 127 80
Circle -7500403 true true 110 75 80
Line -7500403 true 150 100 80 30
Line -7500403 true 150 100 220 30

butterfly
true
0
Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240
Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240
Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163
Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165
Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225
Circle -16777216 true false 135 90 30
Line -16777216 false 150 105 195 60
Line -16777216 false 150 105 105 60

car
false
0
Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180
Circle -16777216 true false 180 180 90
Circle -16777216 true false 30 180 90
Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89
Circle -7500403 true true 47 195 58
Circle -7500403 true true 195 195 58

circle
false
0
Circle -7500403 true true 0 0 300

circle 2
false
0
Circle -7500403 true true 0 0 300
Circle -16777216 true false 30 30 240

cow
false
0
Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167
Polygon -7500403 true true 73 210 86 251 62 249 48 208
Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123

cylinder
false
0
Circle -7500403 true true 0 0 300

dot
false
0
Circle -7500403 true true 90 90 120

face happy
false
0
Circle -7500403 true true 8 8 285
Circle -16777216 true false 60 75 60
Circle -16777216 true false 180 75 60
Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240

face neutral
false
0
Circle -7500403 true true 8 7 285
Circle -16777216 true false 60 75 60
Circle -16777216 true false 180 75 60
Rectangle -16777216 true false 60 195 240 225

face sad
false
0
Circle -7500403 true true 8 8 285
Circle -16777216 true false 60 75 60
Circle -16777216 true false 180 75 60
Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183

fish
false
0
Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166
Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165
Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60
Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166
Circle -16777216 true false 215 106 30

flag
false
0
Rectangle -7500403 true true 60 15 75 300
Polygon -7500403 true true 90 150 270 90 90 30
Line -7500403 true 75 135 90 135
Line -7500403 true 75 45 90 45

flower
false
0
Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135
Circle -7500403 true true 85 132 38
Circle -7500403 true true 130 147 38
Circle -7500403 true true 192 85 38
Circle -7500403 true true 85 40 38
Circle -7500403 true true 177 40 38
Circle -7500403 true true 177 132 38
Circle -7500403 true true 70 85 38
Circle -7500403 true true 130 25 38
Circle -7500403 true true 96 51 108
Circle -16777216 true false 113 68 74
Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218
Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240

house
false
0
Rectangle -7500403 true true 45 120 255 285
Rectangle -16777216 true false 120 210 180 285
Polygon -7500403 true true 15 120 150 15 285 120
Line -16777216 false 30 120 270 120

leaf
false
0
Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195
Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195

line
true
0
Line -7500403 true 150 0 150 300

line half
true
0
Line -7500403 true 150 0 150 150

pentagon
false
0
Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120

person
false
0
Circle -7500403 true true 110 5 80
Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90
Rectangle -7500403 true true 127 79 172 94
Polygon -7500403 true true 195 90 240 150 225 180 165 105
Polygon -7500403 true true 105 90 60 150 75 180 135 105

plant
false
0
Rectangle -7500403 true true 135 90 165 300
Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285
Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285
Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210
Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135
Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135
Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60
Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90

sheep
false
15
Circle -1 true true 203 65 88
Circle -1 true true 70 65 162
Circle -1 true true 150 105 120
Polygon -7500403 true false 218 120 240 165 255 165 278 120
Circle -7500403 true false 214 72 67
Rectangle -1 true true 164 223 179 298
Polygon -1 true true 45 285 30 285 30 240 15 195 45 210
Circle -1 true true 3 83 150
Rectangle -1 true true 65 221 80 296
Polygon -1 true true 195 285 210 285 210 240 240 210 195 210
Polygon -7500403 true false 276 85 285 105 302 99 294 83
Polygon -7500403 true false 219 85 210 105 193 99 201 83

square
false
0
Rectangle -7500403 true true 30 30 270 270

square 2
false
0
Rectangle -7500403 true true 30 30 270 270
Rectangle -16777216 true false 60 60 240 240

star
false
0
Polygon -7500403 true true 151 1 185 108 298 108 207 175 242 282 151 216 59 282 94 175 3 108 116 108

target
false
0
Circle -7500403 true true 0 0 300
Circle -16777216 true false 30 30 240
Circle -7500403 true true 60 60 180
Circle -16777216 true false 90 90 120
Circle -7500403 true true 120 120 60

tree
false
0
Circle -7500403 true true 118 3 94
Rectangle -6459832 true false 120 195 180 300
Circle -7500403 true true 65 21 108
Circle -7500403 true true 116 41 127
Circle -7500403 true true 45 90 120
Circle -7500403 true true 104 74 152

triangle
false
0
Polygon -7500403 true true 150 30 15 255 285 255

triangle 2
false
0
Polygon -7500403 true true 150 30 15 255 285 255
Polygon -16777216 true false 151 99 225 223 75 224

truck
false
0
Rectangle -7500403 true true 4 45 195 187
Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194
Rectangle -1 true false 195 60 195 105
Polygon -16777216 true false 238 112 252 141 219 141 218 112
Circle -16777216 true false 234 174 42
Rectangle -7500403 true true 181 185 214 194
Circle -16777216 true false 144 174 42
Circle -16777216 true false 24 174 42
Circle -7500403 false true 24 174 42
Circle -7500403 false true 144 174 42
Circle -7500403 false true 234 174 42

turtle
true
0
Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210
Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105
Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105
Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87
Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210
Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99

wheel
false
0
Circle -7500403 true true 3 3 294
Circle -16777216 true false 30 30 240
Line -7500403 true 150 285 150 15
Line -7500403 true 15 150 285 150
Circle -7500403 true true 120 120 60
Line -7500403 true 216 40 79 269
Line -7500403 true 40 84 269 221
Line -7500403 true 40 216 269 79
Line -7500403 true 84 40 221 269

wolf
false
0
Polygon -16777216 true false 253 133 245 131 245 133
Polygon -7500403 true true 2 194 13 197 30 191 38 193 38 205 20 226 20 257 27 265 38 266 40 260 31 253 31 230 60 206 68 198 75 209 66 228 65 243 82 261 84 268 100 267 103 261 77 239 79 231 100 207 98 196 119 201 143 202 160 195 166 210 172 213 173 238 167 251 160 248 154 265 169 264 178 247 186 240 198 260 200 271 217 271 219 262 207 258 195 230 192 198 210 184 227 164 242 144 259 145 284 151 277 141 293 140 299 134 297 127 273 119 270 105
Polygon -7500403 true true -1 195 14 180 36 166 40 153 53 140 82 131 134 133 159 126 188 115 227 108 236 102 238 98 268 86 269 92 281 87 269 103 269 113

x
false
0
Polygon -7500403 true true 270 75 225 30 30 225 75 270
Polygon -7500403 true true 30 75 75 30 270 225 225 270
@#$#@#$#@
NetLogo 6.0.1
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
default
0.0
-0.2 0 0.0 1.0
0.0 1 1.0 0.0
0.2 0 0.0 1.0
link direction
true
0
Line -7500403 true 150 150 90 180
Line -7500403 true 150 150 210 180
@#$#@#$#@
1
@#$#@#$#@
