; NOTES
; [1] When running Behavior Space experiments, it is recommended that 'setup.BS' be used as setup command (rather than the normal 'setup'). For
;     an explanation, see comment to the 'to setup.BS' procedure.
; [2] The declaration of every procedure is followed by a notation stating which context (observer, turtles, patches) it belongs to.
; [3] Documentation for the 'numanal' extension is available in the extension's installation folder. Such folder can generally be found
;     in the subfolder:
;        Library/Application Support/NetLogo (on Mac OS X)
;        AppData\Roaming\NetLogo\6.2\extensions (on Windows)
;        .netlogo (on Linux)
;     For more information on where to find NetLogo extensions, see: https://ccl.northwestern.edu/netlogo/docs/extensions.html#where-extensions-are-located.
;     Tip for Windows: a quick way to access the AppData folder (which might be hidden) is to type %appdata% in your File Explorer search bar.
;
; A NOTE ON COMPARING BEAN PRICES AND COFFEE PRICES
; Bean prices in Brazil: https://www.tridge.com/intelligences/common-bean/BR
; Coffee prices in Brazil: https://www.tridge.com/intelligences/coffee-bean/BR
; Producer prices can also be found from the FAO: http://www.fao.org/faostat/en/#data/PP
; These sources suggest that the ratio of the price per kg of coffee to that of beans may range from 0.15 to 8.5.
; 0.15 comes from comparing the cheapest coffee price per kg found to the most expensive bean price.
; 8.5 comes from comparing the most expensive coffee price per kg found to the least expensive bean price
; The (2016) FAO producer price data puts the ratio at 1.85 (using 'beans' and 'coffee, green')
; Bean are mainly consumed domestically and prices at farmgate are volatile
; In our case, we are assuming a focus on coffee exports.


extensions [numanal]

; ******************************************************************************************************************************************
; *********************************************************** CREATING VARIABLES ***********************************************************
; ******************************************************************************************************************************************


globals [
; The following globals are set once at the beginning of the run ('to set.globals') and are never changed.

  ha.to.patch                       ; [number] Each patch is 900 sqm. Multiplying ha-based values by this variable gives the corresponding patch-based values.

  farm.hrs.day                      ; [hours/day] Hours spent on farm per day.

  beans.labour                      ; [person-days/ha/yr] Amount of work needed for one hectare of beans, as performed by one adult in one year.
  beans.labour.patch                ; [person-days/patch/yr] Amount of work needed for one patch of beans, as performed by one adult in one year.
  beans.yield                       ; [kg/ha/yr] Yearly yield of beans on one hectare with full fertility.
  beans.yield.patch                 ; [kg/patch/year] Yearly yield of beans on one patch with full fertility.
  beans.kcal                        ; [kcal/kg] Kilocalories from 1kg of beans.
  beans.kcal.patch                  ; [kcal/patch/yr] Kilocalories yielded by each patch planted in beans with full fertility in one year.

  corn.labour                       ; [person-days/ha/yr] Amount of work needed for one hectare of corn, as performed by one adult in one year.
  corn.labour.patch                 ; [person-days/patch/yr] Amount of work needed for one patch of corn, as performed by one adult in one year.
  corn.yield                        ; [kg/ha/yr] Yearly yield of corn on one hectare with full fertility.
  corn.yield.patch
  corn.kcal                         ; [kcal/kg] Kilocalories from 1kg of corn.
  corn.kcal.patch                   ; [kcal/patch/yr] Kilocalories yielded by each patch planted in corn with full fertility in one year.

  coffee.labour                     ; [person-days/ha/yr] Amount of work needed for one hectare of coffee, as performed by one adult in one year.
  coffee.labour.patch               ; [person-days/patch/yr] Amount of work needed for one patch of coffee, as performed by one adult in one year.
  coffee.yield                      ; [kg/ha/yr] Yearly yield of coffee on one hectare with full fertility.
  coffee.yield.patch                ; [kg/patch/yr] Yearly yield of coffee on one patch with full fertility.
  coffee.kcal                       ; [equivalent of kcal/kg] Equivalent of kilocaries from 1kg of coffee, as calculated according to conversion to beans.
  coffee.kcal.patch                 ; [equivalent of kcal/patch/year] Equivalent of kilocalories yielded by each patch planted in coffee with full fertility in one year, as calculated according to conversion to beans.

  coffee.exchange.price             ; [USD] Foreign currency earned through export of coffee produced in the model since the start.
  price.adjustment

; As opposed to the previous ones, the following globals are updated once a year (i.e. once per 'to go').

  households.entered                        ; [number] The number of households that has entered the model since the start.
  households.escaped                        ; [number] The number of households that has escaped the model since the start, as a result of not being able to fulfil conditions.
  coffee.produced.overall                   ; [kg] Kilograms of coffee produced in the model since the start.
  foreign.currency.from.coffee.export.tot   ; [USD]

; While all the globals above are initialised in 'to set.globals' (including 'coffee.produced.overall' and 'coffee.exchange.price', which are included there only for tidyness purposes),
; these two variables below are initialised in 'to setup', each for a different reason: see comments below.

  behavior.space.run?            ; This variable is initialised at each setup because it identifies whether the run is happening in Behavior Space ('behavior.space.run? = TRUE') or in the
                                 ; usual NetLogo interface ('behavior.space.run? = FALSE'). Checking for this variable allows to activate/deactivate the implementation of the model's visuals.
                                 ; If the run is happening in NetLogo, the visual representations are turned off - this saves time and memory, especially considering the number of pathces.

  control                        ; This variable is used to manage the loading time (especially in Behavior Space) reulting from the process of importing the initial map from an external file.
                                 ; The variable is initialised ('control = 1') by the end of the setup procedure, signalling that the 'to import.map' procedure has taken place and that there
                                 ; is no need to perform it again. Infact the imported data (mainly patches-own variables) is never automatically deleted from the model, unless either 'clear-all'
                                 ; or 'clear-patches' are manually invoked. It is exactly for this purpose that 'clear-all' is not used in the model (see custom procedure 'to clear.selected.fields'
                                 ; instead), and all non-imported patches-own variables are reset separately at the beginning of each run (via the 'to initial.map' procedure, called by 'to setup').
                                 ; This is the recommended approach found in the NetLogo website - see https://ccl.northwestern.edu/netlogo/docs/behaviorspace.html (-> "Run options: parallel runs).
]


patches-own [
; The first group of four patches-own variables represent those that are imported via 'to import-world' (called by 'to import.map'). These variables are only imported when 'control = 0', thus at
; the beginning of the first run, and are never reset across runs unless something explicitely clears them (e.g. 'clear-all' or 'clear-patches'). Given this role that they have, they are never
; set nor changed in the code - apart from landcover in patches where 'landcover = 1' (i.e. patches with forest). In fact the initial possible values or landcover are 1, 2, 3 and 6 (see comment
; below to see what they mean). While landcovers 2, 3 and 6 never change, landcover 1 changes if it is deforested. Over time, patches whose initial landcove was 1 might take landcover values
; of 4, 5 or 0. This is the reason why, to restore the initial map, at every setup patches with those landcovers are brought back to have 'landcover = 1' (see 'to set.initial.map').

  landcover                       ; [index] A variable showing the current land cover. Values: 0 = abandoned, 1 = forest, 2 = water, 3 = basin, 4 = crop, 5 = pasture, 6 = road.
  map1.lot                        ; [number] A variable identifying the lot number to which the patch belongs to in the 'baseline' map.
  map2.lot                        ; [number] A variable identifying the lot number to which the patch belongs to in the 'wetlands' map.
  direction                       ; [abbreviation] A variable identifying the direction of the lot from the access road. Values: "n" = North, "s" = South, 0 = none (the patch is not in a lot).

; As opposed to the previous ones, the following patch variables change everytime. Given that 'clear-patches' is never called in the model, these are manually reset at every setup via
; the 'to set.initial.map' procedure.

  lot                             ; [number] A variable identifying the lot number to which a patch belongs.
  owner                           ; [agent] The household to which a patch (and all the other patches from the same lot) belongs.
  which.crop                      ; [index] A variable showing the current crop. Values: 0 = no crop, 1 = beans, 2 = corn, 3 = coffee.
  fertility                       ; [percentage] The level of fertility directly affecting yield on land. Min: 0 (0%); Max: 1 (100%).
  fertility.impact                ; [percentage] The relative impact of fertility on output.
  kcal.yielded                    ; [kcal/year] The kcalories that the patch is yielling per year according to the planted crop and the level of fertility.
  workforce.trapped               ; [person-days/year] The amount of workforce engaged on this patch while this is planted with some crop.
  abandoned                       ; [index] A number showing the abandonment status of the patch. If 'abandoned > 0', the patch has been abandoned. The value increases every year, until the patch become pasture.
  coffee.produced                 ; [kgal/year] Kilograms of coffee produced by the patch in the current year.
]


turtles-own [
; Most of the turtles-own variables are set in the 'to create.families' procedure (via procedures called from within there). Exceptions are: 'my.lot.available' (can be changed during the simulation);
; 'workforce.available' and 'kcal.left' (set and updated during 'to calculate.ex-ante'); 'plant.beans', 'plant.corn', 'plant.coffee', 'illegal?' and 'leaving?' (set and/or updated during 'to plan').

 behaviour                                  ; [string] A string identifying the type of behaviour held by the household, as determined by the user in the Interface.
 my.lot                                     ; [agentset] The full patch agentset (i.e. group of patches) constituiting this households' lot.
 my.lot.f                                   ; [agentset] That part of the lot whose landcover is forest.
 my.lot.available                           ; [agentset] That part of 'my.lot.f' that is available for deforestation according to the level of forest protection and to the propensity to deforest illegally.
 members                                    ; [count] The quantity of members in the household.
 females                                    ; [count] The quantity of adult females in the household.
 males                                      ; [count] The quantity of adult males in the household.
 children                                   ; [count] The quantity of children in the household.
 elderly                                    ; [count] The quantity of elderly in the household..
 tot.workforce                              ; [person-days/yr] The amount of workforce overall usable by the household, as person-days per year.
 workforce.available                        ; [person-days/yr] The amount of workforce currently free in the household (overall workforce minus trapped workforce)
 tot.kcal.required                          ; [kcal/yr] The yearly kcalories requirement of the household, based on its demographics.
 kcal.left                                  ; [kcal/yr] The kcalories that the household needs to find, in addition of those already obtained from current crops, to fulfil the yearly requirement.
 plant.beans                                ; [count] The number of patches that the household intends to plant with beans - according to behaviour, land available, workforce available and kcalories required.
 plant.corn                                 ; [count] The number of patches that the household intends to plant with corn - according to behaviour, land available, workforce available and kcalories required.
 plant.coffee                               ; [count] The number of patches that the household intends to plant with coffee - according to behaviour, land available, workforce available and kcalories required.
 my.solution                                ; [kcal] The solution of the planning algorithym for what concerns the kcalories produced by the household.
 my.preference                              ; [percentage] If the household has a preference for corn, this is the minimum share it will want to have planted with corn (0.25, 0.50 or 0.75).
 direction.t                                ; [abbreviation] A variable identifying the direction of the lot belonging to this household. Values: "n" = North, "s" = South.
 illegal?                                   ; [boolean] Whether the household would deforest beyond the legal limit. This variable is determined once per household. Before being determined, the value is 0.
 leaving?                                   ; [boolean] Whether the household will leave the simulation at the end of the year. Defaults to 'FALSE'.
]


; ******************************************************************************************************************************************
; ************************************************************ SETUP PROCEDURES ************************************************************
; ******************************************************************************************************************************************


to setup   ; [OBSERVER CONTEXT]
; The first block of commands checks if 'control = 0'. The 'control' variable is used to reduce loading time in Behavior Space: it is set to
; 1 at the end of the very first run, and is never brought back to 0. This signals that only at the beginning of the very first run the model
; will need to perform 'import-world' (called by 'import.map') to import the patch-related data, which is a time-consuming process. For all
; subsequent runs (i.e. when 'control != 0') the second command is exectued. This avoids using 'clear-all', which would delete the imported
; data and bring 'control' back to 0. Instead, all the things that should not be kept (e.g. ticks, turtles, plots etc) are deleted separately;
; The desired values of globals and patches-own variables are set to their desired starting level at the end of the run (those procedures are
; called from within the 'to go' procedure, see 'to reset.globals' and 'to reset.patches'.

  clear.selected.fields

; These four globals below need to be reset everytime setup occurs (unlike the ones that are set with 'set.globals' below, which never change
; and therefore are only set on the first setup, i.e. when control = 0).
  set households.entered 0
  set households.escaped 0
  set coffee.produced.overall 0
  set foreign.currency.from.coffee.export.tot 0

  if control = 0 [
   import.map
   set.globals
  ]

  set.initial.map

  set control 1

  set behavior.space.run? FALSE
end


to setup.BS   ; [OBSERVER CONTEXT]
; It is advised that this is used as setup command for Behavior Space experiments. The 'behavior.space.run?' condition is checked everytime that
; a modification to the map (e.g. patches colours) might be performed. If 'behavior.space.run? = TRUE', the map modification is not performed.
; With 116466 patches making up the map, this saves a considerable amount of time and memory.

  setup
  set behavior.space.run? TRUE
end


to clear.selected.fields   ; [OBSERVER CONTEXT]
  clear-ticks
  reset-ticks
  clear-turtles
  clear-drawing
  clear-all-plots
  clear-output
end


to import.map   ; [OBSERVER CONTEXT]
  set-patch-size 1.05
  import-world "netlogomap"
end


to set.globals   ; [OBSERVER CONTEXT]
; For each variable, the unit of measure is reported in square brakets.

  set ha.to.patch 0.09                                              ; [fraction]

  set farm.hrs.day 8                                                ; [hours] Hours spent on farm per day.

  set beans.labour 683 / farm.hrs.day                               ; [person-days/ha/yr] Amount of work needed for one hectare of beans, as performed by one adult in one year. Source for 683: Ibarrola-Rivas et al. (2016).
  set beans.labour.patch (beans.labour * ha.to.patch)               ; [person-days/patch/yr]
  set beans.yield 300                                               ; [kg/ha/yr] Yearly yield of beans on one hectare of healthy soil. Source: Ibarrola-Rivas et al. (2016)
  set beans.yield.patch (beans.yield * ha.to.patch)                 ; [kg/patch/yr]
  set beans.kcal 180 * 10                                           ; [kcal/kg] Kilocalories from 1kg of beans. Source: https://fdc.nal.usda.gov/fdc-app.html#/food-details/1100374/nutrients.
  set beans.kcal.patch (beans.kcal * beans.yield * ha.to.patch)     ; [kcal/patch/yr]

  set corn.labour 383 / farm.hrs.day                                ; [person-days/ha/yr] Amount of work needed for one hectare of corn, as performed by one adult in one year. Source for 383: Ibarrola-Rivas et al. (2016).
  set corn.labour.patch (corn.labour * ha.to.patch)                 ; [person-days/patch/yr]
  set corn.yield 226                                                ; [kg/ha/yr] Yearly yield of corn on one hectare of healthy soil. Source: Ibarrola-Rivas et al. (2016)
  set corn.yield.patch (corn.yield * ha.to.patch)                   ; [kg/patch/yr]
  set corn.kcal 86 * 10                                             ; [kcal/kg] Kilocalories from 1kg of corn. Source: https://fdc.nal.usda.gov/fdc-app.html#/food-details/1103351/nutrients.
  set corn.kcal.patch (corn.kcal * corn.yield * ha.to.patch)        ; [kcal/patch/yr]

  set coffee.labour 114                                             ; [person-days/ha/yr] Amount of work needed for one hectare of coffee, as performed by one adult in one year. Source: de Souza et al. (2012).
  set coffee.labour.patch (coffee.labour * ha.to.patch)             ; [person-days/patch/yr]
  set coffee.yield 540                                              ; [kg/ha/yr] Yearly yield of coffee on one hectare with full fertility. Source: Ibarrola-Rivas et al. (2016)
  set coffee.yield.patch (coffee.yield * ha.to.patch)               ; [kg/patch/yr]
  set coffee.kcal (beans.kcal * bean.to.coffee.kcal.conversion)     ; [Equivalent of kcal/kg]
  set coffee.kcal.patch (coffee.kcal * coffee.yield * ha.to.patch)  ; [Equivalent of kcal/patch/yr]
end


to set.initial.map   ; [OBSERVER CONTEXT]
  ask patches [
   ifelse which.map = "baseline" [set lot map1.lot] [set lot map2.lot]        ; Populates 'lot' based on which map is being used.
   set fertility 1
  ]

  set.fertility.impact

; The list below contains avaerage closing prices for coffee on the international market, in USD/KG, from 1975 to 2020 (https://www.macrotrends.net/2535/coffee-prices-historical-chart-data)
  set coffee.exchange.price (list 2.46 2.24 2.5 2.94 3.02	2.94 3.93	2.78 3.86	5.59 3.62	2.77 2.92	2.6 2.39 2.38	1.69 1.38	1.19 1.23	1.99 2.3 2.85	3.95 2.55 3.23 3.19	1.51 1.44	1.89 2 2.33	2.89 2.57	4.4	3.28 3.16	2.9	2.99 2.7 3.49	3.92 3.45	5.11 3.14	1.45)
; The list below converts USD from 1975 to 2020 in 2020 USD. (https://www.usinflationcalculator.com/)
  set price.adjustment (list 0.21 0.22 0.23 0.25 0.28 0.32 0.35 0.37 0.38 0.4 0.42 0.42 0.44 0.46 0.48 0.51 0.53 0.54 0.56 0.57 0.59 0.61 0.62 0.63 0.64 0.67 0.68 0.7 0.71 0.73 0.75 0.78 0.8 0.83 0.83 0.84 0.87 0.89 0.9 0.91 0.92 0.93 0.95 0.97 0.99 1)

; The commands above are performed on every run.
; The commands below are performed from the second run on (when 'control != 0').

; For what concerns the first command below, that is the case because only from the second run there is the
; need to restore the map (in the first run it is imported). For what concerns the other commands, that is
; the case because in the first run they are set to 0 as their default value - which leaves the need to manually
; setting them to 0 only from the second run on (given that no 'clear-all' nor 'clear-globals' are used).

   if control != 0 [ask patches [
     if landcover = 4 or landcover = 5 or landcover = 0 [set landcover 1]     ; Restores initial forest landcover.
     set owner 0
     set which.crop 0
     set kcal.yielded 0
     set workforce.trapped 0
     set abandoned 0
     set coffee.produced 0
    ]
  ]

  if control != 0 and not behavior.space.run? [set.initial.colours]           ; Only if not in the first run and not in Behavior Space: visually restores the initial landcover.
end


to set.fertility.impact   ; [OBSERVER CONTEXT]
; As the fertility of the soil decreases, it will affect production. However, it may not affect kcalories produced from
; a patch of land in an exactly proportionate way. The code here enables these two effects to be separated.
; Specifically, it presumes that kcalories production is affected less significantly than the decrease of fertility itself.
; This represents the idea that certain human interventions can help support crop growth (e.g. types of fertilization).
; The 'fertility.impact' value is set once for each patch, and so can vary across patches within the simulation.

; In this first block of code, the 'fertility.impact' value is set randomly once for each forested patch belonging to
; a lot (i.e. each patch that might be deforested during the simulation).
; Specifically, the structure of the function to generate such value is: '(random-float x) + y', which means that the
; value will be between (y) and (x + y).
  ask patches with [landcover = 1 and map1.lot != 0] [
    set fertility.impact (random-float 0.2) + 0.3
  ]

; This second block of code makes it possible for the 'fertility.impact' value to not be TOTALLY random across the
; landscape (considering that the value might be dependant on some soil characteristics). This is achieved by asking
; each patch with a fertility.impact value to make it the mean of the value belonging to its neihboring patches.
  ask patches with [fertility.impact > 0] [
    if not empty? [fertility.impact] of neighbors with [fertility.impact > 0] [
      set fertility.impact mean [fertility.impact] of neighbors with [fertility.impact > 0]
    ]
  ]
end


; *******************************************************************************************************************************************
; ************************************************************** GO PROCEDURES **************************************************************
; *******************************************************************************************************************************************


to go   ; [OBSERVER CONTEXT]
  if ticks > (simulation.end - 1976) [stop]

  create.families
  calculate.ex-ante
  ask turtles [plan]
  crop
  calculate.ex-post
  escape

  tick
end


; ************************************************ BEGINNING OF HOUSEHOLDS CREATION *************************************************


to create.families   ; [OBSERVER CONTEXT]
; A specific amount of households enters the model based on the year (tick). As soon as they are created,
; each household is given its specific characteristics ('set.household'), which include having a lot assigned
; ('to choose.lot').
; The number of households entering the simulation has been originally taken from the literature for a similar
; case. However, than number has been multiplied by 0.35119047619047619047619047619048 to reflect the re-sizing
; of the map.

; The first line below creates a list of one element, i.e. the number of available lots.

  let x (list (count patches with [ lot != 0 and owner = 0 ] / 1072))
  let y 0
  (ifelse
    ticks = 0 [set y 20]                     ; Initial number was 57.
    ticks < 6 [set y 8]                      ; Initial number was 24.
    ticks = 6 [set y 6]                      ; Initial number was 16.
    ticks < 30 [set y 3]                     ; Initial number was 8.
    [set y 0]
    )

; This block of commands adds 'y' (as conditionally determined above) to the list, which thus becomes a list of two elements, and
; then creates as many households as the lower ('min') number from the list. Considering that 'x' is the number of available lots
; and that 'y' is the potential number of households entering the model, and considerint that households are created in a number
; equalling the minimum between 'x' and 'y', this means that there will never be more households entering the simulation than lots
; available.

  set x fput y x
  create-turtles min x [
   hide-turtle
   set.household
  ]
  set households.entered households.entered + min x

; Conceptually, the 'set.behaviour' procedure could have been called from within the block of commands above (i.e. 'create-turtles [...]'). However,
; that would have been a turtle-context and would have meant having each turtle evaluating the conditions needed to assign behaviours. Calling it
; from outside the 'create-turtles' procedure, instead, means calling it from the observer-context and thus having only the observer (which is one)
; evaluating the same conditions (therefore saving time and memory).

  set.behaviour
end


to set.household   ; [TURTLE CONTEXT]
; It is recommended that 'choose.lot' remains the first of the list. In fact, turtles might leave the simulation before settling into a lot.
; In that case, all the following computations are avoided.

  choose.lot
  set.numerosity
  set.individuals
  set.workforce
  set.tot.kcal.required
  set leaving? FALSE
end


to choose.lot   ; [TURTLE CONTEXT]
; The lot-assignment process takes place in four steps.
; In the first line, the household finds a patch that belongs to a lot owned by no one, and sets "myself" as the owner of that patch.
; In the second line, the household assigns to "my.lot" that patch's "lot" value. [at this stage, "my.lot" is a number]
; In the third line, all patches with that same "lot" value are asked to set that household (identified by "myself") as their owner.
; In the fourth line, the group of patches with that household as owner becomes the "my.lot" household's variable. [at this stage, "my.lot" is an agentset]

  ask one-of patches with [lot != 0 and owner = 0] [set owner myself]
  set my.lot [lot] of one-of patches with [owner = myself]
  ask patches with [lot = [my.lot] of myself] [set owner myself]
  set my.lot patches with [owner = myself]

; While the 'my.lot' variable stores the entire lot (which is useful for patch-management purposes), the 'my.lot.f' variable below
; stores patches of my lot that are forest (which is useful for managing the deforestation side of things). In fact, the other patches
; might be wetland or water, and it is not possible for households to crop there.

  set my.lot.f my.lot with [landcover = 1]

  if count my.lot.f < (legal.farming * count my.lot) / 100 [
    clear.lot
    set households.entered households.entered - 1
    die
  ]

; The next block of code sets the portion of lot available for deforestation as the one closest to the road.
; This is done by first checking the direction of patches in 'my.lot' (i.e. 'n' = North, 's' = South), and
; then setting as 'my.lot.available' the percentage (as determined in the Interface) of the lot with the
; highest or lowest y-coordinates.

  set direction.t [direction] of one-of my.lot
  ifelse direction.t = "n"
  [set my.lot.available min-n-of (ceiling (legal.farming * count my.lot / 100)) my.lot.f [pycor]]
  [set my.lot.available max-n-of (ceiling (legal.farming * count my.lot / 100)) my.lot.f [pycor]]


; These four lines below ask households to move to the center of their lots and to become visible. Useless for most practical purposes,
; but better to keep it here.

  if not behavior.space.run? [
    move-to patch ((min [pxcor] of my.lot + max [pxcor] of my.lot) / 2) ((min [pycor] of my.lot + max [pycor] of my.lot) / 2)
    set hidden? FALSE
    set size 8
    set color white
  ]
end


to set.numerosity   ; [TURTLE CONTEXT]
; The first line creates a random number from 0.00 to 99.99. The subsequent block of commands determines the number of members
; of the family based on household-numerosity data for rural Brazil.

  let x precision random-float 100 2
  (ifelse
    x < 20.24 [set members 3]
    x < 42.12 [set members 4]
    x < 62.07 [set members 5]
    x < 76.20 [set members 6]
    x < 85.81 [set members 7]
    x < 92.04 [set members 8]
    x < 96.05 [set members 9]
    [set members 10]
    )
end


to set.individuals   ; [TURTLE CONTEXT]
; This block of commands assigns each individual to either a woman, a man, a child or an elderly, based on data from case studies in the same region.
; Only adults are differentiated by gender.

  repeat members [
    let x precision random-float 100 2
    (ifelse
      x < 25.66 [set females females + 1]
      x < 59.07 [set males males + 1]
      x < 98.67 [set children children + 1]
      [set elderly elderly + 1]
      )
  ]

; This block of commands avoids the case of a household having only children and/or elderly. In fact, if a household has been created with only
; children and/or elderly, the following lines of code take one of them and turning it into an adult.

  if (females = 0) and (males = 0) [
    ifelse children > 0 [set children children - 1] [set elderly elderly - 1]
    ifelse precision random-float 100 2 < 43.45 [set females females + 1] [set males males + 1]
  ]
end


to set.workforce   ; [TURTLE CONTEXT]
; Source for child-labour: United States Department of Labor - Bureau of International Labor Affairs (no date). Numbers are 2.9% and 55.6%.

  let working.children 0
  let working.elderly 0

  if children > 0 [
   repeat children [
     if precision random-float 100 2 < 1.61 [
       set working.children working.children + 1
      ]
    ]
  ]

  if elderly > 0 [
    repeat elderly [
     if precision random-float 100 1 < 2.9 [
       set working.elderly working.elderly + 1
      ]
    ]
  ]

  set tot.workforce (females + males + ((working.children + working.elderly) / 4)) * 365
end


to set.tot.kcal.required   ; [TURTLE CONTEXT]
; This approach is based on a paper estimating an adult-equivalent conversion factor to determine the consumption
; unit of a households (assigning then a requirement of 2550 kcal/day). The coefficients are derived from empirical
; research on the Brazilian population. The resulting figure represents the kilocalories requirement of a household
; per year, based on the demographics of its members.

  set tot.kcal.required round ((precision (females * 0.827 + males * 1.0704 + children * 0.750667 + elderly * 0.825) 2) * 2550 * 365)
end


to set.behaviour   ; [OBSERVER CONTEXT]
  (ifelse
    global.behaviour = "subsistence.optimised" [ask turtles with [behaviour = 0] [set behaviour "subsistence.optimised"]]
    global.behaviour = "subsistence.preference" [ask turtles with [behaviour = 0] [set behaviour "subsistence.preference"]]
    global.behaviour = "all.resources.coffee" [ask turtles with [behaviour = 0] [set behaviour "all.resources.coffee"]]
    global.behaviour = "all.resources.mixed" [ask turtles with [behaviour = 0] [set behaviour "all.resources.mixed"]]
    global.behaviour = "random.behaviour" [allocate.random.behaviour]
    )

  ask turtles with [behaviour = "subsistence.preference" and my.preference = 0] [          ; potentially this can go as a separate procedure, but maybe it is ok here.
   let x random 100
   (ifelse
      x < 33 [set my.preference 0.25]
      x < 66 [set my.preference 0.5]
      [set my.preference 0.75]
      )
  ]
end


to allocate.random.behaviour   ; [OBSERVER CONTEXT]
  ask turtles with [behaviour = 0] [
    let x random 100
    (ifelse
      x < 25 [set behaviour "subsistence.optimised"]
      x < 50 [set behaviour "subsistence.preference"]
      x < 75 [set behaviour "all.resources.coffee"]
      [set behaviour "all.resources.mixed"]
      )
  ]
end


; **************************************************** END OF HOUSEHOLDS CREATION ****************************************************
; ************************************************ BEGINNING OF EX-ANTE CALCULATIONS *************************************************


to calculate.ex-ante   ; [OBSERVER CONTEXT]

; This block of commands increases the count of the years that patches have been abandoned. If they have been abandoned for more than 5 years, the assumption is that they are
; taken as pasture land by cattle ranchers.
  ask patches with [abandoned > 0 and abandoned < 6] [
   set abandoned abandoned + 1
   if abandoned = 6 [become.pasture]
  ]

; This block of commands first decreases the fertility (which can result in patches becoming abandoned, see 'to become.abandoned') and then asks patches that are still cropped to calculate
; how many kcalories they produce and how much workforce they need. The fact that the same condition ('landcover = 4') is tested twice is not a msitake. In fact, as a result of the first command
; ('decrease.fertility'), some of the patches that initially had 'landcover = 4' might now have 'landcover = 0'. Therefore, the need for a second landcover test.
  ask patches with [landcover = 4] [
   decrease.fertility
   if landcover = 4 [calculate.output]
  ]

; Firstly ask households to compare the total calories they require against the calories that will be produced from any land they have already
; converted to the production of crop. This determines how many additional calories (if any) they need to provide through new deforestation
; and cropping. Secondly, households are also asked to determine the amount of workforce they have which is not already committed to working the land
; that has already been put to cropping. This is a measure of the resources they have to put to new land conversion and cropping.
; Technical note: sometimes the way NetLogo handles decimal places means that when it should show workforce.available = 0, it will actually
; show a very, very small negative number (e.g. -0.0000000000000001). Whenever this happens, it needs to be over-written and reset to 0.00.
  ask turtles [
    set kcal.left (tot.kcal.required - sum [kcal.yielded] of my.lot)
    set workforce.available (tot.workforce - sum [workforce.trapped] of my.lot)
    if workforce.available < 0 [set workforce.available 0.00]
  ]
end


to become.pasture   ; [PATCH CONTEXT]
  set landcover 5
  if not behavior.space.run? [set pcolor yellow]
end


to decrease.fertility   ; [PATCH CONTEXT]
; Although tropical soils can support tropical forests well, they do not support agricultural production for very long.
; In fact, soil fertility declines fairly quickly as compared to other soil types. Most plots of land are abandoned after 5 years.
; Thus, the patches in this simulation also lose fertility with time (20% per year for 5 years)

  set fertility precision (fertility - 0.2) 1
  if fertility <= 0 [become.abandoned]
end


to become.abandoned   ; [PATCH CONTEXT]
  set abandoned 1
  set landcover 0
  set which.crop 0
  set kcal.yielded 0
  set workforce.trapped 0
  set coffee.produced 0
  if not behavior.space.run? [set pcolor grey]
end


to calculate.output   ; [PATCH CONTEXT]
; As the fertility of the soil decreases, it will affect production. However, it may not affect kcalories produced
; from a patch of land in an exactly proportionate way. The code here enables these two effects to be separated.
; For beans and corn, kcalories come from eating the crops grown. For coffee, kcalories come from selling the coffee
; and being able to use the money to buy beans for consumption.

  let lost.fertility (1 - fertility)
  let scaled.fertility.impact (lost.fertility * fertility.impact)
  let reduction.multiplier (1 - scaled.fertility.impact)

  if which.crop = 1 [
    set kcal.yielded (beans.kcal.patch * reduction.multiplier)
    set workforce.trapped beans.labour.patch
  ]

  if which.crop = 2 [
    set kcal.yielded (corn.kcal.patch * reduction.multiplier)
    set workforce.trapped corn.labour.patch
  ]

; For what concerns the calculations for coffee below, note that kcalories from coffee production (and,
; specifically, the 'coffee.kcal.patch' variable) are not intended as coming from consumption, but rather
; from the purchasing power that one household obtains from producing and selling coffee. In fact, a
; conversion has been applied to go from coffee production to kcalories from consuming purchased beans.
; How the value (which is dependent on 'bean.to.coffee.kcal.conversion' in the Interface) is calculated
; can be seen in 'to set.globals'.
; Also, note that coffee is the only crop for which the quantity produced ('coffee.produced', below) is
; calculated, as this is needed to keep track of the contribution to international exports.

  if which.crop = 3 [
    set kcal.yielded (coffee.kcal.patch * reduction.multiplier)
    set workforce.trapped coffee.labour.patch
  ]
end


; **************************************************** END OF EX-ANTE CALCULATIONS ***************************************************
; **************************************************** BEGINNING OF PLANNING PHASE ***************************************************


to plan   ; [TURTLE CONTEXT]
  (ifelse
     behaviour = "subsistence.optimised" [plan.subsistence.optimised]
     behaviour = "subsistence.preference" [plan.subsistence.preference]
     behaviour = "all.resources.coffee" [plan.all.resources.coffee]
     behaviour = "all.resources.mixed" [plan.all.resources.mixed]
     )
end


to plan.subsistence.optimised   ; [TURTLE CONTEXT]

  set plant.beans 0  ; These two lines are only for reset purposes and for making sure that no unwanted values are
  set plant.corn 0   ; carried through the code from previous (simulated) years.

; This condition ('if kcal.left > 0') encloses all rest of the procedure. The logic is: the optimisation problem
; needs to be performed only by households that have a pending need for kcalories.
  if kcal.left > 0 [

    let x count my.lot.available with [landcover = 1]

    let objective (list beans.kcal.patch corn.kcal.patch)          ; Version 1
    ;let objective (list 1 1)                                       ; Version 2

    let constraint1 (list (list beans.kcal.patch corn.kcal.patch) "<=" kcal.left)   ; Version 1
    ;let constraint1 (list (list beans.kcal.patch corn.kcal.patch) ">=" kcal.left)  ; Version 2
    let constraint2 (list (list beans.labour.patch corn.labour.patch) "<=" workforce.available)
    let constraint3 (list (list 1 1) "<=" x)

    let constraints (list constraint1 constraint2 constraint3)


    let goal TRUE       ; Version 1
    ;let goal FALSE      ; Version 2

    let nonnegative TRUE

    let solution (numanal:LPsimplex objective constraints goal nonnegative)

    set plant.beans floor first first solution
    set plant.corn floor last first solution
    set my.solution ceiling last solution

; This block of code checks if the solution to the optimisation is less than the kcalories needed. If that is the case, first
; it is checked if the household already decided whether to deforest illegally or not (default value of 'illegal' is 0, so
; 'illegal' being 0 means that the household hasn't chosen yet). If they have not chosen yet (i.e. if 'illegal? = 0'), then
; the households chooses ('check.illegal'). Instead, if they have choosen already, it means that they were not able to satisfy
; their needs with their choice, and thus 'leaving?' is set to TRUE - which means that the household will leave the simulation
; at the end of the 'go'.
    if my.solution < kcal.left [
      ifelse illegal? = 0
        [ifelse imitation?
          [imitate]
          [check.illegal]]
        [set leaving? TRUE]
    ]
  ]
end


to plan.subsistence.preference   ; [TURTLE CONTEXT]   ; an idea might be that if a turtle doesn't meet kcal, can lower preference.

; Note: the structure of 'constraint4' follows from the following formulation of the constraint (example made with 'my.preference = 0.25'):
; (ha of corn) >= (0.25)(ha of corn + ha of beans)
; which can be rearranged as:
; (-0.25)(ha of beans) + (0.75)(ha of corn) >= 0
; which, in general terms, is:
; (0 - my.preference)(ha of beans) + (1 - my.preference)(ha of corn) >= 0.

  set plant.beans 0  ; These two lines are only for reset purposes and for making sure that no unwanted values are
  set plant.corn 0   ; carried through the code from previous (simulated) years.

  if kcal.left > 0 [
    let x count my.lot.available with [landcover = 1]
    let y (0 - my.preference)
    let z (1 - my.preference)

    let objective (list beans.kcal.patch corn.kcal.patch)          ; Version 1
    ;let objective (list 1 1)                                       ; Version 2

    let constraint1 (list (list beans.kcal.patch corn.kcal.patch) "<=" kcal.left); Version 1
    ;let constraint1 (list (list beans.kcal.patch corn.kcal.patch) ">=" kcal.left)  ; Version 2
    let constraint2 (list (list beans.labour.patch corn.labour.patch) "<=" workforce.available)
    let constraint3 (list (list 1 1) "<=" x)
    let constraint4 (list (list y z) ">=" 0)

    let constraints (list constraint1 constraint2 constraint3 constraint4)

    let goal TRUE       ; Version 1
    ;let goal FALSE      ; Version 2

    let nonnegative TRUE

    let solution (numanal:LPsimplex objective constraints goal nonnegative)

    set plant.beans floor first first solution
    set plant.corn floor last first solution
    set my.solution ceiling last solution

; This block of code checks if the solution to the optimisation is less than the kcalories needed. If that is the case, first
; it is checked if the household already decided whether to deforest illegally or not (default value of 'illegal' is 0, so
; 'illegal' being 0 means that the household hasn't chosen yet). If they have not chosen yet (i.e. if 'illegal? = 0'), then
; the households chooses ('check.illegal'). Instead, if they have choosen already, it means that they were not able to satisfy
; their needs with their choice, and thus 'leaving?' is set to TRUE - which means that the household will leave the simulation
; at the end of the 'go'.
    if my.solution < kcal.left [
      ifelse illegal? = 0
        [ifelse imitation?
          [imitate]
          [check.illegal]]
        [set leaving? TRUE]
    ]
  ]
end


to plan.all.resources.coffee   ; [TURTLE CONTEXT]
; Coffee is a cash crop. It is sold for money, and that money can be used to by other food in order to meet nutritional needs.
; If coffee is sold at a very high price, then 1 kg of coffee can buy many more calories than households would get from 1 kg of beans.
; However, if coffee is sold at a low price, then 1 kg of coffee might not buy as many calories as households would get from 1 kg of beans.
; This is reflected in the slider called 'coffee.to.bean.kcal.conversion'. This is the multiplier showing what percentage of calories 1 kg
; of coffee can buy relative to what a household can get from growing 1 kg of beans. When the value is set to 1, it means 1 kg of coffee
; buys exactly the same calories as a household would get from growing 1 kg of beans. If the value is set to 1.5, it means that 1 kg of
; coffee buys 50% more calories than a household would get from growing 1 kg of beans.

; The x variable calculated as below equals the number of patches that a household is able to clear for coffee based on the available
; workforce and the required labour for coffee. This can be seen by keeping track of the units of measure of the three variables
; involved in the calculation, and see how they reduce each other to just <patches>.

  set plant.coffee 0  ; This is only for reset purposes.

; The line of code below checks how many patches (x) the household would be able to plant with coffee. Under this behaviour, the goal
; of the household is to use 100% of the households'available workforce.
  let x floor (workforce.available / coffee.labour.patch)

; If the condition below is met, it means the household has enough land available to use up all of its workforce for coffee.
; If that is the case, the household checks whether the coffee produced would eventually supply enough calories.

  ifelse x <= count my.lot.available with [landcover = 1] ; If the households has enough land to use up all of its labour...
    [let tot.kcal.from.coffee (coffee.kcal.patch * x)     ; ...then it checks if that would meed nutritional requirements.
     ifelse tot.kcal.from.coffee >= kcal.left             ; If nutritional requirements are met...
       [set plant.coffee x]                               ; ...then it plants that amount of coffee ...
       [set leaving? TRUE]]                               ; ...otherwise, it leaves the simulation-
    [ifelse illegal? = 0                                  ; If nutritional requirements are not met, it checks if a decision has been taken on illegal behaviour.
      [ifelse imitation?                                  ; If a decision has not been made yet, it checks whether it should imitate other households.
        [imitate]                                         ; If that is the case, it imitates...
        [check.illegal]]                                  ; ...otherwise, it takes the decision on illegal behaviour on its own.
      [set leaving? TRUE]]                                ; If a decision has already been made on illegal behaviour, it leaves the simulation.

; NOTE
; The above code should ensure that the only households that remain in the simulation while growing only coffee are those that can:
; 1) use 100% of their available labour on production (work-a-holic agents who would not be happy to use less than 100% of their labour).
; 2) are able to meet at least 100% of the nutritional needs from the money they get from selling their coffee.
; Said another way, if they cannot meet their nutritional needs from the sale of their coffee, while usingn 100% of their labour,
; then they leave the simulation.
end


to plan.all.resources.mixed   ; [TURTLE CONTEXT]
; First of all, the normal 'to plan.subsistence.optimised' is performed. Later, the 'leaving?' condition is checked to see if the
; household has the potential to do more work. If 'leaving? = FALSE' (i.e. 'not leaving? = TRUE'), first of all 'workforce.available'
; is re-calculated. This is because normally 'workforce.available' is updated in 'to calculate.ex-ante', but this will only happen
; in the next round. This means that the share of workforce engaged with land just cleared as a result of 'plan.subsistence.optimised'
; has not yet been subtracted from 'workforce.available'. The same reasoning applies to the re-calculation of the count of 'my.lot.available'.

; STEP 1: reset crop-patch values.
  set plant.beans 0
  set plant.corn 0
  set plant.coffee 0

  if kcal.left > 0 [

; STEP 2 Determine how many patches of beans and corn to plant.
    let x count my.lot.available with [landcover = 1]

    let objective (list beans.kcal.patch corn.kcal.patch)

    let constraint1 (list (list beans.kcal.patch corn.kcal.patch) "<=" kcal.left)
    let constraint2 (list (list beans.labour.patch corn.labour.patch) "<=" workforce.available)
    let constraint3 (list (list 1 1) "<=" x)

    let constraints (list constraint1 constraint2 constraint3)

    let goal TRUE

    let nonnegative TRUE

    let solution (numanal:LPsimplex objective constraints goal nonnegative)

    set plant.beans first first solution
    set plant.corn last first solution
    set my.solution last solution

; STEP 3: Consider coffee production on top of the results for beans and corn. Agents will only seek to do this if they are UNABLE to meet
; their caloric needs from beans and corn. They are subsistence agents, and not in the business of maximising production for financial gain.
    if my.solution < kcal.left [
      let workforce.available.coffee (workforce.available - (plant.beans * beans.labour.patch) - (plant.corn * corn.labour.patch))
      if workforce.available.coffee < 0 [set workforce.available.coffee 0]

      let y ((count my.lot.available with [landcover = 1] - plant.beans - plant.corn))
      let z floor (workforce.available.coffee / coffee.labour.patch)

      ifelse z <= y
        [set plant.coffee z]
        [set plant.coffee y]

; STEP 4: Consider kcalories from coffee production.
; Coffee is a cash crop. It is sold for money, and that money can be used to by other food in order to meet nutritional needs.
; If coffee is sold at a very high price, then 1 kg of coffee can buy many more calories than households would get from 1 kg of beans.
; However, if coffee is sold at a low price, then 1 kg of coffee might not buy as many calories as households would get from 1 kg of beans.
; This is reflected in the slider called 'coffee.to.bean.kcal.conversion'. This is the multiplier showing what percentage of calories 1 kg
; of coffee can buy relative to what a household can get from growing 1 kg of beans. When the value is set to 1, it means 1 kg of coffee
; buys exactly the same calories as a household would get from growing 1 kg of beans. If the value is set to 1.5, it means that 1 kg of
; coffee buys 50% more calories than a household would get from growing 1 kg of beans.
      let tot.kcal.from.coffee (plant.coffee * coffee.kcal.patch)
      let tot.kcal.from.farming (my.solution + tot.kcal.from.coffee)

      if tot.kcal.from.farming < kcal.left [      ; In the test of this condition, it is implicit that if tot.kcal.from.farming >= kcal.left, nothing needs to change.
        ifelse illegal? = 0
          [ifelse imitation?
            [imitate]
            [check.illegal]]
          [set leaving? TRUE]
      ]
    ]
  ]
end


to imitate   ; [TURTLE CONTEXT]
; The first command in response to the first 'ifelse' is the exact copy of the second command in response to the first
; 'ifelse' in 'to check.illegal'. What those lines do is to check if a household is an illegal deforester based on the
; probability set in the Interface. The reason why that block of code is copy-pasted instead of just calling the procedure
; 'to check.illegal' is that such procedure contains a call to 'to imitate'. Therefore, if 'imitation? = TRUE' the turtle
; would go back and forth between 'to check.illegal' and 'to imitate' until the first 'ifelse' in 'to imitate' is FALSE,
; thus always obtaining 'illegal? = FALSE' in the end. To avoid this loop, only the bit of code after
; 'ifelse imitation? [imitate]' is copied here.

  ifelse random 3 < 1                                         ; This (i.e. 66% chance to imitate) is an arbitrary assumption. A different option could be to have this set in the
    [check.illegal]                                           ; interface, but the downside would be having too many parameters to mess about with.
    [ifelse any? turtles with [illegal? != 0]
      [let x turtles with [illegal? != 0]
       let y [illegal?] of min-one-of x [distance myself]
       set illegal? y]
      [check.illegal]]
end


to check.illegal   ; [TURTLE CONTEXT]
; NOTE TO THE PROGRAMMER: Anything that gets changed after '[imitate]' should be copied to the first command in response
; to the first 'ifelse' in 'to imitate'. To read the reason, check the comment to 'to imitate' below.

  ifelse random 100 < illegal.propensity
    [set illegal? TRUE
     set my.lot.available my.lot.f
     plan]
    [set illegal? FALSE
     plan]
end


; ******************************************************* END OF PLANNING PHASE ******************************************************
; ******************************************************* BEGINNING OF CROPPING ******************************************************


to crop   ; [OBSERVER CONTEXT]
  ask turtles [
    (ifelse
      direction.t = "n" [
        ask min-n-of plant.beans my.lot.available with [landcover = 1] [pycor] [
         set landcover 4
         set which.crop 1
        ]
        ask min-n-of plant.corn my.lot.available with [landcover = 1] [pycor] [
         set landcover 4
         set which.crop 2
        ]
        ask min-n-of plant.coffee my.lot.available with [landcover = 1] [pycor] [
         set landcover 4
         set which.crop 3
        ]
      ]
      direction.t = "s" [
        ask max-n-of plant.beans my.lot.available with [landcover = 1] [pycor] [
         set landcover 4
         set which.crop 1
        ]
        ask max-n-of plant.corn my.lot.available with [landcover = 1] [pycor] [
         set landcover 4
         set which.crop 2
        ]
        ask max-n-of plant.coffee my.lot.available with [landcover = 1] [pycor] [
         set landcover 4
         set which.crop 3
        ]
      ]
      )
  ]

  if not behavior.space.run? [update.colours]
end


; ********************************************************** END OF CROPPING *********************************************************
; *************************************************** BEGINNING EX-POST CALCULATIONS *************************************************


to calculate.ex-post   ; [OBSERVER CONTEXT]
  ask patches with [which.crop = 3] [

    let lost.fertility (1 - fertility)
    let scaled.fertility.impact (lost.fertility * fertility.impact)
    let reduction.multiplier (1 - scaled.fertility.impact)

    ; The following line calculates coffee currently produced on each patch.
    set coffee.produced (coffee.yield.patch * reduction.multiplier)
  ]

  ; The following line calculates the coffee produced over the whole simulation (by adding all the coffee grown in this tick to
  ; all the coffee grown in previous ticks).

  if any? patches with [coffee.produced > 0] [
    set coffee.produced.overall (coffee.produced.overall + sum [coffee.produced] of patches with [which.crop = 3])

    let foreign.currency.from.coffee.export.now (sum [coffee.produced] of patches with [which.crop = 3] * first coffee.exchange.price * first price.adjustment)
    set foreign.currency.from.coffee.export.tot (foreign.currency.from.coffee.export.tot + foreign.currency.from.coffee.export.now)
  ]

  set coffee.exchange.price but-first coffee.exchange.price
  set price.adjustment but-first price.adjustment
end


; **************************************************** END OF EX-POST CALCULATIONS ***************************************************
; **************************************************** BEGINNING OF EXIT PROCEDURES **************************************************


to escape   ; [OBSERVER CONTEXT]
  ask turtles with [leaving? = TRUE] [
    clear.lot
    set households.escaped households.escaped + 1
    die
  ]
end


to clear.lot   ; [TURTLE CONTEXT]

  if my.lot.available != 0 [
    if any? my.lot.available with [landcover = 4] [
      ask my.lot.available with [landcover = 4] [
        become.abandoned
      ]
    ]
  ]

  ask my.lot [set owner 0]
  set my.lot 0
end


; *******************************************************************************************************************************************
; **************************************************************** UTILITIES ****************************************************************
; *******************************************************************************************************************************************


to go5   ; [OBSERVER CONTEXT]
  let rounds.left (simulation.end - 1975 - ticks)
  ifelse rounds.left > 5
    [repeat 5 [go] stop]
    [repeat rounds.left [go] stop]
end


to go10   ; [OBSERVER CONTEXT]
  let rounds.left (simulation.end - 1975 - ticks)
  ifelse rounds.left > 10
    [repeat 10 [go] stop]
    [repeat rounds.left [go] stop]
end


to set.initial.colours ;   [OBSERVER CONTEXT]
; In order to restore the initial colours, this procedure does not need to ask to change landcovers because that has already been done
; by 'to set.initial.map'. In fact, when this procedure kicks in, patches that originally had forest have already returned to have
; 'landcover = 1'. Thus, this procedure only takes care of the colours part.

  ask patches with [landcover = 1] [set pcolor 53]
end


to update.colours ;   [OBSERVER CONTEXT]
  ask patches [
   (ifelse
     landcover = 4 [set pcolor orange] ; Crops (any)
     landcover = 5 [set pcolor yellow] ; Pasture
     landcover = 0 [set pcolor grey]   ; Abandoned land
     )
  ]
end
@#$#@#$#@
GRAPHICS-WINDOW
245
10
943
204
-1
-1
1.05
1
10
1
1
1
0
0
0
1
0
657
0
176
0
0
1
ticks
30.0

MONITOR
971
71
1140
116
Households
count turtles
0
1
11

MONITOR
968
10
1053
55
Current year
ticks + 1975
0
1
11

MONITOR
1222
71
1293
116
Empty lots
count patches with [lot != 0 and owner = 0] / 1072
0
1
11

BUTTON
10
16
73
49
NIL
setup
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

INPUTBOX
10
216
150
276
simulation.end
2020.0
1
0
Number

BUTTON
13
98
86
131
1 year
go
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

BUTTON
13
136
86
169
5 years
go5
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

BUTTON
98
98
178
131
10 years
go10
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

BUTTON
98
136
178
169
Until end
go
T
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

TEXTBOX
11
64
161
89
Advance for:
20
63.0
0

TEXTBOX
12
184
162
209
Inputs by user:
20
63.0
0

PLOT
243
215
556
458
Crop Cover
Time
Percentage of Land
0.0
45.0
0.0
15.0
true
true
"plot-pen-down" ""
PENS
"Beans" 1.0 0 -955883 true "" "plot (count patches with [which.crop = 1] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100"
"Corn" 1.0 0 -14439633 true "" "plot (count patches with [which.crop = 2] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100"
"Coffee" 1.0 0 -8431303 true "" "plot (count patches with [which.crop = 3] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100"
"Abandoned" 1.0 0 -2064490 true "" "plot (count patches with [landcover = 0] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100"

CHOOSER
10
351
151
396
global.behaviour
global.behaviour
"subsistence.optimised" "subsistence.preference" "all.resources.coffee" "all.resources.mixed" "random.behaviour"
0

SLIDER
10
454
207
487
illegal.propensity
illegal.propensity
0
100
75.0
1
1
NIL
HORIZONTAL

SLIDER
10
407
206
440
legal.farming
legal.farming
0
100
20.0
1
1
NIL
HORIZONTAL

CHOOSER
10
290
150
335
which.map
which.map
"baseline" "wetlands"
1

MONITOR
1149
71
1208
116
Escaped
households.escaped
0
1
11

SWITCH
10
504
113
537
imitation?
imitation?
1
1
-1000

MONITOR
1088
135
1177
180
Insuccess (%)
(households.escaped / households.entered) * 100
2
1
11

BUTTON
89
16
170
49
NIL
setup.BS
NIL
1
T
OBSERVER
NIL
NIL
NIL
NIL
1

MONITOR
971
135
1073
180
Forest cover (%)
(count patches with [landcover = 1] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100
2
1
11

SLIDER
8
552
205
585
bean.to.coffee.kcal.conversion
bean.to.coffee.kcal.conversion
0.1
10
1.2
0.01
1
NIL
HORIZONTAL

PLOT
563
215
877
456
Pasture
Time
Percentage of Land
0.0
45.0
0.0
50.0
true
false
"" ""
PENS
"default" 1.0 0 -7500403 true "" "plot (count patches with [landcover = 5] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100"

PLOT
882
215
1196
456
Forest Cover
Time
Percentage of Land
0.0
45.0
0.0
100.0
true
false
"" ""
PENS
"default" 1.0 0 -14439633 true "" "plot (count patches with [landcover = 1] / count patches with [landcover = 1 or landcover = 4 or landcover = 5 or landcover = 0]) * 100"

MONITOR
1193
134
1320
179
Wetland disturbance
count patches with [(landcover = 4 or landcover = 5 or landcover = 0) and any? neighbors with [landcover = 3]]
0
1
11

PLOT
1203
215
1467
454
USD from coffee export
Time
USD
0.0
45.0
0.0
10.0
true
false
"" ""
PENS
"default" 1.0 0 -13791810 true "" "plot (foreign.currency.from.coffee.export.tot) / 1000000"

@#$#@#$#@
## WHAT IS IT?

This model simulates the occurrence of deforestation based on hypothetic agricultural behaviours of households in the Brazilian Amazon.
The map comes from real GIS data, imported from an external file which is the result of previous work.

## HOW IT WORKS

(what rules the agents use to create the overall behavior of the model)

## HOW TO USE IT

(how to use the model, including a description of each of the items in the Interface tab)

## THINGS TO NOTICE

(suggested things for the user to notice while running the model)

## THINGS TO TRY

(suggested things for the user to try to do (move sliders, switches, etc.) with the model)

## EXTENDING THE MODEL

(suggested things to add or change in the Code tab to make the model more complicated, detailed, accurate, etc.)

## NETLOGO FEATURES

(interesting or unusual features of NetLogo that the model uses, particularly in the Code tab; or where workarounds were needed for missing features)

## RELATED MODELS

(models in the NetLogo Models Library and elsewhere which are of related interest)

## CREDITS AND REFERENCES

(a reference to the model's URL on the web if it has one, as well as any other necessary credits, citations, and links)
@#$#@#$#@
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.2.0
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
<experiments>
  <experiment name="experiment" repetitions="20" runMetricsEveryStep="true">
    <setup>setup.BS</setup>
    <go>go</go>
    <metric>count patches with [landcover = 1 and lot != 0] / count patches with [lot != 0]</metric>
    <metric>count patches with [(landcover = 4 or landcover = 5 or landcover = 0) and any? neighbors with [landcover = 3]]</metric>
    <enumeratedValueSet variable="global.behaviour">
      <value value="&quot;random.behaviour&quot;"/>
      <value value="&quot;all.resources.mixed&quot;"/>
    </enumeratedValueSet>
    <enumeratedValueSet variable="simulation.end">
      <value value="2020"/>
    </enumeratedValueSet>
    <enumeratedValueSet variable="illegal.propensity">
      <value value="20"/>
      <value value="50"/>
      <value value="80"/>
      <value value="100"/>
    </enumeratedValueSet>
    <enumeratedValueSet variable="which.map">
      <value value="&quot;baseline&quot;"/>
      <value value="&quot;wetlands&quot;"/>
    </enumeratedValueSet>
    <enumeratedValueSet variable="legal.farming">
      <value value="30"/>
      <value value="70"/>
    </enumeratedValueSet>
    <enumeratedValueSet variable="bean.to.coffee.kcal.conversion">
      <value value="1.2"/>
    </enumeratedValueSet>
    <enumeratedValueSet variable="imitation?">
      <value value="true"/>
    </enumeratedValueSet>
  </experiment>
</experiments>
@#$#@#$#@
@#$#@#$#@
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
@#$#@#$#@
0
@#$#@#$#@
