;changes (17/01/06): ;D now == C == 0 ;Ap now == P == 1 ;L no longer exists ;Ab == 2 (no tax for Ab) globals [ number_of_agent_clusters number_of_cover_clusters largest_patch mp_size prop_A prop_P prop_NA prop_Ab valueC valueP costC costP costAb farmCost prev_valueC prev_valueP prev_costC prev_costP prev_farmCost max_cover_value prop_lsp_cult ;propM ;propT timestep season year min_tot_patch_profit max_tot_patch_profit mean_tot_patch_profit market_patch_price market_pricesC market_pricesP market_costC market_costP market_farmCost agent_filename cluster_filename lsp_filename filename_mov ;agri_pop ;agri_pop_values mean_age death_probs spin-up ] ;--------------- patches-own [ cover cover_age previous_cover last_cover patch_best_alt tot_patch_profit est_patch_profit max_diffc lcap road_dist homestead agent_ID agent_cluster_ID previous_owner cover_cluster_ID cluster ;; Holds a patch which is that cluster's "leader" - arbitrarily chosen ] ;--------------- turtles-own [ ;wealth/profit variables wealth profit count_neg_profit tot_annual_profit est_wealth est_alt_wealth est_profit best_alternative set_price ;age variables age age_vari perspective ;square=Traditional circle=Modern largest_cluster_ID ;bid variables consider_bid bid max_bid bid_cover bid_x bid_y ;value estimate variables actual_value_diffcP actual_value_diffcC actual_cost_diffcP actual_cost_diffcC actual_cost_diffcFarm est_valueC est_valueP est_costC est_costP est_farmCost prev_est_valueC prev_est_valueP prev_est_costC prev_est_costP prev_est_farmCost ] ;--------------- to setup ca set timestep 0 set season 0 set year 0 setup_patches set spin-up true file-close-all file-open "NetLogo/death_probs.txt" set death_probs file-read file-close file-open "NetLogo/marketpricesC.txt" set market_pricesC file-read file-close file-open "NetLogo/marketpricesP.txt" set market_pricesP file-read file-close file-open "NetLogo/marketcostC.txt" set market_costC file-read file-close file-open "NetLogo/marketcostP.txt" set market_costP file-read file-close file-open "NetLogo/farmCost.txt" set market_farmCost file-read file-close set_values set prev_valueC valueC set prev_valueP valueP set prev_costC costC set prev_costP costP set prev_farmCost prev_farmCost set max_cover_value 0 if ( valueC > ( max_cover_value - 5 ) ) [ set max_cover_value ( valueC + 5 ) ] if ( valueP > ( max_cover_value - 5 ) ) [ set max_cover_value ( valueP + 5 ) ] ; set costC 1 ; set costP 1 ;set costP costP / 2 set costAb 0.1 ; set farmCost 1 setup_turtles ;set max_tfarm_size 50 ; set max_tfarm_size round ( (screen-size-x * screen-size-y) / number_of_farmers ) ask patches [ ;display_pixels set last_cover cover ] agent_cluster_counter cover_cluster_counter re-display set mean_age mean values-from turtles [ age ] set min_tot_patch_profit 999999 set max_tot_patch_profit -9999999 end ;--------------- ;--------------- to setup_turtles ; set-default-shape turtles "circle" crt number_of_farmers ask turtles [ ;set intial wealth/profit variables set wealth random 500 ;set initial age variables set age 0 while [ age < 25 ] [ set age ( random 60 ) ] ;set farmer perspective at random let pers_prob ( random-float 1 ) ifelse (pers_prob <= commercial_probability) [set shape "circle"] [set shape "square"] set_agent_cluster_ID ] ask turtles ;kill turtles without any patches (may occur when cluster_probability is high) [ if (not any? patches with [ agent_ID = who-of myself]) [ die ] ] ask turtles [ ;set bid initial variables set consider_bid false set bid false set max_bid 0 set bid_cover nobody set label who set best_alternative nobody set bid_x nobody set bid_y nobody set set_price 0 set count_neg_profit 0 set tot_annual_profit 0 ;set intial value estimate variables set actual_value_diffcP 0 set actual_value_diffcC 0 set actual_cost_diffcC 0 set actual_cost_diffcP 0 set actual_cost_diffcFarm 0 set est_valueC valueC set est_valueP valueP set est_costC costC set est_costP costP set est_farmCost farmCost set prev_est_valueC valueC set prev_est_valueP valueP set prev_est_costC costC set prev_est_costP costP set prev_est_farmCost farmCost ;set other variables set color 0 set largest_cluster_ID 0 without-interruption [ setup_agent_cluster_ID ;; set cluster IDs find_largest_cluster_ID set_cover_cluster_ID set_homestead ;;set homestead to random one of patches owned by agent ] move_home ] end ;--------------- ;--------------- to setup_patches set_random_seeds ;; randomly distribute cluster seeds (Step 1 in Saura & Martinez-Millan 2000 p.664) set_agent_ID ;; identify and label clusters (Steps 2 & 3 in above) fill_landscape ;; fill remaining patches to dominant neighbour (Step 4 in above) ask patches [ set previous_owner nobody set homestead nobody set cover_age 1 ;set lcap 1 + ( pxcor / 20 ) set road_dist 9999999 ;if (pxcor = 0 or pycor = 0) [ set road_dist 0 ] ] ;sets gradient of land capability from left to right across lansdcape ask patches [ set lcap 1 + ( pxcor / (max-pxcor * 2) ) ] ;sets a 'cross' road in lsp ask patches [ if (pxcor = 0 or pycor = 0) [ set road_dist 0 ] ] let roads patches with [ road_dist = 0 ] ask patches with [ road_dist != 0 ] [ ask roads [ let dist distance-nowrap myself if (dist < road_dist-of myself) [ set road_dist-of myself dist ] ] ] end ;--------------- ;--------------- to set_homestead ask one-of patches with [ (agent_ID = who-of myself) and (agent_cluster_ID = largest_cluster_ID-of myself) ] [ set homestead who-of myself ] ask patches with [ agent_ID = who-of myself ] [ if ( homestead != nobody ) [ set plabel ( who-of myself ) ] ] end ;--------------- ;--------------- to find_largest_cluster_ID let counter 0 let cluster_size 0 let largest_cluster 0 let s patches with [ agent_ID = who-of myself ] ifelse ( count s > 0 ) [ let t max-one-of s [ agent_cluster_ID ] let max_counter agent_cluster_ID-of t while [ counter < max_counter + 1 ] [ let p patches with [ agent_cluster_ID = counter and agent_ID = who-of myself ] if ( count p > cluster_size ) [ set cluster_size (count p) set largest_cluster counter ] set counter counter + 1 ] set largest_cluster_ID largest_cluster ] [ kill_agent ] end ;--------------- ;--------------- to go ;TIMESTEP AND DATAFILE MANAGEMENT set timestep timestep + 1 set season season + 1 set spin-up false if (timestep = 2) [ask turtles [ set wealth random 500 ] ] if ( year = run_length ) ;stop model run if the run length is completed [ stop ] if ( spin-up = false ) [ ;TIMESTEP MANAGEMENT show word "timestep: " timestep if ( remainder season 4 = 0 ) ;IF END OF YEAR [ set_values set year year + 1 ;INCREASE YEAR BY ONE show word "year: " year ask turtles [ set age age + 1 ;show word "Age: " age let rand_no random-float 1 ;; FARMER RETIREMENT AND DEATH PROCEDURES ifelse ( age = 65 ) ;IF FARMER HAS REACHED RETIREMENT AGE [ if ( shape = "circle" ) ;IF RETIRING FARMER IS MODERN [ ;show "I am a retiring Modern farmer." ifelse ( rand_no < (propM + 0.25) ) ;IF RANDOM NUMBER < PROPORTION OF MODERN FARMERS THEN SON INHERITS [ while [ age < 25 or age > 40 ] [ set age ( random 40 ) ] ;show word "My son inherits farm with age " age ] [ set shape "square" ;show "I have no son to inherit my farm. I will become a traditional farmer" ] ;ELSE SET FARMER PERSPECTIVE TO TRADITIONAL ] ] [ ;IF FARMER IS NOT OF RETIREMENT AGE CHECK IF HE DIES ifelse ( shape = "circle" ) ;IF FARMER IS MODERN [ let rand_death ( random-float 1 ) if ( rand_death < item age-of self death_probs ) ;IF FARMER DOES DIE [ ;show "I am a Modern Farmer dying of old age" ifelse ( age > 40 ) ;IF FARMER IS OLDER THAN 40 THERE IS A CHANCE HE HAS A SON TO INHERIT THE FARM [ let original_age age ifelse ( rand_no < (propM + 0.25) ) ;IF RANDOM NUMBER < PROPORTION OF MODERN FARMERS THEN SON INHERITS [ while [ age < 20 or age > 40 ] [ set age ( random (original_age - 20) ) ] ;show word "My son inherits my Modern Farm with age " age ] [ kill_agent ] ] [ kill_agent ] ] ] [ ;ELSE IF RETIRING FARMER IS TRADITIONAL let rand_death ( random-float 1 ) if ( rand_death < item age-of self death_probs ) ;IF FARMER DOES DIE [ ;show "I am a Traditional Farmer dying of old age" ifelse ( age > 40 ) ;IF FARMER IS OLDER THAN 40 HE HAS A SON TO INHERIT THE FARM [ let original_age age while [ age < 20 or age > 40 ] [ set age ( random (original_age - 20) ) ] ifelse ( (mean_tot_patch_profit + propM - ( 3 * age / 100 )) > 0 ) ;IF RANDOM NUMBER < PROPORTION OF MODERN FARMERS THEN SON INHERITS [ set shape "circle" ;show word "My son inherits farm as a Modern Farmer (I was Traditional) with age " age ] [ set rand_no random-float 1 ifelse ( rand_no < (propT + 0.25 ) ) [ ;show word "My son inherits farm as a Traditional Farmer with age " age ] [ kill_agent ] ] ] [ kill_agent ] ] ] ] ] ] ] set min_tot_patch_profit 999999 ;;for tot_patch_profit histogram set max_tot_patch_profit -9999999 ;;for tot_patch_profit histogram ;CALCULATE CURRENT WEALTH/PROFIT FOR MODERN FARMERS ;print "calculating wealth/profit for modern farmers" ask turtles with [ shape = "circle" ] [ show "calculate_profit" set profit calculate_profit - calc_farmCost set tot_annual_profit tot_annual_profit + profit set wealth ( wealth + profit ) ;calculate wealth in this timestep if (count patches with [ agent_ID = who-of myself and cover != 2 ] > max_tfarm_size) [ ;show word "farmCost is " calc_farmCost ] ] ;SET MEAN PATCH PRICE (MEASURE OF PROFITABILITY OF LSP AS A WHOLE) ifelse ( count turtles with [ shape = "circle" ] > 0 ) [ let modern_patches 0 let total_profit 0 ask turtles with [ shape = "circle" ] [ set modern_patches modern_patches + count patches with [ agent_ID = who-of myself ] ask patches with [ agent_ID = who-of myself ] [ set total_profit total_profit + tot_patch_profit ] set total_profit total_profit - calc_farmCost ] ifelse ( modern_patches > 0 ) [ set mean_tot_patch_profit total_profit / modern_patches ] [ set mean_tot_patch_profit 0 ] ] [ set min_tot_patch_profit min values-from patches [tot_patch_profit] ;;for tot_patch_profit histogram set max_tot_patch_profit max values-from patches [tot_patch_profit] ;;for tot_patch_profit histogram ] ;show word "mean patch profit is " mean_tot_patch_profit set_market_patch_price ;CHECK IF MODERN FARMERS ARE DOING POORLY (IF SO CHANGE TO TRADITIONAL) OR ARE BUST (IF SO, KILL) if ( remainder season 4 = 0 ) ;IF END OF YEAR [ ;IF PROFITABILITY OF WHOLE LSP IS HIGH, PROPORTION OF TRADITIONAL FARMERS IS LOW, AND AGE IS LOW, CHANGE TRADITIONAL FARMERS TO MODERN ask turtles with [ shape = "square" ] [ let score mean_tot_patch_profit + propM - ( 3 * age / 100 ) ;show word "change to Modern score (chg if > 0) " precision score 3 if ( score > 0 and age < 65 ) [ ;show "changing from traditional to modern perspective" set shape "circle" ] ] ask turtles with [ shape = "circle" ] [ ;show word "wealth " precision wealth 2 ;show word "annual profit " precision tot_annual_profit 2 ifelse ( tot_annual_profit < wealth * -0.05 ) ;IF LOSS ON YEAR IS GREATER THAN 5% OF TOTAL WEALTH [ set count_neg_profit count_neg_profit + 1 ;INCREASE count_neg_profit BY ONE set tot_annual_profit 0 ;show word "count_neg_profit set to " count_neg_profit ] [ set count_neg_profit 0 ;ELSE RE-SET count_neg_profit TO ZERO set tot_annual_profit 0 ] let rand_no random-float 1 if ( count_neg_profit >= 5 ) ;IF FARM HAS BEEN LOSS-MAKING FOR THE LAST 5 YEARS [ ifelse ( rand_no < (propT + 0.25) or age-of self >= 50 ) ;IF RANDOM NUMBER < PROPORTION OF TRADITIONAL FARMERS OR FARMER IS OLDER THAN 50 [ ;show "changing from modern to traditional perspective" set shape "square" ;SET perspective TO traditional set count_neg_profit 0 ;incase future descendent is modern and does poorly ] [ ;show "I died because I have been doing poorly as a modern farmer and I do not want to become a hobby farmer" kill_agent ] ] if ( wealth < 0 ) [ ifelse ( rand_no < (propT + 0.25) or age-of self >= 50 ) ;IF RANDOM NUMBER < PROPORTION OF TRADITIONAL FARMERS OR FARMER IS OLDER THAN 50 [ ;show "changing from modern to traditional perspective" set shape "square" ;SET perspective TO traditional set count_neg_profit 0 ;incase future descendent is modern and does poorly ] [ ;show "I died because my wealth < 0 and I do not want to become a hobby farmer" kill_agent ] ] set_patch_price ] ;CHECK SIZE OF TRADITIONAL FARMS ;show word "max_tfarm_size " max_tfarm_size without-interruption [ ask turtles with [ shape = "square" ] [ set_patch_price ifelse (count patches with [ agent_ID = who-of myself and cover != 2] > max_tfarm_size ) [ while [ count patches with [ agent_ID = who-of myself and cover != 2] > max_tfarm_size ] [ ;show word "Current farm size " count patches with [ agent_ID = who-of myself and cover != 2] ;ask min-one-of patches with [ agent_ID = who-of myself and cover != 2] [ tot_patch_profit ] ask max-one-of patches with [ agent_ID = who-of myself and cover != 2] [road_dist] [ set cover 2 ] ] ] [ if (any? patches with [ agent_ID = who-of myself and cover = 2 ] and (count patches with [ agent_ID = who-of myself and cover != 2] < max_tfarm_size) ) [ ask max-one-of patches with [ agent_ID = who-of myself and cover = 2 ] [lcap] [ ifelse (lcap > 1) [ set cover 0 ] [ set cover 1 ] ] ] ] ] ] ] ;DISPLAY ROUTINE ;ask patches ;[ ; display_pixels ;] re-display ;;farmers can only convert one pixel per time-step ;;farmers modify their own land before considering other land ;MODERN FARMERS ESTIMATE PROFIT FOR NEXT TIMESTEP AND CHANGE OWN LAND ACCORDINGLY ask turtles with [ shape = "circle" ] [ show "calculate_est_profit" set est_wealth ( wealth + calculate_est_profit - calc_farmCost) ;;Calculate est_wealth for next time step with current land configuration ;show word "est_wealth " est_wealth set est_alt_wealth est_wealth without-interruption [ alternatives ;;'alternatives' calculates est_wealth for next time step with least profitable patch in alternative states set_alt_covers ;;(current, converted, abandoned) and changes the least profitable patch to that state ] ;show word "best alternative is " best_alternative ] ask turtles [ move_home ] ;CHECK IF SPIN-UP COMPLETE if ( spin-up = true ) [ if ( not any? turtles with [ consider_bid = false ] ) [ set spin-up false ;exit "spin-up" next timestep print "exiting spin-up" ask turtles [ set wealth wealth / 10 ] ] ] ;IF SPIN-UP COMPLETE AND YEAR-END if ( spin-up = false and remainder season 4 = 0 ) [ ask turtles with [ shape = "circle" ] [ ;IF MODERN FARMERS' LAND IS CURRENTLY IN OPTIMAL STATE CONSIDER BIDDING FOR OTHER'S LAND ifelse ( best_alternative = nobody ) [ set consider_bid true ;;If state does not change set consider_bid to true for next "ask turtles" call ] [ set est_wealth est_alt_wealth ;;Else set new estimated wealth for new configuration (no need for this if no change!) set bid false ;;No bid is to be made move_home ] ;show word "Consider bid? " consider_bid if ( consider_bid = true ) ;;If least profitable patch did not change [ without-interruption [ ;show "Finding dead neighbours " find_dead_neighbours ;;examines all 'dead' patches neighbouring this turtles' patches ] ;;finds most profitable patch/option and move turtle to that patch ; ;;sets bid to true ifelse ( bid = false ) ;;if no bid is to be made by this agent [ move_home ;;move the turtle to one of its own patches (needed for make_bids below) ;show "no bid to be made" ] [ show "making a bid" make_bids ] ] ] ;RE-SET TURTLES READY FOR NEXT TIMESTEP ask turtles [ move_home set bid false ;;reset bid variables set bid_cover nobody set max_bid 0 set bid_x nobody set bid_y nobody if ( remainder season 4 = 0 ) [ set_est_values ] set_agent_cluster_ID ;calculate necessary parameters for next timestep set_cover_cluster_ID ] ] ;RE-SET PATCHES FOR NEXT TIMESTEP if (any? patches with [agent_ID = nobody]) [ ask patches [ if ( agent_ID = nobody and cover != -1 ) [ set cover 2 ] ;;set all dead patches to cover = nobody (this was not done at the end of find_dead_neighbours ;;so that make_bids does not need to assign the patch to an agent ] set_nobody_cluster_ID ] ;STOP MODEL RUN IF ALL FARMS HAVE DIED if (count turtles = 0 ) [ stop ] ;CODE FOR OUTPUT DATAFILES AND PLOTS set mean_age mean values-from turtles [ age ] ; ask patches [ display_pixels ] re-display agent_cluster_counter cover_cluster_counter setup_patch_profit_histogram min_tot_patch_profit max_tot_patch_profit do_patch_profit_histogram if ( spin-up = false ) [ ;setup_wealth_plot ;do_wealth_plot if ( remainder season 4 = 0 ) [ setup_cover_plot do_cover_plot setup_value_plot max_cover_value do_value_plot ask patches [ ifelse ( cover = last_cover ) [ set cover_age cover_age + 1 ] [ set cover_age 1 set last_cover cover ] ] set season 0 ] ] end ;--------------- ;--------------- to set_patch_price set set_price ( ( wealth-of self ) / ( count patches with [ agent_ID = who-of myself ] ) ) if ( set_price < market_patch_price ) [ set set_price market_patch_price ] end ;--------------- ;--------------- to set_market_patch_price set market_patch_price 40 * mean_tot_patch_profit if ( market_patch_price < 1 ) [ set market_patch_price 1 ] end ;--------------- ;--------------- to make_bids show "Bidding for patches" ifelse ( agent_ID-of patch-here != nobody ) [ ifelse ( count other-turtles-here < 1 ) [ ;show "I am the only turtle bidding" ifelse ( max_bid-of self > set_price-of turtle (agent_ID-of patch-here) ) [ ;show word "Bid successful with max_bid of: "max_bid ;show word "Patch cost me " set_price-of turtle (agent_ID-of patch-here) ;show word "Bought from turtle " agent_ID-of patch-here set agent_ID-of patch-here who-of self set cover-of patch-here bid_cover set wealth ( wealth - ( set_price-of turtle (agent_ID-of patch-here) ) - set_conv_cost 2 bid_cover ) ] [ ;show word "Bid unsuccesful for " patch-here ;show word "I bid " max_bid ;show word "asking price was " set_price-of turtle (agent_ID-of patch-here) ] ] [ ;show "There are other turtles bidding" ifelse ( count other-turtles-here with [ max_bid > max_bid-of myself ] > 0 ) [ if ( max_bid-of self > set_price-of turtle (agent_ID-of patch-here) ) [ set set_price-of turtle (agent_ID-of patch-here) ( max_bid-of self + 1 ) ;show word "Bid unsuccesful for " patch-here ;show word "I was outbid bid. My bid was " max_bid ] ] [ ifelse ( max_bid-of self > set_price-of turtle (agent_ID-of patch-here) ) [ ;show word "Bid successful with max_bid of: "max_bid ;show word "Patch cost me " set_price-of turtle (agent_ID-of patch-here) ;show word "Bought from turtle " agent_ID-of patch-here set agent_ID-of patch-here who-of self set cover-of patch-here bid_cover set wealth ( wealth - ( set_price-of turtle (agent_ID-of patch-here) ) - set_conv_cost 2 bid_cover ) ] [ ;show word "Bid unsuccesful for " patch-here ;show word "I bid " max_bid ;show word "asking price was " set_price-of turtle (agent_ID-of patch-here) ] ] ] ] [ ;show "Nobody owns the patch I am bidding for" ifelse ( count other-turtles-here < 1 ) [ ;show "I am the only turtle bidding" ifelse ( max_bid-of self > market_patch_price ) [ ;show word "Bid successful with max_bid of: "max_bid ;show word "Patch cost me " market_patch_price set agent_ID-of patch-here who-of self set cover-of patch-here bid_cover set wealth ( wealth - market_patch_price - set_conv_cost 2 bid_cover) ] [ ;show word "Bid unsuccesful for " patch-here ;show word "I bid " max_bid ;show word "asking price was " market_patch_price ] ] [ ;show "There are other turtles bidding" ifelse ( count other-turtles-here with [ max_bid > max_bid-of myself ] > 0 ) [ if ( max_bid-of self > market_patch_price ) [ set market_patch_price ( max_bid-of self + 1 ) ;show word "Bid unsuccesful for " patch-here ;show word "I was outbid bid. My bid was " max_bid ] ] [ ifelse ( max_bid-of self > market_patch_price ) [ ;show word "Bid successful with max_bid of: "max_bid ;show word "Patch cost me " market_patch_price set agent_ID-of patch-here who-of self set cover-of patch-here bid_cover set wealth ( wealth - market_patch_price - set_conv_cost 2 bid_cover ) ] [ ;show word "Bid unsuccesful for " patch-here ;show word "I bid " max_bid ;show word "asking price was " market_patch_price ] ] ] ] end ;--------------- to set_est_values set actual_value_diffcC ( valueC - prev_valueC ) set actual_value_diffcP ( valueP - prev_valueP ) set actual_cost_diffcC ( costC - prev_costC ) set actual_cost_diffcP ( costP - prev_costP ) set actual_cost_diffcFarm ( farmCost - prev_farmCost ) set prev_est_valueC est_valueC set prev_est_valueP est_valueP set prev_est_costC est_costC set prev_est_costP est_costP set prev_est_farmCost est_farmCost set est_valueC ( ( valueC + actual_value_diffcC + ( random-float 0.5 * ( valueC - prev_est_valueC ) ) ) ) set est_valueP ( ( valueP + actual_value_diffcP + ( random-float 0.5 * ( valueP - prev_est_valueP ) ) ) ) set est_costC ( ( costC + actual_cost_diffcC + ( random-float 0.5 * ( costC - prev_est_costC ) ) ) ) set est_costP ( ( costP + actual_cost_diffcP + ( random-float 0.5 * ( costP - prev_est_costP ) ) ) ) set est_farmCost ( ( farmCost + actual_cost_diffcFarm + ( random-float 0.5 * ( farmCost - prev_est_farmCost ) ) ) ) end ;--------------- to set_random_seeds ask patches [ set agent_ID nobody ;; initially no patches have an agent_ID set agent_cluster_ID nobody ;; initially no patches have an agent_cluster_ID set cluster nobody ;; initially no patches are in a cluster ] ask patches [ ifelse ( (random-float 1) < cluster_probability ) ;set patch as seed if rand no is less than cluster_probability [ set pcolor blue ] [ set pcolor red ] ] end ;--------------- ;--------------- to set_agent_ID loop [ let seed one-of patches with [ ( cluster = nobody and pcolor = blue ) ] ;; pick a random seed we haven't labelled yet if seed = nobody ;; if we have labelled all seeds stop [ stop ] ask seed [ set cluster self ;; make the seed the "leader" of a new cluster by assigning itself to its own cluster set agent_ID ( random number_of_farmers ) ;; assign this "leader" a random agent_ID ;set cover ( random 2 ) ;; assign assign this "leader" a random cover grow-agent_cluster ;; then grow-agent_cluster to find the rest of the cluster ] ] end ;--------------- ;--------------- to grow-agent_cluster ;; patch procedure without-interruption ;; we use without-interruption here so each patch only gets added to the cluster once [ ask patches in-radius-nowrap 1 with [ cluster = nobody and pcolor = pcolor-of myself ] ;; check neighbours - no screen-edge wrap! [ set cluster cluster-of myself ;;assign neighbouring patch to "leader" patch agent-cluster set agent_ID agent_ID-of myself ;;assign neighbouring patch to "leader" patch agent_ID ;set cover cover-of myself ;;assign neighbouring patch to "leader" patch cover grow-agent_cluster ;;recursive call! ] ] end ;--------------- ;--------------- to fill_landscape ;; assign patches not initially assigned (to dominant agent in neighbourhood loop [ if ( not any? patches with [ cluster = nobody ] ) ;;if all patches have been assigned to an agent-cluster [ stop ] ask one-of patches with [ cluster = nobody ] ;;pick a patch that has not been assigned to an agent-cluster yet [ ifelse ( any? patches in-radius-nowrap 1 with [ cluster != nobody ] ) ;; check if there are any assigned patches in neighbourhood (no-wrap!) [ ;; if so... let counts [] ;; create list to hold counts of agents let agent_number 0 ;; set dummy agent counter while [ agent_number < number_of_farmers ] ;; while dummy agent counter < max no of agents [ let temp_count 0 if ( any? patches in-radius-nowrap 1 with [ agent_ID = agent_number ] ) [ set temp_count ( count patches in-radius-nowrap 1 with [ agent_ID = agent_number ] ) ] set counts lput temp_count counts set agent_number ( agent_number + 1 ) ] set agent_number 0 let max_count 0 let max_agent 0 without-interruption ;; we use without-interruption here so foreach iterator is not interrupted [ foreach counts ;; iterate through counts list [ if ( ? > max_count ) ;; if current counts list value > max_count [ set max_count ? ;; set current counts list value to max_count set max_agent agent_number ] set agent_number ( agent_number + 1 ) ] ] let p one-of patches in-radius-nowrap 1 with [ agent_ID = max_agent ] ;;assign qualities of one of dominant neighbours to patch (no wrap!) set pcolor pcolor-of p set cluster cluster-of p set agent_ID agent_ID-of p ;set cover cover-of p ] [ ;; if no assigned agents in neighbourhood assign an agent at random set agent_ID ( random number_of_farmers ) ;set cover ( random 2 ) set cluster self ;; remember to start a new cluster! ] ] ] end ;--------------- ;--------------- to set_cover_cluster_ID ask patches with [ agent_ID = who-of myself ] [ set cluster nobody set cover_cluster_ID nobody] let counter 0 ;; counter to give sequential cluster_IDs loop [ let p one-of patches with [ cover_cluster_ID = nobody and agent_ID = who-of myself ] ;; pick a random patch we haven't labelled yet (and is owned by ) if ( p = nobody ) [ stop ] ask p [ set cluster self ;; make the seed the "leader" of a new cluster by assigning itself to its own cluster set cover_cluster_ID counter ;; assign this "leader" a cluster_ID ;set plabel counter ;; assign this "leader" a label equal to the cluster_ID (remove ";" to view) grow-patch_cover_cluster ;; then grow-patch_cluster to find the rest of the cluster ] set counter counter + 1 ;set number_of_clusters ( counter - 1 ) ;; output to "No. of Clusters" monitor ] end ;--------------- ;--------------- to grow-patch_cover_cluster ;; patch procedure for use in conjunction with set_cluster_ID without-interruption ;; we use without-interruption here so each patch only gets added to the cluster once [ ask patches in-radius-nowrap 1 with [ cluster = nobody and agent_ID = agent_ID-of myself and cover = cover-of myself ] [ set cluster cluster-of myself ;;assign neighbouring patch to "leader" patch patch_cluster set cover_cluster_ID cover_cluster_ID-of myself ;;assign neighbouring patch to "leader" patch cluster_ID ;set plabel cover_cluster_ID-of myself grow-patch_cover_cluster ;;recursive call! ] ] end ;--------------- ;--------------- to setup_agent_cluster_ID ask patches with [ agent_ID = who-of myself ] [ set cluster nobody set agent_cluster_ID nobody] let counter 0 ;; counter to give sequential cluster_IDs loop [ let p one-of patches with [ agent_cluster_ID = nobody and agent_ID = who-of myself ] ;; pick a random patch we haven't labelled yet (and is owned by ) if ( p = nobody ) [ stop ] ask p [ set cluster self ;; make the seed the "leader" of a new cluster by assigning itself to its own cluster set agent_cluster_ID counter ;; assign this "leader" a cluster_ID set cover ( random 2 ) ;set plabel counter ;; assign this "leader" a label equal to the cluster_ID (remove ";" to view) grow-patch_agent_cluster_setup ;; then grow-patch_cluster to find the rest of the cluster ] set counter counter + 1 ;set number_of_clusters ( counter - 1 ) ;; output to "No. of Clusters" monitor ] end ;--------------- ;--------------- to set_agent_cluster_ID ask patches with [ agent_ID = who-of myself ] [ set cluster nobody set agent_cluster_ID nobody] let counter 0 ;; counter to give sequential cluster_IDs loop [ let p one-of patches with [ agent_cluster_ID = nobody and agent_ID = who-of myself ] ;; pick a random patch we haven't labelled yet (and is owned by ) if ( p = nobody ) [ stop ] ask p [ set cluster self ;; make the seed the "leader" of a new cluster by assigning itself to its own cluster set agent_cluster_ID counter ;; assign this "leader" a cluster_ID ;set cover ( random 2 ) ;set plabel counter ;; assign this "leader" a label equal to the cluster_ID (remove ";" to view) grow-patch_agent_cluster ;; then grow-patch_cluster to find the rest of the cluster ] set counter counter + 1 ;set number_of_clusters ( counter - 1 ) ;; output to "No. of Clusters" monitor ] end ;--------------- ;--------------- to set_nobody_cluster_ID ask patches with [ agent_ID = nobody and cover = 2 ] [ set cluster nobody set agent_cluster_ID nobody] let counter 0 ;; counter to give sequential cluster_IDs loop [ let p one-of patches with [ agent_cluster_ID = nobody and agent_ID = nobody and cover = 2 ] ;; pick a random patch we haven't labelled yet (and is owned by ) if ( p = nobody ) [ stop ] ask p [ set cluster self ;; make the seed the "leader" of a new cluster by assigning itself to its own cluster set agent_cluster_ID counter ;; assign this "leader" a cluster_ID ;set cover ( random 2 ) ;set plabel counter ;; assign this "leader" a label equal to the cluster_ID (remove ";" to view) grow-patch_agent_cluster ;; then grow-patch_cluster to find the rest of the cluster ] set counter counter + 1 ;set number_of_clusters ( counter - 1 ) ;; output to "No. of Clusters" monitor ] end ;--------------- ;--------------- to agent_cluster_counter set number_of_agent_clusters 0 ask turtles [ set number_of_agent_clusters ( number_of_agent_clusters + ( max values-from patches with [agent_ID = who-of myself] [ agent_cluster_ID ] ) + 1 ) ] end ;--------------- ;--------------- to cover_cluster_counter set number_of_cover_clusters 0 ask turtles [ set number_of_cover_clusters ( number_of_cover_clusters + ( max values-from patches with [agent_ID = who-of myself] [ cover_cluster_ID ] ) + 1 ) ] end ;--------------- ;--------------- to grow-patch_agent_cluster_setup ;; patch procedure for use in conjunction with set_cluster_ID without-interruption ;; we use without-interruption here so each patch only gets added to the cluster once [ ask patches in-radius-nowrap 1 with [ cluster = nobody and agent_ID = agent_ID-of myself ] [ set cluster cluster-of myself ;;assign neighbouring patch to "leader" patch patch_cluster set agent_cluster_ID agent_cluster_ID-of myself ;;assign neighbouring patch to "leader" patch cluster_ID set cover cover-of myself grow-patch_agent_cluster_setup ;;recursive call! ] ] end ;--------------- ;--------------- to grow-patch_agent_cluster ;; patch procedure for use in conjunction with set_cluster_ID without-interruption ;; we use without-interruption here so each patch only gets added to the cluster once [ ask patches in-radius-nowrap 1 with [ cluster = nobody and agent_ID = agent_ID-of myself ] [ set cluster cluster-of myself ;;assign neighbouring patch to "leader" patch patch_cluster set agent_cluster_ID agent_cluster_ID-of myself ;;assign neighbouring patch to "leader" patch cluster_ID ;set plabel agent_cluster_ID-of myself grow-patch_agent_cluster ;;recursive call! ] ] end ;--------------- ;--------------- to display_pixels ;;display the patches with colours according to their owner and cover type ifelse ( agent_ID = nobody ) [ set pcolor 9.9999 ] [ ifelse ( agent_ID = 0 or ( remainder agent_ID 10 = 0 ) ) [ if (cover = 0) [ set pcolor 113 if (patch-labels = true) [set plabel cover]] if (cover = 1) [ set pcolor 114 if (patch-labels = true) [set plabel cover]] if (cover = 2) [ set pcolor 115 if (patch-labels = true) [set plabel cover]] ] [ if (cover = 0 ) [ set pcolor (( (remainder agent_ID 10) * 10 ) + 3 ) if (patch-labels = true) [set plabel cover]] if (cover = 1 ) [ set pcolor (( (remainder agent_ID 10) * 10 ) + 5 ) if (patch-labels = true) [set plabel cover]] if (cover = 2 ) [ set pcolor (( (remainder agent_ID 10) * 10 ) + 7 ) if (patch-labels = true) [set plabel cover]] ] ] end ;--------------- ;--------------- to set_patch_cover ;; sets initial cover type randomly ask patches [ set cover ( random 2 ) ] ;;CHANGE TO ACOUNT FOR INITIAL PROPORTION end ;--------------- ;--------------- to do_cover_plot set-current-plot-pen "C" plot ( ( count patches with [ cover = 0 ] ) / ( count patches with [ cover != -1 ] ) ) set-current-plot-pen "P" plot ( ( count patches with [ cover = 1 ] ) / ( count patches with [ cover != -1 ] ) ) set-current-plot-pen "Ab_owned" plot ( ( count patches with [ cover = 2 ] ) / ( count patches with [ cover != -1 ] ) ) ;set-current-plot-pen "Ab_unowned" ;plot ( ( count patches with [ cover = -1 ] ) / ( count patches != -1 ) ) end ;--------------- ;--------------- to setup_cover_plot set-current-plot "Cover Type" set-plot-y-range 0 1 end ;--------------- ;--------------- to do_value_plot set-current-plot-pen "C" plot ( valueC ) set-current-plot-pen "P" plot ( valueP ) end ;--------------- ;--------------- to setup_value_plot [ max_val ] set-current-plot "Cover Values" set max_val precision max_val 1 set-plot-y-range 0 max_val end ;--------------- ;--------------- to setup_patch_profit_histogram [ min_val max_val ] set-current-plot "Patch Profit" set max_val precision max_val 1 set min_val precision min_val 1 set-plot-x-range ( min_val - 1 ) ( max_val + 1 ) set-plot-y-range 0 count patches with [ agent_ID != nobody ] set-histogram-num-bars 10 end ;--------------- ;--------------- to do_patch_profit_histogram histogram-from patches [ tot_patch_profit ] end ;--------------- ;--------------- to-report calculate_profit ;;calculates profit for an agent let profit_C 0 let profit_P 0 let profit_abandoned 0 ;let tage age without-interruption [ ask patches with [ agent_ID = who-of myself and cover = 0 ] [ set tot_patch_profit ( ( valueC * lcap ) - (calc_frag * 2 * costC ) - (road_dist / world-width) ) set profit_C ( profit_C + tot_patch_profit ) if ( tot_patch_profit < min_tot_patch_profit ) [ set min_tot_patch_profit tot_patch_profit ] ;;for profit histogram if ( tot_patch_profit > max_tot_patch_profit ) [ set max_tot_patch_profit tot_patch_profit ] ;;for profit histogram ] ask patches with [ agent_ID = who-of myself and cover = 1 ] [ set tot_patch_profit (( valueP * lcap ) - costP - (road_dist / world-width) ) set profit_P ( profit_P + tot_patch_profit ) if ( tot_patch_profit < min_tot_patch_profit ) [ set min_tot_patch_profit tot_patch_profit ] ;;for profit histogram if ( tot_patch_profit > max_tot_patch_profit ) [ set max_tot_patch_profit tot_patch_profit ] ;;for profit histogram ] ask patches with [ agent_ID = who-of myself and cover = 2 ] [ set tot_patch_profit ( -1 * costAb ) ;;if abandoned set profit to zero (minus costs) set profit_abandoned ( profit_abandoned - costAb ) if ( tot_patch_profit < min_tot_patch_profit ) [ set min_tot_patch_profit -1 * costAb ] if ( tot_patch_profit > max_tot_patch_profit ) [ set max_tot_patch_profit -1 * costAb ] ] ] set profit ( profit_C + profit_P + profit_abandoned ) ;;profit_abandoned included here in case where all patches are abandoned ;show word "profit" profit report profit end ;--------------- ;--------------- to-report calculate_est_profit ;;calculates an agent's estimated profit for the next time step let est_profit_C 0 let est_profit_P 0 let est_profit_abandoned 0 let tage age let temp0 0 let temp1 0 let temp2 0 ;without-interruption ;[ ask patches with [ agent_ID = who-of myself and cover = 0 ] [ set temp0 ( est_valueC-of myself * lcap ) - (calc_frag * 2 * costC ) - (road_dist / world-width) set est_profit_C ( est_profit_C + temp0 ) ] ask patches with [ agent_ID = who-of myself and cover = 1 ] [ set temp1 ( est_valueP-of myself * lcap ) - costP - (road_dist / world-width) set est_profit_P ( est_profit_P + temp1 ) ] ask patches with [ agent_ID = who-of myself and cover = 2 ] [ set est_profit_abandoned ( est_profit_abandoned - costAb ) ;;if abandoned set profit to zero ] ;] set est_profit ( est_profit_C + est_profit_P + est_profit_abandoned ) ;;est_profit_abandoned included here in case where all patches are abandoned report est_profit end ;--------------- ;--------------- to kill_agent ;;if agent dies of old age or goes bust (i.e. wealth falls beow zero) ask patches with [ agent_ID = who-of myself ] [ reset_patch ] die ;;kill turtle!! end ;--------------- ;--------------- to reset_patch set agent_ID nobody ;;clear patch variable values set agent_cluster_ID nobody set cover_cluster_ID nobody set cover 2 ;;set cover to abandoned! needed for set_conv_cost procedure set est_patch_profit -999999 set tot_patch_profit -999999 set previous_cover nobody set patch_best_alt nobody set homestead nobody set plabel "" set previous_owner nobody set max_diffc -999999 end ;--------------- ;--------------- to alternatives ;;calculates the best options for patches owned by agent and set this as patch_best_alt ;;if the best option results in no change in cover sets as nobody ;;options are 0 (C), 1 (P), 2 (abandoned) show "checking alternatives" set best_alternative nobody ;;turtle variable set consider_bid false ;;turtle variable ; let max_patch_profit -999999 let ID who-of self ask patches with [ agent_ID = who-of myself ] [ set patch_best_alt nobody ;;holds the best alternative option for this patch ] loop [ set est_alt_wealth est_wealth let this_patch one-of patches with [ patch_best_alt = nobody and agent_ID = who-of myself ] if ( this_patch = nobody ) [ stop ] ;;ask patches that have not been assessed yet (i.e. patch_best_alt = nobody let current_option cover-of this_patch ;;holds the current best option (cover type) ; let duration cover_age-of this_patch ;;holds cover_age set previous_cover-of this_patch cover-of this_patch ;;two previous_cover variables here. this one is owned by patch ; let max_diffc 0 ; show word "current_option is " current_option ; show word "previous_cover is " previous_cover-of this_patch ;;stop if all have been assessed ask this_patch [ if (previous_cover != 0) [ set cover 0 ;;option 1 is cover = 0 ; show "cover set to 0" ; show word "current_option is " current_option ;show word "previous_cover is " previous_cover ] ] set_cover_cluster_ID ;set_cover_cluster_ID is a turtle function so need to break out of asking patch ask this_patch [ set est_patch_profit ( est_valueC-of turtle ID * lcap ) - (calc_frag * 2 * costC ) - (road_dist / world-width) set est_patch_profit est_patch_profit - set_conv_cost previous_cover 0 ;show word "max_diffc is " max_diffc if( (est_patch_profit - tot_patch_profit) > max_diffc ) ;;if profitability with this patch cover improves the patch's profitability [ set max_diffc (est_patch_profit - tot_patch_profit) ;;set this patch's profit to the best profit set current_option 0 ;;set this option to the current best option ; show word "max_diffc changed to " max_diffc ; show word "current option is " current_option ;show word "previous_cover is " previous_cover ] if (previous_cover != 1) [ set cover 1 ;;option 2 is cover = 1 ; show "cover set to 1" ; show word "current_option is " current_option ;show word "previous_cover is " previous_cover ] ] set_cover_cluster_ID ;set_cover_cluster_ID is a turtle function so need to break out of asking patch ask this_patch [ set est_patch_profit ( est_valueP-of turtle ID * lcap ) - costP - (road_dist / world-width) set est_patch_profit est_patch_profit - set_conv_cost previous_cover 1 ; show word "max_diffc is " max_diffc if( (est_patch_profit - tot_patch_profit) > max_diffc ) ;;if profitability with this patch cover improves the patch's profitability [ set max_diffc (est_patch_profit - tot_patch_profit) ;;set this patch's profit to the best profit set current_option 1 ;;set this option to the current best option ; show word "max_diffc changed to " max_diffc ; show word "current option is " current_option ; show word "previous_cover is " previous_cover ] if (previous_cover != 2) [ set cover 2 ;;option 3 is cover = 2 ; show "cover set to 2" ; show word "current_option is " current_option ; show word "previous_cover is " previous_cover ] ] set_cover_cluster_ID ;set_cover_cluster_ID is a turtle function so need to break out of asking patch ask this_patch [ set est_patch_profit -1 * costAb ; show word "max_patch_profit is " max_diffc if( (est_patch_profit - tot_patch_profit) > max_diffc ) ;;if profitability with this patch cover improves the patch's profitability [ set max_diffc (est_patch_profit - tot_patch_profit) ;;set this patch's profit to the best profit set current_option 2 ;;set this option to the current best option ; show word "max_diffc changed to " max_diffc ; show word "current option is " current_option ; show word "previous_cover is " previous_cover ] ] ifelse (current_option = previous_cover-of this_patch) [ ; show "current_option = previous_cover-of this patch" ;show word "current_option is " current_option ; show word "previous_cover-of this_patch is " previous_cover-of this_patch ; show word "previous_cover is " previous_cover ask this_patch [ set cover previous_cover set patch_best_alt -999 ;;set to dummy value so no selected by initial ask patches call of this procedure set previous_cover -999 ; show word "cover re-set to " cover ; show word "patch_best_alt set to " patch_best_alt ; show word "previous_cover-of this_patch is " previous_cover-of this_patch ; show word "previous_cover is " previous_cover ] ] [ set est_alt_wealth ( wealth + calculate_est_profit - set_conv_cost previous_cover-of this_patch current_option - calc_farmCost) ;;if land is to be converted we need to assess how the cost of conversion inluences total agent est_wealth ifelse ( est_alt_wealth > est_wealth ) [ ask this_patch [ set patch_best_alt current_option ;;set the patch's best alternative to the current option set cover previous_cover ;;but re-set the cover to the original (we will set the cover if indeed it does change in set_best_alts) ; show word "cover re-set to " cover ; show word "patch_best_alt set to " patch_best_alt ; show word "previous_cover-of this_patch is " previous_cover-of this_patch ; show word "previous_cover is " previous_cover ] ] [ ask this_patch [ set cover previous_cover set patch_best_alt -999 ;;set to dummy value so no selected by initial ask patches call of this procedure set previous_cover -999 ; show word "patch_best_alt set to " patch_best_alt ; show word "previous_cover-of this_patch is " previous_cover-of this_patch ; show word "previous_cover is " previous_cover ] ] ] ] end ;--------------- ;--------------- to set_alt_covers ;;changes patch cover according to the best alternative set by alternatives ;;unlimited changes are allowed for conversions that do not cost the agent anything (i.e. down the ladder of covers) ;;e.g. from D or Ap to L, or from anythng to abandoned ;;only one change "up the ladder" is allowed (i.e. conversions that cost the agent) e.g. from anything to D let alts patches with [ agent_ID = who-of myself and previous_cover != -999 ] ;;previous_cover was set to -999 if best alternative was nobody ask alts ;;allow unlimited changes down the ladder of covers [ without-interruption [ if ( patch_best_alt = 2 ) ;;these calls are for changes "down the ladder". All conversions are made [ ;show word "set cover to (d) " patch_best_alt set cover patch_best_alt set previous_cover -999 ;;set to -999 so not selected fo "up" change below ] if ( patch_best_alt = 1 and previous_cover = 0 ) [ ;show word "set cover to (d)" patch_best_alt set cover patch_best_alt set previous_cover -999 ] if ( patch_best_alt = nobody ) [ set previous_cover -999 ;show word "set cover to (d)" patch_best_alt ] ] ] let temp_xcor 0 ;;temporary variable to hold x co-ord of patch let temp_ycor 0 ;;temporary variable to hold y co-ord of patch let best_alt nobody set alts patches with [ agent_ID = who-of myself and previous_cover != -999 ] ;;ask patches that want to change up the ladder if ( count alts > 0 ) ;;check if there are any patches that want to change up! [ ; show word "count of alts is " count alts ask max-one-of alts [ max_diffc ] ;;change the patch that will increase profit most [ set cover patch_best_alt set temp_xcor pxcor set temp_ycor pycor ;show word "set cover to (up)" patch_best_alt set best_alt patch_best_alt ] ] ifelse ( count alts > 0 ) [ set best_alternative best_alt ;;set agent's best alternative setxy temp_xcor temp_ycor ;;move agent to that patch ] [ ; show "count of alts not > 0" set best_alternative nobody ;;if none to change set nobody (agent will then find dead neighbours) move_home ] end ;--------------- ;--------------- to find_dead_neighbours show "find_dead_neighbours" ;;STEP 1. Generate agentset of dead neighbours let temp_dead_neighbours [] ;;list to hold patches and their profit values (convert to agentset below) let temp_alt_wealth 0 without-interruption [ ask patches with [ agent_ID = who-of myself ] [ ask patches in-radius-nowrap 1 with [ cover = 2 and agent_ID != agent_ID-of myself and agent_ID != 999 and homestead = nobody ] [ set temp_dead_neighbours lput self temp_dead_neighbours set previous_owner agent_ID set agent_ID 999 ;;dummy (non-nobody) set so not added to temp_dead_neighbours twice ] ] ] let dead_neighbours patches with [ member? self temp_dead_neighbours ] ;;convert list to an agentset ;;STEP 2. Evaluate each member of dead neighbours agentset for their relative profitability if ( count dead_neighbours > 0 ) [ ;let neighbour_found 0 let current_option nobody ;;dummy variable to hold the current best option (cover type) ;let temp_profit 0 ;;dummy variable to hold current patch profit value let temp_xcor 0 ;;temporary variable to hold x co-ord of patch let temp_ycor 0 ;;temporary variable to hold y co-ord of patch ;let tage age ;let ID who-of self set bid false loop ;;at the start of this loop we will move the turtle to the patch being considered and use ask patch-here [ ;;we can then break out from asking a patch to make a turtle call for frag_value or agent_cluster_ID set current_option nobody let duration 0 without-interruption[ let this_patch one-of dead_neighbours ;[ ; set temp_xcor pxcor ; set temp_ycor pycor ;] ;setxy temp_xcor temp_ycor ;;move the agent to the patch under consideration and use patch-here ;ask this_patch [ set duration cover_age ] ask this_patch [ set cover 0 ;;option 1 is cover = 0 set agent_ID who-of myself ] ;show word "cover set to " cover ;show word "frag_value " frag_value ;show word "agent_ID set to " agent_ID ;;need to break out of ask patch as only a turtle can call cluster_ID and frag_value procedures set_agent_cluster_ID set_cover_cluster_ID set temp_alt_wealth ( wealth + calculate_est_profit - set_conv_cost 2 0 - calc_farmCost) if ( temp_alt_wealth > est_alt_wealth ) [ set est_alt_wealth temp_alt_wealth set temp_alt_wealth 0 set current_option 0 ;;set this option to the current best option ] ask this_patch [ set cover 1 ] ;;option 2 is cover =1 ;show word "cover set to " cover ;show word "frag_value " frag_value ;set_agent_cluster_ID ;calculate_frag_value ;;frag_values need to be recalculated for calculate_bought-pixel_profit on next line ;;we use calculate_agent_frag_value because a single an agent is making the call ;ifelse (previous_owner = nobody) ;[ set temp_alt_wealth ( wealth + calculate_est_profit - set_conv_cost 2 1 - market_patch_price ) ] ;;if land is to be converted we need to assess how the cost of conversion inluences total agent est_wealth ;[ set temp_alt_wealth ( wealth + calculate_est_profit - set_conv_cost 2 1 - set_price-of turtle previous_owner ) ];show word "temp_alt_wealth " temp_alt_wealth set_agent_cluster_ID set_cover_cluster_ID set temp_alt_wealth ( wealth + calculate_est_profit - set_conv_cost 2 1 - calc_farmCost) if ( temp_alt_wealth > est_alt_wealth ) [ set est_alt_wealth temp_alt_wealth set temp_alt_wealth 0 set current_option 1 ;;set this option to the current best option ] if (current_option != nobody ) [ let temp_x pxcor-of this_patch let temp_y pycor-of this_patch setxy temp_x temp_y set bid_cover current_option set bid_x pxcor-of patch-here set bid_y pycor-of patch-here set bid true ;show word "Wealth will increse with " patch-here ;show word "to " est_alt_wealth ;show word "with cover " bid_cover setxy bid_x bid_y ;;move turtle to the patch it is going to bid for set max_bid (( 100 - age ) * ( est_alt_wealth - est_wealth ) - set_conv_cost 2 bid_cover - calc_farmCost) ;;set bid value if ( max_bid > (( (100 - age) / 20 ) * wealth) ) [ set max_bid (( (100 - age) / 20 ) * wealth - set_conv_cost 2 bid_cover - calc_farmCost) ] ] ask this_patch [ set cover 2 set agent_ID previous_owner ] ;;STEP 5. reset patch for other turtles and remove from dead_neighbours agenset set dead_neighbours dead_neighbours with [ agent_ID = 999 ] ;;remove the patch that has just been under consideration from the dead_neighbours agentset ] if ( not any? dead_neighbours ) [ stop ] ;;if the dead_neighbours agentset is empty we have checked all dead neighbours and can stop the loop ] ] end ;--------------- ;--------------- to calculate_est_pixel_profit [ ID ] ;;calculates profit for a single calling patch. used with alternatives if ( cover = 0 ) [ set est_patch_profit ( est_valueC-of turtle ID * lcap ) - (calc_frag * 2 * costC ) - (road_dist / world-width) ] if ( cover = 1 ) [ set est_patch_profit ( est_valueP-of turtle ID * lcap ) - costP - (road_dist / world-width) ] if ( cover = 2 ) [ set est_patch_profit ( -1 * costAb ) ] end ;--------------- ;--------------- to set_values set prev_valueC valueC set prev_valueP valueP set prev_costC costC set prev_costP costP set prev_farmCost farmCost set valueC ( item year market_pricesC ) set valueP ( item year market_pricesP ) set costC ( item year market_costC ) set costP ( item year market_costP ) set farmCost ( item year market_farmCost ) if ( valueC > ( max_cover_value - 5 ) ) [ set max_cover_value ( valueC + 5 ) ] if ( valueP > ( max_cover_value - 5 ) ) [ set max_cover_value ( valueP + 5 ) ] end ;--------------- ;--------------- ;to set_age ; set age ( agri_pop + ( age_vari * agri_pop ) ) ; set age round age ;end ;--------------- ;--------------- to-report set_profitable_neighbour report myself end ;--------------- ;--------------- to move_home let temp_xcor 0 let temp_ycor 0 ifelse ( any? patches with [ agent_ID = who-of myself ] ) [ ask patches with [ homestead = who-of myself ] [ set temp_xcor pxcor set temp_ycor pycor ] setxy temp_xcor temp_ycor ] [ kill_agent ] end ;--------------- ;--------------- to grow_newfarm cct 1 [ ;set intial wealth/profit variables set wealth ( random ( wealth-of max-one-of turtles [ wealth ] ) ) ;set initial age variables set age 1 while [ age < 25 ] [ set age ( random 60 ) ] ;set farmer perspective set shape "circle" set_agent_cluster_ID ;set bid initial variables set consider_bid false set bid false set max_bid 0 set bid_cover nobody set label who set best_alternative nobody set bid_x nobody set bid_y nobody set set_price 0 set count_neg_profit 0 set tot_annual_profit 0 ;set intial value estimate variables set actual_value_diffcP 0 set actual_value_diffcC 0 set actual_cost_diffcC 0 set actual_cost_diffcP 0 set actual_cost_diffcFarm 0 set est_valueC valueC set est_valueP valueP set est_costC costC set est_costP costP set est_farmCost farmCost set prev_est_valueC valueC set prev_est_valueP valueP set prev_est_costC costC set prev_est_costP costP set prev_est_farmCost farmCost ;set other variables set color 0 set largest_cluster_ID 0 let nobody_clusters [] ask max-one-of patches with [ agent_ID = nobody and cover = 2 ] [lcap] [ set homestead who-of myself set plabel who-of myself set agent_ID who-of myself set agent_cluster_ID 0 set cluster self set nobody_clusters lput agent_cluster_ID-of self nobody_clusters ifelse ((costC - set_conv_cost 2 0) > (costP - set_conv_cost 2 1)) [ set cover 0 ] [ set cover 1 ] ifelse (agent_ID = 0) [ if (cover = 0) [ set pcolor 113 ] if (cover = 1) [ set pcolor 115 ] if (cover = 2) [ set pcolor 117 ] ] [ if (cover = 0) [ set pcolor ((agent_ID * 10) + 3) ] if (cover = 1) [ set pcolor ((agent_ID * 10) + 5) ] if (cover = 2) [ set pcolor ((agent_ID * 10) + 7) ] ] ] let original_wealth wealth set wealth wealth - market_patch_price let temp_bid true while [ wealth > ( original_wealth / 2 ) and temp_bid = true ] [ let temp_wealth wealth set est_wealth ( wealth + calculate_est_profit ) ;;Calculate est_wealth for next time step with current land configuration ;show word "est_wealth " est_wealth set est_alt_wealth est_wealth ;show word "est_alt_wealth " est_alt_wealth find_dead_neighbours ifelse ( bid = false ) ;;if no bid is to be made by this agent [ move_home set temp_bid false ] ;;move the turtle to one of its own patches (needed for make_bids below) [ make_bids set bid false ;;reset bid variables set bid_cover nobody set max_bid 0 set bid_x nobody set bid_y nobody move_home ] if ( wealth = temp_wealth ) ;;if wealth has not changed since start of loop, no patch was bought [ set temp_bid false ] ] ;check other unowned clusters while [ wealth > ( original_wealth / 2 ) and temp_bid = true ] [ let temp_wealth wealth set est_wealth ( wealth + calculate_est_profit ) ;;Calculate est_wealth for next time step with current land configuration ;show word "est_wealth " est_wealth set est_alt_wealth est_wealth ;show word "est_alt_wealth " est_alt_wealth ;ask one of unowned patches in a cluster that has not yet been checked (i.e. not a member of nobody_clusters) let check max-one-of patches with [ agent_ID = nobody and cover = 2 and not member? agent_cluster_ID nobody_clusters ] [lcap] ifelse (check = nobody) ;if all unowned clusters have been checked [ set temp_bid false ] ;breaks while loop [ ask check [ ; set nobody_clusters lput find_nobody_neighbours nobody_clusters who-of myself agent_cluster_ID-of self ] ] if( bid = true) ;;if bid is to be made by this agent [ make_bids set bid false ;;reset bid variables set bid_cover nobody set max_bid 0 set bid_x nobody set bid_y nobody move_home ] ] set_agent_cluster_ID ;; set cluster IDs find_largest_cluster_ID set_cover_cluster_ID ] end ;--------------- ;to-report find_nobody_neighbours farmer this_cluster ;;STEP 1. Generate agentset of dead neighbours ; let temp_nobody_neighbours patches with [agent_cluster_ID = this_cluster] ;;list to hold patches and their profit values (convert to agentset below) ;; edited function to here 11.50 26/01/06 ;--------------- to-report next-index [ prefix suffix ] let index 0 let filename_ni (word prefix index suffix ) while [ file-exists? filename_ni ] [ set index index + 1 set filename_ni (word prefix index suffix ) ] report index end ;--------------- ;--------------- to-report set_conv_cost [ original new ] ; let t 0 ; if ( duration > 20 ) [ set t 20 ] ifelse ( ( original = 2 and new != 2) or ( original = 1 and new = 0 ) ) [ if (new = 0) [ report ( conv_cost * 3 ) ] if (new = 1) [ report conv_cost ] ] [ report 0 ] end ;--------------- ;--------------- to-report propM let M count turtles with [shape = "circle"] let tot count turtles report M / tot end ;--------------- ;--------------- to-report propT let T count turtles with [shape = "square"] let tot count turtles report T / tot end ;--------------- ;--------------- to-report cover_cluster_size [ a_ID cc_ID ] report count patches with [ agent_ID = a_ID and cover_cluster_ID = cc_ID ] end ;--------------- ;--------------- to-report cover_cluster_count [ lc ] ;differs from cover_cluster_counter - counts clusters of a given cover for for a single turtle let max_cID max values-from patches with [agent_ID = who-of myself] [ cover_cluster_ID ] let i 0 let counter 0 while [i <= max_cID] [ if (any? patches with [ agent_ID = who-of myself and cover_cluster_ID = i and cover = lc ]) [ set counter counter + 1 ] set i i + 1 ] report counter end ;--------------- ;--------------- to write_cluster_sizes [ lc ] ;differs from cover_cluster_counter - counts clusters of a given cover for for a single turtle let max_cID max values-from patches with [agent_ID = who-of myself] [ cover_cluster_ID ] let i 0 let counter 0 while [i <= max_cID] [ set counter count patches with [ agent_ID = who-of myself and cover_cluster_ID = i and cover = lc ] if (counter > 0 ) [ ;file-write "," file-write counter ] set i i + 1 ] end ;--------------- ;--------------- to write_nobody_cluster_sizes ;differs from cover_cluster_counter - counts clusters of a given cover for for a single turtle let max_cID max values-from patches with [agent_ID = nobody and cover = 2 ] [ agent_cluster_ID ] let i 0 let counter 0 while [i <= max_cID] [ set counter count patches with [ agent_ID = nobody and cover = 2 and agent_cluster_ID = i] if ( counter > 0 ) [ ;file-write "," file-write counter ] set i i + 1 ] end ;--------------- ;--------------- to-report calc_frag let max_dist 0 ;show "calculating frag_value" without-interruption[ ask patches with [ agent_ID = agent_ID-of myself and cover_cluster_ID != cover_cluster_ID-of myself ] [ if (distance myself > max_dist) [ set max_dist distance myself ] ]] let farm_size count patches with [ agent_ID = agent_ID-of myself ] let cluster_size count patches with [ cover_cluster_ID = cover_cluster_ID-of myself and agent_ID = agent_ID-of myself] let prop_farm cluster_size / farm_size ifelse ( max_dist != 0 ) [report 1 - ( prop_farm / max_dist )] [report 0 ] end ;--------------- ;--------------- to-report calc_farmCost ifelse ((count patches with [agent_ID = who-of myself and cover != 2 ]) > max_tfarm_size) [ report (max_tfarm_size - (count patches with [agent_ID = who-of myself and cover != 2 ])) * farmCost ] [ report 0 ] end ;--------------- ;--------------- to re-display ask patches [ set plabel "" ] if (DisplayMap = "Cover-Owner") [ ask patches [ display_cover ]] if (DisplayMap = "LandCap") [ask patches [ display_lcap ]] if (DisplayMap = "Roads") [ask patches [ display_roads ]] set prop_A (count patches with [ cover = 0 ]) / (count patches) set prop_P (count patches with [ cover = 1 ]) / (count patches) set prop_NA (count patches with [ cover = -1 ]) / (count patches) set prop_Ab (count patches with [ cover = 2 ]) / (count patches) cover_cluster_counter agent_cluster_counter ;set number_of_agent_clusters 0 let largest_p 0 let count_clusters 0 without-interruption [ ask turtles [ find_largest_cluster_ID show (count patches with [ agent_cluster_ID = largest_cluster_ID-of myself and agent_ID = who-of myself]) if (count patches with [ agent_cluster_ID = largest_cluster_ID-of myself and agent_ID = who-of myself ] > largest_p) [ set largest_p (count patches with [ agent_cluster_ID = largest_cluster_ID-of myself and agent_ID = who-of myself])] ] ] set largest_patch largest_p set mp_size count patches with [cover != -1] / number_of_agent_clusters end ;--------------- ;--------------- to display_cover ;;display the patches with colours according to their owner and cover type ifelse ( agent_ID = nobody ) [ set pcolor 9.9999 ] [ ifelse ( agent_ID = 0 or ( remainder agent_ID 10 = 0 ) ) [ if (cover = 0) [ set pcolor 113 if (patch-labels = true) [set plabel cover]] if (cover = 1) [ set pcolor 114 if (patch-labels = true) [set plabel cover]] if (cover = 2) [ set pcolor 115 if (patch-labels = true) [set plabel cover]] ] [ if (cover = 0 ) [ set pcolor (( (remainder agent_ID 10) * 10 ) + 3 ) if (patch-labels = true) [set plabel cover]] if (cover = 1 ) [ set pcolor (( (remainder agent_ID 10) * 10 ) + 5 ) if (patch-labels = true) [set plabel cover]] if (cover = 2 ) [ set pcolor (( (remainder agent_ID 10) * 10 ) + 7 ) if (patch-labels = true) [set plabel cover]] ] ] end ;--------------- ;--------------- to display_lcap set pcolor scale-color red lcap 0 2 end ;--------------- ;--------------- to display_roads ifelse (road_dist = 0) [ set pcolor 0 ] [ set pcolor scale-color blue road_dist 0 world-width ] end ;--------------- @#$#@#$#@ GRAPHICS-WINDOW 216 10 583 398 10 10 17.0 1 15 1 1 1 0 1 1 1 -10 10 -10 10 CC-WINDOW 5 482 887 577 Command Center 0 BUTTON 12 10 75 43 NIL setup NIL 1 T OBSERVER T NIL SLIDER 14 140 186 173 number_of_farmers number_of_farmers 1 10 9 1 1 NIL SLIDER 12 215 184 248 cluster_probability cluster_probability 0 1 0.25 0.01 1 NIL BUTTON 85 10 148 43 NIL go T 1 T OBSERVER T NIL PLOT 678 162 878 312 Patch Profit Profit Patches 0.0 10.0 0.0 10.0 true false PENS "Farmer 1" 1.0 1 -8630108 true "Farmer 2" 1.0 0 -2674135 true "Farmer 3" 1.0 0 -955883 true "Farmer 4" 1.0 0 -7500403 true "Farmer 5" 1.0 0 -1184463 true "Farmer 6" 1.0 0 -10899396 true "Farmer 7" 1.0 0 -13840069 true "Farmer 8" 1.0 0 -11221820 true "Farmer 9" 1.0 0 -14835848 true "Farmer 10" 1.0 0 -13791810 true PLOT 678 315 876 465 Cover Type Time Prop of Lsp 0.0 10.0 0.0 1.0 true false PENS "C" 1.0 0 -955883 true "P" 1.0 0 -10899396 true "Ab_Owned" 1.0 0 -7500403 true "Ab_unowned" 1.0 0 -16777216 true TEXTBOX 406 413 493 457 0 = Crops \n1 = Pasture \n2 = Abandoned MONITOR 598 418 675 467 Mean Age mean_age 1 1 PLOT 678 10 878 160 Cover Values NIL NIL 0.0 10.0 0.0 10.0 true false PENS "C" 1.0 0 -955883 true "P" 1.0 0 -10899396 true SLIDER 12 255 184 288 run_length run_length 0 500 210 10 1 NIL SLIDER 14 178 186 211 conv_cost conv_cost 0 1 0.3 0.1 1 NIL MONITOR 597 111 675 160 Commercial propM 2 1 MONITOR 597 162 675 211 Hobby propT 2 1 MONITOR 597 11 675 60 Year year 0 1 MONITOR 597 61 675 110 No Farmers count turtles 3 1 SLIDER 13 300 185 333 max_tfarm_size max_tfarm_size 0 100 50 1 1 NIL SWITCH 18 384 142 417 patch-labels patch-labels 1 1 -1000 SLIDER 14 101 186 134 commercial_probability commercial_probability 0 1 0.8 0.1 1 NIL CHOOSER 18 423 156 468 DisplayMap DisplayMap "Cover-Owner" "LandCap" "Roads" 0 BUTTON 17 347 104 380 ReDisplay re-display NIL 1 T OBSERVER T NIL MONITOR 597 214 675 263 Arable prop_A 2 1 MONITOR 597 265 674 314 Pasture prop_P 2 1 TEXTBOX 486 417 583 447 Square = Hobby\nCircle = Commercial\n MONITOR 597 316 675 365 Abandoned prop_Ab 2 1 @#$#@#$#@ SPANISH FARMER MODEL V3 Contents of this information file: 1. Model Usage 2. Model Display 3. Model Rationale MODEL USAGE This version (V3) of the model now allows the user to decide at setup of a run whether to generate a new "random" landscape (specifying certain paramters such as spatial distribution of land capability, number of farmers etc.) or whether a landscape should be read from file. Before clicking setup, the user should select either "Random" or "From File". - "Random" If setup is random, all usual parameters should be specified. - "From File" If setup is from file, the appropriate files (created using CreateLandscapes.nlogo) should be located in the same directory as the model environment. Using this option in conjunction with the Behaviour Space will allow multiple runs for the same landscape setup to be run. See the Information tab of CreateLandscapes.nlogo for more details. IMPORTANT NOTE: The display window must be set to the same dimensions as the landscape files being imported from file (Farmers.nldat does not specify a landscape size). The dimensions of the landscape file are denoted on lines 2 (screen-size-x) and 3 (screen-size-y) of the .nldat files. For example, if the landscape file has dimensions of 21 x 21, the view window should be set (click edit) to "Screen Edge X" = 10, "Screen Edge Y" = 10. If the dimensions do not match, an error message will be displayed in the Command Centre and the files will not be loaded. MODEL DISPLAY Model display options have been changed in this version. Three different types of map may be viewed in the display window using the DisplayMap chooser and the Reload Display button. Select Cover-Owner, LandCap or Roads from the DisplayMap chooser, specify whether patch cover labels should be shown, then click the Reload Display button to view. The monitors on the right of the display window detail; - number of farmers in the landscape - proportion of 'Traditional' farmers - proportion of 'Commercial' farmers - proportion of the landscape in use as arable agriculture - proportion of the landscape in use as pastoral agriculture - proportion of the landscape in an 'abandoned' state - proportion of the landscape not used for agriculture - the size of the largest cluster (in patches) used for agriculture - mean cluster size (in patches) of all clusters used for agriculture - number of clusters (counted by cover) - number of clusters (counted by agent) MODEL RATIONALE In light of the November Fieldtrip to Madrid I have modfied the structure of the agricultural decision-making module. The primary modification to 'Version 2' of the model is the distinction between two different types of farmer which I will term 'commercial' and 'hobby'. Second, the available land use options are reduced from three (Pastoral, Arable or Dehesa) to two (Pastoral and Arable only). Third, the way fragmentation is calculated has been modified so that the location of the homestead is not required. Finally, new variables are considered when calculating a patch's profit; namely, land capability and distance to the nearest road or track. Rationale for 'Commercial' and 'Hobby' Farmer Types It became clear during interviews with local farmers and farming officials that there is a clear distinction between commercial farms that operate in a rationally economic, profit-maximising manner, and those that operate merely to maintain traditional agricultural practices and landscape asthetics. "Whoever has a vineyard nowadays is like a gardener... they like to keep it, even if they lose money. They maintain vineyards because they have done it all their life and they like it, even having to pay for it. If owners were looking for profitability there would be not a singe vineyard... People here grow wine because of a matter of feeling, love for the land..." [F_NDR] Thus, for many land owners in the landsape their farm is a hobby kept with no regard for its financial rewards. Clearly the economically rational agent is not appropriate for these 'hobby farmers'. Further, there are many farms across the study area that are run to provide supplementary household income. For example, in one area, Santa Maria, one farmer [LF_SM] stated that of the 80 livestock farmers in the area only 20 (one quarter) made their living solely from farming with the rest taking their primary income from alternate sources (light industry or building nearby) but still keeping some land and livestock active. The farmer termed this supplementary activity 'extensive farming': "Extensive [pastoral] farming is less time demanding... once a day, 1 or 2 hours can be enough... I see in the future extensive farming will be the most important though - I don’t know if it is more profitable or not - but because it needs less time." [LF_SM] In San Martin del Valdeglesias, a farming official described a similar situation: "In general, [pastoral] farming is part-time, with only a few exceptions. The main problem is that it is not economically profitable - it is difficult to sell the product." [FO_SMV] And again in Villa del Prado, a spokesperson for a Farming Association: "[arable] agriculture here is part time... there are a few farmers that live on horticulture, and have vineyards as an extra." [APG_VDP] Finally, in an area traditionally known for its vineyards: "Part-time workers? Yes, most of them... there are no full-time farmers. Here there are only retired people and their children, who work somewhere else, and help their retired parents with the labouring. There is no way to live on wine production." This part-time nature must be acknowledged in the behaviour of agents of the model. In general, we might say that these hobby and part-time farmers are less concerned with the economic state of the market, and their activities will not be sensitive to changes in it. In contrast, those farmers for whom their farm is their sole source of income treat their land as a commercial enterprise: "There are some young farmers, 5 or 6 of whom are less than 25 years old, that are making important investments. If someone wants to live from livestock farming, they need to have an entrepreneurial vision, a business mentality, like in any company." [LF_SM] These farmers will adopt land use and farming practices to maximise their income. Different behaviours [model rules] are therefore appropriate for each type of agent; 'commercial farmer' or 'hobby farmer'. Model Structure Figure X illustrates the step taken during one 'time-step' of a model run. Each time-step represents one season of the year, for seasons per year. This model description will briefly describe setup procedures before moving through each of the 12 steps illustrated in the flow chart (Figure X). Setup Procedures At setup the defined number of agents (farmers) are created with a random wealth, age (between 25 and 60 years) perspective (i.e. 'commercial' or 'hobby'). 'Clusters' of patches are then randomly generated across the landscape, the size of which is determined by the cluster_probability variable (see Saura & Martinez-Millan 2000 for method). Clusters are then randomly assigned a land use (Crops, Pasture, Abandoned) and then randomly assigned to an agent. One of each agents patches is then assigned as the 'homestead' (this assignment is now redundant as homestead is NOT used to calculate a patch's fragmentation value). Model Execution Step 1. Start or iterate season loop (add one to 'season'). Step 2. If this time-step is the fourth season of the year, increase farmers' ages by one year. Step 3. If this time-step is the fourth season of the year, check if commercial farmers have reached retirement age (currently 65 years). Step 4. If a commercial farmer has reached the retirement age a check is made to establish if the farmer has a son. The code for this check is; ( rand_no < (propM + 0.25) ) Thus, if a randomly generated number (between 0 and 1) is less than the proportion of farmers that are 'commercial' plus 0.25 then the farmer does have a son to inherit the farm as a 'commercial farmer'. The likelihood that a commercial farmer has a son is based on the proportion of commercial farmers in the neighbourhood not because this is the mechanism that dictates whether a farmer has a son (clearly that is not right!) but because this is likely to be an important factor in determining whether a son WANTS to continue his father's business. 0.25 is added to the likelihood to ensure that when there are no commercial farmers in the landscape, there is still a chance that a son will want to continue the business - this accounts simply for personal choice (of the son) and the father's individual influence over his son's attitudes (which are likely to be just as, if not more, important than the proportion of the local community that has the 'commercial perspective'). The son's age is randomly set to a value between 20 and 40, ensuring that the value is less than the dying farmer's age minus 20 (this assumes that farmers do not have children before the age of 20). If the farmer does not have a son, the farmer becomes a hobby farmer. This transition is made because it is assumed that having farmed his land all his life the farmer is unlikely to want to simply give up his land for nothing (a sentiment that interviews suggested to be strong). Step 5. Check if farmer (both perspectives) dies. A random is generated between 0 and 1. If this number is less than the probability for the farmer's age (provided by the 'death probabilities' file that is read in during set-up; data source: http://www.lifetable.de/data/MPIDR/ESP_1998-1999.txt) the farmer is deemed to have died during this year. Step 6. Check if the farmer has a son. If the dying farmer is commercial and older than 40 years the method described in Step 4. is used; if a son is present he inherits the farm as a commercial farmer. If the farmer is younger than 40 it is assumed that either he does not have a son, or if he does the son is not old enough to take over the running of the farm. If a son is not present the farm 'dies'; ownership of all patches is released to 'nobody' and are assumed to be abandoned. If the dying farmer is a hobby farmer and older than 40, checks are made to establish if there is a son to inherit the farm - as either type of farmer. The first check establishes if the son inherits as a commercial farmer; (mean_tot_patch_profit + propM - ( 3 * age / 100 )) > 0 If this code is true a son inherits the farm as a commercial farmer. Thus, if the mean patch profit of all patches currently in use by commercial farmers (i.e. NOT abandoned; this value will generally lie between 0 - 2) plus the proportion of neighbouring farms that are commercial minus 3 times the age of the farmer divided by 100, is greater than zero, the son becomes a commercial farmer. This assumes that the son will be willing to become a commercial farmer when the profit in the landscape is generally high, there are other commercial farmers in the landscape (i.e. he sees that others are finding it possble to make a living from their land) and his age is low (and therefore he assumed to be more willing to take a risk and 'give it a go'). If this check is false a check is made to establish if the farmer has a son to inherit the farm as a hobby farmer in a similar manner to that described in Step 4. The code for this check is; ( rand_no < (propT + 0.25) ) Thus, if a randomly generated number (between 0 and 1) is less than the proportion of farmers that are 'hobby farmers' plus 0.25 then the farmer does have a son to inherit the farm as a hobby farmer. As above, the likelihood that a hobby farmer has a son is based on the proportion of hobby farmers in the neighbourhood not because this is the mechanism that dictates whether a farmer has a son (clearly that is not right!) but because this is likely to be an important factor in determining whether a son WANTS to continue in the steps of his father. 0.25 is added to the likelihood to ensure that when there are no hobby farmers in the landscape, there is still a chance that a son will want to continue the business - this accounts simply for personal choice (of the son) and the father's individual influence over his son's attitudes (which are likely to be just as, if not more, important than the proportion of the local community that has the 'hobby perspective'). Again, the son's age is randomly set to a value between 20 and 40, ensuring that the value is less than the dying farmer's age minus 20 (this assumes that farmers do not have children before the age of 20). If both checks are false the farm 'dies'; ownership of all patches is released to 'nobody' and are assumed to be abandoned. Step 7. Commercial farmers calculate their profit for this season. Profit is calculated for the three potential land uses (for each patch) using the following code: Crops profit = ( valueC * lcap ) - ( calc_frag * 2 * costC ) - (road_dist / screen-size-x) ) Pasture profit = ( valueP * lcap ) - costP - (road_dist / screen-size-x) ) Abandoned profit = -0.1 Crops: The current value of crops is multiplied by the land capability value (a value scaled between 0 and 2 indicating the suitability of the patch for agriculture based on slope, soil and climate). From this, twice the fragmentation value of the farm multiplied by the current cost to produce crops is subtracted, followed by the subtraction of the distance to the nearest road divided by the maximum possible distance (giving a range for this value of 0 - 1). Thus, the highest profit is earnt by patches with a high land capability, low fragmentation value, and low distance to the nearest road when the value for crops is high and the cost of production is low. Fragmentation value has changed from previous versions of the model. These previous versions assumed the location of the farmhouse ('homestead') was known for each farm; this data is not available for SPA56 so the calculation has been duly changed. Fragmentation is now calculated using the following code; 1 - ( prop_farm / max_dist ) where prop_farm is the proportion of the total farm area composed by the cluster in which the patch under consideration lies, and max_dist is the maximum distance between the patch under consideration and another patch owned by the same farmer. Thus, when prop_farm is large and max_dist is small, the fragmentation value of the patch is low. This index penalises patches in small clusters that are of larger distances from other patches owned by the farmer. This index has a theoretical range of 0 (when max_dist is infinite) to 1. Pasture: Pasture profit is calculated in a very similar manner to crops, the difference being that the fragmentation value of the patch is not considered. The rationale behind this is that land for grazing does not afford much advantage by being clustered in large patches. Small areas of land may be used for grazing just as easily as large. However, the distance to the nearest road or trail is deemed important as this will ease movement of livestock between areas of pasture and to the market. Abandoned: There is no immediate value afforded by owning land in an abandoned state. However, the costs of doing so are also minimal. As the land may be useful in the future, and long term planning or forecasting of the state of the market is not represented in the model the profit per abandoned patch per season is therefore set at -0.1. This value is minmial compared to the proces and costs of the other land uses (which should range between 0 and 2). Once profit for all individual patches has been calculated, the sum of these values is calculated for the entire farm. If the total farmed area of the farm exceeds a 'maximum single farmer area', for each patch exceeding this area a further cost is subtracted from the total farm profit. This cost is designed to reflect the infrastructure and labour required to farm an area greater than that possible by a single farmer with no hired labour. Thus, while currently abritrary, in the future the given area will be set to the maximum area that could be maintained by a single farmer not employing hired labour. Step 8. Commercial farmers check their annual profit at each year's end. If their wealth is negative, go to Step 11. Step 9. If annual profit is equal to, or less than, -5.0% of their wealth, go to step 10. Otherwise, go to Step 12. Step 10. The 'negative profit' year counter is increased by one. If this counter is now equal to five (i.e. the last five consecutive years have been loss-making) go to Step 11. Otherwise, go to Step 12. (N.B. this counter is re-set to zero if annual profit is not less than -5% of wealth.) Step 11. A check is made to see if the commercial farmer changes to become a hobby farmer. This check is made by the follwoing code: rand_no < (propT + 0.25) or age-of self >= 50 If either statement in this block is true, the commercial farmer becomes a hobby farmer. The first half of the block (before 'or') is the same as found in Step 6 when the check to establish if the farmer has a son to inherit the farm as a hobby farmer is made, and is based on the same premises and assumptions. The second statement in the block checks the age of th farmer. If the farmer is 50 or older he becomes a hobby farmer. This is based on the assumption that a younger farmer will want to move onto another job elsewhere because they still have 'time on their side' to start a different career. If older than 50, it is assumed that the farmer will be less inclined (or skilled) to endeavour to find a new full-time career and will therefore maintain the farm as a supplementary income. However, if both statements are false, the farm 'dies'; ownership of all patches is released to 'nobody' and are assumed to be abandoned. Step 12. Hobby farmers check the size of their farm. If the farm is larger than the 'maximum single farmer area' (see Step 7) the farmer reduces farm size by abandoning the patch furthest from a road/trail until the specified area is reached. Distance to road is used as it is assumed that the hobby farmer will reduce maintainence costs rather than maximising productivity. This step is only needed for the case in Step 11 where a commercial farmer becomes a hobby farmer. Step 13. Commercial farmers estimate their profit for the next season with the land they currenly own. Each possible configuration of their land (i.e. with each patch they own in each of the three possible land use states) is checked and patches change land use accordinly to maximise profit for the next season. Farmers' estimates for their profit in the next season is based on their estimates of the values and costs for crops and pasture for that next season. These estimates are based on the values and costs of the current and previous seasons, and the accuracy of the farmers' estimate in the previous season. For example, the code for a farmer to estimate the value of crops for the next season is; valueC + actual_value_diffcC + random-float 0.5 * ( valueC - prev_est_valueC ) where actual_value_diffcC is the difference between the previous value of crops and the current value of crops, and prev_est_valueC is the previous estimated value of crops. Thus, the current estimate is given by the error in the last estimate multiplied by a random number between 0 and 0.5 added to the current value of crops and actual_value_diffcC. This method ensure farmers can estimate future prices reasonably well when values and costs change slowly, but perform worse when changes are rapid. If the land use configuration of the land currently owned can be modified to imrove profit land use conversions are made. A 'ladder' of land uses is considered to restrict some land use conversions. In this ladder Cropland is above Pasture land which in turn is above Abandoned land. An unlimited number of patches conversions 'down the ladder' may be made in any one season. Only one conversion 'up the ladder' may be made in any one season. Conversion up the ladder (e.g. from abandoned to cropland) will require both resources of both time and money and so representation of this process should be slowed within the model. Conversions down the ladder require vastly less resources and are simply achieved by reducing maintainance levels. If conversions to currently owned land are made and the program continue to the next iteration (Step 1.) Otherwise, if land currently owned is in the optimal state to maximise profit, Step 14 is executed. Step 14. Commercial farmers bid to buy abandoned patches that neighbour their own land. All neighbouring abandoned patches are examined to assess if their ownership and conversion, to either cropland or pasture, will increase the farmer's profit in the season. The neighbouring abandoned patch which will increase profit by the largest margin is then bid for. The bid a farmer will offer is given by the estimated increased profit it will afford multiplied by (100 - age of farmer). The age of the farmer is considered as this gives a rough guide to the number of years the patch (if bought) will provide to the farmer. If the bid being made is larger than the asking price of the current owner, ownership passes to the bidding farmer and land use change to the most profitable state. The asking price of a farmer is set as the current wealth of the farmer divided by the total number of patches owned by that farmer. If the patch is abandoned but unowned (i.e. 'dead' as it once belonged to a farm that was 'killed') the asking prices is set to the 'current market price' for patches. This price is set to; 40 * mean_tot_patch_profit where mean_tot_patch_profit is the mean patch profit for the season across all patches owned by commercial farmers in the landscape. Multiplying by 40 gives an estimate of potential profit to be made by that patch (in the current market state) over the next decade. If a bid is not as large as the asking price, ownership stays with the current owner and the patch remains in the 'abandoned' state. Whatever the result of a bid, the once all farmers bids have been considered the program continues to the next iteration (Step 1.) @#$#@#$#@ default true 0 Polygon -7500403 true true 150 5 40 250 150 205 260 250 link true 0 Line -7500403 true 150 0 150 300 link direction true 0 Line -7500403 true 150 150 30 225 Line -7500403 true 150 150 270 225 airplane true 0 Polygon -7500403 true true 150 0 135 15 120 60 120 105 15 165 15 195 120 180 135 240 105 270 120 285 150 270 180 285 210 270 165 240 180 180 285 195 285 165 180 105 180 60 165 15 arrow true 0 Polygon -7500403 true true 150 0 0 150 105 150 105 293 195 293 195 150 300 150 box false 0 Polygon -7500403 true true 150 285 285 225 285 75 150 135 Polygon -7500403 true true 150 135 15 75 150 15 285 75 Polygon -7500403 true true 15 75 15 225 150 285 150 135 Line -16777216 false 150 285 150 135 Line -16777216 false 150 135 15 75 Line -16777216 false 150 135 285 75 bug true 0 Circle -7500403 true true 96 182 108 Circle -7500403 true true 110 127 80 Circle -7500403 true true 110 75 80 Line -7500403 true 150 100 80 30 Line -7500403 true 150 100 220 30 butterfly true 0 Polygon -7500403 true true 150 165 209 199 225 225 225 255 195 270 165 255 150 240 Polygon -7500403 true true 150 165 89 198 75 225 75 255 105 270 135 255 150 240 Polygon -7500403 true true 139 148 100 105 55 90 25 90 10 105 10 135 25 180 40 195 85 194 139 163 Polygon -7500403 true true 162 150 200 105 245 90 275 90 290 105 290 135 275 180 260 195 215 195 162 165 Polygon -16777216 true false 150 255 135 225 120 150 135 120 150 105 165 120 180 150 165 225 Circle -16777216 true false 135 90 30 Line -16777216 false 150 105 195 60 Line -16777216 false 150 105 105 60 car false 0 Polygon -7500403 true true 300 180 279 164 261 144 240 135 226 132 213 106 203 84 185 63 159 50 135 50 75 60 0 150 0 165 0 225 300 225 300 180 Circle -16777216 true false 180 180 90 Circle -16777216 true false 30 180 90 Polygon -16777216 true false 162 80 132 78 134 135 209 135 194 105 189 96 180 89 Circle -7500403 true true 47 195 58 Circle -7500403 true true 195 195 58 circle false 0 Circle -7500403 true true 30 30 240 circle 2 false 0 Circle -7500403 true true 16 16 270 Circle -16777216 true false 46 46 210 cow false 0 Polygon -7500403 true true 200 193 197 249 179 249 177 196 166 187 140 189 93 191 78 179 72 211 49 209 48 181 37 149 25 120 25 89 45 72 103 84 179 75 198 76 252 64 272 81 293 103 285 121 255 121 242 118 224 167 Polygon -7500403 true true 73 210 86 251 62 249 48 208 Polygon -7500403 true true 25 114 16 195 9 204 23 213 25 200 39 123 face happy false 0 Circle -7500403 true true 8 8 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Polygon -16777216 true false 150 255 90 239 62 213 47 191 67 179 90 203 109 218 150 225 192 218 210 203 227 181 251 194 236 217 212 240 face neutral false 0 Circle -7500403 true true 8 7 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Rectangle -16777216 true false 60 195 240 225 face sad false 0 Circle -7500403 true true 8 8 285 Circle -16777216 true false 60 75 60 Circle -16777216 true false 180 75 60 Polygon -16777216 true false 150 168 90 184 62 210 47 232 67 244 90 220 109 205 150 198 192 205 210 220 227 242 251 229 236 206 212 183 fish false 0 Polygon -1 true false 44 131 21 87 15 86 0 120 15 150 0 180 13 214 20 212 45 166 Polygon -1 true false 135 195 119 235 95 218 76 210 46 204 60 165 Polygon -1 true false 75 45 83 77 71 103 86 114 166 78 135 60 Polygon -7500403 true true 30 136 151 77 226 81 280 119 292 146 292 160 287 170 270 195 195 210 151 212 30 166 Circle -16777216 true false 215 106 30 flag false 0 Rectangle -7500403 true true 60 15 75 300 Polygon -7500403 true true 90 150 270 90 90 30 Line -7500403 true 75 135 90 135 Line -7500403 true 75 45 90 45 flower false 0 Polygon -10899396 true false 135 120 165 165 180 210 180 240 150 300 165 300 195 240 195 195 165 135 Circle -7500403 true true 85 132 38 Circle -7500403 true true 130 147 38 Circle -7500403 true true 192 85 38 Circle -7500403 true true 85 40 38 Circle -7500403 true true 177 40 38 Circle -7500403 true true 177 132 38 Circle -7500403 true true 70 85 38 Circle -7500403 true true 130 25 38 Circle -7500403 true true 96 51 108 Circle -16777216 true false 113 68 74 Polygon -10899396 true false 189 233 219 188 249 173 279 188 234 218 Polygon -10899396 true false 180 255 150 210 105 210 75 240 135 240 house false 0 Rectangle -7500403 true true 45 120 255 285 Rectangle -16777216 true false 120 210 180 285 Polygon -7500403 true true 15 120 150 15 285 120 Line -16777216 false 30 120 270 120 leaf false 0 Polygon -7500403 true true 150 210 135 195 120 210 60 210 30 195 60 180 60 165 15 135 30 120 15 105 40 104 45 90 60 90 90 105 105 120 120 120 105 60 120 60 135 30 150 15 165 30 180 60 195 60 180 120 195 120 210 105 240 90 255 90 263 104 285 105 270 120 285 135 240 165 240 180 270 195 240 210 180 210 165 195 Polygon -7500403 true true 135 195 135 240 120 255 105 255 105 285 135 285 165 240 165 195 line true 0 Line -7500403 true 150 0 150 300 pentagon false 0 Polygon -7500403 true true 150 15 15 120 60 285 240 285 285 120 person false 0 Circle -7500403 true true 110 5 80 Polygon -7500403 true true 105 90 120 195 90 285 105 300 135 300 150 225 165 300 195 300 210 285 180 195 195 90 Rectangle -7500403 true true 127 79 172 94 Polygon -7500403 true true 195 90 240 150 225 180 165 105 Polygon -7500403 true true 105 90 60 150 75 180 135 105 plant false 0 Rectangle -7500403 true true 135 90 165 300 Polygon -7500403 true true 135 255 90 210 45 195 75 255 135 285 Polygon -7500403 true true 165 255 210 210 255 195 225 255 165 285 Polygon -7500403 true true 135 180 90 135 45 120 75 180 135 210 Polygon -7500403 true true 165 180 165 210 225 180 255 120 210 135 Polygon -7500403 true true 135 105 90 60 45 45 75 105 135 135 Polygon -7500403 true true 165 105 165 135 225 105 255 45 210 60 Polygon -7500403 true true 135 90 120 45 150 15 180 45 165 90 square false 0 Rectangle -7500403 true true 30 30 270 270 square 2 false 0 Rectangle -7500403 true true 30 30 270 270 Rectangle -16777216 true false 60 60 240 240 star false 0 Polygon -7500403 true true 60 270 150 0 240 270 15 105 285 105 Polygon -7500403 true true 75 120 105 210 195 210 225 120 150 75 target false 0 Circle -7500403 true true 0 0 300 Circle -16777216 true false 30 30 240 Circle -7500403 true true 60 60 180 Circle -16777216 true false 90 90 120 Circle -7500403 true true 120 120 60 tree false 0 Circle -7500403 true true 118 3 94 Rectangle -6459832 true false 120 195 180 300 Circle -7500403 true true 65 21 108 Circle -7500403 true true 116 41 127 Circle -7500403 true true 45 90 120 Circle -7500403 true true 104 74 152 triangle false 0 Polygon -7500403 true true 150 30 15 255 285 255 triangle 2 false 0 Polygon -7500403 true true 150 30 15 255 285 255 Polygon -16777216 true false 151 99 225 223 75 224 truck false 0 Rectangle -7500403 true true 4 45 195 187 Polygon -7500403 true true 296 193 296 150 259 134 244 104 208 104 207 194 Rectangle -1 true false 195 60 195 105 Polygon -16777216 true false 238 112 252 141 219 141 218 112 Circle -16777216 true false 234 174 42 Rectangle -7500403 true true 181 185 214 194 Circle -16777216 true false 144 174 42 Circle -16777216 true false 24 174 42 Circle -7500403 false true 24 174 42 Circle -7500403 false true 144 174 42 Circle -7500403 false true 234 174 42 turtle true 0 Polygon -10899396 true false 215 204 240 233 246 254 228 266 215 252 193 210 Polygon -10899396 true false 195 90 225 75 245 75 260 89 269 108 261 124 240 105 225 105 210 105 Polygon -10899396 true false 105 90 75 75 55 75 40 89 31 108 39 124 60 105 75 105 90 105 Polygon -10899396 true false 132 85 134 64 107 51 108 17 150 2 192 18 192 52 169 65 172 87 Polygon -10899396 true false 85 204 60 233 54 254 72 266 85 252 107 210 Polygon -7500403 true true 119 75 179 75 209 101 224 135 220 225 175 261 128 261 81 224 74 135 88 99 wheel false 0 Circle -7500403 true true 3 3 294 Circle -16777216 true false 30 30 240 Line -7500403 true 150 285 150 15 Line -7500403 true 15 150 285 150 Circle -7500403 true true 120 120 60 Line -7500403 true 216 40 79 269 Line -7500403 true 40 84 269 221 Line -7500403 true 40 216 269 79 Line -7500403 true 84 40 221 269 x false 0 Polygon -7500403 true true 270 75 225 30 30 225 75 270 Polygon -7500403 true true 30 75 75 30 270 225 225 270 @#$#@#$#@ NetLogo 3.1 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@ setup go not any? turtles @#$#@#$#@