Charcoal

Charcoal preview image

3 collaborators

Default-person Richard Taylor (Author)
Default-person Hannah Wanjiru (Author)
Hannah Wanjiru (Advisor)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by the author
Model was written in NetLogo 5.2.0 • Viewed 384 times • Downloaded 22 times • Run 0 times
Download the 'Charcoal' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;; 22 Feb 2017
;; charcoal model for Kenya CS
;; supply side


extensions [gis profiler bitmap table]

breed [producers producer]
breed [transporters transporter]
breed [buyers buyer]
breed [markets market]
breed [levys levy]   ;; one levy agent may be sufficient

breed [landparcels landparcel] ;; contains a set of patches and some rules, possibly including CPG info
;; ranches ?

breed [lp-labels lp-label]

undirected-link-breed [trades trade]
undirected-link-breed [collections collection]

levys-own [
  taxed            ;; list of transporters taxed this trading cycle
  revenue          ;; amount taken this trading cycle
  levytype         ;; "greedy" or "normal"
  annual-profit
]

patches-own [
  partof           ;; part of landparcel - macro area
  cover
  species          ;; type of tree (int)
  quantity         ;; quantity of resource here - can only have one type
  maxQ             ;; maximum quantity 
  patch-biomass    ;; to be initialised from GIS or raster data ?
  
  quality          ;; depends on type of tree
  ;when-quantity-updated
  ;when-quality-updated 
  ;; Means are defined in terms of kilos per pixel for stock and kilos per pixel per year for growth (pixels are 1 ha). for 1km this needs to be x100
  ;; So the numbers indicate the average density of woody biomass stock and growth within each admin unit. 
  stk              ;; standing stock in kg
  mai              ;; mean annual increment - using GIS data  (growth is a function of standing stock) or a.a.c (growth is a linear function of ss) 
  take             ;; wood extracted this year. a suggested maximum take is given by the take-constraint global (mai or fixed %)
  deficit  
  subloc
]

landparcels-own [
  lpquality
  size-xy                               
  area             ;; number of patches
  lpatches         ;; patchset         
  tenancy          ;; ownership is either private (eg. land owned by CPG members) or trust land (eg. rangeland or ranches)
  practice         ;; descriptive string. CPG (management entity) or private owners (can be either producers own land or other private owner)
  permit           ;; t/f
  permit-type      ;; regulated or sustainable           
  members          ;; agentset of producers if a CPG
  near-producers   ;; all producers nearby - measure for new woodlots applications
  num-near-producers
  
  stock            ;; unsold charcoal stock, measured in bags, but can be in-part bags
  collected        ;; in kg, wood collected in the current period (ie.month)-  a list with one entry for each tree type
  annual-collected ;; collected each period (list - combine tree types in one figure)
  production       ;; charcoal produced in the current period (ie.month) can be in-part bags
  annual-production;; production each period (list)
  sales            ;; in bags, sales for the current period  
  returns-income
  tcosts           ;; trade costs (paid for wood)
  accepted-price   ;; data for current period
  
  annual-profit    ;; *share* of profit each period (list)
  quota            ;; is there a quota on the total wood that producers/CPG is allowed to collect
  date             ;; year in which the practice was initialised or last renewed - important for transitions
  kiln-efficiency  ;; a number representing efficiency - either standard 0.1 or improved 0.3
  loanK            ;; loan for kiln (year issued)
  loanW            ;; loan for woodlot (year issued) - ie. new woodlot
  ;; normative requirements - monitoring
  efficacy         ;; proportion of members active in current tc
  reputation       ;; always conform or always violate
  sanction         ;; sanction strategy - fine or ban period - number of trading periods to fine and ban
]   

producers-own [
  parcels               ;; parcels accessible based on agent location - does not include CPG
  collected             ;; in kg, wood collected in the current period (ie.month)-  a list with one entry for each tree type
  annual-collected      ;; collected each period (list)
  production            ;; charcoal produced in the current period (ie.month) can be in-part bags
                        ;; -note - if producers are in a CPG they don't do individual production - the production variable is only set in the landparcel agent
  annual-production     ;; production each period (list)
  stock                 ;; unsold charcoal stock, measured in bags, but can be in-part bags
  sales                 ;; in bags, sales for the current period         
  permit                ;; true or false
  permit-type
  CPG                   ;; name of one  landparcel associated with 
  intensification       ;; level of intensification, start at 100
 
  approval              ;; social approval for the producer, used in normative scenario only    
  reputation            ;; normative reputation - do agents in my CPG follow collectivity norm
          
  strategy              ;; marketing strategy 
  target-price
  accepted-price        ;; data for current period
  returns-income        ;; gross monthly income 
  tcosts                ;; trades costs - assume obtaining wood for free
  ;costs                ;; TODO period costs/expenses (ie of living)
  annual-profit         ;; surplus each period (list)
  collecting-strategy
  loanW                 ;; loan for woodlot (year issued)
  loanK                 ;; loan for kiln (year issued)
  kiln-efficiency       ;; a number representing efficiency - either standard 10 or improved eg 30 %
  ;speciesprefs          ;; list of species that producer will target (will avoid those not listed) updated in set-collecting-strategy
  
  trade-price-strengths-reject     ;; both producers and transporters have CS values stored for each of trade-price-points
  trade-price-strengths-accept
  rejected               ;; have to store any rejected prices this month for later feedback
  lastpayoff             ;; set these back to 0 at end of month 
] 

transporters-own [
  visit-range           ;; distance from home site considered visitable -  could depend on type of transport available
  tick-range            ;; distance I can travel per tick
  nearest-producers     ;; visitable
  ;visited               ;; visited this month
  unvisited
  
  bought
  stock                 ;; purchased this month  ;; unsold stock ?
  sales                 ;; sold this month
  capacity              ;; max number of bags that this transporter can bring to market
  homepatch             ;; home location (a patch) to which the transporter returns
  status                ;; visiting or leaving market, or visiting CPG
  association           ;; whether organised in a collective
  permit                ;; transportation permit - true/false 
  permit-type           ;; "RC" affiliated to CTA and regulated ; "SC" sustainable charcoal with proposed new NAMA regulation (obtained from compliant CPG)
  bulk-supplier         ;; name of landparcel this is associated with, or similarly, name of producer
  trade?                ;; true if trade within Kitui; false if exporting
  
  ; betteroff?          ;; true and false - better off and poor producer
  labour-int            ;; labour is an integer                  
  strategy              ;; marketing strategy 
  returns-income        ;; includes costs
  tcosts                ;; period trade costs (costs of purchasing charcoal from producers)
  annual-profit         ;; surplus each period (list)
  
  ;; variables for CS with producers
  trade-price-strengths
  price-point-index     ;; index from the list of price points
    
  ;; variables for reinforcement learning
  propensities   ;; propensity value of each strategy
  mchoice        ;; market agent
  exportchoice   ;; patch
  aspiration     ;; the threshold for whether a choice is considered successful or not (compare with outcome)
  satisfaction   ;; from comparison of payoff(s) with aspiration(s) T or F
  history
  satisfaction-history
  payoff stimulus;; raw payoff value and the stimulus (reward or punishment value)
  
  levycosts      ;; amount paid in levys this trading period
  cesscosts      ;; amount paid in cess to county goverance
]

buyers-own [
  nearest-market                    ;; can obtain charcoal through nearby market
  demand
  bought
  location              
  strategy                  ;; marketing strategy 
  buyingprefs
]

to *TOP 
end 

globals
[
  ;; the following are fixed, user-defined global variables chosen or input by the user
  ;; overall number of market chain actors, needs to be set before they are created
  numberProducers  numberTransporters numberBuyers 
  number-markets 
  marketnames                  ;; list of strings
  market-locations          ;; list of x,y locations of centroids
  treetype0 treetype1 treetype2          ;;  integers   Acacia spp.(hardwood), Commiphora spp.(softwood) 
  farmland trustland ranchland ;; tenancy types
  ;min-parcels max-parcels   ;; how many parcels does each producer have access to
 
  max-number-landparcels    ;; max number of land parcels in the model
  min-demand max-demand     ;; buyers monthly demand parameters
  max-collected             ;; maximum wood extracted per month eg. 0.01 ;; 0.1
  lorry-capacity            ;; 170
  bulk-stock-amount         ;; bulk stock triggering a) transporter call out, b) transporter takes stock to distant rather than local market
  order-mag                 ;; parameter for multiplication factor for order of magnitude used in transporters trade/export decision rule
  overUtil                  ;; annual overutilisation - number of patches
  meanUtil                  ;; average utilisation - float
  annual-collected-all      ;; used in reporter
  annual-marketsizes        ;; used in reporter - number of bags accounted for in each market channel (formal, informal, RC, SC)
  ;; policy related globals
  numCPGS                   ;; not set directly. CPGscenario is the corresponding variable set either from r or from the interface
  transporter-list          ;; licenced transporter-list
  loanWlength loanKlength   ;; 5
  strictloans               ;; true or false - true assumes they come with conditions

 
  
  fiscal                    ;; not set direcly, amount calculated as gov. revenue annually
  list-price                ;; SC price - NAMA
  cess                      ;; licence charcoal transportation price
  reg-price                 ;; price the transporter is obliged to pay the CPG - 500 according to fieldwork (also 100 cess , 20 conservation fee)
  trade-price-points        ;; possible values in negotiation - informal sector
  
  
  transporters-learning-rate
  transporters-memorysize
  p-cutoff                  ;; lowest propensity allowed
  max-rval                  ;; max-reinforcement value is equal to lorry capacity
  imitation                 ;; copy other transporters if aspirations are not met 
  
  lr-producers
  CS-intial-values reject-value
  producers-trade-price-profits
  transporters-trade-price-profits   ;; for accounting
  producer-costs            ;; 100
  transporter-costs         ;; 400
  
  retail-price              ;; does not fluctuate much - but interesting to look at effect of prices
                            ;; target-price 0.3 * retail-price 
  export-price              ;; ie. Nairobi (literature KES 700-750 with permit and KES 400-450 without permit)
  export-price-permit       ;; higher export price with a permit of "SC" type only
 
  export-sales              ;; sales in the curent month (all stock is bought) 
  annualExport              ;; overall figures for export sales and sales in 4 towns
  annualSales
  numberUnhappy             ;; list with one entry per trading period
  annual-profit-share       ;; the percentage on average, that each actor type receives in profits per bag :  divide the aggregated profit for each agent type by the total number of bags circulating annually 
  annual-movement-permits   ;; number of RC and SC permits issued when CPGs telephone to arrange bulk trade with transporters
  
  aspiredProducerProfit     ;; lower thereshold - below which intensify
  exceededProducerProfit    ;; upper threshold - above which deintensify
  intensificationStep       
  
  trade-tax
  retail-tax                ;; income could be used to support sustainable forest management, producer support or enforcement of regs
 
  aac                       ;; annual allowable cut - percentage CPGs are permitted to sustainably extract eg. 2% of biomass if growback rate is 2%
  kiln-eff-standard         ;; 0.1
  ;kiln-eff-improved         ;; 0.3 CPGs have improved efficiency
  bag-weight                ;; bag weight in kg (if a patch has mai of 2000 kg this can only provide about 17 bags p.a. with improved kilns)
  
  tries-paddys              ;; a maximum number. number-paddys is also constrained by min-distance
  cf-size
  landparcel-size           ;; distance in km          farmsize-min farmsize-max ;; minimum and maximum (acres)
  forestsize-min forestsize-max
  min-distance-farm         ;; min distance between any two agents              
  
  max-distance-collection     ;; distance a producer can travel - defining which landparcels accessible
  min-distance-market         ;; distance of buyer away from market
  max-transporter-visit-range ;; max distance transporter considers for visiting producer
  max-transporter-tick-range  ;; max distance transporter can travel per time step, in km
  
  min-distance-landparcels  ;; min distance land parcels
  min-distance-gardens
  ticks-per-month           ;; allow for time-level below the month
  months-per-year           ;; months now correspond to trading periods of transporters - 100 months means 1200 ticks per year
 
  ;; non-fixed variables
  number-landparcels        ;; count of number
  year-id                   ;; integer initial value of init-year
  init-year                 ;; number eg. 1980
  ;warmup-years              ;; before policy implementation
  the-month                 ;; string variable in french
  month-id                  ;; integer from 0 to months-per-year (eg 11) incl.
  task-id                   ;; time level above tick and below month - to allow multiple tasks to be carried out - e.g. 0 or 1 
  the-period                ;; integer. lowest time level equivalent to tic
  
  treetypes   ;; list of ints
  treequalities  ;; list of numbers between 0 and 1

  croptypes                 ;; list of cashcrop types: cacao/ coffee
  crops                     ;; monthly calendar for each croptype
  gardentypes
  gardening-calendar
  ;;headset                 ;; turtleset of all household heads, set in set-livelihoods
  ;farmers gardeners         ;; turtlesets of all male and all female (in simple hh case)
  workforce                 ;; all individuals not allocated to jobs yet
  all-locations             ;; farms, mangrove, village
  livelihoods               ;; occupations that are done over the course of one or more months
  max-initial-labour        ;; initial labour is integer value random-uniform distributed between 0 and some number
  chance-labour             ;; at start of year, there is a chance any hh accumulates additional labour (eg . 5% random)
  farmingtasks              ;; a list of SHBWC farming tasks not including Co, F, H (activities) etc
  farming-calendar-cacao expansion-calendar-cacao  ;; two alternative calendars
  
  ;; display
  ntfp-size 
  person-size 
  
  ;; GIS globals
  ;villages-dataset roads-dataset cf-dataset abm-dataset hz-dataset commu-dataset
  mwingi-boundary
  kitui-boundary
  county-patches  ;; patches within the boundaries of union of mwingi and kitui
  outside         ;; other patches
  hotspot-patches ;; charcoal hotspot features (29)
  urban-patches
  
  ;; towns
  matuu-patches
  kitui-patches
  km-patches
  mwingi-patches
  tulia-patches
  marimanti-patches
  
  ;;GIS
  kitui-features mwingi-features matuu-features tulia-features 
  
  ;"Urban centres are KITUI, MWINGI, MATUU TOWNSHIP, and TULIA"
  kitui-loc mwingi-loc matuu-loc tulia-loc
  ;; population data
  matuu-population kitui-population mwingi-population tulia-population
  
  ;; village law
  buffer-distance           ;; buffer zone around village where shrimp ponds are not allowed to be established
  seed
  
  boundaries-dataset  ;; ie sublocs
  urban-dataset
  roads-dataset
  
  roads-patches        ;; patches that roads lie on
  roadsxhotspots       ;; patches that roads lie on, in production hotspot areas
  roadsxhotspotsxurban ;; patches that roads lie on, in production hotspot areas OR in urban areas
  
  export-locations
  
  ;stock-dataset       ;; biomass stock (tif)
  ;growth-dataset      ;; biomass growth(tif)
  
  
  
  table-pg 
]        

;; need an expert to write/check these

to write-climate-scenarios
  ;; open a connection to a further file
end 

to test-accounting [who-num]
  ask turtle who-num 
  [
    if [breed] of self = producers 
    [
    print (word "Producer-" who-num " produced " production " bags and sold " sales " bags.")
    print (word "Surplus is " first annual-profit " .. and stock remaining is " stock " bags.")
    ]
    if [breed] of self = transporters
    [ 
      ifelse bulk-supplier != nobody 
      [
        ifelse [breed] of bulk-supplier = landparcels  ;; ifelse  permit != false 
        [
          print (word "Transporter-" who-num " collected " bought " bags from CPG" bulk-supplier " and sold " sales " bags.")
          if  permit != false [print (word "Transporter-" who-num " has a permit")]
        ]
        [
          print (word "Transporter-" who-num " collected " bought " bags from producer " bulk-supplier " and sold " sales " bags.")
        ]
      ]
      [
         print (word "Transporter-" who-num " collected " bought " bags from producers and sold " sales " bags.")
      ]
      print (word "Surplus is " first annual-profit " .. and stock remaining is " stock " bags.")
    ]
    
    if [breed] of self = landparcels
    [
      print (word "CPG at Landparcel-" who-num " produced " production " bags and sold " sales " bags.")
      print (word "Surplus is " first annual-profit " .. and stock remaining is " stock " bags.")
    ]
  ]
end 
  
  

;; setup command which is run before setting desired parameters in R
;; make sure there is nothing in setup which depends on parameters set from R

;; now using county-patches in the call to initialise-markets  and initialise-landparcels for Kitui

to setup [myseed]
  ;; resets all global variables to zero, and calls reset-ticks, clear-turtles, clear-patches, clear-drawing, clear-all-plots, and clear-output.
  ;; also sets seed to 0
  clear-all               ;; set seed new-seed
  if myseed = 0 [set myseed new-seed]
  set seed myseed         ;;-377305244
  random-seed seed
  
  ;setup-gis
  setup-gis-kitui
  
  ;set warmup-years 3
  set init-year 2014  ;; start a year before NAMA period 2017-2030 7 + 7
  set annual-profit-share n-values 4 [0]
  set annual-movement-permits list 0 0      ;; RC SC
  set year-id init-year
  set month-id 0
  set the-month "January"
  set ticks-per-month 12
  set months-per-year 100
  set annual-collected-all 0
  
  ;; parameters needed before agent creation - EXCEPT world-width and world-height set in view
  ;;set max-distance 10
  set tries-paddys 40
  ;; min-distance parameters are min allowable distance from chosen spot (patch) to any other turtle.
 
  set min-distance-landparcels 5  ;; distance between land parcels 
  set min-distance-market 10
  
  ;; these parameters would be set depending on the location and calendar - could be put in setup munshiganj method
  ;set farmsize-min 3
  ;set farmsize-max 3
  set landparcel-size 3
  set min-distance-farm 5         ;; distances between two farms - normally same as farmsize
  set forestsize-min 20
  set forestsize-max 30
  
  ;set numberProducers number-of-producers  ;;20
  ;set numberTransporters number-of-transporters ;;10
  ;set numberBuyers number-of-buyers ;40
  ;; initialise using values specific to kitui rather than interface buttons or from r
  set numberProducers 400
  set numberTransporters 50
  set numberBuyers  50 

  ;; headcount of population for 4 selected markets
  set matuu-population [3838 3965 6486 3975 3732]  ;KANYONYONI""MUSINGINI" "KALULUINI", "KATULANI" ,"KYASIONI"
  set tulia-population [8125 5066]
  set kitui-population [4584 5719 6899 6778 13265 4180 3987 10335]
  set mwingi-population [12640 4348 7676]
 
  set number-markets length marketnames
 
  ;; Overall charcoal production cost amount to an average of KES 100/bag. With the sales price of KES 250-350,

  let trade-price 400                  ;; negotiated price between producer and transporter
  ;; prices that the transporter can offfer in CS rules
  set trade-price-points  [300 380 460];; [300 380 460]   ;; mean is 380
  set lr-producers 0.5                 ;; producers learning rate
  set producer-costs 100               ;; estimate cost of labour/materials 100 per bag
  set CS-intial-values  3 * (trade-price - producer-costs)            ;; an estimate based on hypothetical sale of 3 bags, 900 which is rather low
  set reject-value 0
  set transporter-costs 400            ;; estimate: depends on many factors such as where the market is (petrol), labour
  set cess 100                         ;; paid by a transporter (with a permit) to county authorities
  ;The overall costs average KES 229, 267, 295 per bag for Nakuru, Naivasha and Nairobi markets respectively p49
  
  set reg-price 500                                  ;; a fixed price when a permit is obtained - 500 according to fieldwork (also 100 cess , 20 conservation fee)
  set retail-price 1600                              ;; choose-retail-price ;100
  set export-price retail-price                      ;; assuming retail price is same in local and export markets, and does not depend on whether a permit is owned
  ;; in r-dependencies
  ; set the list price based on the POLICYcertification policy or in case of no certification policy
  ; set the export-price-permit based on the POLICYcertification policy or in case of no certification policy   
 
  set numberUnhappy []                               ;; reported at end of year 
  
  set loanWlength 5
  set loanKlength 5
  set strictloans true
  
  set producers-trade-price-profits map [? - producer-costs] trade-price-points     ;; assuming homog costs - speed up computation
  set transporters-trade-price-profits map [retail-price - ?] trade-price-points    ;;  estimated profit assuming sold to normal retailer
 
  ;; collection and production related
  set max-number-landparcels 50        ; 100 ;50
  set max-collected 1440               ;; kg per month per producer - 1000kg wood can make 2.5 bags (standard) or 7.5 (improved)  . assuming 3.6 bags this is 1440 kg
  set max-distance-collection 10       ;; 10 or 15 source: Hannah
  set kiln-eff-standard 10             ;; NEW percentage
  set kiln-eff-improved 30
  set intensificationStep 50           ;; ie additional 50 percent is added to producer intensification
  ;set ScenarioBAmount 100              ;; step amount to increase the list-price by
  
  set aspiredProducerProfit 70000     ;; annual profit aspired to eg. 100000
  set exceededProducerProfit aspiredProducerProfit * (1 + intensificationStep / 100 )
  
  ;; transportation related
  set lorry-capacity 170 ;; source Hannah
  set bulk-stock-amount 100           ;; call out threshold/ export threshold
  set order-mag  5                   ;; parameter for multiplication factor for order of magnitude
  set max-rval lorry-capacity
  set max-transporter-visit-range 40 ;; distance considered visitable from home location
  set max-transporter-tick-range 40  ;; distance travellable in 1 tick (km)
  ;set condition-export 0.75
  set imitation true
  set transporters-memorysize 10   ;; after 10 months, base market decision on RL 
  set transporters-learning-rate  0.5
  
  ;; buyer related
  set min-demand 4
  set max-demand min-demand                 ; 4     Retailers’ average monthly 30 bags per month - 360 per year or 3.6 per cycle
  
  set bag-weight 40

  ;; use ints to represent species
  set treetype0 0  ;; TODO change the names to actual types
  set treetype1 1
  set treetypes (list treetype0 treetype1)
  set treequalities (list 0.5 1)  ;; how good is the corresponding wood for making charcoal
  
  set farmland 0 
  set trustland 1
  set ranchland 2 ;; tenancy types
  
  if show-pcolor = "county"
  [
    ask county-patches [
      set pcolor grey
      set partof 0
    ]
  ]
  ;TODO other options if show-patch = "stock"
  
  
;  let outside patch-set filter [not member? ? county-patches] sort patches 
;  
;  ask outside
;  [
;    set pcolor white
;  ]
  ;ask patches [
  ;  set pcolor grey
  ;  set partof 0
  ;]
  
  ;; import GIS information - suitable size of grid - to get the landscape features as polygons (rivers, roads, villages, CF)
  ;; set coordinate system (projection) and then load any datasets (shp)
  ;;setup-gis-4 
  
  ;; import from earth engine forest cover data
  ;; set cover for all patches including jachere. Fertility is set with initial-land-fertility through interface button. 
  import-map
  table-patch-growth ;;  make table
  
  ;; create landscape entities
  initialise-markets  
  initialise-landparcels max-number-landparcels ;50 ;
  
  ;; initialising CPGs and actors is done in set-rdependencies
 
 
  ;; print out the model settings
  ;print-initial-settings
  
  ;; distribution of patches into forest
  ;; let sforests reverse sort-on [count patches with [partof = myself]] (turtle-set secondarys primarys)
  ;; foreach sforests [show count patches with [partof = ?]]

  ;; create-spinner
  ;; set display properties
  setup-display-properties
  
  reset-ticks
end 



;; setup the model elements which may be dependent on the  desired parameters set from R

to set-rdependencies
  
   
  initialise-producers
  initialise-transporters
  initialise-buyers
 
  initialise-CPGs   ;; CPGscenario can be set in R or can be read from the interface
  
  initialise-levys  ;; create and locate the levy agents at checkpoints
  
  setup-display-properties

  update-accessible-parcels
  
  initialise-transporter-list
  
  print-initial-settings

;  ;; ask agents to set variables

;  ;; update/reset methods moved due to dependencies
end 

to setup-display-properties
  set-default-shape producers "house"
  ask producers [set size 1.5]
  ask producers [set color brown]
  
  set-default-shape transporters "truck"
  ask transporters [set size 2]
  
  set-default-shape buyers "face happy"
  ask buyers [set size 1]
  ask buyers [set color red]
  
  set-default-shape markets "flag"
  ask markets [set size 2]
  ask markets [set color red]
  ;ask markets [show label]
  
  set-default-shape levys "triangle 2"
  ask levys [set size 2]
  ask levys [set color red]
  
  ;; other setup

  ;; set forestset after all forests have been created (each patch can only be in one set)
  ;; paint-forests
end 

to update-display-properties
  ask buyers [set shape ifelse-value (bought = 0) ["face sad"] ["face happy"] ]
  ask buyers [set color ifelse-value (bought = 0) [yellow] [red] ]
  
  ask transporters with [permit = false] [set color 1 ] ; [set color lime ] ;; dark grey
  ask transporters with [permit != false] [set color 9 ] ;; light grey
end 

to paint-landparcels
  
    ifelse (practice = "CPG")
    
    [ask lpatches [set pcolor 62]] ;; greenish
    [ask lpatches [set pcolor 2]]  ;; grey
    
    ;; ask patches on edges of forest area to recolour
    ;; ask forestset [if count neighbors with [partof = thisforest] < 8 [set pcolor 36] ]   
end 

to import-tif
  ; Reads an image file, scales it to the same dimensions as the patch grid while maintaining the original aspect ratio
  ; and transfers the resulting pixel colors to the patches. 
  import-pcolors "data/kitui-biomass-map-crop.png" 
  ;; set blended colors to a pure NetLogo color 
  ASK PATCHES [ SET PCOLOR ( 5 + PRECISION PCOLOR -1 ) ] 
 ;; export the view so you don't have to process it again. 
EXPORT-VIEW "data/kitui-biomass-map-crop-post.png" 
  
  let allcolors remove-duplicates [pcolor] of patches
  show length allcolors
  
  foreach allcolors [
    show count patches with [pcolor = ?]
    ;ask patches with [pxcor < -2] [set pcolor ?]
    ;wait 0.2
    ]   
end 

;; import data from Rob

to setup-gis-kitui
  
  let wordy false
  ;  first define a transformation between GIS data space and NetLogo space
  ;; mask project file for kitui
  gis:load-coordinate-system "kitui_data/Kitui_mask.prj"    
  ;; shapefile to set boundaries
  set boundaries-dataset gis:load-dataset "kitui_data/Kitui_sublocs_WGS84.shp"
  
  ;; Also load urban areas, roads
  set urban-dataset gis:load-dataset "kitui_data/Kitui_urban.shp" ;; this has the label Core Urban or Peri urban
  set roads-dataset gis:load-dataset "kitui_data/Kitui_Roads.shp" ;; data is used for levy locations and journey end points
  
  ;; set vegetation-dataset gis:load-dataset "data/Kitui_forest.shp"
  
  gis:set-world-envelope gis:envelope-of boundaries-dataset
  ;; get extent
  
  let kitui-envelope gis:world-envelope 
  let kmwidth (item 1 kitui-envelope - item 0 kitui-envelope) * 111 ;; kilometers
  let kmlength (item 3 kitui-envelope - item 2 kitui-envelope) * 111
  if wordy [show (word "width: " kmwidth " km, length: " kmlength " km")]
  ;; output property names for all GIS features/elements
  ;; show gis:property-names boundaries-dataset  ;; ["OBJECTID" "SLCODE" "FIRST_PROV" "MIN_DISTCO" "FIRST_DIST" "MIN_DIVCOD" "FIRST_DIVN" "MIN_LOCCOD" "FIRST_LOCN" "FIRST_SLNA" "SUM_AREA_S" "SUM_MALE" "SUM_FEMALE" "SUM_TOTAL" "SUM_HOUSEH" "DENSITY" "SHAPE_LENG" "SHAPE_AREA" "COUNTY" "COUNT" "SUM" "MEAN" "MEDIAN" "STDEV" "MIN" "MAX" "MAICOUNT" "MAISUM" "MAIMEAN" "MAISTDEV" "MAIMIN" "MAIMAX" "STK_COUNT" "STK_SUM" "STK_MEAN" "STK_STDEV" "STK_MIN" "STK_MAX" "TR_SAMPLE" "URB_STATUS" "TOWN_NAME"]

  ;; output the outer coordinates of the shapefile data
  ;show gis:world-envelope ;; [37.59397888199955 39.07511138900003 -3.0751477082397107 -0.049275776760199674]
  ;; 161 km E-W by 333 N-S
  gis:draw boundaries-dataset 1
  
  set county-patches patches gis:intersecting (list boundaries-dataset)
 
  let TR-features gis:find-features boundaries-dataset "TR_sample" "1"   ;; filter features by district
  if wordy [show (word "Imported GIS vector dataset with " length TR-features " charcoal hotspot features!")]
  ;let relationships gis:relationship-of (list boundaries-dataset) (list patches)
  set hotspot-patches patches gis:intersecting TR-features
   
  ;show (word "Of " count county-patches " county patches, the TR hotspots area intersects with " count hotspot-patches " hotspot patches")
  ;gis:property-value VectorFeature property-name
  ;show gis:find-greater-than boundaries-dataset "TOWN_NAME" "" ;; find features
  ;show gis:property-value one-of TR-features "TOWN_NAME"
  ;show gis:property-value one-of TR-features "FIRST_PROV"
  ;show gis:property-value one-of TR-features "OBJECTID"
 
  let urban-features-core gis:find-features urban-dataset "STATUS" "Core Urban"   ;; filter features by urban status - core
  let urban-features-peri gis:find-features urban-dataset "STATUS" "Peri-Urban"   ;; filter features by urban status - peri
  let urban-patches-core patches gis:intersecting urban-features-core  ;; urban features may have corresponding object ID 
  let urban-patches-peri patches gis:intersecting urban-features-peri
  set urban-patches (patch-set urban-patches-core urban-patches-peri)
  
  ; TODO add core/peri attribute if needed
  
  let km-features gis:find-features urban-dataset "TOWN_NAME" "KITUI MUNICIPALITY"   ;; filter features by town name
  ;set km-patches patches gis:intersecting km-features
  
  let k-features gis:find-features urban-dataset "TOWN_NAME" "KITUI"   ;; filter features by town name
  ;; subtract km features
  set kitui-features filter [not member? ? km-features] k-features
  set kitui-patches patches gis:intersecting kitui-features
  
  set mwingi-features gis:find-features urban-dataset "TOWN_NAME" "MWINGI"   ;; filter features by town name
  set mwingi-patches patches gis:intersecting mwingi-features
  
  set matuu-features gis:find-features urban-dataset "TOWN_NAME" "MATUU TOWNSHIP"   ;;
  set matuu-patches patches gis:intersecting matuu-features
  
  set tulia-features gis:find-features urban-dataset "TOWN_NAME" "TULIA"   ;; filter features by town name
  set tulia-patches patches gis:intersecting tulia-features
  
  ;let marimanti-features gis:find-features urban-dataset "TOWN_NAME" "MARIMANTI"   ;; filter features by town name
  ;set marimanti-patches patches gis:intersecting marimanti-features
   ;let urban-patches-peri patches gis:intersecting urban-features-peri
  ;let urban-features gis:find-features  "Core Urban"   ;; filter features by district
  
  ;show (word "Imported dataset with urban features which intersects with " count urban-patches " urban patches")
;  show (word "KITUI MUNICIPALITY: " count km-patches)
;  show (word "KITUI: " count kitui-patches)
;  show (word "MWINGI: " count mwingi-patches)
;  show (word "MATUU TOWNSHIP: " count matuu-patches)
;  show (word "TULIA: " count tulia-patches)
;  show (word "MARIMANTI: " count marimanti-patches)
  
  if wordy [show "Urban centres are KITUI, MWINGI, MATUU TOWNSHIP, and TULIA"]
  set marketnames (list "Kitui" "Mwingi" "Matuu" "Tulia") ;;(list "Ngiri" "Wemba" "Chuluni" "Kitui" )  ;; made up names
  
  set kitui-loc gis:location-of gis:centroid-of first kitui-features
  set mwingi-loc gis:location-of gis:centroid-of first mwingi-features
  set matuu-loc gis:location-of gis:centroid-of first matuu-features
  set tulia-loc gis:location-of gis:centroid-of first tulia-features
 
 
  set market-locations (list kitui-loc mwingi-loc matuu-loc tulia-loc )
  ;set outside patch-set filter [not member? ? county-patches] sort-on [who] patches  ?
  
  ;; add information about the total number of people to each market, so that this can be used to add buyers to markets
  ;; show gis:property-value one-of kitui-features "SUM_TOTAL"
  ;; have to get the objectid codes of the features from urban dataset ,and then use these in the  boundaries-dataset
;  foreach mwingi-features
;  [
;  let fid gis:property-value ? "OBJECTID"
;  let ff gis:find-one-feature boundaries-dataset "OBJECTID" (word fid)
;  ;show gis:property-value ff "FIRST_SLNA"
;  ;show gis:property-value ? "FIRST_SLNA"
;  show gis:property-value ff "SUM_TOTAL"
;  ]
  ;; this is used to set the population lists
  
  ;; patches used for setting up the levy agents, using the roads dataset
  set roads-patches  patches gis:intersecting roads-dataset
  set roadsxhotspots patch-set filter [ member? ? hotspot-patches] sort roads-patches
  let hotspot-urban-patches (patch-set hotspot-patches urban-patches)
  set roadsxhotspotsxurban patch-set filter [ member? ? hotspot-urban-patches] sort roads-patches
  
  ;; print gis:find-features roads-dataset "ROADID" "1"
  ;; according to google maps two main routes are b7 and c97
  ; these patches are roughly in the right location and are on a road
  ;set export-locations [[-78 48] [ -59 18 ]]
  set export-locations (patch-set patch -78 48 patch -59 18)
   
  ;show count roadsxhotspots
  ;; show gis:property-names roads-dataset
  ;; show gis:property-value one-of kitui-features "SUM_TOTAL"
  ;let c-list (list county-patches)
  ;let p-list (list patches)
  ;let m-list map occurrence
  ;let m-list map member? c-list p-list reduce
  ;map member? p-list (list county-patches)
  ;let o-list n-values (length p-list) [ifelse-value (member? (item ? p-list) c-list) [nobody] [item ? p-list] ];; end
  ;let o-list n-values (length m-list) [ifelse-value (item ? m-list = true) [nobody] [item ? p-list] ];; end
  ;show first o-list;[ ifelse-value m-list [ ? ] [ nobody ]  
  ;show n-values 10 
  ;let other-patches patches not gis:intersecting (list boundaries-dataset) ;[not member? ? county-patches] list patches
  
  ;; load other GIS datasets. Png files converted from tif files using 'convert stock-test.tif -trim stock-trim.png'
  ;; import-pcolors Reads an image file, scales it to the same dimensions as the patch grid while maintaining the original aspect ratio
  ;; and transfers the resulting pixel colors to the patches. 
  import-pcolors "kitui_data/stock-trim.png"
  
  ;; make a table with the colours in
   
;  let table-set-stock-from-pcolor-low table:make
;  table:put table-set-stock-from-pcolor-low 29   0 ;; count: 28261"37.8 0 ;;
;  table:put table-set-stock-from-pcolor-low 37.8 1 ;; count: 24608"
;  table:put table-set-stock-from-pcolor-low 38.7 2 ;; count: 8930"
;  table:put table-set-stock-from-pcolor-low 39.4 3 ;; count: 19857
;  table:put table-set-stock-from-pcolor-low 38.3 4 ;; count: 69804
;  table:put table-set-stock-from-pcolor-low 9.9  5 ;; count: 140930
;  table:put table-set-stock-from-pcolor-low 36.9 6 ;; count: 2596
;  table:put table-set-stock-from-pcolor-low 29.7 7 ;; count: 80
  
  let table-set-stock-from-pcolor-l table:make
  
  table:put table-set-stock-from-pcolor-l 9.9  0 ;; y count: 140930
  table:put table-set-stock-from-pcolor-l 29.7 1 ;; count: 80
  table:put table-set-stock-from-pcolor-l 39.4 1001 ;; count: 19857
  table:put table-set-stock-from-pcolor-l 29   5001 ;; count: 28261 ;;
  table:put table-set-stock-from-pcolor-l 38.7 10001 ;; count: 8930"
  table:put table-set-stock-from-pcolor-l 38.3 20001 ;; count: 69804
  table:put table-set-stock-from-pcolor-l 37.8 40001 ;; count: 24608"
  table:put table-set-stock-from-pcolor-l 36.9 100001 ;; count: 2596
  
  let amts [0 1 1001 5001 10001 20001 40001 100001]
  ;;show table:values table-set-stock-from-pcolor-l
  ;;let amts table:values table-set-stock-from-pcolor-l
  ;ask hotspot-patches [set stk table:get table-set-stock-from-pcolor-l pcolor] 
  
  let allcolors-s remove-duplicates [pcolor] of patches
  ;show (word "Importing stock data makes " length allcolors-s " colours (There is supposed to be 8!)")
  ;; world settings custom -192 191 -396 396
  if length allcolors-s = 8 
  [
  foreach amts [
    let amt ?
    ;show amt
    foreach allcolors-s [
      if table:get table-set-stock-from-pcolor-l ? = amt
      [
         ask patches with [pxcor < -180] [set pcolor ?]
         ;show (word "color: " ? " stk: " amt " count: " count patches with [pcolor = ?])
         wait 2
      ]
    ]
  ]
  ]
     
  ;; check growth data
  ;; load other GIS datasets. Png files converted from tif files using 'convert stock-test.tif -trim stock-trim.png'
  
  ;;import-pcolors "kitui_data/growth-trim.png"    ;; Kitui_biomass_growth_WGS84_1km.tif"
  ;import-pcolors "kitui_data/growth-image2-crop.png"
  import-pcolors "kitui_data/growth-convert-trim.png"
  ;;import-pcolors "kitui_data/Kitui_biomass_growth_WGS84_1km.png"
  
   ;; set blended colors to a pure NetLogo color 
  ;ASK PATCHES [ SET PCOLOR ( 5 + PRECISION PCOLOR -1 ) ] 
  
  let allcolors-g remove-duplicates [pcolor] of patches
  if wordy [show (word "Importing growth data makes " length allcolors-g " colours (There is supposed to be 8!)")]
  ;; world settings custom -192 191 -397 396
  
 
  
  if length allcolors-g = 8 
  [
    foreach allcolors-g
    [
      ask patches with [pxcor < -180] [set pcolor ?]
      show (word "color: " ? " stk: " "?" " count: " count patches with [pcolor = ?])
      wait 2
    ]
  ]
  
;  let amts [0 1 251 501 751 1001 1501 2001]
;  
;  
;  let table-set-growth-from-pcolor-l table:make
;  
;  table:put table-set-growth-from-pcolor-l 9.9  0 ;; y count: 140930
;  table:put table-set-growth-from-pcolor-l 29.7 1 ;; count: 80
;  table:put table-set-growth-from-pcolor-l 39.4 251 ;; count: 19857
;  table:put table-set-growth-from-pcolor-l 29   501 ;; count: 28261 ;;
;  table:put table-set-growth-from-pcolor-l 38.7 751 ;; count: 8930"
;  table:put table-set-growth-from-pcolor-l 38.3 1001 ;; count: 69804
;  table:put table-set-growth-from-pcolor-l 37.8 1501 ;; count: 24608"
;  table:put table-set-growth-from-pcolor-l 36.9 2001 ;; count: 2596
;  
;  
;  
;  foreach amts [
;    let amt ?
;    foreach allcolors [
;      if table:get table-set-growth-from-pcolor-l ? = amt
;      [
;         ask patches with [pxcor < -180] [set pcolor ?]
;         show (word "color: " ? " stk: " amt " count: " count patches with [pcolor = ?])
;         wait 2
;      ]
;    ]
;  ]

  ;; set patches subloc and set growth rate according to mean of subloc
  if take-constraint = "mai"
  [
    gis:apply-coverage boundaries-dataset "MAIMEAN" mai  
    ;ask hotspot-patches [set mai 100 * mai]              ;; the maimean is per ha, so multiply by 100 to get mai per km2
    ask hotspot-patches [set mai precision (100 * mai) 0] ;; NEW using integers MAI in kg. see max-amt-collected
    
  ]
  ;; otherwise set mai according to linear a.a.c
  if take-constraint = "2.6"
  [
    ask hotspot-patches [set mai 0.026 * stk]
  ]
  if take-constraint = "1.3"
  [
    ask hotspot-patches [set mai 0.013 * stk]
  ]
  if take-constraint = "3.9"
  [
    ask hotspot-patches [set mai 0.039 * stk]
  ]
  ;; there may be some NaN - don't understand how hotspot patches can be outside the area covered by the GIS/raster dataset
  ; set color to blue if value is a number, red if value is "not a number"
  let allpatches count hotspot-patches   
  let goodpatches count hotspot-patches with [mai > 0]
  if wordy [show (word "There are  " allpatches " hotspot patches, and " (allpatches - goodpatches) " bad patches with NaN crept in!")]
  
  
  ;ask hotspot-patches with (value <= 0) or (value >= 0)
;[ set color blue ]
;[ set color red ]
;  show count hotspot-patches with [mai = "NaN"]
  ;ask hotspot-patches with [mai = "NaN"] [ set mai [mai] of one-of neighbors with [mai != "NaN"]] 
  ;gis:apply-coverage boundaries-dataset "TR_SAMPLE" subloc
  ;gis:apply-coverage boundaries-dataset "OBJECTID" subloc
   
  
  ;ask hotspot-patches [set stk table:get table-set-stock-from-pcolor-l pcolor]   
end 

;to setup-gis
;  ;  first define a transformation between GIS data space and NetLogo space
;  
;  gis:load-coordinate-system "data/ke_district_boundaries.prj" 
;  set boundaries-dataset gis:load-dataset "data/ke_district_boundaries.shp"
;  ;let biomass-dataset gis:load-dataset "data/kitui-biomass-map.tif"
;  ;let landuse-dataset gis:load-dataset "data/kitui-vegetation-map.tif"
;  
;  ;gis:set-world-envelope (gis:envelope-union-of (gis:envelope-of biomass-dataset) (gis:envelope-of landuse-dataset))
; 
;  ;gis:set-world-envelope gis:envelope-of boundaries-dataset
;  ;show gis:world-envelope
;  
;  show gis:property-names boundaries-dataset ; DISTNAME
;  show gis:feature-list-of boundaries-dataset ;["DISTNAME":"KITUI"]}
;  set kitui-boundary gis:find-one-feature boundaries-dataset "DISTNAME" "KITUI"
;  set mwingi-boundary gis:find-one-feature boundaries-dataset "DISTNAME" "MWINGI"
; 
;  let county-boundary list kitui-boundary mwingi-boundary
;  ;gis:set-world-envelope gis:envelope-of  county-boundary
;  ;show gis:world-envelope
;  ; show county-boundary ;
;  ;let county-boundary gis:envelope-union-of (gis:envelope-of kitui-boundary) (gis:envelope-of mwingi-boundary) 
;  gis:set-world-envelope (gis:envelope-union-of (gis:envelope-of kitui-boundary) (gis:envelope-of mwingi-boundary))
;  ;gis:set-world-envelope (gis:envelope-union-of (gis:envelope-of biomass-dataset) (gis:envelope-of landuse-dataset))
;  ;show gis:envelope-of kitui-boundary 
;  ;show gis:envelope-of county-boundary 
;  show gis:world-envelope  ;; [37.22978662321898 39.431842099925554 -3.0706589221954346 -0.05302734300494194]
;  ;[37.59589767456055 39.065731048583984 -3.0706589221954346 -1.056693196296692] for kitui
;  ; [37.22795797724928 39.43367074589525 -3.0706589221954346 -0.05302734300494194] for both
;  ; 2.2057127686 3.01763157919 or 243.879043686 by 333.650470816km (try 163 by 333)(+-81 +-166) 
;  ; [37.22978662321898 39.431842099925554 -3.0706589221954346 -0.05302734300494194]
;  ;gis:set-transformation [37.22795797724928 39.43367074589525 -3.0706589221954346 -0.05302734300494194] (list min-pxcor max-pxcor min-pycor max-pycor)
;  ;gis:set-transformation [37.59589767456055 39.065731048583984 -3.0706589221954346 -1.056693196296692] (list min-pxcor max-pxcor min-pycor max-pycor)
;  gis:draw kitui-boundary 1
;  gis:draw mwingi-boundary 1
;  ;gis:draw county-boundary 1
;  ; 1.469833374 in x direction 2.0139657259 in y
;  ; 110.567 between degree at equator
;  ; km 223km 163 km
;  
;  set county-patches patches gis:intersecting (list kitui-boundary mwingi-boundary)
;  
;  show count county-patches
;  ;ask county-patches [set pcolor blue]
;  ;gis:raster-world-envelope RasterDataset x y
;;Reports the GIS envelope needed to match the boundaries of NetLogo patches with the boundaries of cells in the given raster dataset. This envelope could then be used as an argument to set-transformation-ds.
;  
;  ;gis:apply-raster biomass-dataset cover
;  ;gis:set-world-envelope gis:envelope-of biomass-dataset
;  ;gis:apply-raster biomass-dataset cover
;;ask patches with [ hab = 2] [set pcolor white]
;;gis:set-transformation (list 1209616.305 1213916.305  384568.397 387568.397) (list min-pxcor max-pxcor min-pycor max-pycor)
;end


;; GIS sent by Richard and edited by Tahia - v2 data
;; 4.3 by 3km  (mapped onto netlogo view 145*100)
;to setup-gis-kfs
;  ;; coordinate system
;  let projection "Kitui_biomass"
;  gis:load-coordinate-system (word "data/" projection ".prj")
;  ;;; load GIS datasets
;  set biomass-dataset gis:load-dataset (word "data/" projection ".shp") 
;  set vegetation-dataset gis:load-dataset "data/Kitui_forest.shp"
;
;;  ;; set the world envelope to the union of all our dataset's envelopes
;  gis:set-world-envelope (gis:envelope-union-of (gis:envelope-of biomass-dataset) (gis:envelope-of vegetation-dataset) ); (gis:envelope-of commu-dataset) (gis:envelope-of hz-dataset) (gis:envelope-of cf-dataset))
;  show gis:world-envelope ;[37.595981597900376 39.08422088623057 -3.0744288921060026 -0.03403819876886227]
; 
;  
;  show gis:property-names biomass-dataset ; ["DISTRICT" "PROVINCE" "AREA_SQKM_" "BIOM_ACCES" "TOT_M3_KM2"]
;  let all-biomass-features gis:feature-list-of biomass-dataset                      ;; all features
;  let kitui-biomass-feature gis:find-one-feature biomass-dataset "DISTRICT" "Kitui" ;; filter features by district
;  let kitui-biomass-features gis:find-features biomass-dataset "DISTRICT" "Kitui"   ;; filter features by district
;  show length kitui-biomass-features ;630
;  
;;  foreach kitui-biomass-features
;;  [
;;    gis:draw ? 1  ;; argument is the line thickness
;;    ;show  gis:property-value ? "BIOM_ACCES"
;;  ]
;  
;  ;; In order to get agents or patches to be aware of vector data, we establish their topological relationship to the data. 
;  
;  ;; gis:intersects? determines whether the agent or patch intersects with the data
;  
;  ;let cop one-of county-patches
;  ;ask one-of county-patches [
;   ask county-patches [
;    let cop self
;    foreach all-biomass-features 
;    [ 
;      if  gis:intersects? cop ?
;        
;      [;set patch-biomass gis:property-value ? "TOT_M3_KM2"
;        ;set patch-biomass gis:property-value ? "AREA_SQKM_"
;        set patch-biomass gis:property-value ? "BIOM_ACCES" 
;        set pcolor patch-biomass
;      ] 
;      
;    ;kitui-biomass-features
;    ; gis:intersects? biomass-dataset patch-biomass
;    ;ifelse  gis:intersects? biomass-dataset patch-biomass patch-biomass >= 0 [ set pcolor scale-color green patch-biomass 0 2000 ] [
;    ;  set pcolor white
;    ]
;  ]
;  ;show kitui-biomass-feature
; ; show gis:property-value kitui-biomass-feature "BIOM_ACCES"
;  show remove-duplicates [patch-biomass] of county-patches
;  ;gis:draw kitui-biomass-feature 6
;  ;show length gis:feature-list-of biomass-dataset ; 749
;  ;show length gis:feature-list-of biomass-dataset ; 749
; 
;  ;show gis:property-maximum biomass-dataset "DISTRICT"
;;  ;; Do a transformation between GIS and netlogo coordinates
;;  ;; assuming central point for MANG is 1211766.304900,386068.397200
;;  ;; [1103075.6570775004 1304055.8913225003 298497.71360000223 437104.77170000225]
;;  
;;  ;; area  4.3 by 3km
;;  ;; view 145*100
;;  ;; top 387568.397 (386068.397200 + 1500.000 m)
;;  ;; left 1209616.305 (1211766.304900 - 2150.000 m)
;;  ;; right 1213916.305 (1211766.304900 + 2150.000 m) 
;;  ;; bottom 384568.397 (386068.397200 - 1500.000 m)
;;  gis:set-transformation (list 1209616.305 1213916.305  384568.397 387568.397) (list min-pxcor max-pxcor min-pycor max-pycor)
;;  
;end


;to draw-gis [s]
;  gis:draw villages-dataset s
;  
;  gis:draw roads-dataset s
;  gis:draw cf-dataset s
;  gis:draw commu-dataset s 
;  gis:draw hz-dataset s
;  
;end
;; levels for fertility are: good fair poor 
;;  current farmed land has medium fertility, but abandoned land would presumably be poor

;to initial-land-fertility
;  
;  
;  ask patches
;  [ set  when-quantity-updated init-year
;    set when-quality-updated init-year
;  ]
; 
;  paint-landparcels ;; repaint the forest
;end



;to paint-quality   ;; same colours as in earth engine map
;  ask patches
;  [
;    select-case quality
;    [ ;; levels == good, fair, poor, clear 
;      [ "clear" "set pcolor [0 0 0]"]
;      [ "poor" "set pcolor [0 85 0]"]
;      [ "fair" "set pcolor [0 170 0]"]
;      [ "good" "set pcolor [0 255 0]"]
;    ]
;   
;  ]
;end
;
;;; for monitoring patch cover and/or fertility in aggregate 
;to-report patch-health [attribute value]
;  report count patches with [attribute = value]
;end


;; transporter selects a market given the current propensities

to-report select-market 
  let wordy false
  
  ;; to avoid when the case when the algorithm sometimes doesnt make a valid choice - when the rn exceeds the sum of propensities 
  let toret one-of marketnames   ;; selection
  let rn random-float 1
  
  let counter 0
  let cummulative 0
  let selected false
  foreach propensities
  [ let current-prop item counter propensities 
    set cummulative cummulative + current-prop
    ;show cummulative
    if rn < cummulative and selected = false 
    [ set toret item counter marketnames 
      set selected true
    ]
    set counter counter + 1
  ]
  if wordy
  [ show (word "Rn is " rn)
    show (word "choice is " toret)  
  ]
  
  report one-of markets with [label = toret]
end 

;; evaluate transporter monthly proc
; evaluate is only done if the transporter did not export this month - did not get bulk order (from CPG etc) and did not otherwise opt to export

to transporters-evaluate-market
  
  ;; calculate payoff and update propensities only if transporter did not export this month
  if trade?  ;; (permit = false) or (bulk-supplier = nobody)
  [
    set payoff sales                ;; payoff is the value obtained following current strategy
    
    ;; reinforcement
    let rval 0
    if (max-rval != aspiration)   ;; max-rval is equal to lorry capacity
    [
      set rval (payoff - aspiration ) / (max-rval - aspiration)
    ]
    set stimulus rval     ;; stimulus call uses the payoff value to calculate the reward/punishment signal
                           ;; - these are used later to modify the propensities
                                                                
    ;; calculate satisfaction - from comparison of payoff(s) with aspiration(s)
    set satisfaction ifelse-value (stimulus > 0) [true] [false]
      
    if aspiration != 0
    [  
       update-propensities stimulus ;; first indicator (for subsistence) 
    ]
   
    ;; history should only be updated if traded  
    set history butfirst history
    set history lput payoff history 
   
    set satisfaction-history butfirst satisfaction-history
    set satisfaction-history lput satisfaction satisfaction-history
    
    ;; **new** update aspiration (without including export data) 
    set aspiration mean history

  ]
end 
   
;; count the number of occurrences of an item in a list

to-report occurrences [x the-list]
  report reduce
    [ifelse-value (?2 = x) [?1 + 1] [?1]] (fput 0 the-list)
end 
    


;; combine RL with imitation

to transporters-select-market
  
  ;; make new selelction   
  let new-choice 0
    
  ifelse imitation = false or satisfaction = true
  [
    ;; if satisfied, choose based on propensity levels, using select method
    set new-choice select-market 
  ]
  [
    ;; choose by imitation if unsatisfied (aspirations are not met)
    ;; - copy the choice of portfolio from one whose aspirations are met
    ifelse any? other transporters with [satisfaction = true]
    [
      let nbr one-of other transporters with [satisfaction = true]
      set new-choice [mchoice] of nbr
    ]
    [
      set new-choice select-market
    ]
  ]
  set mchoice new-choice  
end 

;; update accessibilit ywhen a new landparcel is added or when a landparcel becomes CPG

to update-accessible-parcels
  let wordy false
  ;if wordy [ show sum [count parcels] of producers] 
 
  ask producers 
  [
    set parcels landparcels with [practice = "private"] in-radius max-distance-collection
  ]
  if wordy [  
    show (word "Accesible parcels :  " sum [count parcels] of producers)
    let unaff producers with [CPG = nobody]
    show (word sum [count parcels] of unaff " parcels available to "  count unaff " non-CPG producers :  " )
  ]
end 

;; update the annual account for each market channel (formal, informal, RC, SC), done every trading cycle

to update-marketchannel-data
  set annual-marketsizes replace-item 0 annual-marketsizes (item 0 annual-marketsizes + sum [sales] of transporters with [permit])            ;; formal - sold by transporter with permit of any type
  set annual-marketsizes replace-item 1 annual-marketsizes (item 1 annual-marketsizes + sum [sales] of transporters with [permit = false])    ;; informal -  sold by transporter without permit
  set annual-marketsizes replace-item 2 annual-marketsizes (item 2 annual-marketsizes + sum [sales] of transporters with [permit-type = "RC"]);; regulated - sold by transporter with RC permit
  set annual-marketsizes replace-item 3 annual-marketsizes (item 3 annual-marketsizes + sum [sales] of transporters with [permit-type = "SC"]);; regulated - sold by transporter with RC permit
    
  ;show annual-marketsizes  
end 


;; transporters - one indicator (the sales) is used as the reinforcement value

to update-propensities [outcome]
  let wordy false
  
  let pos position [label] of mchoice marketnames ;; pos is unique
  
  let current-prop item pos propensities 
  ;set propensities replace-item pos propensities (current-prop + outcome)  ;; roth-erev

  if wordy [
    show (word "before:  " propensities )
    show (word "pos: " pos ", outcome:  "  outcome)
  ]
  ;; macy and flache
  ifelse outcome > 0
  [
    set propensities replace-item pos propensities (current-prop + (transporters-learning-rate * outcome) * (1 - current-prop))
  ]
  [
    set propensities replace-item pos propensities (current-prop + (transporters-learning-rate * outcome) * current-prop)
  ]
  
  ;; Modify to keep all propensities (including those not selected) above the cutoff value 
  let counter 0
  foreach propensities
  [ if ? < p-cutoff
    [  set propensities replace-item counter propensities p-cutoff
    ]
    set counter counter + 1
  ]
  ;; normalise propensities to 1
  let divisor sum propensities
  set counter 0
  foreach propensities
  [ if ? > 0 
    [ set propensities replace-item counter propensities (? / divisor)
    ]
    set counter counter + 1
  ]
  if wordy
  [ show (word "after:  " propensities )
  ]
end 

to print-initial-settings 
  print (word "Seed: " seed " Model set up with " numberProducers " producers, " numberTransporters " transporters, and " numberBuyers " buyers.")
  print (word "params: min-demand " min-demand ", CPGscenario " CPGscenario " ,kiln-eff-improved " kiln-eff-improved " landparcel-size " landparcel-size ", and ticks-per-month " ticks-per-month)
  print (word "Policies biomass:"  POLICYbiomass ", efficiency:" POLICYefficiency ", certification:"  POLICYcertification)
  print (word "Scenarios intensify?:"  intensify? ) ;", ScenarioA:" ScenarioA ", ScenarioB:"  ScenarioB)
end 


;; drawing polyline data from shapefile 
;to display-GIS-dataset [ds]
;  gis:draw ds 1
;  ;; loading data into turtles
;  foreach gis:feature-list-of ds
;  [ 
;    let centroid gis:location-of gis:centroid-of ?
;    if not empty? centroid
;    [
;      create-village-labels 1
;      [
;        set xcor item 0 centroid
;        set ycor item 1 centroid
;        set size 0
;        if member? "ANNOTXT" gis:property-names ds
;        [  set label gis:property-value ? "ANNOTXT"
;        ]
;      ]
;    ]
;  ]
;end


;; orphaned method

to update-environment
  
  ;; mai (growth in kg ) needs to be added to stk at the end of each year for patches
  ;; TODO compute patch growth 
  ;; compute or look up growth rate (% mai-perc ) which is a function of standing stock based on an exponential curve fit 
  
  ask patches [
    ;; let mai-perc ...y = 37.058x-0.588
    ;set stk random 1000
    let stk-th (precision stk -6) / 100000 ;; stock in tonnes per hectare (1000 kg = 1 tonne) to nearest 10 t
                      
    let mai-perc table:get table-pg stk-th  ;; mai-perc is a function of standing stock - eg 1 to 16%
    set mai stk * (mai-perc / 100)  ;; amount in kg
    ;; let mai mai-perc * stk
    set stk stk + mai              ;; growth rate   - growth as a function of standing stock
    
  ]
  ask one-of patches [show stk]
end 

 ;;put in a table, stock is measured in tons. growth rate in %

to table-patch-growth
 
  set table-pg table:make
  table:put table-pg 0 0
  foreach n-values 100 [10 * (? + 1)]  ;; possible values of x
  [
    ;; not able to compute using primatives of netlogo
    let y 37.058 / (sqrt ?) ;; rough 
    ;;print y
    table:put table-pg ? y
  ]
  ;;print table-pg
end 

to efficient-kilns
    let wordy false
    let intervention-efficiency POLICYefficiency ;item 0 NAMApolicy
    
    if intervention-efficiency > 0 and year-id >= 2017 ;!= init-year
    [
      let applicants (turtle-set landparcels with [kiln-efficiency = kiln-eff-standard] producers with [kiln-efficiency = kiln-eff-standard])
      ;print (word "annual production: " [annual-production] of applicants)
      ;; sort on amount of production in the past trading cycle /year
      ;; - this also prioritises CPGs because they have more than two members
      let applicants-on-production sort-on [(- sum annual-production)] applicants ;; sort-on is ascending
      let top-producers turtle-set sublist applicants-on-production 0 intervention-efficiency
      
      if wordy 
      [
        ask top-producers
        [
          print (word "Top annual production: " breed "-" who " " precision sum annual-production 1)
          print annual-production 
        ]
      ]
      ;; TODO why don't producerss do any production for the first 18 trading cycles in year 0
      ;; sort on amount of collection done in the past trading cycle /year
      let applicants-on-collection sort-on [(- sum annual-collected)] applicants ;; sort-on is ascending
      let top-collectors turtle-set sublist applicants-on-collection 0 intervention-efficiency
      ;;show [sum annual-collected] of applicants-on-collection
      ;print (word "Top annual collection: " [sum annual-collected] of top-collectors)
      ;; TODO why is collection non-integer
      
      ;; top producers could be landparcels/CPGs or individuals   
      ask top-producers   
      [
        set kiln-efficiency kiln-eff-improved     ;;; receive improved kilns
        set loanK year-id 
      ]
      
    ]
end 

;; TODO second possible criteria is quality of landparcel for charcoal production
;; -- tree quality currently this is set after creating
;; -- MAI could be a possible measure of quality
;; assess 'business models' on both of these criteria
;; TODO add MAI limit on these new woodplots

to additional-woodlots
  let wordy false
  let aw-practice "CPG"                  ;; assuming the new woodlots are CPG, not private type
   
  let intervention-biomass POLICYbiomass ;item 0 NAMApolicy
  
  if intervention-biomass > 0 and year-id >= 2017 ;and year-id != init-year
  [
    
    ;; place this number of new landparcels at random
    ;initialise-landparcels intervention-biomass
    let new-landparcels no-turtles 
    
    let applications intervention-biomass * 5  ;; number of applications
    
    create-landparcels applications [
      set size-xy (list landparcel-size landparcel-size)
      set area (item 0 size-xy) * (item 1 size-xy)

      position-landparcel
      set new-landparcels (turtle-set new-landparcels self)
      
      set near-producers producers with [loanW = 0] in-radius max-distance-collection  ;; a new measure for applications
      set num-near-producers count near-producers
      
    ]

    ;show [num-near-producers] of turtle-set new-landparcels
    ;show [num-near-producers] of turtle-set (sort-by [[num-near-producers] of ?1 < [num-near-producers] of ?2] new-landparcels)

    let best-counts sublist (sort-by > [num-near-producers] of new-landparcels) 0 intervention-biomass
    if wordy [print (word "Found landparcels with most nearby producers " best-counts)]
    
    let best-parcels turtle-set filter  [member? [num-near-producers] of ? best-counts] sort new-landparcels
    ;; put in a check in case more than one lp have the same number of nearby producers
    set best-parcels n-of intervention-biomass best-parcels 
    
    ;show (sort-by [count ?1 > count ?2] [near-producers] of new-landparcels)
    
    ;show [num-near-producers] of turtle-set (sort-by [count [near-producers] of ?1 > count [near-producers] of ?2] new-landparcels)
    ;show [num-near-producers] of turtle-set (sort-by [[num-near-producers] of ?1 < [num-near-producers] of ?2] sort new-landparcels)
    ;let applications-sorted-by-near-producers (sort-on [num-near-producers] of new-landparcels)
    ;show [num-near-producers] of turtle-set applications-sorted-by-near-producers
    
   
    foreach sort best-parcels   ;; all but the best parcels die
    [  
      set new-landparcels turtle-set remove ? sort new-landparcels   
    ]
    ask new-landparcels [die]
       
    ;; finish setting up the lp - give properties to do with CPG
    ask best-parcels
    [    
      set members no-turtles ;; initialisation
      set date year-id       ;; 
      set tcosts 0
      set accepted-price 0
      set sales 0
      set annual-profit []
      set collected [0 0] 
      set annual-collected []
      set annual-production []
      
      hide-turtle
    
      let lparcel self       ;; ask patches to set partfarm to the current landparcel
      ask lpatches
      [         
        set partof lparcel
        set species one-of treetypes
        set quality item species treequalities   ;; eg.  0.5 or 1
      ]
      
      ifelse aw-practice = "CPG" 
      [      
        set practice "CPG"
        ;show (sum [mai] of lpatches)           
      ]
      [
        set practice "private"
      ]
      
      ;; nearby producers take the loan (they are not counted in the next bidding). loans are reset to 0 after 5 years
      ask near-producers [set loanW year-id] 
      set loanW year-id                         ;; although landparcel members actually take the loan 
      set kiln-efficiency kiln-eff-standard
      if strictloans [set quota true  ]         ;; whether there is MAI limit - true if created through loan - regardless of practice type
      set permit true                           ;; new CPG should get a permit for regulated charcoal
      set permit-type "RC"                      ;; The permit would be upgraded to "SC" only if it meets all criteria - updated in year start events
      paint-landparcels
    ]  
      
    ;; reallocate members
    foreach sort producers
    [
      let dlist sort-on [distance ?]  landparcels with [practice = "CPG"]
      if min [distance ?] of landparcels with [practice = "CPG"] < max-distance-collection
      [
        ;; TODO add stock to stock of CPG ?
        ask ?     ;; ask producer members
        [
          ;; quite a few variables need to be reset when the producer joins CPG
          set CPG first dlist 
          ;; set annual-profit [] ;; goes back to zero at start of year
          ;; set annual-collected [] ;; goes back to zero at start of year
          ;; set annual-production [];; goes back to zero at start of year
 
          set collected [0 0]  ;; these were not getting reset, apparently
          set production 0
  
          set intensification 100
          set stock 0    ;; not sure about these
          ;set permit false  ;; producer should only get a permit if the CPG meets all criteria - updated in year start events
        ]
        ask first dlist [set members (turtle-set ? members)]
      ]
    ]
    
    if wordy 
    [
      ask best-parcels
      [
        print (word "Landparcel " who " created with practice " practice )
        print (word "Members: " members)
      ]
    ]
      
    ;; setup the landparcels so they are accessible - not really needed if new woodlots are CPGS
    update-accessible-parcels
  ]
end 

to year-start-events
    ; reset-year                                ;; ensures to calculate returns for the previous year, and any other needed steps ..
    let wordy false
    
    ;; there are warmup years before policies come into effect
    additional-woodlots  ;; if this policy is supported
    efficient-kilns      ;; producers get loans
    
    ;; POLICYcertification policy scenario parameters should only be set when the policy period first starts in 2017
    if year-id = 2017
    [  
      set list-price max (list reg-price (item 0 POLICYcertification))  
      set export-price-permit item 1 POLICYcertification               ;; -- this can be zero as it is not used if NAMAcertification policy is not  set.
    ]

    if item 0 POLICYcertification  > 0 and year-id >= 2017
    [
      foreach sort landparcels with [practice =  "CPG" and kiln-efficiency = kiln-eff-improved ]
      [
        ;; assume that CPGs will take the opportunity to get certified and will adopt/comply with the quota
        ask ? 
        [
          set quota true
          set permit true          ;; permit at the landparcel level
          set permit-type "SC"     ;; set the type to sustainable charcoal
        ]
        ;; update producer permits to include those that recently met the requirements (member of CPG with improvedKiln)
        ask [members] of ?
        [
          set permit true          ;; permit at the producer level
          set permit-type "SC"      
        ]
      ]
    ]
    if wordy [show (word "certified CPGs: " count landparcels with [kiln-efficiency = kiln-eff-improved ] )]
    
;    if ScenarioA and year-id != init-year ;; scenario a where the number of CPGs increases at the start of each year
;    [
;      
;      let new%CPGs min list ((year-id - init-year) * CPGscenario + CPGscenario) 100
;      set numCPGs  round (new%CPGs * max-number-landparcels / 100)  
;      update-CPGs                         ;; new number of CPGs including existing ones
;      update-accessible-parcels 
;    ] 
;    
;    ; Scenario B explored the policy measure to increase the 'list price' that transporters are obliged to pay CPGs for collecting their licensed charcoal product.
;    if ScenarioB and year-id != init-year
;    [
;      let increase-list ScenarioBAmount let increase-export ScenarioBAmount ;; ScenarioBAmount = 100 
;      set list-price list-price + increase-list
;      set export-price-permit export-price-permit + increase-export
;      if wordy [ show ( word "list price is " list-price ", export-price-permit is " export-price-permit) ]
;    ]
    
    ;; intensification strategy is used in all scenario experiments and can happen in warm up years
    if year-id != init-year and intensify?
    [
      ask producers with [permit = false and CPG = nobody ]  ;; producers that are not members of CPG may intensify
      [
        producer-intensification
      ]
    ]
    
    ;; update environment not needed - simply compare take with growback (mai) for all hotspot patches
    ;update-environment                        ;; update land cover (forest growback) - growth as a function of standing stock
    ask hotspot-patches [
      set deficit mai - take
      set take 0           ;; reset take
    ]
    ask landparcels with [practice = "CPG"]
    [
      ;let lpbiomass sum [quantity] of lpatches  ;; quantity is initialised as a random float
      ;set quota aac * lpbiomass
      set annual-profit []
      set annual-collected []
      set annual-production []
    ]
 
    ask producers
    [    
      set annual-profit [] 
      set annual-collected [] 
      set annual-production []
      ;; loans are reset to 0 after loanWlength years
      if loanW + loanWlength = year-id 
      [ 
        ;print (word " loan taken in " loanW " is ending")  
        set loanW 0 
      ]   
    ]
     
    ask transporters
    [  set annual-profit []
    ] 
    
    ask levys
    [  set annual-profit []
    ]
    ;; reset globals
    set annual-marketsizes [ 0 0 0 0]
    set annualExport 0             ;; overall figures for export sales and sales in 4 towns
    set annualSales 0
    set fiscal 0                   ;; annual fiscal income from cess taxes
    set numberUnhappy []
    set annual-movement-permits list 0 0
end 

to month-start-events
    let wordy false
    ;; reset-month  ;; reset-month has to come after reset-year because of calculating the NTFP collection
    ask collections [die]
     
    ;; decide where to collect at random
    ;; TODO decide based on indicators/criteria
    ask producers [
      
      ;let pchoice one-of (turtle-set parcels CPG)
      let pchoice ifelse-value (CPG = nobody)[one-of parcels] [CPG]  ;; updated this so that producer always chooses the CPG if available
      create-collection-with pchoice
      ifelse [practice] of pchoice = "CPG" [set strategy "in"] [set strategy "out"]
    ]
    ask collections [set color brown]
    
    
    ask transporters [
      
      transporters-evaluate-market         ;; new selection method based on RL / imitation
      transporters-select-market           ;; second part
   
      ;; transporter variables updated every trading cycle
      set unvisited sort nearest-producers ;; a list
      set permit false                     ;; ie. transporter does not have a permit for this trading cycle (permit-type is invariable)
      set permit-type 0                    ;; NEW permit-type is also nullified rather than invariable
      set bulk-supplier  nobody
      set bought 0                         ;; period amount collected from producers
      set sales 0
      set trade? false
      ;transporters-update-tradeprice
      set levycosts 0      
      set cesscosts 0                
      set returns-income 0
    ]
    
    ask buyers [
      ;set bought 0
    ]
    
    ;; producers do their wood collecting and charcoal production
    ask producers 
    [
      set collected [0 0]   ;; ?? I think this reset was skipped but is needed
      set production 0
      set sales 0
      set accepted-price 0
      ;; individual producers call charcoal-production procedure
      if strategy = "out"  [  charcoal-production]
    ]
    
    ;;  landparcels call charcoal-production-CPG procedure
    ask landparcels with [practice = "CPG"]
    [
      set collected [0 0]   ;; ?? I think this reset was skipped but is needed
      set production 0
      set sales 0
      set accepted-price 0
      CPG-production            
    ]
    
    ask levys
    [
      set taxed []  ;; list of transporters taxed this trading cycle
      set revenue 0 ;; current trading cycle 
    ]
    
    if wordy [
      let numavail length filter [ [stock] of ? = 0 ] sort transporters
      show (word "There are " numavail " bulk traders  with empty lorry")
    ]
    
    ;; if CPG has more than 100 bags, contact listed transporter 
    ;; if transporter has stock or is already comitted to a bulk call it is not available
    ask landparcels with [practice = "CPG" and stock > bulk-stock-amount]
    [
      bulk-traders-call-transporters
    ]
    ;; assumption that producers with large amount of stock can also telephone transporters (not on list ?) 
    ask producers with [stock > bulk-stock-amount]
    [
      bulk-traders-call-transporters 
    ]
    
    set export-sales 0
  
    
    ;; task list activities are set on monthly step. 
    ;; calculate the main activity based on the farming/gardening strategy, and calculate the secondary activity based on availability in agent context 
    
    ;; ask people [set-main-activity]     ;; sets the activity  - deprecated
    
    ;;ask farmers [set-farming-activity [farming-strategy] of hh]          ;; sets the activity 
    ;; ask gardeners [set-gardening-activity [gardening-strategy] of hh]  ;; sets the activity

    ;; The secondary-activity list is based on agent context (farm size and labour available)

    
    ;; TODO - Monthly, update agent strategy (from knets rules) for targetted NTFPs.   ;; differently for poor/rich and men/women
    ;; if availability is poor they may change to one similarly classified  (amount yielded per unit effort?)
    ;; let availabletypes filter [any? turtles with [breed = ?]] NTFPtypes
    ;; print (word "available NTFPs are: " availabletypes)
    ;; set strategy one-of availabletypes
    ;; after gardening, collecting, farming land productivity may go down
end 

to go
  let wordy false
  let updatedisplay false 
  if make-video [
    export-view (word "pngs/" "frame" but-first (word (100000 + round ticks)) ".png")
  ]
  ;; use this kind of command in terminal from the png folder
  ;; ~/netlogo models/Charcoal/pngs$ ffmpeg -r 10 -b 1800 -i frame%05d.png kitui-0-2.mp4
  ;; ffmpeg -framerate 4 -i frame%05d.png -r 10 kitui-0-2b.mp4
  
  ;; reset-tick     ;; currently empty
  ;; the period increases 1 with each tick and is reset to 0 at end of month
  ifelse (the-period = ticks-per-month)
  [ set the-period 1 set-month ]                   ;; new month has started; ;; set the month (string and id) 
  [ set the-period the-period + 1]
  
;  if the-period = 1
;  [ reset-month     ;; reset-month has to come before reset-year because of calculating the NTFP collection (month-col is added to ann-col)
;  ]

  ;; simulation events at start of annual step
  if month-id = 0 and the-period = 1
  [  year-start-events   
  ]
 
  ;; events at the beginning of the month
  if the-period = 1
  [  
    month-start-events         ;; colleccting and  producing 
    if updatedisplay [update-display-properties]   ;; change look of buyers & transporters -  after (market day and) CPG calling 
    
    ;; initialise aspirations after few trading periods
    if year-id = init-year and month-id = transporters-memorysize
    [
      ;; calculate a historical max payoff used in updating propensities 
      ;set max-rval max  [max rhistory] of farmers
      ;set min-rval min  [min rhistory] of farmers
      ask transporters
      [
        set aspiration mean history
        
      ]
    ]
  ] 

  ask transporters with [ status = "leaving market"]
  [
    ;; if near to favourite change status from leaving market to visiting producers
    ;ifelse    member? favourite (turtles in-radius tick-range) ; visit-range
    ifelse distance homepatch < tick-range ; visit-range
    [
      set status "visiting" 
      ask my-trades [die]
    ]
    [
      forward tick-range ;; hope heading in the right direction (towards favourite)
    ]
  ]
   
   ;; check does it do this in first tick of month 
   
  ;; transporters visit producers nearby, or they visit CPGs, and they export (if they reach capacity)
  ;; if they run out of time, they will then head for nearest local market
  ;ask transporters with [ status = "visitingBulk" or status = "visiting" or status = "heading for market"] ;; ie not exporting
  ask transporters with [ status = "visitingBulk" or status = "visiting" or status = "heading for market" or status = "exporting"] ;; exporters also move
  [
    transporters-actions  ;; buying, selling, and NEW levy agent action is included within transporter actions
  ]
 

  ;; period end events
  if the-period = ticks-per-month [
    
    ask buyers
    [
      buyers-visit-markets      ;; assuming buyers visit markets at the end of each 'month'
    ]  
    if updatedisplay [update-display-properties]   ;; change look of buyers & transporters - when - at the beginning of the month or just after market day and CPG calling 
    
    set numberUnhappy fput unhappy numberUnhappy   ;; add data for current trading period
    
    set annual-movement-permits replace-item 0  annual-movement-permits ( item 0  annual-movement-permits + count transporters with [permit-type = "RC"])
    set annual-movement-permits replace-item 1  annual-movement-permits ( item 1  annual-movement-permits + count transporters with [permit-type = "SC"])
    ;; show annual-movement-permits
    
    ;; if the transporter is now at the market, the transporter should prepare to travel back to the favourite producer
    ask transporters 
    [ 
      set status "leaving market"
      if patch-here != homepatch
      [
        set heading towards homepatch
      ]
      ;; period accounting  - update annual returns for the current period
      ;; -- returns-income accounted for other transporter-costs (like petrol and daylabour per bag, added at POS) 
      ;; -- tcosts are trading costs to obtain wood (purchases) and informal levy costs
      
      let balance returns-income - tcosts  - levycosts   - cesscosts
      set annual-profit fput balance annual-profit
      ;set returns-income 0 ;; reset at start of month
      set tcosts 0
      ;set levycosts 0 ;; reset at start of month
    ]
     
    ;; calculate returns for producers in the CPG
    ask landparcels with [practice = "CPG" and count members > 0]
    [
      ;; assuming producters are limited to one CPG - they shold be prohibited because double benefit 
      let share floor ((returns-income - tcosts) / count members)
      ;if wordy [show (word "share for CPG produers is " share)]
      set annual-profit fput share annual-profit
      if sales > 0 ; reset variables
      [
        if wordy [show (word "share for CPG producers in landparcel-" who " is " share)]
        ask members [
          set returns-income returns-income + share
        ]
        set returns-income 0
        set tcosts 0
      ]
      ;; update annual collection and production
      set annual-collected fput sum collected annual-collected
      set annual-production fput production annual-production
    ]
    
    ;; finish for producers - CPG income may be added to individual balance
    ask producers
    [ 
      ;; here trades costs are assumed to be zero - TODO consider other operational costs
      let balance returns-income - tcosts  
      set annual-profit fput balance annual-profit
      set returns-income 0
      set tcosts 0
      if wordy and balance > 0 [show (word "balance for independent producer-" who " is " balance)]
      ;; update annual collection and production
      set annual-collected fput sum collected annual-collected
      set annual-production fput production annual-production
      
      ;; classifier learning for rejected offers, the ? index is the ppi
      foreach rejected [
        let newval (1 - lr-producers) * (item ? trade-price-strengths-reject) + (lr-producers * lastpayoff )
        ;show newval
        set trade-price-strengths-reject replace-item ? trade-price-strengths-reject newval
        
      ]
      set rejected []
      set lastpayoff reject-value  ;; 0
      ;set lastpayoff CS-intial-values
      
    ]
    
    ask levys
    [
      set annual-profit fput revenue annual-profit    ;; many levys tax more than 20 transporters
      ;print taxed  ;; gets reset at start of month
    ]

    ;; update the annual overall figures for export sales and sales in 4 towns  
    set annualExport annualExport + export-sales              
    set annualSales annualSales + sum [bought] of buyers
    ;;show list annualExport annualSales
    
    ;; update the annual account for each market channel (formal, informal, RC, SC)
    update-marketchannel-data
    
    ;; update the annual overall figures for cess costs
    set fiscal fiscal + (sum [cesscosts] of transporters)
    ;show fiscal
  ]
  
  ;; done every tick ??
  ask trades [set color black]
  
  ifelse show-labels
  [
    ask transporters [set label stock]
  ]
  [
    ask transporters [set label ""]
  ]

  ;; End of year events
  if the-period = ticks-per-month and month-id = (months-per-year - 1)
  [
    ;; calculate utilisation scores
    set overUtil length filter [? > 1] sentence utilisationCPG  utilisationPrivate             
    set meanUtil mean sentence utilisationCPG  utilisationPrivate
    ;show list overUtil meanUtil
    ;; reset take
    ask hotspot-patches [ set take 0]
    
    set annual-collected-all sum [sum annual-collected] of (turtle-set producers landparcels with [practice = "CPG"])
    
    ;; used in reporter - number of bags accounted for in each market channel (formal, informal, RC, SC)

    calculateAnnualProfitShare
   
    
    ;show (word "annual profit share is :    " annual-profit-share);
    ;show (word "individual producers collected:   : " sum [sum annual-collected] of (turtle-set producers with [strategy != "in"]))
    ;show (word "individual producers avg.Intensity: " precision (mean [intensification] of producers with [strategy != "in"]) 2) ;; with [permit = false]) 2
    ;show (word "CPG producers collected           : " sum [sum annual-collected] of (turtle-set landparcels with [practice = "CPG"]))
    ;show (word "CPG producers avg.Intensity       : " precision (mean [intensification] of producers with [strategy = "in"]) 2) ;; with [permit = false]) 2
    ;show (word "PAP CPG producers: " mean [sum annual-profit] of producers with [CPG != nobody])
    ;show (word "PAP non-CPG producers: " mean [sum annual-profit] of producers with [CPG = nobody])
  ]
  
  ;update-spinner                         ;; report the climate regime, track the climate and the current month
  tick  ; move tick and update plots (after end of year events)
end 

;; no update of stock, only update of take

to charcoal-production
  
  ;let avail-patches patch-set filter [[mai] of ? > [take] of ? ] sort lpatches 
  ;let chosenneighbor one-of one-of collection-neighbors
  let chosenpatch no-turtles
  let col one-of collection-neighbors 
  
  ifelse [quota] of col   
  [
    ;; if the chosen land parcel has a quota then consider amount already taken and take-constraint patch-wise
    let avail-patches patch-set filter [[mai] of ? > [take] of ? ] sort [lpatches] of col 
    if any? avail-patches
    [
      set chosenpatch one-of avail-patches
    ]
  ]
  [
    ;; if the land parcel has no quota, choose the patch at random
    set chosenpatch one-of [lpatches] of col   
  ]
 
  if is-patch? chosenpatch 
  [
  
    let pos-quality position [quality] of chosenpatch treequalities ;; find correct position in list of tree qualities
                                                                    ;let amt-collected min list max-collected [stk] of chosenpatch
                                                                    ;let amt-collected min list max-collected [mai] of chosenpatch  ;;
    let multiplier precision (intensification / 100) 1   ;; avoid many d.p. s
  

  
    let amt-collected precision (multiplier * max-collected) 0      ;; amount to collect equals the default value or in scenarios depends on intensification
    set collected replace-item pos-quality collected amt-collected
    ;ask chosenpatch [set quantity quantity - amt-collected]
    ask chosenpatch [set take take + amt-collected]                 ;;  update take 
                                                                    ;; efficiency of kiln
                                                                    ;; set production floor (kiln-eff-standard * amt-collected * [quality] of chosenpatch)
  
    set production precision (((kiln-efficiency / 100 ) * amt-collected * [quality] of chosenpatch) / bag-weight) 1
    set stock precision (stock + production) 1  ;; increase in stock of producer
   
  ]
   ;show production
end 

;; report and plot utilisation of biomass 
;; -- compute overall rate for each landparcel ( if > 1 the landparcel is overexploited , if less than 1 it is underexlpointed)
;; -- one list for CPG parcels and one for private landparcels
;; run this at end of each year,  when annual take has been computed -  corresponding to biomass growth cycle (mai)

to-report utilisationCPG
  ;report 0 
  ;; otherwise compare the overall take for the landparcel with the sum allowed 
  report [(sum [take] of lpatches) / (sum [mai] of lpatches) ] of landparcels with [practice = "CPG"]
end 

to-report utilisationPrivate

  report [(sum [take] of lpatches) / (sum [mai] of lpatches) ] of landparcels with [practice = "private"] 
  ;report list utilisationCPG utilisationPr
  ;let overall-take sum [take] of lpatches
  ;let overall-mai sum [mai] of lpatches
  ;show (word "landparcel " who " overall avail: " overall-mai ", overall take: " overall-take)
end 

to-report unhappyAnnual
  report precision (mean numberUnhappy) 2
end 

;to debug-report-utilisation
; foreach sort landparcels with [practice = "private"]
; [
;   if any? ([lpatches] of ?) with [mai = 0] [show (word ? "has 0patch")]
; ]
;
;end

to-report averageIntensity
  report precision (mean [intensification] of producers) 2 ;; with [permit = false]) 2
end 

;; only run by non CPG producers

to producer-intensification
  if  sum annual-profit < aspiredProducerProfit
  [
    set intensification intensification + intensificationStep   ;; eg intensify (increase take) by 50 percent
  ]
  if  sum annual-profit > exceededProducerProfit and intensification > 100
  [
    set intensification intensification - intensificationStep   ;; eg decrease take) by 50 percent, but not to below 100
  ]
end 

;; producers collaborate with common stockpile. Constraint on take
;; no update of stock, only update of take

to CPG-production
  let wordy false
  ;; If the CPG is obliged to comply with a quota, constrain the patches available
  ;; - consider amount already taken and take-constraint patch-wise
  let avail-patches ifelse-value quota [patch-set filter [[mai] of ? > [take] of ? ] sort lpatches] [patch-set sort lpatches] 
  
  if any? avail-patches
  ;if any? lpatches with [ stk > labour * max-collected]
  [
    let labour count members with [strategy = "in"]
    let chosenpatch one-of avail-patches

    ;let chosenpatch one-of lpatches with [ quantity > 0.1] ;; TODO or the amount demanded
    ;let chosenpatch one-of lpatches with [ stk > labour * max-collected] 
    
    let pos-quality position [quality] of chosenpatch treequalities 
  
    ;; calculate collected by multiplying by the number of members
    ;; max extraction is adapted to the take-constraint ;; NEW abandoned this constraint - quota boolean is used above in identifying avail-patches
    
    ;let amt-collected min list (max-collected * labour) [mai - take] of chosenpatch
    let amt-collected ifelse-value quota [min list (max-collected * labour) [mai - take] of chosenpatch] [(max-collected * labour)]    
    
    ;; same code as for producers
    set collected replace-item pos-quality collected  amt-collected
  
    ;ask chosenpatch [set stk stk - amt-collected]
    ask chosenpatch [set take take + amt-collected]
    
    ;set production (kiln-eff-improved * amt-collected * [quality] of chosenpatch) / bag-weight
    ;; changed all CPG kilns to standard efficiency initially
    set production precision (((kiln-efficiency / 100)  * amt-collected * [quality] of chosenpatch) / bag-weight) 1
      
    set stock precision (stock + production) 1 ;; increase in stock
    if wordy [print (word "Landparcel-" who " total collected is " amt-collected " and production is " production)]
  ]
end 



;; telephone calls for collection of bulk stocks
;; both CPGs and producers operate in a similar way
;; due to the size constraint, they always supply the external market
;; replace separate methods and use an if switch on the breed

to bulk-traders-call-transporters
  let wordy false
  ;if wordy [show (word breed who " now calling")]
  let sbnlt []  ;; nearest licenced transporters
  let cnt 0
  let currtr nobody  
  let exit false
  
  ifelse [breed] of self = producers
  [  
    set sbnlt sort-on [distance myself] turtle-set transporters     ;; sortby ALL transporters - not only listed
  ]
  [  
    set sbnlt sort-on [distance myself] turtle-set transporter-list ;; sortby nearest licenced transporter
  ]
  
  
  while [exit = false and cnt < length sbnlt]
  [
    set currtr item cnt sbnlt
    set cnt cnt + 1
    
    ;; For bulk stock from producers, transporter has to have capactity available
    ;; TODO transporters may combine bulk visits or visit > 1 trips per month ? (can stack them/fix them in month start events?)
    if ([status] of currtr  != "visitingBulk") and ([stock] of currtr = 0 )  ;;condition transporter is available
    [
      set exit true
      ;; An additional condition for CPGs - assumes that licenced transporter may not mix licensed and non-licensed stock
      if [breed] of self = landparcels and [stock] of currtr > 0 [set exit false]   
    ]  
  ]
   
  if exit = true
  [
    ask currtr [
      set status "visitingBulk"  
      if patch-here != [patch-here] of myself [set heading towards myself]
      set bulk-supplier myself
      ask my-trades [die]
      ;; if the current trader is a landparcel where certified charcoal is produced (ie the landparcel has permit) then the current transporter gets a permit 
      ;; but not if the trader is an individual producer 
      if [breed] of myself = landparcels ;; and [permit] of myself   ;; I think all CPGS now have permits
      [
        set permit true
        set permit-type [permit-type] of myself                      ;; set the permit type to be the same
        if wordy [show (word self " gets a " permit-type " permit for trading with " myself)]
      ] 
     
    ]
    ;if wordy [show (word [breed] of currtr ([who] of currtr) " is heading for bulk supplier at " breed who)] 
  ]
end 



;; proc run by producers, in month-start-events
;; Contact transporters starting with the nearest - likely will currently be at the nearest market
;; set status and set new heading

;to producers-call-transporters   ;; if producer has more than 100 bags, contact listed transporter - ask it to set status
; let wordy false 
; if wordy [show (word breed who " now calling")]
; let pstock stock
; let sbnlt sort-on [distance myself] turtle-set transporters ;; sortby ALL transporters - not only listed
;
; let cnt 0
; let exit false
; while [exit = false and cnt < length sbnlt]
; [
;   let currtr item cnt sbnlt
;   set cnt cnt + 1
;   ;ask currtr [show status]
;   ;ask currtr [show stock]
;   ;show [who] of currtr
; 
;   ;; Assume transporter won't be able to mix licensed and non-licensed stock, therefore has to have empty truck !
;   ;; Also assumes no combining from 2 groups! (ie transporter cannot accept to visit more than CPG per month
;   ;;  TODO transporters may visit > 1 CPG/month ?
;   
;   ;; stock must be > 100 to be worth transporter coming
;   if ([status] of currtr  != "visitingCPG") and ([status] of currtr  != "visiting") and ([stock] of currtr = 0 )  ;;condition transporter is available
;   [
;     set exit true
;     
;     ask currtr [                 ;; set transporter variables 
;       set status "visiting"      ;; same status or "visiting1" ?
;       set heading towards myself
;       ;set permit myself
;       set bulk-supplier myself  
;       ask my-trades [die]
;     ]     
;     if wordy [show (word [breed] of currtr ([who] of currtr) " is heading for producer at " breed who)]   
;   ]  
; ] 
;end



;; done once at end of month

to buyers-visit-markets
  let wordy false
  let xm [xcor] of nearest-market
  let ym [ycor] of nearest-market
  let mydemand demand
  let avail-vendors transporters with [distancexy  xm ym <= 5  and stock >= mydemand]
  
  ifelse count avail-vendors > 0
  [
    let choice one-of avail-vendors
    create-trade-with choice
    let amt mydemand
    set bought mydemand
    ask choice                  ;; update variables of vendor (transporter)
    [
      set stock precision (stock - amt)  1
      
      set sales sales + amt
      set returns-income returns-income + amt * (retail-price - transporter-costs)
    ]
    if wordy [print (word "Buyer-" who " traded with Transporter-" [who] of choice " for " mydemand " bags at retail price " retail-price )]
  ]
  [
     set bought 0
  ] 
end 


;; done every tick - includes paying informal levys

to transporters-actions
 
  let wordy false ; true
  
  ;; select export market if nearly full lorry or if having traded with bulk supplier
  ;; TODO this can only be done at start of trading-cycle to allow time to travel to nairobi ?
;  ifelse (stock >= bulk-stock-amount )  ;; bulk-supplier either landparcel CPG or producer 
;  [
;    set sales stock                                           ;; update variables of vendor
;    ifelse permit = true
;    [ set returns-income returns-income + sales * (export-price-permit - transporter-costs) ]  ;; other transporter costs per bag, petrol, labour etc added at POS
;    [ set returns-income returns-income + sales * (export-price - transporter-costs )]
;    set status "exporting"
;    set stock 0                                               ;; reset variables
;    ;set permit false                                          ;; reset these variables immediately ?
;    ;set bulk-supplier nobody
;    set export-sales export-sales + sales                     ;; update global variable
;    
;    ;; TODO when do they get back - place them at the favourite producer in tick 1
;    ;; -- are they still visitingCPGs ? they don't move the rest of the time
;  ]
;  [ ;; otherwise if stock is zero visit CPG to collect charcoal
    
    ;ifelse  status = "visitingBulk"
    if status = "visitingBulk" 
    [
      ;; TODO allow to visit more than one CPG if less than capacity   ;; < 0.9 * capacity
      transporters-visit-bulk-suppliers
    ]
    if status = "visiting"
    [ 
      ;; otherwise visit producers or goto local market
      ;let time-left floor (min [distance myself] of markets / tick-range)
      let time-left floor ([distance myself] of mchoice / tick-range)
      ;show time-left ;compute how far away and how long left to arrive at market 

      ifelse the-period + time-left + 1 <  ticks-per-month     ;; eg 12
      [
        ;; check if transporter now has enough stock (and time) to export 
        ;; ifelse (stock >= bulk-stock-amount )  ;; bulk-supplier either landparcel CPG or producer 
        ;; ifelse year-id > init-year and month-id = 0
       
        ;; Updated decision rule to determine trading or export 
        ;; - -export is done under condition stock exceeds bulk level OR stock is order of magnitude higher than aspiration
        ;; (ie if the agent thinks market sales will be significantly lower than export sales), otherwise do trading
     
        ifelse (stock >= order-mag * aspiration and stock >= 10) or (stock >= bulk-stock-amount)  ;; NEW stock is more than one unit magnitude greater than expected trade 
        [
          set sales stock                                      ;; similar code to transporters-visit-bulk-suppliers
          set returns-income returns-income + sales * (export-price - transporter-costs )
          ;if wordy [print (word "Transporter-" who " (visiting) exported " sales " bags at export price " export-price)]
          set status "exporting"
          set exportchoice one-of export-locations                  ;; new - choose one of two locations at random
          set trade? false
          set stock 0                                          ;; reset variables
          set export-sales export-sales + sales                ;; update global variable

        ]
        [
          transporters-visit-producers                          ;; otherwise carry on visiting
        ]
    
      ]
      [ ;; else there is no time left - head to market
        set status "heading for market"
        set trade? true
        ;; -- assuming nearest market is preferred market
        ;let current-market min-one-of markets [distance myself]  ;; nearest one
        ;let current-market select-market  ;; New - selected one
        ;if patch-here != [patch-here] of current-market [set heading towards current-market]
        if patch-here != [patch-here] of mchoice [set heading towards mchoice]
        ;jump min list tick-range [distance myself] of current-market - 2
      ]  
    ]
    if status = "heading for market"
    [
      
      
      jump min list tick-range [distance myself] of mchoice - 2
      
      ;let numnearlevys count levys in-radius (tick-range / 2) 
      let demandinglevys levys in-radius (tick-range / 2) with [not member? myself taxed]
      let tick-costs 0
      ask demandinglevys
      [
        let amount ifelse-value (levytype = "greedy") [2000] [1000]         
        set revenue revenue + amount
        set taxed fput myself taxed
        set tick-costs tick-costs + amount
        ;if wordy [print (word "levy-" who " (" levytype ") demanded " amount)]
      ]
      set levycosts levycosts + tick-costs   ;; add all costs for this tick
   
    ]
    
    ;; TODO if I am at the export location, stop moving
    if status = "exporting"
    [
      
      if patch-here != exportchoice [set heading towards exportchoice]
      jump min list tick-range [distance myself] of exportchoice - 2 
      
      let demandinglevys levys in-radius (tick-range / 2) with [not member? myself taxed]
      let tick-costs 0
      ifelse permit 
      [
        ask demandinglevys  ;;  added check if transporter already paid  this levy agent
        [
          let amount ifelse-value (levytype = "greedy") [2000] [0]   ;; if I have a permit AND they are greedy they will collect 2000 levy     
          set revenue revenue + amount                               ;; if I have a permit AND they are NOT greedy they will collect no levy   
          set taxed fput myself taxed
          set tick-costs tick-costs + amount
          ;ask myself [set levycosts levycosts + amount]
          ;if wordy [print (word "levy-" who " (" levytype ") demanded " amount)]
        ]
        set levycosts levycosts + tick-costs   ;; add all costs for this tick
      ]
      [
        ask demandinglevys  ;;  added check if transporter already paid  this levy agent
        [
          let amount ifelse-value (levytype = "greedy") [2000] [1000]  ;; if I have NO permit AND they are greedy they will collect 2000 levy          
          set revenue revenue + amount                                 ;; if I have NO permit AND they are NOT greedy they will collect 1000 levy
          set taxed fput myself taxed
          set tick-costs tick-costs + amount
          ;ask myself [set levycosts levycosts + amount]
          ;if wordy [print (word "levy-" who " (" levytype ") demanded " amount)]
        ]
        set levycosts levycosts + tick-costs   ;; add all costs for this tick
      ]
      
;      if any? levys in-radius (tick-range / 2) 
;      [  
;        ;; if I have a permit AND they are greedy they will collect the levy
;        ;; if I don't have a permit they will collect the levy   -- either type of permit
;         
;        ifelse permit 
;        [
;          ask levys in-radius (tick-range / 2) with [not member? myself taxed]  ;;  added check if transporter already paid  this levy agent
;          [
;            let amount ifelse-value (levytype = "greedy") [2000] [0]   ;; if I have a permit AND they are greedy they will collect 2000 levy     
;            set revenue revenue + amount                               ;; if I have a permit AND they are NOT greedy they will collect no levy   
;            set taxed fput myself taxed
;            ask myself [set levycosts levycosts + amount]
;            if wordy [print (word "levy-" who " (" levytype ") demanded " amount)]
;          ]
;        ]
;        [
;          ask levys in-radius (tick-range / 2) with [not member? myself taxed]  ;;  added check if transporter already paid  this levy agent
;          [
;            let amount ifelse-value (levytype = "greedy") [2000] [1000]  ;; if I have NO permit AND they are greedy they will collect 2000 levy          
;            set revenue revenue + amount                                 ;; if I have NO permit AND they are NOT greedy they will collect 1000 levy
;            set taxed fput myself taxed
;            ask myself [set levycosts levycosts + amount]
;            if wordy [print (word "levy-" who " (" levytype ") demanded " amount)]
;          ]
;        ]
;      ]
      
    ]
end 

;; this procedure is run by transporters every tick. It should only be run while visiting-CPGs is set.

to transporters-visit-bulk-suppliers
  let wordy false ; true
 
  ifelse [distance myself] of bulk-supplier < tick-range ;; check if at the place the permit is for
  [
    ;; move nextdoor and make trade                      ;; transaction occurs TODO price conditions?
    jump ([distance myself] of bulk-supplier - 2)        ;; go 2 away from the trader and trade
    
    let seller-bags floor [stock] of bulk-supplier
    let amt min list seller-bags capacity - stock        ;; included constraint on transporters capacity
    let tpr 0
    
    ;; Either use the regular price or the list price depending on the permit type. If no permit then use the trade price point
    ifelse permit                                        ;; transporter permit is already set when the CPG telephones 
    [
      set tpr ifelse-value (permit-type = "SC") [list-price] [reg-price]       ;; set the price according to the permit type and policy
    ] 
    [
      set tpr item price-point-index trade-price-points  ;; updated this to the same as for small sales (transporters price) TODO it could be a bit higher
    ]  
                                                             
     
    set stock precision (stock + amt) 1                                ;; take all of stock and update transporter variables 
    set bought bought + amt
    set tcosts tcosts + amt * tpr                        ;; update costs
    
    create-trade-with bulk-supplier

    ask bulk-supplier  ;; update land parcel/CPG
    [
      set sales sales + amt 
      ; set returns-income returns-income + amt * tpr     
      set returns-income returns-income + amt * (tpr - producer-costs)  ;; other producer costs per bag, access, labour added at POS
      set accepted-price tpr  ;; for monitoring aggregate price
      set stock precision (stock - amt) 1   ;; producer can not sell stock to another trader!
    ] 
    if wordy [print (word self " traded with " bulk-supplier " for " amt " bags at price " tpr ifelse-value permit [(word " with permit "  permit-type)][" without permit"])]
     
    set status "exporting"                                    ;; immediately do the exporting and accounting
    set trade? false                                          ;; it is an export
    set exportchoice one-of export-locations
    set sales stock 
    
    if permit [set cesscosts sales * cess] ;; if the transporter has a permit then agent must pay the cess of 100 per bag                                 
    ;; cesscosts are deducted at the same time as levycosts - period end events in go proc
    
    ;ifelse permit = true                  ;; assuming export-price is 1600 and export-price-permit is 1800 or 2000
    ifelse permit-type = "SC"              ;; the special price now only available for certified SC
    [ set returns-income returns-income + sales * (export-price-permit - transporter-costs) ]  ;; other transporter costs per bag, petrol, labour etc added at POS
    [ set returns-income returns-income + sales * (export-price - transporter-costs )]         ;; - but does not include levys (accounted for at end of period)
    
    if wordy [print (word self " exported " amt " bags at price " tpr )]   ;; testing
    ;; if wordy [print (word self " exported " amt " bags at price " ifelse-value permit [(word export-price-permit " with permit")][(word export-price " without permit")])]

 
    set stock 0                                               ;; reset variables
    set export-sales export-sales + sales                     ;; update global variable
    ;; TODO when do they get back - place them at the favourite producer in tick 1
    ;; -- are they still visitingCPGs ? they don't move the rest of the time    
  ]
  [ ;; else
    if patch-here != [patch-here] of bulk-supplier
    [ set heading towards bulk-supplier
      jump tick-range
    ]
  ] 
end 

to transporters-visit-producers
  let wordy false ; true
  
  ;let nearest-traders producers in-radius visit-range      ;; nearest  producers
  ;set nearest-traders turtle-set filter [not member? ? visited] sort nearest-traders ;; less those already visited
  let distance-sorted-traders sort-on [distance myself] turtle-set unvisited  ;; speed up execution  using unvisited list which is set to nearest-producers an agent variable          

  ifelse length distance-sorted-traders > 0                 ;; nearest-traders
  [
    let nearest first distance-sorted-traders
    set unvisited remove nearest unvisited 
  
    if patch-here != [patch-here] of nearest [set heading towards nearest]
    ifelse  ([distance myself] of nearest < tick-range)     ;; eg. 25 check if transaction occurs
    [
      jump ([distance myself] of nearest - 2)               ;; go 2 away from the trader and trade
      
      let seller-bags floor [stock] of nearest
      ;let seller-remainder [stock] of nearest - seller-bags
      let amt min list seller-bags capacity - stock  ;; include constraint on transporters capacity 
      
      ;; new bit
      let ppi  price-point-index
      if amt >= 1 
      [
        let tpr item price-point-index trade-price-points  ;; get price from the price point list
        ;; use the index with roulette wheel to decide accept or reject
        let space-reject item price-point-index [trade-price-strengths-reject] of nearest
        let space-accept item price-point-index [trade-price-strengths-accept] of nearest
        
        ifelse random-float (space-reject + space-accept) < space-reject
        [
          ;; reject
          ask nearest [  set rejected fput ppi rejected]
        ] 
        [
          ;; accept
          set stock precision ( stock + amt    ) 1                            ;; take all of stock and update transporter variables
          set bought bought + amt
          set tcosts tcosts + amt * tpr  ;; trade costs
         
          ask nearest                ;; update producer
          [
            set sales sales + amt 
            set accepted-price tpr ;; for monitoring aggregate price
            ;set returns-income returns-income + amt * tpr
            
            set returns-income returns-income + amt * (tpr - producer-costs)  ;; other producer costs per bag, access, labour added at POS
            set stock precision (stock - amt  ) 1   ;; producer can not sell stock to another trader!
            
            ; update with feedback payoff is amt * (tpr - producer-costs)
            set lastpayoff amt * (tpr - producer-costs)
            ;show (word "amount is " amt)
            ;show (word " " (1 - lr-producers) " " (item ppi trade-price-strengths-accept) " " (lr-producers * lastpayoff ))
            let newval (1 - lr-producers) * (item ppi trade-price-strengths-accept) + (lr-producers * lastpayoff )
            ;show newval
            set trade-price-strengths-accept replace-item ppi trade-price-strengths-accept newval
          ]
          ;if wordy [print (word self " traded with " nearest " for " amt " bags.")]
        
        ]                                        ;; transaction occurs TODO price condition
      ]
    ] ;end of trading bit
    [ ;else (not in trading distance)
      jump tick-range 
    ]  
  ] ; end of the if part
  [ ; else part (when there are no nearest traders, go further away)
    let not-visited turtle-set filter [not member? ? nearest-producers] sort producers  ;; when selecting nearest, don't revisit
    ;;let nearest min-one-of (turtle-set producers buyers) [distance myself]  ;; nearest one
    let nearest min-one-of not-visited [distance myself]  ;; nearest one
    if patch-here != [patch-here] of nearest [set heading towards nearest]
    jump tick-range 
    ;if wordy [print (word self " went further away.")]
  ]
end 


;  let wordy false ; true
;  ;; make list of nearest traders
; 
;  ;let nearest-traders (turtle-set producers in-radius visit-range buyers in-radius visit-range)
;  let nearest-traders producers in-radius visit-range ;; just producers
;  
;  set nearest-traders turtle-set filter [not member? ? visited] sort nearest-traders ;; less those already visited
;  let distance-sorted-traders sort-on [distance myself] nearest-traders              ;; just producers
;  let nearest first distance-sorted-traders
;  
;  ifelse length distance-sorted-traders > 0 ;; nearest-traders
;  [
;    ;let current-trader one-of nearest-traders  ;; may have preferences for buyer/producer or specific one
;    let current-trader nearest  ;; have preferences for nearby one
;    ;ifelse [breed] of current-trader = buyers [ trade-transporter-buyer] [trade-transporter-producer]
;    ;; make list of those traders already visited this month
;    set visited (turtle-set visited current-trader)
;    if patch-here != [patch-here] of current-trader [set heading towards current-trader]
;    
;    
;    ifelse  ([distance myself] of current-trader < tick-range) ;; eg. 25 check if transaction occurs
;    [
;      jump ([distance myself] of current-trader - 2)               ;; go 2 away from the trader and trade
;      ;let amt [stock] of current-trader                           ;; take all of stock of producer, not just current production 
;      let amt min list [stock] of current-trader capacity - stock  ;; include constraint on transporters capacity
;      let tpr trade-price                                          ;; price of transporter 
;    
;                                                                   ;; transaction occurs TODO price conditions?
;      if amt > 0 and tpr >= [target-price] of current-trader
;      [
;      ;; take all of stock and update transporter variables
;        set stock stock + amt ;; 
;        set bought bought + amt
;        set tcosts tcosts + amt * tpr
;        create-trade-with current-trader
;      
;        ask current-trader  ;; update producer
;        [
;          set sales sales + amt 
;          set returns-income returns-income + sales * tpr
;          ;; set production 0  ;; producer can not sell production to another trader
;          set stock stock - amt  ;; producer can not sell stock to another trader!
;        ]
;      
;        if wordy [print (word self " traded with " current-trader " for " amt " bags.")]
;      ]
;    ] ; distance
;    [ ;else (not in trading distance)
;      jump tick-range 
;    ]  
;  ] ; end of the if part
;  [ ; else part
;    let not-visited turtle-set filter [not member? ? visited] sort producers  ;; when selecting nearest, don't revisit
;    ;;let current-trader min-one-of (turtle-set producers buyers) [distance myself]  ;; nearest one
;    let current-trader min-one-of not-visited [distance myself]  ;; nearest one
;    if patch-here != [patch-here] of current-trader [set heading towards current-trader]
;    jump tick-range 
;  ] 
;  
;  ;if favourite = 0 and count visited = 1 [set favourite item 0 sort visited] ;; TODO use code in initialise-producers to set the favourite 
;  
;end

;to trade-transporter-buyer
;end
;
;; draw a trade
;to trade-transporter-producer
;  
;    ;; a negotiation 
;end

;to animate-task
;  ;; events at each tick, or lowest level cycle, which are animated
; 
;;  ;; ladies first rule for the opening animation
;;  ifelse year-id = init-year and month-id = 0
;;    [  
;;      ask n-of 5 turtle-set filter [member? ? farmers] sort turtles-on patch 0 0 [ animate-task] ;; allow only 5 farmers to leave origin
;;      ;; ask gardeners [animate-task]
;;    ]
;;    [
;;      ;; at end of task 1 / beginning of task 2 switch to the new activity
;;      if the-period = item 0 task-id [
;;        ask people [
;;          set activity item 1 tasklist
;;          if wordy [show (word "switching to task-" "2: " activity)]
;;        ]    
;;      ]
;;   ]  
;  foreach sort producers [ 
;    let thisp ?
;    let passociation [association] of ?
;    
;    if [activity] of ? = "NTFPS" [
;      ;; TODO select target NTFPS - check if prefs can be reached
;      ;; how often do I review my target?
;      ;; if person is at village - setting off for forest
;      ask ?
;      [
;        ifelse pdest = [patch-here] of village 0   ;; if person is currently heading for village
;        [
;          ifelse member? pdest patches in-radius walk-speed ;; arrival
;          [
;            ;; get a new target            
;            set fdest primary-of-clan
;            set status "going to forest"
;            set pdest one-of forestset-of-clan
;            set heading towards pdest
;          ]
;          [
;            ;; otherwise, continue walking towards destination (village)
;            fd walk-speed
;          ]
;        ]
;        [
;          ;; otherwise person is a) either in the farm /forest area and needs to return towards village (case where fdest is 0)
;          ifelse fdest = nobody [
;            set pdest [patch-here] of village 0
;            set heading towards pdest
;            set status "returning"
;            fd walk-speed
;          ]
;          ;; or b) already has pdest in the forest (not the village) and person is either heading there or has arrived:
;          [
;            ;; if I am at my destination, collect any NTFPs within walking distance, and change destination to another within forest set
;            ;; TODO if I am at my forest destination collect any. only change patch destination when I reach near there
;            ;; TODO collecting some products takes a long time
;            ifelse member? pdest patches in-radius walk-speed
;            [ 
;              ;; collect and account for NTFPs 
;              set status "collecting"        
;              recueilleNTFPs              
;              set pdest one-of forestset-of-clan  ;; get a new patch destination in the same forest
;              set heading towards pdest 
;            ]
;            [
;              fd walk-speed   ;; otherwise, continue walking towards destination
;            ]
;          ]      
;        ]
;      ]
;    ]
    
   
    
;  ]

  
;end





;; set the strategy for targetting high or low val, and based on experience/ expectation. This is updated annually

;; mangues kokos mempas assas dogote, (Talala, Mtondo, Djansang and Djembe)
;to set-collecting-strategy  
;    
;    let expectation 0.5    ;; threshold for targeting preferred NTFPs versus just collecting any
;    set collecting-strategy "collecting-preferred"
;    
;    set speciesprefs 
;    ;;[(list filter [NTFP-high-value ?] NTFPS)] ;; I am rich  - prefer HV
;    (list "mangues" "kokos" "mempas") ;; I am rich male
;    
;    ;; rich women include high value ones such as black pepper and A'ssa....poorer ones do not 
;    ;; (they focus on collecting for consumption/not sale so much and putting labour into agriculture).
;   
;    
;    
;;    ;; follow my preferences only if my experience matches my expectation
;;    let sum-avg 0   ;; sum of averages
;;    foreach NTFPprefs [
;;      let pos position ? NTFPtypes
;;      set sum-avg sum-avg + item pos avg-col 
;;    ]
;;    ;;show (word "sum-avg=" sum-avg " length=" length NTFPprefs)
;;    if year-id - init-year > NTFP-memory and (sum-avg / length NTFPprefs) < expectation [
;;      set NTFPprefs NTFPtypes    ;; otherwise I collect all (without preferences)
;;      set collecting-strategy "collecting-all"
;;      ;; show (word "Person-" who " is collecting any NTFP this year; sum-avg=" sum-avg)
;;      ;; show (word "sum-avg=" sum-avg " length=" length NTFPprefs)
;;    ]
;;    
;    
;    
;end



;; shifting demand patterns for crop and amount to be supplied
;to update-demands
;  set croptype item 0 one-of croptypes
;  set demand random 100
;end

;; chance of change of state of hh labour eg. 5 percent chance
;to update-labour
;  ;; if not labour-bool [set labour-bool random 100 < chance-labour]
;  set labour-int ifelse-value (random 100 < chance-labour) [labour-int + 1] [labour-int]
;end

;;  initialiase using buttons step by step

to initialise-producers
   create-producers numberProducers [
    
    ;; locate producers away from markets, near to landparcels, in an empty patch
    let exit false
    while [exit = false]
    [
      set exit true
      ;setxy random-pxcor random-pycor 
      move-to one-of hotspot-patches with [any? turtles-here = false] 
      if any? markets with [distance myself < min-distance-market][set exit false]
      if not any? landparcels in-radius max-distance-collection [set exit false]
    ]
    
    set parcels landparcels in-radius max-distance-collection
    set collected [0 0]
    set target-price 0.3 * retail-price ;; initialise target price
    set tcosts 0                        ;; assume trades costs are zero (producers get wood for free)
    
    set annual-profit []
    set annual-production []
    set annual-collected []
    set loanW 0
    set loanK 0
    
    set permit false   
    set permit-type 0                    ;; permit-type not set here/ may not be needed ?
    set CPG nobody
    set intensification 100
    set kiln-efficiency kiln-eff-standard
    
    ;set stock one-of [25 50 75 100] 
    ; set stock random 100
    set stock 0
    set trade-price-strengths-reject n-values length trade-price-points [CS-intial-values]  ;; both producers and transporters have CS values stored
    set trade-price-strengths-accept n-values length trade-price-points [CS-intial-values]  ;; both producers and transporters have CS values stored
    set rejected   []
  ]
end 

to initialise-transporters
  create-transporters numberTransporters [
    
    ;setxy random-pxcor random-pycor 
    move-to one-of hotspot-patches with [any? turtles-here = false]
    
    set visit-range max-transporter-visit-range  ; could depend on type of transport available
    set nearest-producers producers in-radius visit-range 
    set tick-range max-transporter-tick-range
    set capacity lorry-capacity   ; max number of bags processed
    set status "visiting"         ; set status "leaving market"
   
    set permit false 
    set permit-type 0             ;; permit-type not set here/ may not be needed ?
    set bulk-supplier nobody
    
    ;; nearest producer that transporter heads towards after visiting market
    let sorted-producers sort-on [distance myself] producers
    set homepatch patch-here
    set tcosts 0                  ;; trade costs obtaining charcoal 
    set annual-profit [] 

    set propensities n-values number-markets [ (1 / number-markets)]
    set aspiration 0             ;; initial value
    set trade? false
    set mchoice one-of markets ;; initial random choice
    
    set history n-values transporters-memorysize [aspiration]  ;; all zeros
    
    set satisfaction-history n-values transporters-memorysize [0]
    set stock 0;one-of [25 50 75 100] 
    
    set trade-price-strengths n-values length trade-price-points [1]  ;; both producers and transporters have CS values stored
    set price-point-index random length trade-price-points
  ]
  
  
  setup-display-properties
end 

to initialise-buyers
  ;; set numbers for each market based on population data
  let matuu-tpop sum matuu-population
  let tulia-tpop sum tulia-population
  let kitui-tpop sum kitui-population
  let mwingi-tpop sum mwingi-population
  let pratio (matuu-tpop + tulia-tpop + kitui-tpop + mwingi-tpop) / numberBuyers
  let matuu round (matuu-tpop / pratio ) ;show matuu
  let mwingi round (mwingi-tpop / pratio ) ;show mwingi
  let tulia round (tulia-tpop / pratio ) ;show tulia
  let kitui (numberBuyers - matuu - mwingi - tulia) ;show kitui
  create-buyers kitui [ 
   move-to one-of kitui-patches with [any? turtles-here = false] 
   set nearest-market one-of markets with [label = "Kitui"]  ; bags/month
  ]
  create-buyers matuu [ 
   move-to one-of matuu-patches with [any? turtles-here = false] 
   set nearest-market one-of markets with [label = "Matuu"]  ; bags/month
  ]
  create-buyers tulia [ 
   move-to one-of tulia-patches with [any? turtles-here = false] 
   set nearest-market one-of markets with [label = "Tulia"]  ; bags/month
  ]
  create-buyers mwingi [ 
   move-to one-of mwingi-patches with [any? turtles-here = false] 
   set nearest-market one-of markets with [label = "Mwingi"]  ; bags/month
  ]
  
  ask buyers [
    set demand min-demand + random (max-demand - min-demand + 1) 
    ;show demand
  ]
  

;   (list "Kitui" "Mwingi" "Matuu" "Tulia")
;   
;   create-buyers numberBuyers [
;    let found false
;    
;    while [found = false]
;    [
;      ;; place in one of urban patches
;      move-to one-of urban-patches with [any? turtles-here = false]
;      ;setxy random-pxcor random-pycor
;      if any? markets with [distance myself < min-distance-market][set found true]
;    ]  
;    set demand min-demand + precision (random max-demand) -1  ; bags/month
;    set nearest-market min-one-of markets [distance myself]
;  ]
   setup-display-properties
end 

;; create and locate the levy agents at checkpoints

to initialise-levys
  let wordy false
  
  let numvalues-x 0
  let numvalues-y 0
  ;;show count roadsxhotspots
  
  if checkpointfreq > 0 [
    set numvalues-x round (80 / checkpointfreq)
    set numvalues-y round (166 / checkpointfreq)
  ]
  
  let checkpoints-x sort remove-duplicates sentence n-values numvalues-x [checkpointfreq * ?] n-values numvalues-x [checkpointfreq * ? * -1]
  let checkpoints-y sort remove-duplicates sentence n-values numvalues-y [checkpointfreq * ?] n-values numvalues-y [checkpointfreq * ? * -1]
  ;show (list checkpoints-x checkpoints-y)
  
  let nearestpoints []
  
  foreach checkpoints-x
  [ 
    let x ?
    foreach checkpoints-y
    [
      let y ?
      ;let nearest-patch first sort-on [distancexy x y] roadsxhotspots
      let nearest-patch first sort-on [distancexy x y] roadsxhotspotsxurban   ;; include urban patches as potential checkpoints
      ;print min [distancexy x y] of roadsxhotspots
      set nearestpoints fput nearest-patch nearestpoints 
    ]
  ] 
  set nearestpoints remove-duplicates nearestpoints
  if wordy [show (word "There are " length nearestpoints " checkpoints in hotspot or urban areas")]
  let nearestpatches patch-set nearestpoints
  
  ;; greedyness quota
  let gquota round (length nearestpoints * greedy? / 100) 
  ;; add one levy agent to each checkpoint
  let index 0   
  create-levys length nearestpoints 
  [
    move-to item index sort nearestpatches
    set index index + 1 
    set levytype ifelse-value (index < gquota) ["greedy"] [ "normal"]
    
    ;set nearestpatches other patches patch-here
    ;; move-to one-of (nearestpatches with [any? levys-here = false])
    ;set nearest-market one-of markets with [label = "Tulia"]  ; bags/month
  ]
    
  
  ; show map round [pxcor / 20] of roadsxhotspots
  ;;   pxcor pycor
end 


;; use locations based on the centroids of features
;  set 

to initialise-markets
  
  let index 0
  create-markets number-markets [
    set label item index marketnames
    let mloc item index market-locations
    set index index + 1
    ;; position-market
    let exit false
    let tries 0
    set xcor item 0 mloc
    set ycor item 1 mloc
;    while [exit = false] [
;      ;;print "stuck in while"
;      let spot one-of county-patches 
;      
;      let rfx [pxcor] of spot 
;      let rfy [pycor] of spot 
;      set xcor rfx
;      set ycor rfy
;      ;; distancexy reports distance from this agent to the point (xcor, ycor) and distance reports distance from this agent to another
;      ;; paddys not allowed too close to other paddy or the village or mangrove
;      ;; myself here refers to the current paddy that we are positioning
;      ;;show distance min-one-of rivernodes [distance myself] ;;< riverbank-distance  
;      ifelse any? other markets with [distance myself < min-distance-landparcels][
;        set tries tries + 1
;        if tries > 500 
;        [ die 
;          set exit true
;        ] ;; limit the number of paddy agents
;      ]
;      [ 
;        ; let river-distance distance min-one-of rivernodes [distance myself]
;        set exit true
;      ]
;    ] 
  ]
  ;; highlight markets
  ;ask markets [set label-color red]
  ;ask markets [ask neighbors [set pcolor red]]
end 



;; Update CPGs, reallocate producers to new CPG when they are nearer
;; -- orphaned procedure, may be used where innovation & norm diffusion becomes active
;; -- see year start events

to update-CPGs
   let wordy false
   if wordy [show word "Number of CPGs: " numCPGs] 
   
   
   let numnewCPGs numCPGs - count landparcels with [practice =  "CPG"]
   
   ;; select new CPGs at random
   ask n-of numnewCPGs landparcels with [practice =  "private"]
   [
     set practice "CPG"
     set quota true
     set permit false
     paint-landparcels
     set stock 0
   ]
   
   ;; reset members
   ask landparcels with [practice =  "CPG"] [set members no-turtles]
   
   ;; reallocate members
   foreach sort producers
    [
      let dlist sort-on [distance ?]  landparcels with [practice = "CPG"]
      if min [distance ?] of landparcels with [practice = "CPG"] < max-distance-collection
      [
        ask ?
        [
          set CPG first dlist
          ifelse [permit] of first dlist  ;; set permit of producer
          [
            set permit true
          ]
          [
            set permit false
          ]
        ]
        ask first dlist [set members (turtle-set ? members)]
      ]
    ]
   ;; check for empty CPGs 
   foreach sort landparcels with [practice = "CPG"]
   [
     if wordy [show (word "CPG " [who] of ? " has " count [members] of ? " members") ]
     if count [members] of ? < 2
     [ 
       ;disband the group if the size is less than threshold size (eg. 2)
       ask ? [set practice "private" set quota false set permit false]
       ask [members] of ? [set CPG nobody set permit false]
     ]
   ]
   ; reset intensification automatically for producers with permits
   ask producers with [permit = true] [set intensification 100]
end 

to initialise-CPGs
  let wordy false
  ;; determine which (if any) landparcels are managed by CPGs  -- assuming trust land can't have CPG practice
  ;let numCPGs ifelse-value (CPGscenario = "noCPG") [ 0] [ round (max-number-landparcels / 8)]  ;; TODO don't round
  set numCPGs round (max-number-landparcels * CPGscenario / 100)  ;; CPGscenario can be set in r
   
  if wordy [show word "Number of CPGs: " numCPGs]
  
  let CPGparcels n-of numCPGs landparcels ;with [tenancy = "private"]
  
  ask landparcels [
    ;; TODO add two distinct categories of "private" practice : trust (accessible) and reserve (illegal)
    ifelse member? self CPGparcels [set practice "CPG"] [set practice "private"]   
    paint-landparcels
    ;show (word "landparcel" who " has " count lpatches " patches") 
  ]
  
  ;; for each producer, check if the nearest CPG is within collection distance, and if so join it
  ;; -- producers are members of one CPG only (now the nearest - NOT the first to be initialised)
  if numCPGs > 0
  [
    foreach sort producers
    [
      let dlist sort-on [distance ?]  landparcels with [practice = "CPG"]
      if min [distance ?] of landparcels with [practice = "CPG"] <= max-distance-collection
      [
        ask ?        ;; ask producers
        [
          set CPG first dlist
          set permit true  
          set permit-type [permit-type] of CPG   ;; depends on namacertification policy and other requirement (kiln, mai)     
        ]
        ask first dlist [set members (turtle-set ? members)]
      ]
    ]
    foreach sort landparcels with [practice = "CPG"]
    [
      if wordy [show (word "CPG has " count [members] of ? " members") ]
      ifelse count [members] of ? < 2
      [ 
        ;disband the group if the size is less than threshold size (eg. 2)
        ask ? 
        [
          set practice "private"
          set quota false
          set permit false
          set permit-type 0
        ]
        ask [members] of ? 
        [
          set CPG nobody
          set permit false
          set permit-type 0
        ]
      ]
      [     
        ask ? 
        [
          set stock 0                            ;; initial stock of zero
          set kiln-efficiency kiln-eff-standard  ;; initial standard efficiency - - some may use improved kilns see below
          set loanK false
          set permit true                        ;; proto cpg has a permit
          set permit-type "RC"                   ;; regulated
        ]
      ]
    ]
  ]
  
  ;; some CPGs may use improved kilns - set using interface chooser
  show (word "There are " numCPGs " CPGS, of which " round ((CPGscenario * UseImprovedK * max-number-landparcels) / 10000) " are using improved kilns")
  ask n-of round ((CPGscenario * UseImprovedK * max-number-landparcels) / 10000)  CPGparcels
  [
    set kiln-efficiency kiln-eff-improved
  ]
end 

;TODO update  licenced transporter-list
;; assume that all transporters work both formal and informal

to initialise-transporter-list
  set transporter-list sort transporters
end 




;; this is done in setup
;; it is done before setting up the social infrastructure
;; land parcels must be entirely located within hotspot-patches

to initialise-landparcels [given-number-landparcels]
 
  create-landparcels given-number-landparcels [
    set size-xy (list landparcel-size landparcel-size)
    set area (item 0 size-xy) * (item 1 size-xy)
    
    position-landparcel
    
    ;; TODO use map to define tenancy. TODO landparcel could also be part of reserve (trustland)
    ;set tenancy one-of ["private" "trust" ] ;; random 3 ;; choose from [0 1 2]
    set members no-turtles
    set date year-id       ;; properties to do with CPG
    set tcosts 0
    set annual-profit []
    set annual-production []
    set annual-collected []
    set collected [0 0] 
    hide-turtle
      
    let lparcel self       ;; ask patches to set partfarm to the current landparcel
    ask lpatches [         ;; set quality and quantity -  a property of patches 
      set partof lparcel
      set species one-of treetypes
      set quality item species treequalities   ;; eg.  0.5 or 1
      ;set quantity random-float  1
      ;; TODO set stk in initialise-landparcels from initial data ;; stk ranges from about 10000 to 60000 kg per ha
    ]
    ;; calculate the overall quality  
    set lpquality mean [quality] of lpatches
    
    set quota false       ;; whether there is MAI (mean annual increment) limit - false if not CPG or not created through loan
    set permit false
    set permit-type 0
  ]   
end 
  
;; resetting of different variables at start of tick

to reset-tick
end 




;; the-month (numeric month-id) timelevel
;; timelevels below the-month are: the-period (numeric mapped to ticks) 

to set-month
  ;; month is calculated from the value of tick
  ;let months-per-year 100  ;; months now correspond to trading periods of transporters - this means 1200 ticks per year
  let period-of-year ticks mod (ticks-per-month * months-per-year) ;; "period" is timelevel below "month" timelevel
  set month-id floor (period-of-year / ticks-per-month)
  
  ;; these variables could be useful
  set year-id init-year + floor (ticks / (ticks-per-month * months-per-year))
  
  ;; remapping the tps to months
  let correct-month-id month-id
  let mulpf months-per-year / 12
  set month-id  floor (month-id / mulpf)  ;; new value from 0 to 11
  
  ;; select the correct string for current month (* - not permitted to resalinise)
  select-case month-id [
    [ 0 "set the-month \"January\""]   ;;  sf harvest pre monsoon
    [ 1 "set the-month \"February\""]   ;; * MAY-JUNE  add sf harvest here? pre-monsoon
    [ 2 "set the-month \"March\""]     ;; * monsoon-saltrinse add sf harvest here? monsoon
    [ 3 "set the-month \"April\""]    ;; * JULY-AUG aman start? add desalinisation law? monsoon
    [ 4 "set the-month \"May\""]    ;; * CHANGE sf harvest -> rice culivation  add desalinisation law? monsoon
    [ 5 "set the-month \"June\""]    ;; paddy harvest add desalinisation law? post monsoon
    [ 6 "set the-month \"July\""]     ;; add sf  here? OCT - NOV aman harvest? post monsoon
    [ 7 "set the-month \"August\""]
    [ 8 "set the-month \"September\""]       ;; one-cycle shrimp (dec-june )
    [ 9 "set the-month \"October\""]        ;; CHANGE sf harvest -> sf cultivation JAN-FEB
    [ 10 "set the-month \"November\""]
    [ 11 "set the-month \"December\""]   ;; add sf harvest here? 
  ]
  set month-id correct-month-id
  ;; calculate climate - now using climate-regime reporter  
end 

to-report year
  report year-id
end 

to-report month
  report the-month
end 

;; useful switch/case procedure
;; Agent runs a command task or a string containing commands.

to select-case [ value cases ]
foreach cases
[ 
  if first ? = value [ run last ? stop ]
]
end  

;; setup forest cover and forest areas - 2000 data
;; this also needs to be done before positioning the farms
;; TODO import forest areas map

to import-map 
 
;  let file bitmap:import ("forestcover-earthengine-f3.png")
;  bitmap:copy-to-pcolors file false
;  ask patches
;  [ set fclayer pcolor
; 
;    select-case pcolor
;    [                                  ;; levels == good, fair, poor, clear 
;      [ [0 0 0] "set cover \"clear\""]
;      [ [0 85 0] "set cover \"poor\""]
;      [ [0 170 0] "set cover \"fair\""]
;      [ [0 255 0] "set cover \"good\""]
;    ] 
;  ]
end 
;; place a river node at each point along x=0 axis
;; river links are directed from top most point of grid (where y= max value)
;; todo set as directed

to-report turtles-intersection [A B] 
   report turtles with [(member? self A) and (member? self B)] 
end  

to-report patches-intersection [A B] 
   report patches with [(member? self A) and (member? self B)] 
end  

to-report patches-difference [A B] 
   report patches with [(member? self A) and (not member? self B)] 
end  

;; return a list
;to-report report-cover
;  let toret n-values 4 [0]
;  let coverlevels (list "good" "fair" "poor" "clear") 
;  foreach coverlevels
;  [
;    let index position ? coverlevels
;    set toret replace-item index toret count patches with [quantity = ?]
;  ]
;  report toret
;end
;
;;; return a list
;to-report report-fertility  ;; of forest
;  let toret n-values 3 [0]
;  let flevels (list "good" "fair" "poor") 
;  foreach flevels
;  [
;    let index position ? flevels
;    set toret replace-item index toret count patches with [quality = ?]
;  ]
;  report toret
;end
;
;;; return a list
;to-report report-NTFPS-collected  ;; of forest
;  ;l
;  let toret n-values (length treetypes) [0]
;   
;  foreach treetypes
;  [
;    let index position ? treetypes
;    ;set toret replace-item index toret sum [item index month-col] of producers
;  ]
;  report toret
;end




; condition of land under plantation farming
;; return a list
;to-report report-fertility-plantations  
;  let toret n-values 3 [0]
;  let patchsetplantations patch-set [farmset] of farms
;  let flevels (list "good" "fair" "poor") 
;  foreach flevels
;  [
;    let index position ? flevels
;    set toret replace-item index toret count patchsetplantations with [fertility = ?]
;  ]
;  report toret
;end




;; position in GIS area
;; note that a farm can be located in a forest area 
;; within county-patches

to position-landparcel
  let exit false
  let tries 0
  let wordy false ;true
  while [exit = false]
  [
    ;;print "stuck in while"
    let spot one-of hotspot-patches
    move-to spot
    let xc xcor
    let yc ycor
      
    ifelse (landparcel-size mod 2) = 1
    [
       set lpatches patches with [abs (pxcor - xc) < ( item 0 [size-xy] of myself / 2 ) and abs (pycor - yc) < ( item 1 [size-xy] of myself / 2)]    
    ]
    [
       set lpatches patches with [(pxcor - xc) < ( item 0 [size-xy] of myself / 2 ) and (pycor - yc) < ( item 1 [size-xy] of myself / 2) and (xc - pxcor) < ( item 0 [size-xy] of myself / 2 + 1) and (yc - pycor) < ( item 1 [size-xy] of myself / 2 + 1)]    
   
    ]
    ;;
    
    let nbr-count-hot length filter [member? ? hotspot-patches] sort lpatches ;[neighbors] of spot ;; how many are within hotspot
    let nbr-count-nan length filter [[mai] of ? > 0] sort lpatches ;[neighbors] of spot            ;; added because of NaNs creeping in sometimes
     ;with [not member? self jachere] 
    let rfx [pxcor] of spot 
    let rfy [pycor] of spot 
    set xcor rfx
    set ycor rfy
    ;; distancexy reports distance from this agent to the point (xcor, ycor) and distance reports distance from this agent to another
    ;; paddys not allowed too close to other paddy or the village or mangrove
     ;; myself here refers to the current paddy that we are positioning
     ;;show distance min-one-of rivernodes [distance myself] ;;< riverbank-distance  
     ifelse (any? other (turtle-set landparcels markets) with [distance myself < min-distance-landparcels]) or nbr-count-hot < area or nbr-count-nan < area [
       set tries tries + 1
       if tries > 500 
       [  die 
          set exit true
       ] ;; limit the number of paddy agents
     ]
     [ 
      ; let river-distance distance min-one-of rivernodes [distance myself]
       set exit true
       if wordy [show (word self " has " nbr-count-hot " hotspot neighbours")]
     ]
  ] 
end 

;to simulate-traders
;  ;; after a certain number of months/years a trader appears
;  if month-id = 2 and the-period = 1 [
;    create-traders 1 [
;      setxy random-pxcor random-pycor
;      set croptype item 0 one-of croptypes
;      ;; turtle moves to the center of a random patch
;      print (word "New " croptype " trader has appeared at " xcor ", " ycor)
;      set demand random 100
;      set color black
;      set destination one-of primarys 
;      set heading towards destination
;    ]
;  ]
;  ask traders [
;    fd walk-speed
;    ;; if arrived at destination and if no people nearby change destination
;    if [partof] of patch-here = destination and not any? people in-radius walk-speed [
;      ;;print "changing direction"
;      set destination one-of primarys 
;      set heading towards destination
;    ]
;    if any? people in-radius walk-speed [
;      create-tradelinks-with people in-radius walk-speed
;    ]
;    
;  ] 
;end

;to create-boundaries
; ;; draw 4 lines around edge of this forestset
; print "entered create-boundaries"
; let halfwidth item 0 size-xy / 2 
; let halfheight item 1 size-xy / 2
; let myx xcor
; let myy ycor
; hatch-boundarys 1 [
;   set xcor myx - halfwidth
;   ;; set xcor myx
;   set ycor myy
;  set heading 0
; ]
; hatch-boundarys 1 [
;   set xcor myx
;   set ycor myy - halfheight
;   set heading 90
; ]
; hatch-boundarys 1 [
;   set xcor myx + halfwidth
;   set ycor myy
;   set heading 0
; ]
; hatch-boundarys 1 [
;   set xcor myx
;   set ycor myy + halfheight
;   set heading 90
; ]
;  ask boundarys [
;   set color white
;   set size 3
;   show-turtle
;  ]
;end



;;Note the inversion of the transparency value so that the larger the number the MORE transparent (can remove or adjust that as you please).

to set-transparency [new-transparency]
  ifelse is-list? color
     [ set color lput (255 - new-transparency) sublist color 0 3 ]
     [ set color lput (255 - new-transparency) extract-rgb color ]
end 

;; reporters for collecting results in R and making plots

;; producers, unweighted mean (not weighted per unit)

to-report mean-accepted-price
  report ifelse-value (any? producers with [accepted-price > 0]) [mean [accepted-price] of producers with [accepted-price > 0]][0]
end 

to-report mean-accepted-price-CPG
  report ifelse-value (any? landparcels with [accepted-price > 0]) [mean [accepted-price] of landparcels with [accepted-price > 0]][0]
end 

to-report totalCollected0
  report sum [item 0 collected] of producers
end   

to-report totalCollected1
  report sum [item 1 collected] of producers
end 

to-report totalCollectedCPG
  report sum [item 0 collected + item 1 collected] of landparcels
end 

to-report annualCollectedAll
  report annual-collected-all ;sum [sum annual-collected] of (turtle-set producers landparcels with [practice = "CPG"])
end 

to-report annualMarketsizes
  report annual-marketsizes 
end  

;; calculate the amount, on average, that each actor receives in profits per bag :  divide the aggregated profit for each agent type by the total number of bags circulating annually 

to calculateAnnualProfitShare
  let aps n-values 4 [0]                     ;; same value as pens : county levy transporter producer (of wholesale price)
  let totalbags annualExport + annualSales   ;; overall figures for export sales and sales in 4 towns
  
  set aps replace-item 0 aps (fiscal / totalbags)
  set aps replace-item 1 aps ifelse-value (count levys > 0) [sum [sum annual-profit] of levys / totalbags ] [0] 
  set aps replace-item 2 aps (sum [sum annual-profit] of transporters / totalbags )
  set aps replace-item 3 aps (sum [sum annual-profit] of producers / totalbags )
  set annual-profit-share map [? * 100 / sum aps] aps
end 

to-report annualProfitShare
  report annual-profit-share 
end 

to-report annualMovementPermits
  report annual-movement-permits
end 

to-report totalProduced
  report sum [production] of producers
end 

to-report totalProducedCPG
  report sum [production] of landparcels
end 

to-report totalBought
  report sum [bought] of buyers
end 

to-report totalExported
  report export-sales
end 

to-report unhappy
  report count buyers with [bought = 0]
end 

;; mean

to-report transporter-annual-profit
  report mean [sum annual-profit] of transporters
end 

;; mean

to-report producer-annual-profit
  report mean [sum annual-profit] of producers
end 

;; mean

to-report levy-annual-profit
  
  report ifelse-value (count levys > 0) [mean [sum annual-profit] of levys] [0]
end 

to-report percentageExportedYr   ; here the 'percentage' is given as a number between 0 and 1
  let exp-sales annualExport + annualSales
   report ifelse-value (exp-sales > 0) [annualExport / (annualExport + annualSales)] [0]             ;; overall percentage of export sales vs sales in 4 towns
end 

to-report percentageOverutilisedYr   ;; here the 'percentage' is given as a number between 0 and 1
  report overUtil / count landparcels
end 

to-report meanUtilisedYr         ;; mean of landparcels
  report  meanUtil
end 

to *TODO
  

 ;; bugfixes 

 ;; TODO 1 checked test-accounting gives an error and flop problem - not sure of source - eg. stock of landparcels/CPGs
  
 ;; TODO 2 how to measure when producers have a shortage of supply
 ;; total production. total producer demand
 ;; 3. how to measure when CPGs have more stock than they can sell
  
 ;; TODO 4 check if independent producers also update permit-types using monitors-  SC permit types are possible when efficient kilns are available
 ;; -- TODO check their permits as well
 
 ;; TODO LATER
 
 ;; Note the adaptation of the dates of the policy phases in the experiment file

 ;; 7.  make the transporters travel near to roads - if they are anywhere near main roads place them actually on the roads patches

 ;; show 3 SCENARIOS and point out some TRENDS (have not really analysed these so far)
 ;; 1. biomass
 ;; -- under POLICYbiomass policy (=2), we see an increase in fiscal returns and a slight reduction in levys (1). The informal sector shrinks and the formal sector grows (6).
 ;; -- however more transporters having permits only slightly reduces levy payment. Most transporters trade informally and pay similar levy charges but have lower stock and profits (4)
 ;; -- plot 3 wood harvested goes down from about 6.2 to 4.2 because of take restrictions obligatory to the many members of CPG. Number overexploited down from 30 to around 7
 ;; 2. biomass and efficiency with more levy agents with greedy behaviour
 ;; -- levy income goes back up again and producers also benefit
 ;; 3. certificaion and efficiency

 ;; uncertainty analysis (calibration) - use same two observations of the current system (% exported and % overexploited) ?
 ;; -- ask stakeholders for suggestions we can use for the uncertainty /calibration - proportion of them overexploited
 ;; sensitivity analysis (robustness of results) - with which input variables (not the policy ones) and which output variables ?
 
 ;; . Fees paid by the transporters varied within the counties. In Kitui
 ;;  County, they pay cess of KES. 50 per bag up from KES. 20 that was reported by PICSES in
 ;;  2010, and KES. 1,500 per lorry to the Nairobi County. The transporters were also forced to pay
 ;;  illegal taxes at police checkpoints along the highways. These illegal taxes vary from place to
 ;;  place, from over KES 20,000 as documented during the study to KES. 80,000 per trip for a lorry
 ;;  carrying 350 bags as reported by traders transporting charcoal from Kajiado and Kitui to Nairobi.
 ;;  These unofficial payments accounted for between 5% to 13% of the final value of a bag of
 ;;  charcoal. A study by Bailis (2006) reported that illegal taxes accounted for between 20% and
 ;;  30% of the final value of charcoal. The lower range reported in this study represents a reduction
 ;;  in illegal taxes by between 15% and 17% mostly likely due to legalisation of charcoal following
 ;;  the enactment of the Charcoal Rules 2009.
 
 ;; TODO a quick way to set up that does not rely on model files ?
 
 ;; - levy agent moves around collecting levies from informal charcoal producers and transporters of informally produced charcoal 
 ;; (not sure if both or just transporters would be best). 
 ;;--  it is often systematic and consistent - people know exactly how much they will have to pay in bribes - having a fixed fee would capture that. 
 ;; But the random action of the “informal levy agent” might be questioned as it might not be so random in reality. Could we have a switch to change between random and non-random agent action?
 ;; to show what? do they go to a random position or do they adapt to where they can maximise their income
 ;; switch to allow a risk-taking behaviour -  asking bribes from transporters with a permit - with the possibility to lose their job
 ;; are they risk -taking (asking bribes from transporters with a permit) or are they risk averse (leaving them alone if papers are presented)
 ;; each levy agent has an attitude (corrupt or not - demand levy?) and a risk aversion for the demand (yes or no to demanding levy from formal transporter)
 ;; levy agent may lose their job if reported and caught - they are replaced by agents adopting the most successful strategy - roulette wheel
 ;; The informal transporter will never report - whereas the formal one probably will.
 ;; might make a mistake
 ;; how can the corrupt/low-risk strategy be bettered ? greedy one has a better payoff
 ;; correct, corrupt/ungreedy, corrupt/greedy
 ;; how can correct beat corrupt/ungreedy
 
 
 ;; update profits of transporters if they have to pay levies
 
 ;; TODO 5 normative agency
 
 ;; TODO slides 
 ;; TODO list of assumptions for Hannah
  
;; TODO simulations
;; check what is necessary for inducing a 'regime shift' to sustainable production
;; define a regime shift - check policy windows


 ;; TODO
 ;; intervention 4 is support for regulation - enforcement/sanctions
 ;; intervention 4 allows tweaking the other policies.
 ;; -- getting rid of corruption agents
 ;; -- norm of compliance to licenced production more likely to be enforced
 ;; Potential capacity buiding which addresses technological barriers 
 ;; -- efficient retort kilns are perceived as complicated - so individual producers might be put off
 ;; -- eg. it might increase the number of actors interested in applying
 
 ;; IDEAS 
 ;; CPGs don't go in teams of 30 members, they go in teams of 6
 ;; normative reputation /social approval  is only given to those observed in the same team as compliant/cheater
 ;; or to those observed cheating by producing elsewhere and selling separately to a transporter
 
 ;; intervention 2 - producers get loans for more efficient kilns - priority to large scale producers - CPGs 
 ;; Loan available until the stated target is reached 
 ;; - 90 percent of large scale <250 kg/day and 50perc of small scale
 ;; Loans are made available for independent producers or for CPGs (if there are any)
 ;; Does not specify business plan, but the target seems to favour the most large scale producers - particularly CPGs 
 ;; - annual amount produced (main criteria for CPGs) 
 ;; - their access to landparcels (for independent producers - as secondary criteria)
 ;; (becuase for producers the output will be almost identical)
 

 ;; Later TODOs
 ;; TODO intervention 1b - loans are supplied for extending/expanding existing landparcels
 ;; the lp could belong to an already existing CPG or private one

 ;; TODO second criteria is quality of landparcel for charcoal production
 ;; assess 'business models' on both of these criteria
 
 ;; TODO sufficiently high ranked plans get accepted - up to target coverage
 ;; TODO business plan - rated by quality of land, and number of producers nearby
 ;; condition is that the landparcel is not overexploited
 ;; condition that CPGs or producers must not already have a loanW
 ;; It also comes with a cap on the take
 ;; say 2 lp per year (14 lp over the duration of 7 years = 14,000 out of 1,000,000)
 ;; say 5 lp per year (35 lp over the duration of 7 years = 35,000 out of 1,000,000)
 
  ;;TODO policy windows
 ;; How deeply implemeted each policy - in terms of investement and timings
 ;;maybe use a policy window approach - when you need to start and when you need to stop a policy/ offering an incentive - 
 ;; NAMA time frame
 
  ;; 4. uncertainty analysis - Determine numbers of agents - use in uncertainty analysis - what scaling factors to use - because cannot do 1-to-1
  ;; - assume only a few landparcels are modelled - subset of total population
  ;; - size of landparcel is modelled on approximate coverage of CPG
  ;; - based on data on how many agents belong to each CPG (landparcels) - Hannah's data
  ;; - a key indicator, utilisation rate, is computed at the landparcel level (is uneffected by model scaling but still weakly validated)
  
  ;; 5. sensitivity analysis
  ;; ;; run the calibration / uncertainty analysis by parameter variation over the number of agents of each type already done
  ;; what else for uncertainty analysis
  ;; use Morris method for global sensitivity analysis ?
  
  ;; 6. scenario analysis adding a normative scenario later after 1st Draft
  ;; Social-economic development and policy-making. It is impossible to introduce new policies, and design and enforce
  ;; institutions aimed at governing existing social-economic processes without investigating what type of effect these 
  ;; will generate on the agents' minds, and more crucially, which mental properties and phenomena could cooperate with 
  ;; the candidate policies and institutions. A general theory of normative intelligence paves the way for such an investigation.
  
 
  ;; 5. update the documentation 
  
  ;; Later TODOs 
  
  ;; TODO what if individuals get certified ?
  
  ;; 1. Load  gridded data into model 
  ;; -- load mai - check with Rob - growth rate correlates to biomass?
  ;; -- set stk in initialise-landparcels from initial data (remember to adapt for 1km pixels)
  ;; 2. add GIS info for land use for hotspot wards
  ;; -- use map to define tenancy. TODO landparcel could also be part of reserve (trustland)
  
  ;; uncertainty - sensitivity analysis
  
  ;; develop scenarios with transition pathways
  ;; use different initial parameters/different assumptions (eg. different a.a.c., different prices, taxation policy )
  ;; a) different take constraints  on CPGs to be set as part of scenario (higher aac or mai may assume some replanting)
  ;; b) different rate of uptake by CPGs ?
  
  ;; construct scenarios for uptake of policy options such as support for establishing licensing  
  ;; a) production permits can be obtained b) Transport permits can be obtained c) taxation at county level.
  ;; - if it was sustainably managed, what would be the constraint on extraction
  ;; write paragraphs about scenario analysis and risk analysis in l.r. or methodology section
  
  ;; decision making
    
  ;; TODO producers decision making about doing CPG or non-CPG (informal) production
  ;; potential drawback is the wait time (to meet transporter capacity demands) and lower resource availability because of management regime constraint 
  ;; TODO producers that don't join CPGs or act outside of them
  ;; check the normative part
  ;; TODO how to establish new CPGs and update producers' membership of CPGs - needed for transition
  ;; TODO transporter decision for export vs. local markets can also depend on price difference
  

  
  ;; IDEAS
  ;; use weeks as the middle time cycle instead of month (tick - week - year) or (tick - month - year) where decisions get made and variables updated
  ;; so 12 ticks per week and 52 weeks so increase to around 600 ticks per year
  ;; allows to animate the movement of transporters. IMPORTANT
  ;; -  how many producers can a transporter visit in a day or week?
  ;;  - charcoal is bought per week or per month ? i.e regularity of trading / 'market' interaction
  ;; how important is the animation? Is 1 market interaction per month good enough.
  ;; If so, the behaviour could be modelled using estimate of the number of visits per month, but you would not see transporters moving 
    
 
  
  ;; ignored TODOs
  ;; TODO more production during the dry season
  ;; TODO Sometimes producers supply buyers (retailers/ wholesalers) directly near roads/towns,
  ;; TODO Oliver to check and prioritise among current model assumptions and suggest some well-supported hypotheses
  ;; TODO add data about markets and their size - number of buyers each market town
  ;; TODO consider different types of markets (roadside) -  buyers
  ;; TODO more elaborate decision tree for producer intensification
  
  ;; Hannah
  ;; allowing producers with direct supply, different types of transporters and buyers (if not too complicated) 
  ;; consider scenarios in which reducing the charcoal production is an option (how ? protected areas?) 
  ;; consider scenarios in which technical innovations are scaled up (eg. efficient kilns) or insitutional innovations (eg. market reform) test and monitor their impact eg. on energy access
  ;; concentrate on fine-tuning only the params/rules we are going to use to understand the differences between scenarios
  ;; test model outputs against the NDG goal of 10 forest cover, similar to backcasting exercise
end 

to *DONE
  ;; DONE create markets (agents) away from landparcels, and place buyers near to markets 
  ;; DONE when transporters leave the markets, for restock at their favourite supplier, delete all of their trade links.
  ;; DONE created retail (exogeneous) and trade prices (negotiated) 
  ;; - ind. producers have target price of 30% of retail and transporters have trade-price initially same
  ;; DONE producer accounting (produced, sold, surplus) transporter accounting (produced, sold, surplus)
  ;; DONE allowed producer and transporter stock can be stored in the next period
  
  ;; NEW for Kitui version
  ;; DONE used new data on transporter capacity - 170 bags
  ;; DONE Kitui environment
  ;; --Kitui presents and ideal charcoal production area
  ;; --Narok is more of land clearing agenda
  
  ;; DONE CPGs added (some of landparcels)
  ;; Assuming a ratio of 1 to 8 of the registered to the non registered producers belonging to CPAs  cvca p21
  
  ;; DONE initial producers membership of CPGs (all nearby are included) - can be more than one
  ;; -- permit is true/false 
  ;; DONE Added CPG work - all producers harvest from same patch together and contribute to stock of CPGs
  ;; added transporter list, official price
  
  ;; DONE added that the transporters  only move tick-range 
  ;; DONE added proc to month-start-event where a CPG with 100+ bags calls a transporter with no stock
  ;; - Assumes transporter won't be able to mix licensed and non-licensed stock, therefore has to have empty truck !
  ;; - Also assumes no combining from 2 groups! (ie transporter cannot accept to visit more than CPG per month
  ;; DONE the transporter then gets permit and goes directly to landparcel to pick up
  ;; - a transporter movement permit lasts  until delivery is made  - not for specific period of 3 days   

  ;; DONE include charcoal export from the region to nairobi (uniform price could be an assumption) - exogeneous part of model
  ;;  - assuming two types of markets are export and local, 
  ;;  - if transporters are full or if they have the permit, they will export, but if only partial load they dont make the journey 180km?
  ;; In these implicitly modeled markets, the suppliers sell their product to one centralized consumer
  ;; agent. Products can be sold at a fixed price (real-world average market price of the corresponding
  ;; date), and the agents can always sell their total amount of produced goods. 
  
 
  ;; DONE producers can be a member of at most one CPG - the first one to be initialised
  ;; - so that producers production licenses are tied to a particular landparcel and CPG 
  
  ;; DONE different colours for lorries set at month start
  ;; -- lorries with permits (white) and without permits (dark grey) 
  ;; DONE - more realistic figures for amounts of biomass harvested and produced
  ;; -- added growback rule to apply to each patch
  ;; -- uses table with mean annual increment and mean-perc based on Rob's model - 
  ;; DONE added kilns with variable efficiency to producers and CPG landparcels
  
  ;; DONE producers and land parcels are entirely located within hotspot-patches
  
  ;; DONE added market towns at the location - the centroid of first vector feature associated with this town
  ;; - Urban centres are KITUI, MWINGI, MATUU TOWNSHIP, and TULIA"
  ;; DONE located buyers in urban-patches (around local markets)
  
  ;; DONE Applied take constraints to charcoal-production-CPG -a.a.c.(following other lit)  or mai 
  ;; --CPG management regime constraint on sustainable extraction - here applied on the patch (possibility to apply at overall land parcel level)
  ;; Report the utilisation rate at the landparcel level for CPG managemed and private landparcels
  
  ;; DONE Transporter learns which market to select with classifier system/ reinforcement
  ;; - don't include payoff when doing charcoal export rather than local sales - ie when agent has permit
  
  ;; DONE Added assumption - those producers with a lot of stock >100) can also telephone someone (not on list) - bulk export
  ;; Assume transporters receiving bulk supply always export 
  ;; DONE Added bagsize -40
  ;; -- PISCES (2010) summarises variations in weight as follows: in Kitui a bag of charcoal weighs 42 kilogrammes
  ;; -- in Kitui District DEC limits charcoal production to not more than 50 bags per year for each CPA member.
  ;; -- desire by members to increase their production beyond this limit
  
  ;; DONE when defining membership of CPG, use  nearest CPG rather than first CPG created 
  ;; -- (helps to limit the tendance for large size of groups and high production)
  ;; -- disband the group if the size is less than threshold size (eg. 2)
  ;; -- Hannah - take a group average of 15
  
  ;; DONE checked amounts produced in literature. For procuders fix at around 30 (normal) or 45 (intensive) bags/month (if 100 months in year that is 3.6/5.4)
  ;; - different figures REF CVCA   30 bags/month-  p22 - 150 bags/month - kitui cvca p74  - 40-60 bags/month cvca p71
  ;; - Note does not consider seasonal changes. During the wet and planting seasons most producers halt production and engage in
  ;;  land preparation for agriculture thereby leading to low supplies of charcoal hence higher prices.
  
  ;; DONE - change the month id to have 100 months in a year (that is 100 trips) , but repeat the name more than once
  ;; -- On average transporters handle about 3000 bags per months making between 2-3 trips to the market each [week?] 250 bags per trip cvca p49

  ;; DONE producers start with a certain stock 25 50 75 or 100 - this can avoid cycles of low to high export seen in some tests
  
  ;; DONE added more realistic prices from literature  in KSh: export price, export price permit, trade price etc 
  ;; -- The average cost of production being
  ;; KES 70000 per 200 bags or KES 350 per bag. The (producer )sales price per bag averages between KES
  ;; 700-750 with permit and KES 400-450 without permit
  
  ;; DONE estimate buyer demand using WISER data
  ;; -- Extract total population numbers for town features into 4 lists. 
  ;; -- Sum these and use totals  to determine how many buyers to initialise for each town and locate in one of the towns patches (corresponding to towns not sublocs) 
  ;; Retailers’ average monthly 30 bags per month - 360 per year or 3.6 per cycle
  ;; - In the case of Kenya, the household sector dominates woodfuel consumption, and the population map is
  ;; instrumental to mapping the relative consumption. No data is available on the spatial distribution of the
  ;;  consumption by the public sector, cottage industries and commercial food producers or the use of wood as construction material.
  ;; We assume these are spatially correlated to population concentrations.
  ;; 
  ;; DONE - annual utilisation  reports the number of patches where ratio > 1 for the year
  ;; DONE - report the total bought as a % of the total exported + total bought (which should add up to total produced) for the year
  ;; DONE considered other trade costs (transporter-costs or producer costs) in returns income - it is added in at POS 
  ;; DONE added producer and transporter other costs using estimates - petrol, access, labour, taxes, bribes etc.
  ;; DONE added the CS for producer accepting or rejecting prices of transporter - transporters have heterog. fixed prices of 300 380 460 trade-price-points 
  ;; -- initialised with some minimum values (900)
  ;; -- producer evaluates the decision (not the particular transporter), payoff is pask-pcost * amt if accepted, and last payoff or 0 if rejected
  ;; -- no classifier system for transporter 
 
  ;; DONE added outputs to r experiment percentageExportedYr and numberOverutilisedYr producer-annual-profit unhappyAnnual (buyers)
  ;; DONE if landparcel size > 3 it is not positioned correctly; if an odd number the lpatches are not added correctly
  ;; nothing effecting numberOverutilisedYr in morris
  
  ;; DONE producer intensification behaviour - active in all scenario experiments
  ;;  producers intensification - increase take by 50% - trigggered by income threshold
  ;; producers change to reduced harvesting if income increases beyond second threshold
  ;; - producers do have costs =see cvca
  ;; added aspiredProducerProfit 100000  and exceededProducerProfit 150000 as thresholds for annual intensification
  
  ;; Ver.0-41
  ;; DONE added trade? (boolean) transporter attribute denoting trade in market town or export
  ;; DONE transporter sales history does not include export sales
  ;; DONE Update aspiration based on history (does not include exporting) when trading
  ;; DONE Decision for trading or export -export is done under condition stock exceeds bulk level OR stock is order of magnitude higher than aspiration  (ie if the agent thinks market sales will be significantly lower than export sales), otherwise do trading
  ;; DONE added parameter for multiplication factor for order of magnitude
  
  ;; Ver 0.5
  ;; added policy interventions based on NAMA but adapted for Kitui context, where there is a charcoal policy act
  ;; -- but currently a lot of policy incoherence
  ;; we know that:
  ;; The scheme allows CPGs to register themselves and to access the list from transporters association 
  ;; Payment goes into group account - a fixed premium price - after inspection
  ;;  --traders are keen on good quality charcoal which is well packaged. 
  ;; Norm compliance among CPGs is expected to be low without benefits of certification (intervention 3)
  ;; and kiln loans (intervention 2)
  
  ;; DONE code for intervention 1 additional woodlots 
  ;; - allows adding new landparcels - called from year-start-events - allows increasing the biomass supply
  ;; -- Idea is for owners/ producers/producer groups to buy land nearby
  ;; business plan [Not done yet - rated by quality of land], and number of producers nearby (who don't already have a loanW)
  ;; DONE new landparcel variable quota  
  ;; DONE added strictloan boolean
  ;; if strictloans, the landparcel is initialised with a cap on the take (quota), but is not defining a CPG status (no premium price)
  ;; ---say 2 new lp per year (14 lp over the duration of 7 years = 14,000 out of 1,000,000)
  ;; ---say 5 new lp per year (35 lp over the duration of 7 years = 35,000 out of 1,000,000)
  ;; DONE if quota, set the MAI limit on these new woodplots
  ;; DONE added new variables loanK loanW - they get reset after time period lengthloanW lengthloanK 
  
  ;; Therefore new CPGs form through intervention 1 - quota is observed for new CPGs (woodlots loans)
  ;; (There is no quota attributed to CPGs at initialisation, however, they may adopt it in response to interventions 2 & 3)
  
  ;; DONE intervention 2a - producers get loans for more efficient kilns - priority to large scale producers - CPGs 
  ;; -- select producers/cpgs with highest annual production from the previous year
  ;; DONE changed all CPG kilns to standard efficiency initially - year 0

  ;; DONE rounded mai into an integer

 ;; DONE - A quota on the annual wood extraction is set (equal to the MAI estimate) for landparcels that are associated to 'sustainable' CPGs
 ;; A CPG can exist without any quota - proto-CPGs 
 ;; But if they receive an efficient kiln through policy intervention 2 then they are obliged to set a quota.
 ;; Also new landparcels/CPGs formed through policy intervention 1 are obliged to set a quota. 
 
 ;; Individual producers do not have to set a quota on their production even if they receive efficient kilns
 ;; -- producers access different landparcels that do not have a quota (a landparcel variable, not a producer variable)
 
 ;; DONE update accessibility when a new landparcel is added or when a landparcel becomes CPG
 ;; DONE added flag aw-practice "CPG" -- assuming the new woodlots are CPG, not private type
 
 ;; DONE (in year start events)
 ;; if POLICYcertification policy is active
 ;; - set CPG compliance to MAI
 ;; - update producer permits to include those that recently met the requirements (member of CPG with improvedKiln)
 
 ;; intervention 3 is POLICYcertification policy
 ;; - A certification and labelling scheme that targets the  consumer - assumes that buyer is able to easily identify and purchase sustainable charcoal
 ;; Key model variables are the fixed premium prices that buyers and transporters are obliged to pay 
 ;; This intervention is where CPGs obtain the greatest benefits - they are able to register themselves and to access the list from transporters association  
 ;; - policy applies to all CPGs - but they have to already have more efficient kilns to qualify 
 
 ;; Permit is allocated for CPG producers and for list transporters in the case of POLICY/intervention 3 - only in this case they can benefit from special prices
 ;; list-price and export-price-permit (if permit is true) They are set with the POLICYcertification global (previously scenarioB)
 
 ;; DONE updated how we set permit in transporter and in producer
 ;; - in transporter permit should only be set if the policy is active CPG telephones them - then the prices should be set accordingly
 ;; - in producer the permit should be set if the policy is active and other requirements met (CPG member, improvedKiln)
 ;; DONE added permit variable to the landparcel breed
 
 ;; DONE Prices differ only if there is a POLICYcertification policy and the suppplier has a permit
 ;; -- 1. If a permit, the price paid by transporter to supplier is the list-price (500 or 600 set with POLICYcertification)
 ;; --    In the abscence of permit, prices paid by transporters for cpg bulk sales, and producer bulk sales are the transporters trade-price-points (300 380 460)
 ;; -- 2. If the transporter exports with a permit, the price received by the transporter is the export-price-permit (1800 or 2000 set with POLICYcertification)
 ;; --    If the transporter exports in the abscence, the price received is the export-price 1600
 ;; -- 3. If the transporter trades at market (without permit), then the  price received is the retail-price (same as export-price) 1600
 ;; --    assumes retail price is same in local and export markets
 
 ;; DONE got rid of scenarios A and B
 ;; -- update-CPGs procedure is now orphaned because intervention 1 (woodlots) now creates new cpgs 
 ;; -- others might be created if innovation diffusion / norm diffusion is implemented later
 
 ;; KEEP the CPGscenario parameter
 ;; It is assumed that some (proto) CPGs exist in which producers work together and and share equally the sales
 ;; - they have neither efficient kilns nor MAI constraint nor special price
 ;; - but they may gain these attributes in response to policy compliance (intervention 2 & 3)
 
 ;; DONE - added interface buttons corresponding to NAMA time frame 2017-2030 - 14 years in two stages - 7+7
 ;; -- 3  warm up years - start year is 2014
 
 ;; DONE - producers that are not menbers of CPG may intensify
 
 ;; ver 0.54 and 0.55
  ;; DONE include an “informal levy agent” to simulate the bribery prevalent in the informal charcoal system.
 ;; DONE added checkpoints (patches) and levys (agents) in urban or hotspot areas
 ;; -- levy agents don't move but are sited on roads, and at a user-defined intervals (every 20/30/40 km - select from dropdown)
 ;; -- interested in levy agents acting only within Kitui (near TR defined regions - urban/hotspot), but not the ones around nairobi
 ;; -- so it does not model the full extent of levys paid by exporters.
 ;; -- more than one levy agent can demand a levy in one trip
 ;; -- they collect 1000/2000 from nearby transporters at each tick - nearby - half of distance travelled per tick
 ;; -- sources suggest officers can demand a levy from a driver with a permit too - we deem this greedy behaviour -see below

 ;; DONE added plot and informal pen for the total amt collected per trading cycle - fiscal and informal levys
 ;; -- record revenues (levy agent) per trading cycle and annually
 ;; -- plot both per t.c and annually
 ;; DONE transporters update the list of those who collected from them 
 ;; -- added levycosts and cesscosts variables 
 
 ;; DONE added export-locations that are patches on main routes (googled) at edge of map, towards nairobi
 ;; - bulk transporters now travel away from producers to export destinations (on the edge of the map) and back, so they also pass levys

 ;; DONE Defined two types of permit for producer/CPGs and for transporters  (permit-types of transporters same as producer ones)
 ;; -- RC affiliated to transporter/producer association and regulated - based on the 2014 act
 ;; -- SC sustainable charcoal - similar but based on the NAMA stipulation of efficiency from 2017 - proposed
 ;; DONE added the fiscal pen to the plot wiht the cess income - with the proviso that it is not full levys

 ;; DONE permit-types of producers/cpgs are updated annually as circumstances change -  RC or SC or 0 (if no permit)
 ;; -- permit-type of producers updated to that of the CPG they are in (if realocated to another one or if CPG status is updated)

 
 ;; DONE Transporters collecting from CPGs receive permits for the trading cycle ("RC"/SC) and also are paying the cess of 100
 
 ;; DONE "added" greedy or normal characteristic to levy agent using levytype attribute  
 ;;  -- "greedy" agents collect also from transporters with a permit (this rule applies with greedy levy agents no matter whether RC or SC permits)
 ;; --  "greedy" agents  collect double from all transporters - 2000 instead of 1000
 ;; -- "normal"/ non-greedy agents don't stop transporters that have a permit (no matter whether RC or SC permits)

 ;; DONE When checkpoint freq is 0, there should not be any levy agents

 ;; DONE -- added a new plot showing what portion of the profits accrue to each of the supply chain steps -- annualProfitShare
 ;; -- although becouse not the 'full levy' we can't use this as a criteria for model uncertainty/calibration

 ;; DONE plot showing the volume of SC, RC, and informally handled charcoal 
 ;; DONE  annual plot of trade and export - comparing and seeing trend
 ;; DONE plot of overexploited landparces and CPG managed parcels
 
 ;; DONE added a button that allows the model user to vary the % of CPGs using the kilns with assumption that the current is 20% 
  
 ;; DONE added a button with Kiln efficiencies which can be varied eg CPGS produce at 10%, 30% etc 
 ;;   -------- show how this affects the wood harvesting and income
 ;; DONE measure the licenses issued annually - the CPG would be obliged to limit harvesting due to the MAI constraint 
 ;; -- therefore there is less production and fewer movement licenses issued towards the end of the year.

 ;; v0.6
 ;; DONE Nama certification prices should not be set until policy period begins
 
 ;; DONE. Get rid of NAMA labels / global names on interface
end 

to *FEEDBACK
;;   Key   comment
;; A. KEFRI and KFS
;; The model has potential to influence future propositions in relation to climate change. The stakeholders felt has connection with what is happening on the ground.s
;; 1.       When   loans for starting the  parcels are availed, - then the model should allow time for the trees to grow. (CAN WE ASSUME ALREADY MATURE? HOW LONG UNTIL FULLY PRODUCTIVE?)
;; 2.       Are we assuming this  parcels are owned by the CPG or they are individual  people within CPGs?
;; 3.       We are assuming that each ‘loan’ leads to  establishment of  3m x 3m.
;; 4.       If possible include a button that allows the model user to vary the % of CPGs using the kilns. Make an assumption that the current is 20%  but we will keep increasing  annually may be. (DONE FOR INITIALISATION)
;; 5.       If possible include a button with Kiln efficiencies which can be varied eg if CPGS produce at 10% what are the implications? (DONE - FOR IMPROVED KILNS)
;;   -------- If they move to 30%? How does this affect the wood harvesting and income. (ALREADY DONE WITH NAMA2 - PERHAPS NOT CLEAR?)
;;   -------  KFS and KEFRI indicated this would be very important for policy making.
;; 6.       George and Emily felt that since NAMA  proposal wasn’t funded  in the  NAMA Facility and since the  proposed interventions of eg increasing biomass through on farm cultivation,
;;   -------  we can drop the  word NAMA and just say policy scenario- since ideally this is covered within the Charcoal Regulations of 2009. Also the kilns aspects.
;; 7.       Sharing the model:  It will be nice if the model can be an open source for that one can generate their own scenarios.
;;   -------  Eg if  KEFRI initiates a project in Kitui, and distributes 20 kilns for  CPGs, then they can show specific results/projections in their  project area. 
;;   -------  George mentioned about the Global Degradation Maps. We can try something like that.
;; 8.       The stakeholders appreciated the work and the model and they felt –it is relating to what is happening on the ground and it can be useful  for climate change/energy  planning.


;; B. GACC, SEI, ICRAF & Practical Action
;; The model looks good and it can answer the sustainability questions within the sector
;; 1. Need to come up with a good a simple way of sharing with wide audience like policy makers.
;; 2. The different scenarios shows many unhappy buyers. Does it mean that there is high preference for markets outside Kitui?
;; 3. Priority outputs that the stakeholders felt would really influence the sector include. A) Revenue to producers; b) revenue to county government and c) Biomass resource extraction.
;; 4. Though the model doesn’t account for re-growth. It will be very important to show regrowth since not all the trees are cut for charcoal grow again as some are browsed by animals.
;; 5. Can the model show seasonal variation as  during the rainy season- the prices of charcoal goes  up.
;; 6. It will be good if the model can tell the maximum licenses   an officer can issue in a specific ward/sub county/county. The model should have a tipping point/threshold to caution the over exploitation.
;; -- For the threshold-  the stakeholder wanted to know if there is a way the model can show maximum harvested wood- and then shows something like ‘danger”- meaning that the officer can allow further charcoal production.
end 

There is only one version of this model, created over 6 years ago by Richard Taylor.

Attached files

File Type Description Last updated
Charcoal.png preview Preview for 'Charcoal' over 6 years ago, by Richard Taylor Download
kitui_data.zip data GIS files need to be extracted into subdirectory kitui_data over 6 years ago, by Richard Taylor Download

This model does not have any ancestors.

This model does not have any descendants.