01 ModEco V1.39

01 ModEco V1.39 preview image

1 collaborator

121210_portrait_of_garvin Garvin Boyle (Author)

Tags

biophysical economics 

Tagged by Garvin Boyle about 7 years ago

ecological economics 

Tagged by Garvin Boyle about 7 years ago

econophysics 

Tagged by Garvin Boyle about 7 years ago

sustainability 

Tagged by Garvin Boyle about 7 years ago

sustainable economics 

Tagged by Garvin Boyle about 7 years ago

utterly simple economics 

Tagged by Garvin Boyle about 7 years ago

Model group Sustainability | Visible to everyone | Changeable by group members (Sustainability)
Model was written in NetLogo 5.0.5 • Viewed 1466 times • Downloaded 33 times • Run 0 times
Download the '01 ModEco V1.39' modelDownload this modelEmbed this model

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


WHAT IS IT?

This model environment is called ModEco (NetLogo ADE), and the configurations that are sustainable are called PMM #2, which is short for The Perpetual Motion Machine, second implementation. The PMM demonstrates a multi-generational sustainable economy having a biophysical subsystem which co-evolves with an economic subsystem. In the biophysical subsystem, many generations of agents are born, live, work, eat, reproduce and die in a world that obeys the laws of conservation of mass and energy - a world in which the carrying capacity is real and 50% of all agents die of hunger or old age, being too unhealthy to reproduce. Mass and energy are conserved in every event, as well as at an overall level. In the economic system, all exchanges of mass and energy (or goods and services) are reciprocated by exchanges of cash, which flows in a direction counter to the physical flows. A variety of emergent phenomena become apparent as a run proceeds, including a distinctive type of spatial distribution and a distinctive distribution of wealth among the agents. [ NOTE: An ODD description is available with this model. See the downloadable files. ]

ModEco is being written as part of a personal study of the dynamics of sustainability. It was inspired by questions such as:

  • What are the minimum essential characteristics (the necessary and sufficient characteristics) of a truly multi-generational sustainable economy in a biophysical world?
  • What is the impact of the laws of conservation of mass and energy on long-term economic dynamics?
  • Where, exactly, does economic profit come from?

These seem like simple questions that could and should be addressed in a first-year economics course. The answers have proven to be very elusive.

When I talk about ModEco in the following material, it is applicable to both this version (written in NetLogo) and to a larger ModEco application (written in C++) as well. ModEco is NOT intended to be a SIMULATION of any real economy, but, rather, a DEMONSTRATION of the dynamics of an extremely simple but complete economy. To my knowledge, it is the only example of such a complete model economy, as of this date (June 18th, 2014). So, what do I mean by 'complete'? A ModEco economy is an abstraction of an economy that is complete in (only) two out of three ways:

  • Vertical completeness - there is a biophysical economy capped by a social (or monetary) economy, and they co-evolve;
  • Longitudinal completeness - there is a cradle-to-grave life-cycle for living agents, and a harvest-to-waste life-cycle for economic goods; and
  • Depth completeness - this third dimension of completeness is not modelled here. There is only one species sharing the universe of ModEco, and the conservation of biodiversity, or the conservation of renewable sources of natural capital are not modelled. Even so, sustainability has been difficult to achieve.

The original ModEco Application was written in C++ and can be downloaded from the OpenABM website at http://www.openabm.org/model/3613/version/2/view . One of the many economic models that could be constructed there was called the PMM, and it has now been dubbed the PMM #1. It is described using the ODD protocol, a protocol of which the purpose is to enable people to recreate the model on a different platform. This version of ModEco was written using that ODD description, and is, itself, also described using the ODD protocol (which can be downloaded from the NetLogo Modeling Commons with this model), since it is in fact slightly different. This version of ModEco, written using the NetLogo ADE, is in many ways more simple, but it was still, nevertheless, very difficult to create a stable dual biophysical/economic model.

The PMM exists in both the C++ version of ModEco, and in this NetLogo version, slightly modified. It is designed to be "sustainable", in the sense that a run should and could continue forever, across many hundreds of generations of agents, if allowed. The PMM#1 (C++ version) has demonstrated sustainability to an amazing 20 million ticks (25,000 generations). I have tested the PMM#2 (this NetLogo version) in an overnight run that remained stable for 128,000 ticks (160 generations).

As mentioned above, ModEco has two integrated sub-systems:

  • In the biophysical subsystem all agents have an initial endowment of resources (mass, energy and food). Agents are born, live, eat, grow old and die, or die young of starvation or while reproducing. There is an implicit carrying capacity determined by the initial endowment of mass and energy which is conserved throughout a run. Agents reproduce by fission, and so once the carrying capacity has been reached, roughly 50% of the agents in each generation fail to reproduce due to lack of resources, and die of starvation or old age.
  • In the economic subsystem, all agents have an initial endowment of cash, and all exchanges of mass and energy (in the form of goods and services) are reciprocated by exchanges of cash of precisely equivalent value.

HOW IT WORKS

Agents come in two mortal 'breeds': frmrs (an abstraction of farmers) and wrkrs (an abstraction of workers). In addition, two immortal and non-local agents called the "Materiel Manager" (MMgr) and the "Estate Manager" (EMgr) play a role in the background, as a sort of passive central government.

Agents hold their valuables in asset classes. Different types of agents have different asset classes, as follows:

  • Cash [dollars ($)] held by both frmrs and wrkrs is used in all commercial transactions.
  • Energy [energy units (eu, eus)] held by both frmrs and wrkrs is produced by consumption of supplies and is contained in agent's bodies and represents health, or ability to do work, such as harvesting.
  • Recycled mass [mass units (mu, mus)] is held by frmrs only and is purchased by frmrs from the MMgr and placed on the fields to prepare for harvest.
  • Inventory [mass/energy units (meu, meus)] is held by frmrs only, is produced during harvest, when frmrs hire wrkrs, and then both wrkrs and frmrs cooperate to harvest food and place it in the frmr's inventory.
  • Supplies [mass/energy units (meu, meus)] is held by consumers (wrkrs and frmrs) who purchase the frmrs' inventory, whereupon it becomes supplies available for consumption by the consumers.
  • Waste mass [mass units (mu, mus)] is held by consumers and sold to the ubiquitous and immortal MMgr for recycling.

Biophysical functions are controlled by explicit parameters, accessible in the user interface in a panel of many sliders. The biophysical parameters were based on those first used by Dr Michael Palmiter in his application 'Simulated Evolution' (1989) and then used my me in a previous purely biophysical model (PSoup, see below)

  • g-DAT - Death Age Threshold - defines old age, agents die when they reach this age.
  • g-DET - Death Energy Threshold - defines collapse due to emaciation, agents die if their energy falls below this level.
  • g-RAT - Reproduction Age Threshold - defines reproductive maturity.
  • g-GTT - Gestation Time Threshold - defines minimum time between successive births.
  • g-RET - Reproductive Energy Threshold - defines minimum health needed for birth.
  • g-EPT - Energy Per Tick - The mandated per-tick consumption of supplies. Wrkrs eat this amount per tick. Frmrs eat four times this amount per tick.

Economic functions are controlled by by explicit parameters, accessible in the user interface in a panel of many sliders. These fall into the two categories of fixed quotas and relative quotas. The fixed quotas operate per transaction, and prevent wealthy agents from over-indulging to the detriment of other agents. The relative quotas ensure that an agent has a balanced portfolio of asset classes and appear as factors associated with specific asset classes. The factor is compared to the net worth of the agent, and a limit on the size of the asset class is dynamically determined.

Relative quotas

  • g-BRF - Buy Recycled Factor ;; for recycled mass, frmrs only.
  • g-HWF - Hire Wrkr Factor ;; for inventory, frmrs only.
  • g-BSF - Buy Supplies Factor ;; for supplies, wrkrs and frmrs.

Fixed quotas

  • g-no-of-rents-max ;; Max wrkrs per residential patch
  • g-no-of-hires-max ;; Max hires per frmr per tick
  • g-recycled-purchase-quota ;; Max recycled mus purchased per transaction
  • g-harvest-quota ;; Max harvest per hired wrkr
  • g-supplies-purchase-quota ;; Max supply meus purchased per transaction

The activities of each mortal agent (i.e. frmrs and wrkrs) are confined to a 'commuting area' consisting of the 25 cells in the immediate vicinity of the agent. Each frmr has a list of local wrkrs it can hire, and a list of local customers to whom it can sell its inventory. Each wrkr has a list of local employers. Each consumer has a list of local suppliers. Each birth must place a daughter agent within the commuting area of the mother, or the birth cannot happen. These spatial restrictions do not apply to the non-localized immortal agents (i.e. the MMgr and the EMgr), who are able to interact with any mortal agent regardless of location.

With each tick of the ModEco clock a series of processes happen in succession, in the same order within each tick:

  • pre-tick [Pre] - this is a step in which minor reset activities necessary for each tick can be undertaken.
  • sell-waste-buy-recycled [ByR] - in this step the MMgr buys all waste mass from all consumers (both wrkrs and frmrs) and then sells it as recycled mass to all frmrs, for virtual placement on the field. The amount of mass a frmr can purchase is controlled by an upper quota per transaction, to prevent one frmr from buying it all, and an upper limit on the size of the asset class, to prevent a frmr from spending all of its cash on manure, leaving it none for other economic opportunities.
  • hire-wrkrs [HWk] - in this step a frmr hires up to g-no-of-hires-max wrkrs living in its commuting area to harvest food from the field and place it in the frmr's inventory. Technically, two recycled mass mus, and two energy eus are combined to form two inventory meus. The energy eus come one each from the frmr and wrkr.
  • sell-inventory [SlI] - in this step each frmr sells inventory meus to consumers (both wrkrs and frmrs) When the food is transferred to consumers, the name changes to supplies, and they are now available for consumption by the owning consumers. Frmrs cannot eat their own inventory, but must sell it to convert it to supplies. They may, however, sell inventory to themselves, so converting it to supplies.
  • eat-supplies [Eat] - in this step each consumer (wrkr or frmr) consumes a mandatory amount of supplies. If it owns insufficient food, it is marked as starved, and will certainly die when the death step is executed, whether or not it could reproduce before then. Having sufficient food available for each and every tick is one of three survival constraints.
  • reproduction [Rep] - in this step each mortal agent is checked for age of maturity (g-RAT) and health (g-RET), and those that pass the check reproduce, but only if there is a place within the commuting area to place one daughter. The mother then replaces herself with a second daughter, leaving the second half of her assets to the second daughter.
  • death [Dea] - in this step each mortal agent is checked for age of expiry (g-DAT), emaciation (g-DET), or starvation (a flag from eat-supplies step), and those that fail to pass the checks are removed from the demonstration. If Darwinian-style natural selection is implemented (which it is not in this current NetLogo model), this is the point at which it would act.
  • post-tick [Pos] - in this step the model takes care of technical details that are not strictly speaking part of the model. This includes updating displays and such.

In the above, I have not mentioned the role of the EMgr (the estate manager). Because cash, mass and energy are conserved in all transactions (and mass and energy, are strictly conserved as greater than zero in all stocks in which they are found), there must be a place to store such assets of agents when they die. When any mortal agent dies, all of its remaining assets are converted to cash, mass and energy and passed to the EMgr. If these assets are allowed to accumulate in the stocks of the EMgr, the economy will collapse, so they must be returned to the economy. To return these assets to the economy, the EMgr offers grants to poor but deserving agents. If an agent has enough of a necessary input asset to begin a transaction, they are considered 'deserving'. However, if they have insufficient quantities of that asset to meet quota for the transaction, they are considered 'poor', at least, for the moment. 'Momentarily deficient' would be a better description, as many very wealthy agents can get handouts from the EMgr in this scheme. If the EMgr has assets to allocate, and if agents request a grant from those assets, and if they are poor and deserving, the EMgr will top up their store of the requested asset with a grant, up to the transactional quota.

You can monitor the activities of the MMgr and the EMgr in the boxes to the right of the township.

HOW TO USE IT

You have heard, I suppose, of one-player games. One of my tutored students calls programs like this a zero-player game. You set the parameters, you start it, and you watch it. For me, the real action starts when a run is terminated, when I can analyze the data collected in CSV files.

The three conserved quantities are monitored in the displays to the right at the top of the main panel. Note that the totals do not change. Aggregates for frmrs and wrkrs are also shown. The amounts held by the immortal agents are included in the conserved totals, but not in this block of monitor boxes. To see them, look below and to the right.

The aggregate values for the asset classes are on display below that. Again, aggregates for frmrs, wrkrs and total are shown. But, also, the aggregates for the immortal agents are shown to the right.

There are very few user-interface controls in the main user interface panel. You must click on 'setup' first, then 'one tick' or 'go'. Runs are reproduceable. Note the seed for the PRNG, and use the same seed to have the same run. There is a slider to let you choose a seed.

There are, however, lots of explicit parameters available in the user interface panels to the right of the main panel. To access these, use the horizontal scroll bar to move the view to the right. I have NOT TESTED many other values for many of these parameters, so there may be bugs in the code. If you find such bugs, email me at orrery@rogers.com .

The user interface is designed for resolution 1024 x 768 pixels, or higher resolution.

THINGS TO NOTICE

  • SURFACE TENSION - Due to the effects of localization, i.e. due to the need for all mortal agents to deal with other agents within their commuting area, the community forms globular towns, or rarely, soap-film-like columns in the township.

  • WEALTH DISTRIBUTION - Due to the effects of entropy production in this system which is closed with respect to cash, mass and energy, the distribution of wealth tends to approach one which is determined by maximal entropy. For example, when seed=7, and the GROWTH scenario is chosen, the wealth distribution of the wrkrs is eventually described by the Maxwell-Boltzmann distribution of speed in an ideal gas (see URL http://en.wikipedia.org/wiki/Maxwell%E2%80%93Boltzmann_distribution ).

THINGS TO TRY

  • SEEDS - Note the behaviour of the system for different seeds.

  • EXPERIMENTATION - Alter some parameters, and note how the carrying capacity, or quantities in the asset classes vary.

  • A VIEW INSIDE - Open the command centre by clicking on the teeny tiny upwards-pointing arrow at the bottom left of the screen. Then click on the 'clear' button at the top right of the command centre. Then use the 'chooser' to turn on debug reporting for one or all of the steps. I have left the debug tools active. Click on 'one tick'. Then scroll through the debug info that has been written into the command centre log.

  • DATA EXPORT - Right click on any of the graphs, and choose export. Or, find the data export panel and export either DPX (data per transaction), DPT (data per tick), or DPG (data per generation), and use MS Excel to load and analyse the resultant files.

EXTENDING THE MODEL

As mentioned earlier, the purpose in building this model is to explore the necessary and sufficient characteristics of a multi-generational sustainable modern economy. This is an area of study that I personally believe is extremely important and seriously ignored.

  • NEGOTIATED PRICES - Is profitability compatible with economic sustainability? In the PMM all prices are fixed at precisely the value of the goods and services. In the C++ version of this model, prices are negotiated, and there is a likely price/value gap in all transactions. This means, in most transactions, one agents makes a profit, and one agent takes a loss. Unfortunately, ALL such models in which profits are allowed have collapsed. While the PMM is stable, as demonstrated in this present model, unfortunately, this PMM is being forcibly held at an unstable equilibrium point of some type. Would the introduction of such price negotiation here lead inevitably to economic collapse, as happens in the C++ version?

  • DEPTH COMPLETENESS - Is biodiversity compatible with economic sustainability? ModEco has vertical and longitudinal completeness, as defined above. Add another breed, such as wild mice, that eat grain in the field, and demonstrate the maintenance of biodiversity in parallel to economic sustainability. What biophysical and economic constraints need to be developed to ensure that there is room for wild creatures that have no economic value, but great biophysical value?

  • NECESSITY AND SUFFICIENCY - What are the necessary and sufficient characteristics of a multi-generational sustainable modern economy? The PMM, as demonstrated herein, has a number of features that were developed to achieve that elusive goal of multi-generational sustainability. (For details, read the ODD description associated with this NetLogo implementation downloadable from the 'Files' tab). These include the non-localized roles of the two immortal agents, fixed quotas on transactions, relative quotas on wealth stocks, or the marketing of waste. I believe this is the most-simple model that is complete, is consistent with the conservation laws of physics, and is sustainable across many generations of agents. Can a more simple model be built that meets that description?

  • BIOPHYSICAL REALISM - Can the model be revised to demonstrate a sustainable economy more in line with Herman Daly's concepts? In the PMM both mass and energy cycle forever. In reality, energy cannot be recycled, and mass can be recycled only a few times. Energy is renewable, however, in the sense that the Sun has an endless supply, and mass is renewable in the sense that nature can reconstitute waste as edible food. Herman Daly sees an economy as flows of mass and energy that are degraded as they flow through the economic system. All of my attempts to implement non-cyclic flows result in economic and biophysical collapse.

  • SOCIAL JUSTICE - Can the model be revised to demonstrate a sustainable economy that exhibits elements of social justice? In the PMM all indications are that social justice is absent. I am drawing this from my experience with the PMM in the C++ version in which I have much greater access to the internal structure and dynamics of the economy. In the PMM the poor are partially disenfranchised, due to the grant methodology. The children of the poor live short lives of disenfranchisement and, ultimately, starvation while the children of the wealthy live lives of open access to economic opportunities, and good prospects of reproduction. Life at the edge of the biophysical carrying capacity is, of necessity, a life of subsistence level activity for the bulk of the population. What mechanisms are needed to improve the quality of life for the bulk of the agents? What constraints on economic and social behaviour are needed to reduce the population below carrying capacity and allow social justice to flourish?

NETLOGO FEATURES

This was my first exercise in writing a NetLogo program. These past few months have been both insightful and frustrating. I clearly have not yet understood the organizing principle behind NetLogo, though I understand it is part of the progeny of LISP, a list-processing language I once knew about. I can see the list-based approach in much of the syntax. In many ways, NetLogo seems to be very powerful, handling a lot of ABM issues behind the scenes; issues such as randomized access to agents, etc. But, I struggled with the syntax, and may have written some very time-inefficient or overly-complicated code. I also struggled with the construction of a user-interface.

These may exists already, but I could not find them. Here is my list of wished-for features:

  • handles for the user interface items such as plots, monitors, notes, sliders, choosers, etc. that would allow me to hide or display, enable or disable them.

  • monitor items that let me monitor, format and display multiple variables in a single table, such as a balance sheet, or a cash-flow sheet.

  • the ability to create generic data structures that can then be included in multiple breeds of agents. For example, my biophysical and economic controls could be packaged into data structures called genes and made specific to agents rather than global. Then processes like mutation, genetic cross-over, or gene-driven behaviour could be more easily managed.

RELATED MODELS

This model is a simplified version of one model (the PMM) from an application (ModEco) written in C++. The PMM has been documented using the ODD protocols, and is available, with such documentation as exists, from the OpenABM site.

A biophysical model demonstrating the evolution of bugs in a pond was used as the basis for the biophysical subsystem of ModEco economies, and, by association, of this model. That application is called PSoup, and is available from my website, also.

Finally, PSoup, in turn, was inspired by a program called "Simulated Evolution" written by Dr Michael Palmiter, and described in an issue of Scientific American about 1989. It used to be available from this website but seems to be offered no longer.

I have borrowed the concepts of 'Lorenz curve' and 'Gini Coefficient' from Uri Wilensky's model, cited below.

CREDITS AND REFERENCES

  • Dr Ludwig Boltzmann, for his theory of entropy.

  • Dr Michael Palmiter, for his program 'Simulated Evolution'.

  • Dr Herman Daly, for his concept of 'Steady-state Economics'.

  • Dr Melanie Mitchel, external professor of Santa Fe Institute, for her MOOC on using NetLogo for the study of complex adaptive systems, which was the immediate trigger for me to undertake this programing exercise.

  • Wilensky, U. (1998). NetLogo Wealth Distribution model. http://ccl.northwestern.edu/netlogo/models/WealthDistribution. Center for Connected Learning and Computer-Based Modeling, Northwestern Institute on Complex Systems, Northwestern University, Evanston, IL.

Comments and Questions

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

Click to Run Model

;;-----------------------------------------------------------------------------|
;; SECTION A – AUTHOR IDENTIFICATION AND CODE ABSTRACT
;;-----------------------------------------------------------------------------|
;;
;; File Name: ModEco_V1.39.nlogo
;; By Orrery Software
;; Dated: 2014-11-14
;; Author contact:
;;   Garvin H Boyle
;;   orrery@rogers.com
;;   orrery-software.webs.com

;; As the author, I welcome questions, discussion of issues and suggestions
;;   for improvements.

;;-----------------------------------------------------------------------------|
;; This ModEco app is a radically simplified version of my ModEco app 
;;   written in C++.  The purpose of both programs is to investigate the 
;;   dynamics of simple complete conservative economic systems and to understand 
;;   the necessary and sufficient conditions for a sustainable economic system.

;;-----------------------------------------------------------------------------|
;; SECTION B – INITIAL DECLARATIONS OF GLOBALS AND BREEDS
;;-----------------------------------------------------------------------------|
;;
;;-----------------------------------------------------------------------------|
;; This program was developed on NetLogo Version 5.0.5
;;

;;-----------------------------------------------------------------------------|
;; code-determined global variables
globals
[
  ;; The version should be coded in this global variable to be included in
  ;;   output files.
  gs-Version
  
  ;; Note: Some global variables are declared inside of switches, sliders and 
  ;;   choosers when the interface is constructed and are not declared here.
  ;;   For the sake of clarity and completeness, they are noted here.
  
  ;; There are several uses of global variables:
  ;;  - Toggles (switches), and choosers which enable or disable features;
  ;;  - Numbers (in variables or sliders) which act as parameters;
  ;;  - Numbers (in variables) which collect data.
  ;;
  ;; Those marked as 'native Boolean' have values of true or false.
  ;; Those marked as 'numeric Boolean' have values of 1 or 0.
   
  ;;---------------------
  ;; MODELING ENVIRONMENT
  ;;---------------------
  
  ;; Assumed “Model Settings” on startup
  ;; horizontal wrap: on
  ;; vertical wrap: on
  ;; location of origin: center
  ;; patch size: 18 pixels
  ;;-----------------------------------------------------------------------------|
  ;; Implicit global variables due to model settings – patch locations
  ;; min-pxcor -9
  ;; max-pxcor  9
  ;; min-pycor -9
  ;; max-pycor  9
  
  ;;----------------------------
  ;; SCENARIO SELECTION CONTROLS
  ;;----------------------------
  
  ;; gs-scenario       ;; Chooser, string converts to a scenario number
  g-scenario-number    ;; scenario number, 0 or 1, interpretation of gs-scenario

  ;; The possible scenarios.
  g-scenario-pmm       ;; pmm scenario, 0
  g-scenario-growth    ;; growth scenario, 1

  ;; Initialize the Pseudo Random Number Generator (PRNG).
  ;; g-use-this-seed   ;; Slider, ( 1 <= g-use-this-seed <= 100 )

  ;;-----------------------------------------------
  ;; BIOPHYSICAL SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;-----------------------------------------------

  ;; Life function controls
  ;; g-DAT                    ;; Slider, Death age threshold
  ;; g-DET                    ;; Slider, Death energy threshold
  ;; g-RAT                    ;; Slider, Reproductive age threshold
  ;; g-GTT                    ;; Slider, Gestation time threshold
  ;; g-RET                    ;; Slider, Reproductive energy threshold
  ;; g-EPT                    ;; Slider, Energy per tick
  
  ;;--------------------------------------------
  ;; ECONOMIC SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;--------------------------------------------
  
  ;; Business control factors, used to compute dynamic quotas
  ;; g-HRF-f                  ;; Slider, Hold recycled factor
  ;; g-HIF-f                  ;; Slider, Hold inventory factor
  ;; g-HSF-f                  ;; Slider, Hold supplies factor - frmrs
  ;; g-HSF-w                  ;; Slider, Hold supplies factor - wrkrs

  ;; Business survival thresholds, used to put a floor on dynamic quotas.
  ;; g-HRL-f-min              ;; Slider, Hold recycled limit minimum
  ;; g-HIL-f-min              ;; Slider, Hold inventory limit minimum
  ;; g-HSL-f-min              ;; Slider, Hold supplies limit minimum - frmrs
  ;; g-HSL-w-min              ;; Slider, Hold supplies limit minimum - wrkrs

  ;; Iteration count quotas
  ;; g-no-of-rents-max        ;; Max wrkrs per residential patch
  ;; g-no-of-hires-max        ;; Max hires per frmr per tick
  ;; g-no-of-waste-xactions-max ;; Max transactions per frmr per tick

  ;; Transaction size quotas (Derived parameters)
  g-waste-sales-quota         ;; Max waste mus sold per transaction
  g-recycled-purchase-quota   ;; Max recycled mus purchased per transaction
  g-harvest-quota             ;; Max harvest per hired wrkr; must be multiple of 2
  g-supplies-purchase-quota   ;; Max supply meus purchased per transaction
   
  ;; Prices ( for fixed price version )
  ;; g-mu-price               ;; Price per mass unit ( mu )
  ;; g-eu-price               ;; Price per energy unit ( eu )
  g-meu-price                 ;; Price per mass/energy unit ( meu )
   
  ;; The materiel manager ( MMgr )
  ;; gb-MMgr                  ;; Switch, enables the MMgr.
  ;; gb-MMgr-debt             ;; Switch, enables MMgr debt.
  g-MMgr-cash                 ;; cash held for buying waste
  g-MMgr-mass                 ;; mass held for sale as recycled mass
   
  ;; MMgr initialization values.
  ;; g-MMgr-cash-at-setup     ;; Slider, In dollars
  ;; g-MMgr-mass-at-setup     ;; Slider, In mus

  ;; The estate manager ( EMgr )
  ;; gb-EMgr                  ;; Switch, enables the EMgr
  g-EMgr-cash                 ;; cash held for redistribution
  g-EMgr-energy               ;; energy held for redistribution
  g-EMgr-mass                 ;; mass held for redistribution
  
  ;; EMgr initialization values.
  ;; g-EMgr-cash-at-setup     ;; Slider, In dollars
  ;; g-EMgr-mass-at-setup     ;; Slider, In mus
  ;; g-EMgr-energy-at-setup   ;; Slider, In eus
  
  ;;-------------------------------------
  ;; END OF MODEL PARAMETERS AND CONTROLS
  ;;-------------------------------------
  
  ;;-------------------------------------
  ;; DATA COLLECTION AND DISPLAY CONTROLS
  ;;-------------------------------------
  
  ;; The following global variables are not model controls or paramaters, 
  ;;   but, rather, are variables used to collect data about the model 
  ;;   for display in the user interface, in some fashion (monitors or plots),
  ;;   or used to manage all of the debug routines and output.
  
  ;; SYSTEM-WIDE AGGREGATES
  ;; Used to verify conservation of cash, mass and energy.
  ;; Also used to make 'balance sheet' display on interface.
  
  g-no-of-agents              ;; count of all agents
  g-no-of-wrkrs               ;; count of all agents
  g-no-of-frmrs               ;; count of all agents

  g-total-cash                ;; total of all cash
  g-total-mass                ;; total of all mass
  g-total-energy              ;; total of all energy

  g-frmr-cash                 ;; total frmr cash
  g-frmr-mass                 ;; total frmr mass
  g-frmr-energy               ;; total frmr energy

  g-wrkr-cash                 ;; total wrkr cash
  g-wrkr-mass                 ;; total wrkr mass
  g-wrkr-energy               ;; total wrkr energy
   
  g-total-cash-class          ;; total cash class
  g-total-recycled-class      ;; total recycled class
  g-total-energy-class        ;; total energy class
  g-total-inventory-class     ;; total inventory class
  g-total-supplies-class      ;; total supplies class
  g-total-waste-class         ;; total waste class
   
  g-frmr-cash-class           ;; frmr cash class
  g-frmr-recycled-class       ;; frmr recycled class
  g-frmr-energy-class         ;; frmr energy class
  g-frmr-inventory-class      ;; frmr inventory class
  g-frmr-supplies-class       ;; frmr supplies class
  g-frmr-waste-class          ;; frmr waste class
  
  g-wrkr-cash-class           ;; wrkr cash class
  g-wrkr-energy-class         ;; wrkr energy class
  g-wrkr-supplies-class       ;; wrkr supplies class
  g-wrkr-waste-class          ;; wrkr waste class
  
  ;; PLOTS
  ;; Switch for plots
  ;; gb-plots-on              ;; Switch, Native Boolean, enables/disables plotting

  ;; Plot "Sector Sizes".
  g-wrkr-sector-size          ;; dollar value of all wrkr assets
  g-frmr-sector-size          ;; dollar value of all frmr assets
  g-emgr-sector-size          ;; dollar value of all emgr assets
  g-mmgr-sector-size          ;; dollar value of all mmgr assets
  
  ;; Plot "Wealth Distribution - wrkrs"
  g-min-wrkr-wealth           ;; the minimum wealth of all wrkrs
  g-max-wrkr-wealth           ;; the maximum wealth of all wrkrs
  g-max-wrkr-count            ;; the maximum number of wrkrs
  
  ;; Plot "Wealth Distribution - frmrs"
  g-min-frmr-wealth           ;; the minimum wealth of all frmrs
  g-max-frmr-wealth           ;; the maximum wealth of all frmrs
  g-max-frmr-count            ;; the maximum number of frmrs
  
  ;; Plot "Age Distribution - wrkrs"
  g-min-wrkr-age           ;; the minimum age of all wrkrs
  g-max-wrkr-age           ;; the maximum age of all wrkrs
  
  ;; Plot "Age Distribution - frmrs"
  g-min-frmr-age           ;; the minimum age of all frmrs
  g-max-frmr-age           ;; the maximum age of all frmrs
  
  ;; Plot "Usage Rates Per Tick"
  g-no-of-hires-this-tick          ;; Running count of hires per tick
  g-cash-spent-this-tick           ;; Running count of dollars spent per tick
  g-cash-spent-this-tick-recycled  ;; Running count of dollars spent per tick
  g-cash-spent-this-tick-labour    ;; Running count of dollars spent per tick
  g-cash-spent-this-tick-food      ;; Running count of dollars spent per tick
  g-cash-spent-this-tick-waste     ;; Running count of dollars spent per tick
  
  ;; Other - built-in or declared implicitly in plot interface items
  ;; See each plot design dialogue.

  ;;------------------------------
  ;; ENTROPY COMPUTATION MECHANISM
  ;;------------------------------

  ;; This requires a little explanation.
  
  ;; Entropy is calculated on the bins in a histogram.  The goal here is to 
  ;;   construct a histogram of wealth for each of wrkrs and frmrs, and plot
  ;;   a time series of entropy readings, for each, as a run proceeds.  I need 
  ;;   two such histograms for computing the entropy values, and two time series
  ;;   of readings to hold the data. I seems I do not have complete control over
  ;;   the structure of a histogram plotted using the NetLogo native 'histogram'
  ;;   command, nor do I have access to its contents.  So, below I declare
  ;;   the variables needed to construct my own temporary histograms. 
  
  ;; A calculation of entropy requires four steps:
  ;;  - Build a standardized histogram, having bins of pre-determined widths
  ;;      and start values;
  ;;  - Compute surprisals for each bin between the lowest non-zero bin and 
  ;;      the largest non-zero bin;
  ;;  - Add the surprisals to get an aggregate measure of entropy;
  ;;  - Convert the entropy measure to an entropy index by scaling it using the
  ;;    factor 1/log(K), where K is the number of bins between the first and the
  ;;    last (inclusively).
  
  ;; Entropy indices are comparable from one tick to the next if they are 
  ;;   re-scaled.  To re-scale an index, multiply by log( old K ) and divide
  ;;   by log( new K ).  K may change from tick to tick, so the time series
  ;;   must be re-scaled and re-drawn with each new K.  So, the scaling factors
  ;;   must be stored with the entropic index.
  
  ;; Note: all variables having to do with entropy calculations have -ent- as
  ;;   part of the variable name.
  
  ;; An entropy reading is a list containing:
  ;;   - Item 0 - ticks value
  ;;   - Item 1 - a computed entropic index for wrkrs
  ;;   - Item 2 - the associated scaling factor g-K-w
  ;;   - Item 3 - a computed entropic index for frmrs
  ;;   - Item 4 - the associated scaling factor g-K-f
  ;;   - Item 5 - a computed entropic index for all turtles
  ;;   - Item 6 - the associated scaling factor g-K-a
  gl-ent-reading
  
  ;; An entropy time series, a global list of entropy readings
  gl-ent-time-series        ;; Time series of readings
  g-no-of-ent-readings      ;; Count of readings
  g-no-of-ent-readings-max  ;; Max limit on count of readings

  ;; The bin width is constant.  The 'bin start' values are always integral 
  ;;   multiples of the bin width.
  g-ent-bin-width-w         ;; The fixed bin width for the wrkr histogram.
  g-ent-bin-width-f         ;; The fixed bin width for the frmr histogram.
  g-ent-bin-width-a         ;; The fixed bin width for the 'all' histogram.
  
  ;; The bins of the histograms are ephemeral, having meaning and value only
  ;;   until the surprisals are calculated.  They do not need a global 
  ;;   declaration.  These histograms are hidden and temporary.
  
  ;; Storage of the 'K' scaling factors for each type of hidden histogram.
  g-K-w  ;; For wrkrs
  g-K-f  ;; For frmrs
  g-K-a  ;; All together
  
  g-entropic-index-w   ;; For wrkrs
  g-entropic-index-f   ;; For frmrs
  g-entropic-index-a   ;; All together
  
  ;;---------------------------------------
  ;; LORENZ CURVE AND GINI INDEX MECHANISMS
  ;;---------------------------------------
  ;; These techniques are copied directly from the model "Wealth Distribution"
  ;;   by Uri Wilensky.
  
  gl-lorenz-points-a       ;; A list, used to plot the points of the Lorenz curve, all agents.
  gl-lorenz-points-w       ;; A list, used to plot the points of the Lorenz curve, wrkrs.
  gl-lorenz-points-f       ;; A list, used to plot the points of the Lorenz curve, frmrs.
  g-gini-index-reserve-a   ;; The Gini coefficient, all ageents.
  g-gini-index-reserve-w   ;; The Gini coefficient, wrkrs.
  g-gini-index-reserve-f   ;; The Gini coefficient, frmrs.


  ;;--------------------------
  ;; DATA CAPTURE TO CSV FILES
  ;;--------------------------

  ;; CSV means "Character Separated Values"
  ;; I use a space to separate values.  This can be read by MS Excel.

  ;; Data Per Xaction
  gb-dpx-on          ;; Numeric Boolean switch
  gs-dpx-status      ;; Interpretation of gb-dpx-on
  gs-dpx-file-name   ;; The file name
  g-dpx-recno        ;; The number of the last record written.
  gl-dpx-record-layout-B ;; A list containing the transaction elements.
  gl-dpx-record-layout-D ;; A list containing the transaction elements - wrkrs.
  gl-dpx-record-layout-F ;; A list containing the transaction elements - frmrs.
  gl-dpx-record-layout-H ;; A list containing the grant data.
  g-recno-max        ;; Maximum record number for all files.

  ;; Data Per Tick
  gb-dpt-on          ;; Numeric Boolean switch
  gs-dpt-status      ;; Interpretation of gb-dpt-on
  gs-dpt-file-name   ;; The file name
  g-dpt-recno        ;; The number of the last record written.


  ;; Data Per Generation
  gb-dpg-on          ;; Numeric Boolean switch
  gs-dpg-status      ;; Interpretation of gb-dpg-on
  gs-dpg-file-name   ;; The file name
  g-dpg-recno        ;; The number of the last record written.


  ;;---------------
  ;; DEBUG CONTROLS
  ;;---------------
  
  gb-debug-on                 ;; Numeric Boolean, opens debug log file, 0 or 1.
  gs-debug-status             ;; for monitor, '1 (On)' or '0 (Off)', 
  ;; gs-debug-step-chooser    ;; Chooser, used with gb-debug-flow-on
  gb-debug-flow-on            ;; Numeric Boolean, in association with chooser, 
  gs-log-file-name            ;; name of the debug log file
                              ;;   opens flow to log file
  ;; gb-debug-show-steps      ;; Switch, Native Boolean, show in command centre
  ;; gb-debug-show-aif        ;; Switch, Native Boolean, show in command centre
  ;; gb-debug-aif-on          ;; Switch, Native Boolean, agent-in-focus = -aif-
  ;; gb-debug-tog-on          ;; Switch, Native Boolean, toggles dump
  g-aif                       ;; who number of the aif 
]


;;-----------------------------------------------------------------------------|
;; Attributes of patches
patches-own 
[
  ;; BUILT-IN ATTRIBUTES 
  ;; pxcor        ;; min-pxcor <= pxcor < max-pxcor
  ;; pycor        ;; min-pxcor <= pxcor < max-pxcor 
  ;; pcolor       ;; color of this patch ( 0 <= color < 140 ) 
  ;; plabel       ;; label of this patch
  ;; plabel-color ;; color of this patch's label ( 0 <= label-color < 140 ) 
   
  ;; MODECO-DETERMINED ATTRIBUTES
  p-no-of-frmrs   ;; the number of frmrs in this farming patch
  p-no-of-wrkrs   ;; the number of wrkrs renting in this residential patch
  com-area        ;; the 25-patch 2-neighbourhood
]

;;-----------------------------------------------------------------------------|
;; Attributes of links
;; nil
;; I don't understand links and did not use any.

;;-----------------------------------------------------------------------------|
;; Turtles and breeds
breed [ frmrs frmr ]
breed [ wrkrs wrkr ]

;;-----------------------------------------------------------------------------|
;; Attributes of frmrs
frmrs-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; fixed id number
  ;; breed       ;; to which breed this turtle belongs [frmr]
  ;; heading     ;; 0 <= heading < 360, 0 = north
  ;; xcor        ;; min-pxcor <= xcor < max-pxcor
  ;; ycor        ;; min-pxcor <= xcor < max-pxcor
  ;; size        ;; size relative to a patch, default is 1
  ;; shape       ;; a shape chosen from the shape library
  ;; color       ;; color of this turtle ( 0 <= color < 140 )
  ;; pen-mode    ;; "up" or "down"
  ;; pen-size    ;; in pixels
  ;; hidden?     ;; true or false
  ;; label       ;; label of this turtle
  ;; label-color ;; color of this turtle's label ( 0 <= label-color < 140 )
   
  ;; USER-DETERMINED ATTRIBUTES
  age         ;; number of ticks since birth
  age-to-reproduce ;; next age at which reproduction can happen
  ma-who      ;; who number of mother
  da-who      ;; who numbers of daughters
   
  ;; Asset classes
  cash        ;; amount of cash ( $ )
  energy      ;; amount of energy ( eu )
  recycled    ;; units of recycled mass ( mu )
  inventory   ;; units of inventory of mass-energy ( meu )
  supplies    ;; units of supplies of mass-energy ( meu )
  waste       ;; units of waste mass ( mu )
  net-value   ;; the total value, in dollars, of all assets
  real-value  ;; the total value, in dollars, of all assets except cash
  
  ;; Computed real-time limits on asset ownership 
  hrl               ;; hold recycled limit
  hil               ;; hold inventory limit
  hsl               ;; hold supplies limit
  energy-set-point  ;; the lowest energy allowed from working.
  available-energy  ;; the energy available for work vice reproduction
   
  ;; Patch access
  my-patch    ;; location of this wrkr
   
  ;; Agent access
  union-set      ;; list of all wrkrs in com-area
  customer-set   ;; list of all frmrs and wrkrs in com-area
  supplier-set   ;; list of all frmrs in com-area
   
  ;; The 'b-can-' Booleans control the participation in economic or 
  ;; physical transactions. The primary agents in the agentset activated by the 
  ;; observer initiate actions.  The responding agents are invoked from union 
  ;; lists, etc., and each may be on several such lists.  Once serviced by one 
  ;; primary agent, they cannot participate in response to another.
  ;;

  b-can-sell-waste     ;; Boolean control on participation
  b-can-buy-recycled   ;; Boolean control on participation
  b-can-hire-wrkrs     ;; Boolean control on participation
  b-can-sell-inventory ;; Boolean control on participation
  b-can-buy-supplies   ;; Boolean control on participation
  b-can-eat            ;; Boolean control on participation
  b-can-reproduce      ;; Boolean control on participation
  b-can-die            ;; Boolean control on participation
  b-can-die-of-hunger  ;; Boolean control on participation
  b-can-die-of-age     ;; Boolean control on participation
  b-can-die-of-lownrg  ;; Boolean control on participation

  ;; Grant management variables
  ;; The EMgr provides grants that may not be all used.
  ;; These variables record the grants given and used.
  ;; Unused grants must be returned to the EMgr.
  ;; This avoids the complicated logic required to get the grant exactly right.
  grt-mgmt-cash-granted       ;; amount of grant of cash
  grt-mgmt-energy-granted     ;; amount of grant of energy
  grt-mgmt-recycled-granted   ;; amount of grant of recycled mass
  grt-mgmt-inventory-granted  ;; amount of grant of inventory
  grt-mgmt-waste-granted      ;; amount of grant of waste mass

  grt-mgmt-cash-used      ;; amount of cash used in grant-supported xaction 
  grt-mgmt-energy-used    ;; amount of energy used in grant-supported xaction 
  grt-mgmt-recycled-used  ;; amount of recycled mass used in grant-supported xaction 
  grt-mgmt-inventory-used ;; amount of inventory used in grant-supported xaction 
  grt-mgmt-waste-used     ;; amount of waste mass used in grant-supported xaction 
  
]

;;-----------------------------------------------------------------------------|
;; Attributes of wrkrs
wrkrs-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who      ;; fixed id number
  ;; breed    ;; to which breed this turtle belongs [wrkr]
  ;; heading  ;; 0 <= heading < 360, 0 = north
  ;; xcor     ;; min-pxcor <= xcor < max-pxcor
  ;; ycor     ;; min-pxcor <= xcor < max-pxcor
  ;; size     ;; size relative to a patch, default is 1
  ;; shape    ;; a shape chosen from the shape library
  ;; color    ;; color of this turtle ( 0 <= color < 140 )
  ;; pen-mode ;; "up" or "down"
  ;; pen-size ;; in pixels
  ;; hidden?  ;; true or false
  ;; label    ;; label of this turtle
  ;; label-color ;; color of this turtle's label ( 0 <= label-color < 140 )
   
  ;; USER-DETERMINED ATTRIBUTES
  age         ;; number of ticks since birth
  age-to-reproduce ;; next age at which reproduction can happen
  ma-who      ;; who number of mother
  da-who      ;; who numbers of daughters
   
  ;; Asset classes
  cash        ;; amount of cash ( $ )
  energy      ;; amount of energy ( eu )
  supplies    ;; units of supplies of mass-energy ( meu )
  waste       ;; units of waste mass ( mu )
  net-value   ;; the total value, in dollars, of all assets
  real-value  ;; the total value, in dollars, of all assets except cash
   
  ;; Patch access
  my-patch    ;; location of this wrkr
   
  ;; Computed real-time limits on asstet ownership
  hsl         ;; hold supplies limit
  energy-set-point  ;; the lowest energy allowed from working.
  available-energy  ;; the energy available for work vice reproduction
   
  ;; Agent access
  employer-set       ;; list of all frmrs in com-area
  supplier-set       ;; list of all frmrs in com-area
   
  ;; The 'b-can-' Booleans control the participation in economic or 
  ;; physical transactions. The primary agents in the agentset activated by the 
  ;; observer initiate actions.  The responding agents are invoked from union 
  ;; lists, etc., and each may be on several such lists.  Once serviced by one 
  ;; primary agent, they cannot participate in response to another.
  ;;
  b-can-sell-waste     ;; Boolean control on participation
  b-can-work           ;; Boolean control on participation
  b-can-buy-supplies   ;; Boolean control on participation
  b-can-eat            ;; Boolean control on participation
  b-can-reproduce      ;; Boolean control on participation
  b-can-die            ;; Boolean control on participation
  b-can-die-of-hunger  ;; Boolean control on participation
  b-can-die-of-age     ;; Boolean control on participation
  b-can-die-of-lownrg  ;; Boolean control on participation

  ;; When a wrkr is sprouted on a residential patch, there may be several wrkrs
  ;;   present.  This flag is used to select the new sprout.
  b-just-sprouted      ;; Boolean control for finding newly sprouted wrkr
   
  ;; Grant management.
  ;; The EMgr provides grants that may not be all used.
  ;; These variables record the grants given and used.
  ;; Unused grants must be returned to the EMgr.
  ;; This avoids the complicated logic required to get the grant exactly right.
  grt-mgmt-cash-granted       ;; amount of grant of cash
  grt-mgmt-energy-granted     ;; amount of grant of energy
  grt-mgmt-waste-granted      ;; amount of grant of waste mass

  grt-mgmt-cash-used          ;; amount of cash used in grant-supported xaction 
  grt-mgmt-energy-used        ;; amount of energy used in grant-supported xaction 
  grt-mgmt-waste-used         ;; amount of waste mass used in grant-supported xaction 
  
]

;;-----------------------------------------------------------------------------|
;; SECTION C – INITIALIZATION OR SETUP PROCEDURE( S )
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; The 'autostart' startup routine

to startup
  ;; This routine is to be executed by the observer.

  ;; The manual describes this routine as follows:
  ;; This procedure, if it exists, will be called when a model is first loaded in 
  ;;   the NetLogo application.  Startup does not run when a model is run headless 
  ;;   from the command line, or by parallel BehaviorSpace.

  ;; On loading the model, the debug feature is always off.
  set gb-debug-on 0
  set gs-debug-status "0 (Off)"
  
  ;; On loading the model, the data capture is always off.
  f-close-dpx-file
  f-close-dpt-file
  f-close-dpg-file
  
  ;; On loading the model, the model, the choosers, switches and sliders are
  ;;   always reset to the values that are known to work.  Only the chooser
  ;;   for the scenario (PMM #2 vs GROWTH) is not reset.  The last saved 
  ;;   selection of scenario is persistant.  This allows the 'Reset Defaults'
  ;;   button to NOT reset the scenario.
  f-reset-default-parameters

  ;; Run the setup routine to initialize other globals.
  setup
end 

;;-----------------------------------------------------------------------------|
;; The setup button(s)

to setup
  ;; This routine is to be executed by the observer.

  ;; NOTE: The contents of switches, sliders, and choosers seem to be 
  ;;   immune to these 'clear' commands.
  clear-ticks
  clear-turtles
  clear-patches
  clear-drawing
  clear-all-plots
  clear-output
  ;; clear-globals   ;; Suppressed to make gb-debug-on value persistent.
  ;; NOTE: Instead of 'clear-globals', you must ensure all globals are 
  ;;   initialized properly in 'setup'.
  
  ;; The version should be coded in this global variable to be included in
  ;;   output files.
  set gs-Version "ModEco_V1.39" 

  ;; Debug features may be off or on depending on history.
  ;;   - Perhaps 'Setup' was called by 'to Startup'.
  ;;   - Perhaps 'setup' was called during a 'BehaviorSpace' run.
  ;;   - Perhaps 'setup' was called by a user-pushed 'setup' button.
  ;; Setup needs to handle some quasi-persistant values correctly regardless of
  ;;   the history.  For gb-debug-on, in particular, I want it to be 
  ;;   persistant so I can have debug output from the 'setup' routine routed
  ;;   to the debug log file, or to the command centre.
  
  ;; 'startup' automatically sets gb-debug-on to 0 when the application is first
  ;;   loaded.  I want to be able to (A) toggle debug on, then, (B) press 
  ;;   'setup' and watch the debug output of the 'setup' command.  The gb-debug-on
  ;;   must be persistant through the above 'clear' commands.  The debug log 
  ;;   file name and status, however, should not be persistent and must be 
  ;;   reset when setup runs, if appropriate.
  ifelse ( gb-debug-on = 1 )
  [
    ;; Debug is on due to user setting, so file name and status should be 
    ;;   reset.  I do this by turn the feature off then on.
    ;; First toggle it off, closing any remnant log file, if needed.
    f-toggle-debug
    ;; Then toggle it back on, opening a new time-stamped log file.
    f-toggle-debug
  ]
  ;; else
  [
    ;; Debug is off, possibly due to startup execution, possibly due to user 
    ;;   choice.
    ;; Ensure associated variables have compatible settings.
    set gb-debug-on 0              ;; Redundant but ensures consistency.
    set gs-debug-status "0 (Off)"  ;; Redundant but ensures consistency.
    set gb-debug-flow-on 0         ;; Step-specific flow is off.
    file-close-all                 ;; Close the debug log file.
    set gs-log-file-name "dummyname"
  ]
  
  ;; Now, do the standard check that is done at the start of each debuggable 
  ;;   routine.  This must follow the clear commands, which reset everything 
  ;;   except globals, switches, sliders and choosers.
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "setup" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-setup: Debug on; tick = " 0 ]
    [ set gb-debug-flow-on 0 ]
  ]

  ;; g-use-this-seed comes from a slider, and is persistant.
  random-seed g-use-this-seed      ;; Tells the PRNG to use this seed.
  
  ;; Data capture to file feature.
  ;;   The data capture files may be open, and the features, stored in switches,
  ;;   may be on, as they are persistent.  Ensure they are off.
  f-close-dpx-file
  f-close-dpt-file
  f-close-dpg-file
  
  ;; Set the limit on the number of records in a CSV data file.
  ;; This applies to dpx, dpt and dpg files.  
  set g-recno-max 500000
  
  ;; Agent-in-focus (AIF) feature.
  ;; This is a debug feature that lets me direct information about a single
  ;;   agent to the debug log file or the command centre as the program
  ;;   runs, independently of other debug information.  This kind of trace 
  ;;   facility is sometimes very useful when debugging a step.  The AIF data
  ;;   is of two kinds: 
  ;;   - data of lasting value from tick to tick; and
  ;    - Boolean flags that are of intermittant value within a step, within 
  ;;     a tick.  I generically call these 'participation flags'.
  ;; To turn the feature on:
  ;;   - gb-debug-on must be toggled on (a button), to open a debug logging file.
  ;;   - gb-debug-aif-on must be toggled on (a switch).
  ;;   - gb-debug-tog-on must be toggled on (a switch), to include the Booleans.
  ;; To divert a copy of the logged information to the command centre:
  ;;   - gb-debug-show-aif must be toggled on (a switch)
  ;; To select the 'agent in focus' set the variable 'g-aif' equal to its who #.
  ;;   This can be done in the command line of the command centre.
  set g-aif 0                      ;; default who # of an 'agent in focus'. 
  
  ;; There are 2 scenarios possible: PMM #2 and GROWTH
  set g-scenario-pmm  0            ;; pmm scenario
  set g-scenario-growth 1          ;; regular operation

  ;; Use the input from the chooser gs-scenario to invoke the selected scenario.
  set g-scenario-number g-scenario-growth  ;; default
  if( gs-scenario = "PMM #2" )
  [
    set g-scenario-number g-scenario-pmm
  ]
  
  ;; For debugging the debug feature!!!  Suppressed now.
  ;; show ( word "SETUP: Debug Is " gb-debug-on )
  ;; show ( word "SETUP: Debug Status Is " gs-debug-status )
  ;; show ( word "SETUP: Step Chooser Is " gs-debug-step-chooser )
  ;; show ( word "SETUP: Flow Control Is " gb-debug-flow-on )

  ;; For debugging the setup procedure, log the values of the globals.
  LOG-TO-FILE ( word "Do-set: Scenario number - " g-scenario-number ) 
  LOG-TO-FILE ( word "Do-set: Scenario name - "   gs-scenario )
  LOG-TO-FILE ( word "Do-set: Random seed - "     g-use-this-seed )

  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: BIOPHYSICAL SUB-SYSTEM PARAMETERS (Sliders):" )
  LOG-TO-FILE ( word g-RAT " - Death Age Threshold ( g-DAT )" )
  LOG-TO-FILE ( word g-DET " - Death Energy Threshold ( g-DET )"  )
  LOG-TO-FILE ( word g-RAT " - Reproduction Age Threshold ( g-RAT )"  )
  LOG-TO-FILE ( word g-GTT " - Gestation Time Threshold ( g-GTT )"  )
  LOG-TO-FILE ( word g-RET " - Reproduction Energy Threshold ( g-RET )" )
  LOG-TO-FILE ( word g-EPT " - Mandatory Energy Consumption Per Wrkr Per Tick ( g-EPT )" )
  LOG-TO-FILE ( word ( g-no-of-hires-max * g-EPT ) " - Mandatory Energy Consumption Per Frmr Per Tick ( Multiple of g-EPT )" )
  
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: ECONOMIC SUB-SYSTEM PARAMETERS (Sliders):" )
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: Iteration Limits:" )
  LOG-TO-FILE ( word g-no-of-rents-max " - Maximum wrkrs per residential patch"  )
  LOG-TO-FILE ( word g-no-of-hires-max " - Maximum hires per frmr per tick"  ) 
  LOG-TO-FILE ( word g-no-of-waste-xactions-max " - Maximum 'buy recycled' transactions per frmr per tick"  ) 
  
  ;; EPT-Derived Transaction Size Quotas
  ;; These are scaled using g-EPT, which is set in a slider.
  set g-waste-sales-quota ( g-EPT * 10 )        ;; Max mus per xaction
  set g-recycled-purchase-quota 
    ( g-EPT * 10 * g-no-of-waste-xactions-max ) ;; Max mus per xaction
  set g-harvest-quota ( g-EPT * 10 )            ;; Max harvest per hired wrkr; must be a multiple of 2
  set g-supplies-purchase-quota ( g-EPT * 10 )  ;; Max supplies bought per transaction
   
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: EPT-derived Transaction Quotas (Sliders):" )
  LOG-TO-FILE ( word g-waste-sales-quota " - Maximum waste mass sold per consumer per tick"   )
  LOG-TO-FILE ( word g-recycled-purchase-quota " - Maximum recycled mass purchased per frmr per tick"   )
  LOG-TO-FILE ( word g-harvest-quota " - Maximum harvest per wrkr per tick; multiple of 2"   )
  LOG-TO-FILE ( word g-supplies-purchase-quota " - Maximum supplies purchased per consumer per tick"  ) 
 
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: Business factors (Sliders):" )
  LOG-TO-FILE ( word g-HRF-f " - Hold Recycled mass Factor ( g-HRF-f )"  )
  LOG-TO-FILE ( word g-HIF-f " - Hold Inventory Factor ( g-HIF-f )"   )
  LOG-TO-FILE ( word g-HSF-f " - Hold Supplies Factor for frmrs ( g-HSF-f )"  ) 
  LOG-TO-FILE ( word g-HSF-w " - Hold Supplies Factor for wrkrs ( g-HSF-w )"  ) 
 
  ;; Prices 
  set g-meu-price ( g-mu-price + g-eu-price ) ;; Price per mass/energy unit ( meu )
   
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: Fixed prices (Sliders):" )
  LOG-TO-FILE ( word g-mu-price " - Unit price per unit of mass ( mu )" ) 
  LOG-TO-FILE ( word g-eu-price " - Unit price per unit of energy ( eu )" )  
  LOG-TO-FILE ( word g-meu-price " - Unit price per unit of mass/energy, or food ( meu )" )  

  ;; Zero the economic measures.
  set g-no-of-hires-this-tick 0
  set g-cash-spent-this-tick 0
  set g-cash-spent-this-tick-recycled 0
  set g-cash-spent-this-tick-labour 0
  set g-cash-spent-this-tick-food 0
  set g-cash-spent-this-tick-waste 0

  ;; Turn on the plotting function.
  ;; Default is 'on'.
  set gb-plots-on true
  
  set-default-shape frmrs "person farmer"     ;; pulled from shapes library
  set-default-shape wrkrs "person service"    ;; pulled from shapes library

  ask patches 
  [ 
    set pcolor lime
    set p-no-of-frmrs 0
    set p-no-of-wrkrs 0
    f-establish-patch-commuting-area
  ]
   
  f-establish-rvp
  
  ;;-------------------------------------------
  ;; Charging the stocks of the MMgr and EMgr.
  ;;-------------------------------------------
  ;;
  ;; The amount placed into the stocks of the MMgr and EMgr during
  ;;   setup has a huge impact on the roll-out of a run.
  ;;
  ;; The net worth of the MMgr never changes, as all commercial transactions
  ;;   are precisee exchanges of value for value.  So, either it must have
  ;;   an initial net worth substantially > 0, or it must be allowed to
  ;;   go deeply into debt.  Otherwise, it cannot both purchase and sell
  ;;   enough waste per tick to keep a large economy running.
  ;;
  ;; I have chosen, for the following reasons, to give the MMgr net worth 
  ;;   by giving it a large dollop of cash.  Cash can be spent on the waste 
  ;;   of all consumers, making it freely available to all rather quickly.  
  ;;   If I gave it a dollop of mass, then that would generate cash for the
  ;;   MMgr slowly as frmrs choose to purchase recycled mass.
  ;;
  ;; The materiel manager ( MMgr )
  ;; Switch settings - declared in switch interface items over-ridden here.
  set gb-MMgr true                  ;; switches the MMgr on/off
  set gb-MMgr-debt true             ;; switches the MMgr debt feature on/off
  set gb-EMgr true                  ;; switches the EMgr on/off

  ;; The estate manager ( EMgr )
  ifelse( g-scenario-number = g-scenario-pmm )
  [
    set g-MMgr-cash   100000          ;; cash held for buying waste mass
    set g-MMgr-mass   0               ;; mass held for sale as recycled mass
    
    ;; PMM #2 scenario
    set g-EMgr-cash   0           ;; cash held for redistribution
    set g-EMgr-energy 0           ;; energy held for redistribution
    set g-EMgr-mass   0           ;; mass held for redistribution
  ]
  [
    ;; Growth scenario
    ;; Put assets into the MMgr as initial float.
    set g-MMgr-cash   g-MMgr-cash-at-setup      ;; cash held for business
    set g-MMgr-mass   g-MMgr-mass-at-setup      ;; mass held for business
    ;; Put assets into the EMgr for initial distribution.
    set g-EMgr-cash   g-EMgr-cash-at-setup      ;; cash held for redistribution
    set g-EMgr-mass   g-EMgr-mass-at-setup      ;; mass held for redistribution
    set g-EMgr-energy g-EMgr-energy-at-setup    ;; energy held for redistribution
  ]
  
  ;; Entropy computation mechanism
  ;; These are used by f-update-aggregates and so must precede that call.
  set gl-ent-reading ( list 0 0 0 0 0 0 0 )
  set gl-ent-time-series ( list gl-ent-reading )
  set g-no-of-ent-readings 0
  set g-no-of-ent-readings-max 1000
  set g-K-w  0 ;; For wrkrs
  set g-K-f  0 ;; For frmrs
  set g-K-a  0 ;; All together
  set g-ent-bin-width-w  250 ;; wrkrs have an expected range of  5,000.
  set g-ent-bin-width-f 3500 ;; frmrs have an expected range of 60,000.
  set g-ent-bin-width-a  250 ;; all turtles have an expected range of 60,000.
  
  ;; Aggregates.
  ;; The aggregates must be updated before any plots are invoked.
  f-update-aggregates  ;; cash, energy, and mass, by breed or sector.
    
  ;; Plotting.
  ;; This call initializes the two graphs.
  f-update-lorenz-and-gini
  ;; This needs data from g-update-aggregates and must follow that call.
  reset-ticks      ;; restarts tick counter and runs setup commands within plots

  ;; This call requires f-update-aggregates to be completed.
  ;; This call also requires that 'reset-ticks' be called first.
  f-update-entropy-graph
  
  
  ;; Debug controls
  set gb-debug-flow-on 0 ;; Boolean, in association with chooser, turns debug LOG-TO-FILE on/off
  set g-halt-at-tick -1  ;; input variable to set a tick for stopping

  ;; ASSERT ( frb-EMgr-is-valid ) ( "EMgr validity check: D-Setup" ) -1
  LOG-TO-FILE "Do-set: procedure completed" 
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single frmr.

to f-setup-frmr
  ;; This routine is to be executed by the observer.
  ;; scenario-growth - the standard operation format

  ;; BUILT-IN ATTRIBUTES
  ;; who        ;; set automatically
  set heading 0 ;; north
  ;; xcor       ;; min-pxcor <= xcor < max-pxcor
  ;; ycor       ;; min-pxcor <= xcor < max-pxcor
  ;; pen-mode   ;; "up" or "down"
  ;; pen-size   ;; in pixels
  ;; size       ;; size relative to a patch, default is 1

  ;; Default values for pmm/growth scenarios
  set age                 ( 0 ) ;; number of ticks since birth
  set age-to-reproduce fr-get-random-age-to-reproduce
  set ma-who             ( -1 ) ;; who number of mother
  set da-who             [-1] ;; list of who numbers of daughters
  set cash             ( 1000 ) ;; amount of cash ( $ )
  set energy   ( 1000 * g-EPT ) ;; amount of energy ( eu )
  set recycled  ( 500 * g-EPT ) ;; units of recycled mass ( mu )
  set inventory ( 100 * g-EPT ) ;; units of inventory of mass-energy ( meu )
  set supplies  ( 200 * g-EPT ) ;; units of supplies of mass-energy ( meu )
  set waste       ( 0 * g-EPT ) ;; units of waste mass ( mu )
  set net-value fr-get-frmr-net-value   ;; the total value, in dollars, of all assets
  set real-value fr-get-frmr-real-value ;; the total value, in dollars, of all assets except cash

  ;; Computed real-time limits on asstet ownership
  set hrl 0                  ;; hold recycled limit
  set hil 0                  ;; hold inventory limit ( on inventory )
  set hsl 0                  ;; hold supplies limit
   
  set b-can-sell-waste 0     ;; Boolean control on participation
  set b-can-buy-recycled 0   ;; Boolean control on participation
  set b-can-hire-wrkrs 0     ;; Boolean control on participation
  set b-can-sell-inventory 0 ;; Boolean control on participation
  set b-can-buy-supplies 0   ;; Boolean control on participation
  set b-can-eat 0            ;; Boolean control on participation
  set b-can-reproduce 0      ;; Boolean control on participation
  set b-can-die 0            ;; Boolean control on participation
  set b-can-die-of-hunger 0  ;; Boolean control on participation
  set b-can-die-of-age 0     ;; Boolean control on participation
  set b-can-die-of-lownrg 0  ;; Boolean control on participation

  set energy-set-point 0     ;; the lowest energy allowed from working.
  f-set-available-energy     ;; available for work 

  set grt-mgmt-cash-granted 0 
  set grt-mgmt-energy-granted 0
  set grt-mgmt-recycled-granted 0
  set grt-mgmt-inventory-granted 0
  set grt-mgmt-waste-granted 0

  set grt-mgmt-cash-used 0   
  set grt-mgmt-energy-used 0   
  set grt-mgmt-recycled-used 0  
  set grt-mgmt-inventory-used 0   
  set grt-mgmt-waste-used 0     
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single wrkr.

to f-setup-wrkr
  ;; This routine is to be executed by the observer.
  ;; scenario-growth - the standard operation format

  ;; BUILT-IN ATTRIBUTES
  ;; who        ;; set automatically
  set heading 0 ;; north
  ;; xcor       ;; min-pxcor <= xcor < max-pxcor
  ;; ycor       ;; min-pxcor <= xcor < max-pxcor
  ;; pen-mode   ;; "up" or "down"
  ;; pen-size   ;; in pixels
  ;; size       ;; size relative to a patch, default is 1

  ;; Default values for pmm/growth operation   
  set age                ( 0 )    ;; number of ticks since birth
  set age-to-reproduce fr-get-random-age-to-reproduce
  set ma-who            ( -1 )    ;; who number of mother
  set da-who            [-1]      ;; list of who numbers of daughters
  set cash            ( 1000 )    ;; amount of cash ( $ )
  set energy  ( 1000 * g-EPT )    ;; amount of energy ( eu )
  set supplies ( 100 * g-EPT )    ;; units of supplies of mass-energy ( meu )
  set waste      ( 0 * g-EPT )    ;; units of waste mass ( mu )
  set net-value fr-get-wrkr-net-value   ;; the total value, in dollars, of all assets
  set real-value fr-get-wrkr-real-value ;; the total value, in dollars, of all assets except cash

  ;; Computed real-time limits on asstet ownership
  set hsl 0                  ;; buy supplies limit
   
  set b-can-sell-waste 0     ;; Boolean control on participation
  set b-can-buy-supplies 0   ;; Boolean control on participation
  set b-can-eat 0            ;; Boolean control on participation
  set b-can-reproduce 0      ;; Boolean control on participation
  set b-can-die 0            ;; Boolean control on participation
  set b-can-die-of-hunger 0  ;; Boolean control on participation
  set b-can-die-of-age 0     ;; Boolean control on participation
  set b-can-die-of-lownrg 0  ;; Boolean control on participation
  set b-just-sprouted 0      ;; Boolean control to find new sprout

  set energy-set-point 0     ;; the lowest energy allowed from working.
  f-set-available-energy     ;; available for work 

  set grt-mgmt-cash-granted 0
  set grt-mgmt-energy-granted 0
  set grt-mgmt-waste-granted 0

  set grt-mgmt-cash-used 0 
  set grt-mgmt-energy-used 0
  set grt-mgmt-waste-used 0 
end 

;;-----------------------------------------------------------------------------|
;; Establish the commuting area for a patch.

to f-establish-patch-commuting-area
  ;; Patches execute this routine – self is a patch.
  set com-area ( patch-set self neighbors 
    patch-at -2  2 patch-at -1  2 patch-at 0  2 patch-at 1  2 patch-at 2  2
    patch-at -2  1                                            patch-at 2  1
    patch-at -2  0                                            patch-at 2  0
    patch-at -2 -1                                            patch-at 2 -1
    patch-at -2 -2 patch-at -1 -2 patch-at 0 -2 patch-at 1 -2 patch-at 2 -2 )
end 

;;-----------------------------------------------------------------------------|
;; Build a village of 4 farmers and 16 workers.

to f-establish-rvp 
  ;; This routine is to be executed by the observer.

  ;; The Rectangular Village Pattern (RVP)
      
  ;; First, place the frmrs, with ( 1 <= who <= 4 ).
  create-frmrs 4
  ask frmr 0 [ set xcor -2 set ycor  0 set color 55 ]
  ask frmr 1 [ set xcor -2 set ycor -1 set color 55 ]
  ask frmr 2 [ set xcor  1 set ycor  0 set color 55 ]
  ask frmr 3 [ set xcor  1 set ycor -1 set color 55 ]
      
  ;; Then place the wrkrs
  create-wrkrs 16
  ask wrkrs with [ ( who >= 4 ) and ( who <= 7 ) ]
    [ set xcor -1 set ycor  0 set color 25  ]
  ask wrkrs with [ ( who >= 8 ) and ( who <= 11 ) ]
    [ set xcor -1 set ycor -1 set color 25  ]
  ask wrkrs with [ ( who >= 12 ) and ( who <= 15 ) ]
    [ set xcor  0 set ycor  0 set color 25  ]
  ask wrkrs with [ ( who >= 16 ) and ( who <= 19 ) ]
    [ set xcor  0 set ycor -1 set color 25  ]
      
  ;; Then initialize, claim a patch, build all lists.
  ask frmrs [ f-setup-frmr f-claim-my-frmrs-patch ]
  ask wrkrs [ f-setup-wrkr f-claim-my-wrkrs-patch ]
  
  ;; The appropriate number of agents have been spawned ( sprouted ).
  ;; Now, stagger the ages of all.
  ask turtles [ set age random g-RAT ]
end 

;;-----------------------------------------------------------------------------|
;; Claim this patch as my-patch.

to f-claim-my-frmrs-patch 
  ;; Frmrs execute this routine – self is a frmr.
  set my-patch patch-here
  set xcor pxcor 
  set ycor pycor
  set p-no-of-frmrs 1 
  set p-no-of-wrkrs 0 
  set union-set wrkrs-on com-area
  set customer-set turtles-on com-area
  set supplier-set frmrs-on com-area
end 

;;-----------------------------------------------------------------------------|
;; Claim this patch as my-patch.

to f-claim-my-wrkrs-patch 
  ;; Wrkrs execute this routine – self is a wrkr.
  set my-patch patch-here
  set xcor pxcor 
  set ycor pycor
  set p-no-of-frmrs 0 
  set p-no-of-wrkrs ( p-no-of-wrkrs + 1 ) 
  set employer-set frmrs-on com-area
  set supplier-set frmrs-on com-area
end 

;;-----------------------------------------------------------------------------|
;; Reset the default values for the interface-declared items.

to f-reset-default-parameters 
  ;; The observer executes this routine.

  ;; Switches, sliders and choosers implicitly declare global variables.  The
  ;;   values in these variables are parameters for the model, and many 
  ;;   combinations of those parameters are not sustainable.  However, the
  ;;   values in those user interface devices are stored with the model and
  ;;   are persistant across a save/load action.  The default values must
  ;;   be reset on load, or available to a user as a parameter set.  The
  ;;   purpose of this routine is to store at least one viable set of 
  ;;   parameter values.
  
  ;; The chooser that selects between the two scenarios is allowed to be 
  ;;   persistant.  It is not reset here.  This gives the user the ability
  ;;   to choose the scenario for which the defaults are to be restored.
  ;; set gs-scenario "PMM #2"  ;; Suppressed.
  
  ;; Initialize the Pseudo Random Number Generator (PRNG).
  set g-use-this-seed 7
   
  ;;-----------------------------------------------
  ;; BIOPHYSICAL SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;-----------------------------------------------

  ;; Slider range settings are shown as (Min,Increment,Max)
  set g-DAT 1600  ;; Slider, Death age threshold (1000,50,2000)
  set g-DET 4     ;; Slider, Death energy threshold (0,4,40)
  set g-RAT 800   ;; Slider, Reproductive age threshold (600,50,900)
  ;; g-GTT should be less than ( g-RAT / 2 )
  set g-GTT 200   ;; Slider, Gestation time threshold (100,25,450)
  set g-RET 1000  ;; Slider, Reproductive energy threshold (500,50,1500)
  set g-EPT 4     ;; Slider, Energy per tick (1,1,10)
   
  ;;-----------------------------------------------
  ;; BIOPHYSICAL SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;-----------------------------------------------

  ;; EMgr Initialization values
  set g-EMgr-cash   400000   ;; Initial float of cash
  set g-EMgr-mass   400000   ;; Initial float of mass
  set g-EMgr-energy 400000   ;; Initial float of energy
  
  ;; Business factors, for dynamic quotas
  set g-HRF-f 0.500    ;; Slider, Hold recycled factor (0,0.05,1)
  set g-HIF-f 0.250    ;; Slider, Hold inventory factor (0,0.05,1)
  set g-HSF-f 0.250    ;; Slider, Hold supplies factor - frmrs (0,0.05,1)
  set g-HSF-w 0.350    ;; Slider, Hold supplies factor - wrkrs (0,0.05,1)
   
  ;; Business survival thresholds, used to put a floor on dynamic quotas.
  set g-HRL-f-min 500  ;; Slider, Hold recycled limit minimum (0,50,500)
  set g-HIL-f-min 300  ;; Slider, Hold inventory limit minimum (0,50,500)
  set g-HSL-f-min 200  ;; Slider, Hold supplies limit minimum - frmrs (0,50,500)
  set g-HSL-w-min 100  ;; Slider, Hold supplies limit minimum - wrkrs (0,50,500)

  ;; Iteration count quotas
  set g-no-of-rents-max 4           ;; Max wrkrs per residential patch
  set g-no-of-hires-max 4           ;; Max hires per tick
  set g-no-of-waste-xactions-max 5  ;; Max transactions per frmr per tick

  ;; Prices 
  set g-mu-price 1     ;; Price per mass unit ( mu )
  set g-eu-price 1     ;; Price per energy unit ( eu )

  ;; Ensure that the derived parameters are properly valued.
  ;; Transaction size quotas
  ;; These are scaled using g-EPT.
  set g-waste-sales-quota ( g-EPT * 10 )        ;; Max mus per xaction
  set g-recycled-purchase-quota 
    ( g-EPT * 10 * g-no-of-waste-xactions-max ) ;; Max mus per xaction
  set g-harvest-quota ( g-EPT * 10 )            ;; Max harvest per hired wrkr; must be a multiple of 2
  set g-supplies-purchase-quota ( g-EPT * 10 )  ;; Max supplies bought per transaction
  set g-meu-price ( g-mu-price + g-eu-price ) ;; Price per mass/energy unit ( meu )
  
  set g-MMgr-cash-at-setup    100000  ;; Endowment of cash for initial float.
  set g-MMgr-mass-at-setup         0  ;; Endowment of mass for initial float.
  set g-EMgr-cash-at-setup   1000000  ;; Endowment of cash for initial float.
  set g-EMgr-mass-at-setup   1000000  ;; Endowment of mass for initial float.
  set g-EMgr-energy-at-setup 1000000  ;; Endowment of energy for initial float.
end 


;;-----------------------------------------------------------------------------|
;; SECTION D – GO OR MAIN-LOOP PROCEDURE( S )
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; The go button

to go
  ;; This routine is to be executed by the observer.

  ;; Stop codes:
  ;; All stop decisions must be here in the 'go' procedure, as it causes an
  ;;   exit from the current procdure only.

  if( g-halt-at-tick = ticks  ) 
  [
    set g-halt-at-tick -1
    stop
  ]
  
  let b-should-stop-now false
  if( count turtles <= 0 ) [ set b-should-stop-now true ]
  if( count frmrs <= 0 )   [ set b-should-stop-now true ]
  if( count wrkrs <= 0 )   [ set b-should-stop-now true ]
  if( b-should-stop-now = true )
  [
    f-close-dpx-file
    f-close-dpt-file
    f-close-dpg-file
    ;; The Debug log file is handled differently elsewhere.
    stop
  ]

  ;; MANUAL CHANGE FOR DEBUG
  ;; If needed, each check for validity can be enabled between steps.
  ;; They have been suppressed (turned into comments) for the sake 
  ;;   of speed of execution, but can be re-enabled if a bug has 
  ;;   somehow been re-introduced.
  ;; A single call to the validity check has been left active inside of the
  ;;   Do-Post-Tick step.  If it flags a problem, re-activate these to
  ;;   narrow down where the problem starts.
  
  ;; Major steps or functions, done once per tick, in order of execution.
  do-pre-tick
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-Pre." ) ]

  do-sell-waste-buy-recycled
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-ByR." ) ]

  do-hire-wrkrs
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-HWk." ) ]

  do-sell-inventory
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-Sli." ) ]

  do-eat-supplies
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-Eat." ) ]

  do-reproduction
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-Rep." ) ]

  do-death
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-Die." ) ]

  do-post-tick
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-Pos." ) ]
end 


;;-----------------------------------------------------------------------------|
;; D1 - do-pre-tick procedure( s )
;;-----------------------------------------------------------------------------|

to do-pre-tick
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "pre-tick" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-Pre-tick: Debug on.; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-Pre" g-aif

  ;; Enter all commands that need to be done before a tick begins.
  ;; Supressed. f-update-aggregates
  
 
  ;; Advance the tick counter by 1 tick.
  ifelse( gb-plots-on = true )
  [
    ;; These two plots need pre-processing every tick.
    f-update-lorenz-and-gini

    ;; Advance the ticks by one and update the plots.
    tick
    ;; 'tick' is exactly the same as 'update-plots' except that the tick counter 
    ;;   is incremented before the plot commands are executed.
    
  ]
  ;; else
  [
    ;; Advance ticks by one but do not update the plots.
    tick-advance 1
  ]

  ;; Check to see if dpx file is full.
  if( gb-dpx-on = 1 )
  [
    if( g-dpx-recno > g-recno-max )
    [
      f-reopen-dpx-file
    ]
  ]
  
  ;; Ensure that the derived parameters are properly valued.
  ;; THESE ARE PLACED HERE TO MAKE BEHAVIOUR SPACE (BS) WORKS CORRECTLY.
  ;; BS ADJUSTS THE SLIDERS, BUT THESE ARE DERIVED THEREFROM. 
  ;; Transaction size quotas.  These are scaled using g-EPT.
  set g-waste-sales-quota ( g-EPT * 10 )        ;; Max mus per xaction
  set g-recycled-purchase-quota 
    ( g-EPT * 10 * g-no-of-waste-xactions-max ) ;; Max mus per xaction
  set g-harvest-quota ( g-EPT * 10 )            ;; Max harvest per hired wrkr; must be a multiple of 2
  set g-supplies-purchase-quota ( g-EPT * 10 )  ;; Max supplies bought per transaction
  ;; Aggregate price must be calculated
  set g-meu-price ( g-mu-price + g-eu-price ) ;; Price per mass/energy unit ( meu )

  ;; Zero the economic measures.
  set g-no-of-hires-this-tick 0
  set g-cash-spent-this-tick 0
  set g-cash-spent-this-tick-recycled 0
  set g-cash-spent-this-tick-labour 0
  set g-cash-spent-this-tick-food 0
  set g-cash-spent-this-tick-waste 0

  LOG-TO-FILE ( word "Do-pre: Halt at tick - " g-halt-at-tick "; current ticks - " ticks ) 

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-Pre" g-aif

  LOG-TO-FILE "Do-pre: routine completed."
end 

;;-----------------------------------------------------------------------------|
;; D2 – buy-recycled procedures(s)
;;-----------------------------------------------------------------------------|

to do-sell-waste-buy-recycled
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "buy-recycled" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-Buy-recycled: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-ByR" g-aif
  
  ifelse( gb-MMgr = true )
  [
    LOG-TO-FILE "Do-ByR: via MMgr"
    
    ;; The MMgr buys up all waste.
    ask turtles [ set b-can-sell-waste 0 ]
    let consumers turtles with [ waste > 0 ]
    ask consumers 
    [ 
      set b-can-sell-waste 1 
      f-sell-waste-to-mmgr 
    ]
    
    ;; The MMgr sells recycled.
    ask frmrs [ set b-can-buy-recycled 0 ]
    let ok-frmrs frmrs with [ cash > g-mu-price ]
    ask ok-frmrs 
    [ 
      set b-can-buy-recycled 1
      f-buy-recycled-from-mmgr 
    ]
  ]
  ;; else
  [
    ;; If the MMgr is disabled, the debt feature must stay disabled.
    set gb-MMgr-debt false
    ;; Manage waste without the help of the MMgr.
    f-sell-waste-buy-recycled-via-frmrs
  ]
  
  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-ByR" g-aif

  ;; Supressed. f-update-aggregates

  LOG-TO-FILE "Do-ByR: procedure completed"
end 

;;-----------------------------------------------------------------------------|
;; a consumer sells waste

to f-sell-waste-to-mmgr
  ;; A consumer executes this routine.
  ;; But, only if g-MMgr-cash > 0 and gb-MMgr = true
  
  ;; See if EMgr will provide grants.
  f-consumer-requests-SeW-mass-grant
  
  let dynamic-quota g-waste-sales-quota
  if( dynamic-quota > waste ) [ set dynamic-quota waste ]
  let extended-price ( dynamic-quota * g-mu-price )
  
  ;; See if the MMgr can afford the purchase.
  ifelse( ( g-mmgr-cash < extended-price ) and ( gb-MMgr-debt = false ) )
  [
    ;; MMgr cannot afford the purchase.
    ;; Zero out the transaction.
    ;; I could check for a partial transaction here, but the logic gets convoluted.
    set dynamic-quota 0
    set extended-price 0
  ]
  ;; else
  [
    ;; Else, the MMgr can afford the purchase.
    set g-mmgr-cash ( g-mmgr-cash - extended-price )
    set cash ( cash + extended-price )
    set g-cash-spent-this-tick ( g-cash-spent-this-tick + extended-price )
    set g-cash-spent-this-tick-waste ( g-cash-spent-this-tick-waste + extended-price )
    
    set g-mmgr-mass ( g-mmgr-mass + dynamic-quota )
    set waste ( waste - dynamic-quota )
    set grt-mgmt-waste-used dynamic-quota
    
    ;; Process DPX data collection option
    if( gb-dpx-on = 1 )
    [
      set gl-dpx-record-layout-B ( list "SeW" who "MMgr" dynamic-quota extended-price )
      f-write-dpx-data-B
    ]
  ]
  set b-can-sell-waste 0
 
  LOG-WITH-AIF-CHECK  ( word "Do-ByR: " dynamic-quota " mus of waste sold to MMgr by agent " 
    who " at price $" extended-price " ; Wst: " waste " mus." ) who

  ;; EMgr may have granted too much.  Return excess.
  f-consumer-returns-unused-grants "ByR-R"
end 

;;-----------------------------------------------------------------------------|
;; frmr buys recycled mass from the MMgr.

to f-buy-recycled-from-mmgr
  ;; Only frmrs execute this routine.
  ;; The frmr buys recycled mass from the MMgr.
  
  if( g-mmgr-mass > 0 )
  [
    f-set-frmr-hrl
    if( recycled < hrl )
    [
      let dynamic-quota g-recycled-purchase-quota
      if( dynamic-quota > g-mmgr-mass )               
        [ set dynamic-quota g-mmgr-mass ]
      let extended-price ( dynamic-quota * g-mu-price )

      ;; See if EMgr will provide grants.
      f-frmr-requests-ByR-cash-grant

      if( extended-price > cash ) 
      [ 
        set dynamic-quota ( floor( cash / g-mu-price ) )
        set extended-price ( dynamic-quota * g-mu-price )
      ]
      
      set cash ( cash - extended-price )
      set g-mmgr-cash ( g-mmgr-cash + extended-price )
      set g-cash-spent-this-tick ( g-cash-spent-this-tick + extended-price )
      set g-cash-spent-this-tick-recycled ( g-cash-spent-this-tick-recycled + extended-price )
      
      set recycled ( recycled + dynamic-quota )
      set g-mmgr-mass ( g-mmgr-mass - dynamic-quota )
      set grt-mgmt-cash-used extended-price
      
      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-B ( list "ByR" "MMgr" who dynamic-quota extended-price )
        f-write-dpx-data-B
      ]
    
      LOG-WITH-AIF-CHECK  ( word "Do-ByR: " dynamic-quota 
        " mus of recycled purchased from MMgr by agent "
        who " at price $" extended-price "; Rec: " recycled " mus; HRL - " hrl " mus." ) who

      ;; EMgr may have granted too much.  Return excess.
      f-frmr-returns-unused-grants "ByR-R"
      
    ]  ;; End of if frmr has quota to buy.
  ]  ;; End of if MMgr has mass to sell.
end 

;;-----------------------------------------------------------------------------|
;; Compute a frmr's net value.

to-report fr-get-frmr-net-value
  ;; Only frmrs execute this routine – self is a frmr.
  set net-value cash
  set net-value ( net-value + ( energy    * g-eu-price  ) )  
  set net-value ( net-value + ( recycled  * g-mu-price  ) )  
  set net-value ( net-value + ( inventory * g-meu-price ) )  
  set net-value ( net-value + ( supplies  * g-meu-price ) )  
  set net-value ( net-value + ( waste     * g-mu-price  ) )  
  report net-value
end 

;;-----------------------------------------------------------------------------|
;; Compute a frmr's real value.

to-report fr-get-frmr-real-value
  ;; Only frmrs execute this routine – self is a frmr. 
  
  ;; Real value is the same as net value, less the cash.
  ;; This is used in finding hrl, hil and hsl using the business factors
  ;;   hrf, hif and hsf.  E.g HRL = ( HRF * real-value ).
  ;; When net value is used, including cash, wrkrs are too quick to take work
  ;;   and burn up energy, thereby being unable to reproduce.  This is due to 
  ;;   the fact that neither energy nor cash are controlled.  High cash assets
  ;;   cause wrkrs to take work and burn up energy.  Frmrs may suffer the 
  ;;   same problem.  I have produce a real-value function for each type
  ;;   of agent.
  
  set real-value                ( energy    * g-eu-price  ) 
  set real-value ( real-value + ( recycled  * g-mu-price  ) )  
  set real-value ( real-value + ( inventory * g-meu-price ) )  
  set real-value ( real-value + ( supplies  * g-meu-price ) )  
  set real-value ( real-value + ( waste     * g-mu-price  ) )  
  report real-value
end 

;;-----------------------------------------------------------------------------|
;; Compute a frmr's 'hold recycled limit' ( g-HRL-f ).

to f-set-frmr-hrl
  ;; Only frmrs execute this routine – self is a frmr.

  ;; HRL stands for 'hold recycled limit' and is the amount of
  ;;   waste mass ( or recycled mass ) a frmr may hold as determined
  ;;   by the business factor g-HRF-f.  If a frmr's holding is less than
  ;;   the allowed amount, it may purchase enough complete transactions
  ;;   to take it over the limit.
  set hrl 0
  ;; Note: decide whether -net-value or -real-value are best here.
  ;; (141031) In V1.31 net-value is stable.
  set hrl floor( g-HRF-f * fr-get-frmr-net-value / g-mu-price ) 
  
  if( hrl < g-HRL-f-min ) [ set hrl g-HRL-f-min ]
  LOG-WITH-AIF-CHECK  ( word "Do-ByR: Agent: " who "; HRL: " hrl " mus; Recycled: " recycled " mus." ) who
end 

;;-----------------------------------------------------------------------------|
;; Buy recycled mass ( and sell waste ) via frmrs routine.

to f-sell-waste-buy-recycled-via-frmrs
  ;; This routine is to be executed by the observer.
  
  LOG-TO-FILE "Do-ByR: via frmrs"
  
  ;; Frmrs participation flags are set.
  ask frmrs 
  [ 
    ;; The 'hold recycled limit' ( g-HRL-f ) is the maximum amount of 
    ;;    recycled mass the frmr can hold based on the value of the 
    ;;    'hold recycled factor' ( HRF ).
    f-set-frmr-hrl   ;; 'hold recycled limit'.
    set b-can-buy-recycled 1 
    if( cash < g-mu-price ) [ set b-can-buy-recycled 0 ]
    if( recycled > hrl )    [ set b-can-buy-recycled 0 ]
  ]

  let ok-frmrs frmrs with [ b-can-buy-recycled = 1 ]
  LOG-TO-FILE word "Do-ByR: Frmrs able to participate - " ( count ok-frmrs ) 
  LOG-TO-FILE word "Do-ByR: Who #s of able frmrs: " [who] of ok-frmrs 
 
  ;; Ensure consumers are flagged as available to sell waste mass.
  ;; Wrkrs can sell waste only once per tick, to a single frmr, and only if they 
  ;;   have waste mass to sell.
  ask turtles
  [ 
    set b-can-sell-waste 1 
    if( waste <= 0 )   [ set b-can-sell-waste 0 ]
  ]

  LOG-TO-FILE word "Do-ByR: Consumers able to participate - " ( count turtles with [ b-can-sell-waste = 1 ] ) 

  ;; Frmrs take the primary role.
  ;; Frmrs with cash buy waste mass from consumers.
  ask ok-frmrs [ f-buy-recycled-from-consumers ]   
  ;; Supressed. f-update-aggregates
end 

;;-----------------------------------------------------------------------------|
;; A frmr buys recycled mass from consumers with waste mass.

to f-buy-recycled-from-consumers
  ;; Only frmrs execute this routine.
  ;; The frmr is determined to purchase enough waste mass to be able to hire 
  ;;   up to g-no-of-hires-max wrkrs from its customer-set.
  ;; Once all purchases are complete, it ceases a search.
  let no-of-waste-xactions-completed 0  ;; Limited by no-of-waste-xactions-max

  ;; Establish a short list of potential customers.
  let cu-set customer-set with [ b-can-sell-waste = 1 ]

  ;; A let as declaration, used later.
  let this-customer one-of cu-set

  ;; And now, a needed let.
  let b-frmr-can-continue 1
  ;; The frmr can continue as long as:
  ;;   - the allowed number of transactions is not yet completed;
  ;;   - the store of cash is not empty.

  let dynamic-quota g-waste-sales-quota

  if( count cu-set <= 0 )               
  [ 
    set b-frmr-can-continue 0 
    LOG-TO-FILE "Frmr cannot purchase waste - no customers." 
  ]

  while [ b-frmr-can-continue = 1 ]
  [
    ;; Pull one customer out of temporary customer-set.
    set this-customer one-of cu-set
    ask this-customer [ set cu-set other cu-set ]
    ;; One mass unit ( mu ) is one unit of waste/recycled mass.
       
    ;; See if EMgr will provide grants.
    f-frmr-requests-ByR-cash-grant
    ask this-customer [ f-consumer-requests-SeW-mass-grant ]
     
    ;; Adjust the dynamic quota for the transaction.
    ;; Amount sold cannot exceed available waste.
    if ( dynamic-quota > [waste] of this-customer )
    [ set dynamic-quota [waste] of this-customer ]
       
    ;; Amount sold cannot exceed available cash.
    if ( ( dynamic-quota * g-mu-price ) > cash )
    [ set dynamic-quota floor( cash / g-mu-price ) ]
     
    ;; Display status.
    LOG-TO-FILE ""  
    LOG-TO-FILE word "      Transaction # - " no-of-waste-xactions-completed 
    LOG-TO-FILE word "           FRMR WHO - " who 
    LOG-TO-FILE word "       Cash on hand - " cash 
    LOG-TO-FILE word "           Recycled - " recycled 
    LOG-TO-FILE word "Hold Recycled limit - " hrl
    LOG-TO-FILE word "       CUSTOMER WHO - " [who] of this-customer 
    LOG-TO-FILE word "              Waste - " [waste] of this-customer 
    LOG-TO-FILE word "      Dynamic quota - " dynamic-quota 

    ;; Complete transfer of waste/recycled mass and cash.
    ask this-customer [ set waste ( waste - dynamic-quota ) ]
    set recycled ( recycled + dynamic-quota )
    let extended-price ( dynamic-quota * g-mu-price )
    set cash ( cash - extended-price )
    ask this-customer [ set cash ( cash + extended-price ) ]
    set g-cash-spent-this-tick ( g-cash-spent-this-tick + extended-price )
    set g-cash-spent-this-tick-recycled ( g-cash-spent-this-tick-recycled + extended-price )
    set g-cash-spent-this-tick-waste ( g-cash-spent-this-tick-waste + extended-price )

    ;; Process DPX data collection option
    if( gb-dpx-on = 1 )
    [
      set gl-dpx-record-layout-B ( list "SeW-ByR" who ( [who] of this-customer ) dynamic-quota extended-price )
      f-write-dpx-data-B
    ]

    if( gb-EMgr = true )
    [
      ;; grant management: note the resources transferred
      set grt-mgmt-cash-used ( grt-mgmt-cash-used + ( dynamic-quota * g-mu-price ) )
      ask this-customer [ set grt-mgmt-waste-used ( grt-mgmt-waste-used + dynamic-quota ) ]
    ]
      
    ifelse( g-aif = ( [who] of this-customer ) )
    [
      let frmr-who who
      ask this-customer
      [
        LOG-WITH-AIF-CHECK ( word "Do-ByR: Customer " who " sold " dynamic-quota " mus of waste to frmr " frmr-who "." ) who
      ]
    ]
    [
      LOG-WITH-AIF-CHECK ( word "Do-ByR: Frmr " who " purchased " dynamic-quota " mus of waste from agent " [who] of this-customer "." ) who
    ]

    ;; Mark the purchase as completed.
    ;; Increment the count of transactions.
    set no-of-waste-xactions-completed ( no-of-waste-xactions-completed + 1 ) 
    ;; Flag the customer as having been serviced.
    ask this-customer [ set b-can-sell-waste 0 ]

    ;; Check if frmr can continue.
    if( cash < g-mu-price ) 
    [ 
      set b-frmr-can-continue 0 
      LOG-TO-FILE word "Do-ByR: Frmr cannot continue, out of cash: $" cash
    ]
 
    ;; Return excess grants to EMgr.
    ask this-customer [ f-consumer-returns-unused-grants "ByR-R"]
    f-frmr-returns-unused-grants "ByR-R"
      
    ;; Check if this completes all allowed transactions for this frmr.
    if ( no-of-waste-xactions-completed >= g-no-of-waste-xactions-max ) 
    [ 
      ;; Tell the frmr to stop trying to buy more waste mass.
      set b-frmr-can-continue 0
      LOG-TO-FILE ( word "Do-ByR: Transactions completed at end - " no-of-waste-xactions-completed )
    ]

    ;; Note if there are no more customers to sell to.
    if ( count cu-set <= 0 ) 
    [ 
      set b-frmr-can-continue 0 
    ]

    LOG-TO-FILE ( word "Do-ByR:       Frmr-can-continue - " b-frmr-can-continue )

  ] ;; end of while frmr can continue
  

  LOG-TO-FILE   ( word "Do-ByR: Unserviced customers at end - " count cu-set )
  
  ;; Flag the frmr as serviced.
  set b-can-buy-recycled 0
end 

;;-----------------------------------------------------------------------------|
;; a frmr requests a grant from the EMgr for cash to buy waste/recycled mass

to f-frmr-requests-ByR-cash-grant
  ;; Only frmrs should execute this.

  ;; ASSERT ( g-EMgr-cash >= 0 ) ( word "EMgr: ByR-cash grant; cash = " g-EMgr-cash " " ) who
 
  ;; LOG-TO-FILE "" LOG-WITH-AIF-CHECK "EMgr: ByR-cash-grant msg 001 - requested" who
  if( gb-EMgr = true )
  [ 
    ;; LOG-WITH-AIF-CHECK "EMgr: ByR-cash-grant msg 002 - EMgr is on" who
    if( g-EMgr-cash > 0 )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: ByR-cash-grant msg 003 - EMgr has cash" who
      let cash-needed floor( g-recycled-purchase-quota * g-mu-price )
      ;; Determine if frmr is poor but deserving.
      if( cash < cash-needed )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: ByR-cash-grant msg 004 - frmr is poor" who
        ;; Determine if frmr is "deserving".
        if( cash > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: ByR-cash-grant msg 005 - frmr is deserving" who
          ;; Frmr is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out?
          let amount-granted ( cash-needed - cash )
          if( amount-granted > g-EMgr-cash )
          [
            set amount-granted g-EMgr-cash
          ]
 
          LOG-WITH-AIF-CHECK ( word "EMgr: Frmr has cash on hand - " cash ) who

          ;; Effect the grant.
          set grt-mgmt-cash-granted amount-granted
          set grt-mgmt-cash-used 0
          
          set cash ( cash + amount-granted )
          set g-EMgr-cash ( g-EMgr-cash - amount-granted )
 
          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            set gl-dpx-record-layout-H 
            ( list "Byr" who "frmr" "cash" amount-granted )
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: ByR-cash grant to frmr - " amount-granted ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-cash >= 0 ) ( word "EMgr: ByR-cash grant; cash = " g-EMgr-cash " " ) who
end 

;;-----------------------------------------------------------------------------|
;; A consumer requests a grant from the EMgr for mass to sell waste.

to f-consumer-requests-SeW-mass-grant
  ;; Only consumers ( frmrs and wrkrs ) should execute this.

  ;; LOG-TO-FILE "" LOG-WITH-AIF-CHECK ( "EMgr: SeW-mass-grant msg 001 - requested" ) who
  if( gb-EMgr = true )
  [
    ;; LOG-WITH-AIF-CHECK "EMgr: SeW-mass-grant msg 002 - EMgr is on" who
    if( g-EMgr-mass > 0 )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: SeW-mass-grant msg 003 - EMgr has mass" who
      ;; Determine if consumer is poor but deserving.
      if( waste < g-waste-sales-quota )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: SeW-mass-grant msg 004 - consumer is poor" who
        ;; Determine if consumer is "deserving".
        if( waste > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: SeW-mass-grant msg 005 - consumer is deserving" who
          ;; Consumer is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out?
          let amount-granted ( g-waste-sales-quota - waste )
          if( amount-granted > g-EMgr-mass )
          [
            set amount-granted g-EMgr-mass
          ]
 
          LOG-WITH-AIF-CHECK ( word "EMgr: Consumer has waste mass on hand - " waste ) who

          ifelse( breed = "frmr" )
          [
            ;; Effect the grant.
            set grt-mgmt-waste-granted amount-granted
            set grt-mgmt-waste-used 0
            
            set waste ( waste + amount-granted )
            set g-EMgr-mass ( g-EMgr-mass - amount-granted )
            
            ;; Process DPX data collection option
            if( gb-dpx-on = 1 )
            [
              set gl-dpx-record-layout-H 
              ( list "SeW" who "frmr" "mu" amount-granted )
              f-write-dpx-data-H
            ]
            
            LOG-WITH-AIF-CHECK ( word "EMgr: SeW-mass grant to frmr - " amount-granted ) who
          ]
          [
            ;; Effect the grant.
            set grt-mgmt-waste-granted amount-granted
            set grt-mgmt-waste-used 0
            
            set waste ( waste + amount-granted )
            set g-EMgr-mass ( g-EMgr-mass - amount-granted )
            
            ;; Process DPX data collection option
            if( gb-dpx-on = 1 )
            [
              set gl-dpx-record-layout-H 
              ( list "SeW" who "wrkr" "mu" amount-granted )
              f-write-dpx-data-H
            ]
            
            LOG-WITH-AIF-CHECK ( word "EMgr: SeW-mass grant to wrkr - " amount-granted ) who
          ]
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-mass >= 0 ) ( "EMgr: SeW-mass grant; mass < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; D3 – hire-wrkrs procedures( s )
;;-----------------------------------------------------------------------------|

to do-hire-wrkrs
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "hire-wrkrs" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-Hire-wrkrs: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Both wrkrs and frmrs must build up a store of energy ( to g-RET ) in order to
  ;;   be able to reproduce when they come of age ( g-RAT ).  They must not expend
  ;;   energy doing work unless it is necessary for survival.  The business factors
  ;;   are used to control the distribution of value across asset classes, and,
  ;;   in particular, to direct energy towards reproduction.  Frmrs use the ( hif, hil )
  ;;   pair of controls to ensure there is always a reasonable percentage of their
  ;;   value held in inventory to ensure survival of all.  Wrkrs and frmrs alike
  ;;   use the ( hsf, hsl ) pair of controls to ensure that they maintain sufficient
  ;;   supplies to survive personally.  Frmrs and wrkrs will not work ( expend
  ;;   energy ) if the hil and hsl thresholds for asset holdings are met.
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-HWk" g-aif
  
  ;; Zero the count of hires this tick.
  set g-no-of-hires-this-tick 0

  ;; Frmrs participation flags are set.
  ask frmrs 
  [ 
    ;; Hold Inventory Limit ( hil ) is set once per tick here, for each frmr.
    f-set-frmr-hil 
    ;; Hold Supplies Limit ( hsl ) is set here, for each frmr.
    f-set-consumer-hsl 
    
    set b-can-hire-wrkrs 1 
    ;; if( ( inventory > hil ) and ( supplies > hsl ) ) [ set b-can-hire-wrkrs 0 ]
    if( inventory > hil )            [ set b-can-hire-wrkrs 0 ]
    if( cash < g-eu-price )          [ set b-can-hire-wrkrs 0 ]
    if( energy <= energy-set-point ) [ set b-can-hire-wrkrs 0 ]
    if( recycled < 2 )               [ set b-can-hire-wrkrs 0 ]
  ]
  let ok-frmrs frmrs with [ b-can-hire-wrkrs = 1 ]
 
  ;; Ensure wrkrs are flagged as available to be hired.
  ;; Wrkrs can be hired only once per tick, but only if they have energy to sell.
  ask wrkrs 
  [ 
    ;; Hold Supply Limit ( hsl ) is set here, for each wrkr.
    f-set-consumer-hsl  

    set b-can-work 1 
    if( supplies > hsl )             [ set b-can-work 0 ]
    if( energy <= energy-set-point ) [ set b-can-work 0 ]
  ]

  LOG-TO-FILE word "Do-HWk: Wrkrs able to participate - " ( count wrkrs with [ b-can-work = 1 ] ) 
  LOG-TO-FILE word "Do-HWk: Who #s of able wrkrs: " [ who ] of ( wrkrs with [ b-can-work = 1 ] ) 
  LOG-TO-FILE word "Do-HWk: Frmrs able to participate - " ( count ok-frmrs ) 
  LOG-TO-FILE word "Do-HWk: Who #s of able frmrs: " [ who ] of ok-frmrs 
  
  ;; Frmrs take the primary role.
  ask ok-frmrs [ f-frmr-hires-wrkrs ]   ;; Frmr hires wrkrs to harvest grain as inventory.
  ;; Supressed. f-update-aggregates

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-HWk" g-aif

  LOG-TO-FILE "Do-HWk: procedure completed."
end 

;;-----------------------------------------------------------------------------|
;; Frmr-hires-wrkrs routine.

to f-frmr-hires-wrkrs
  ;; only frmrs execute this routine – self is a frmr

  ;; The frmr will hire up to g-no-of-hires-max wrkrs from its union-set.
  ;; The frmr will attempt to fill its inventory to hil 'hold inventory limit'.
  ;; Once all hires are complete or hil is passed, it ceases a search.
  let b-transaction-completed 0
  let no-of-hires-completed 0

  ;; Hire a wrkr from the union-set.
  ;; Include only those wrkrs that are able and have not been hired this tick.
  let un-set union-set with [ b-can-work = 1 ]

  ;; A let as declaration, used later.
  let this-wrkr one-of un-set

  ;; And now, a needed let.
  let b-frmr-can-continue 1

  ;; Redundant conditionals suppressed, but left here for explanation.
  ;; if ( no-of-hires-completed >= g-no-of-hires-max )     [ set b-buyer-can-continue 0 ]
  ;; if ( cash < g-meu-price )           [ set b-buyer-can-continue 0 ]
  ;; if ( recycled < 2 )                 [ set b-buyer-can-continue 0 ]
  ;; if ( energy <= energy-set-point )   [ set b-buyer-can-continue 0 ]

  ;; The 'hold inventory limit' ( HIL ) is the maximum amount of 
  ;;    inventory the frmr can hold based on the value of the 'hold inventory factor' ( HIF ).
  ;; The HIL for this farmer was set at time of qualification for hiring for this tick.
  
  let meus-yet-to-buy ( g-harvest-quota * g-no-of-hires-max )
  if( meus-yet-to-buy < 2 ) [ set meus-yet-to-buy 2 ] ;; must buy at least 2 per hire

  if ( meus-yet-to-buy <= 0 ) 
  [ 
    set b-frmr-can-continue 0 
    LOG-TO-FILE      "Do-HWk: Frmr can continue - 0 - ( yet to buy <= 0 )" 
  ]

  if ( count un-set <= 0 )               
  [ 
    set b-frmr-can-continue 0 
    LOG-TO-FILE      "Do-HWk: Frmr can continue - 0 - no unserved customers on union list" 
  ]

  while [ b-frmr-can-continue = 1 ]
  [
    ;; pull one wrkr out of temporary union-set
    set this-wrkr one-of un-set
    ask this-wrkr [ set un-set other un-set ]
    ;; initialize a control counter for meus purchased
    ;; one mass/energy unit ( meu ) is 1 mu + 1 eu
       
    LOG-TO-FILE      ""  
    LOG-TO-FILE      "----------------------------------------"  
    LOG-TO-FILE ( word "Do-HWk: Frmr [" who 
                    "]; Wrkr [" [who] of this-wrkr "]" )

    ;; See if EMgr will provide grants.
    f-frmr-requests-HWk-cash-grant
    f-frmr-requests-HWk-mass-grant
    
    ;; Serve energy to wrkr before frmr.  Improves probability of grant to wrkr.
    ask this-wrkr [ f-wrkr-requests-HWk-energy-grant ]
    f-frmr-requests-HWk-energy-grant
    
    ;; The frmr and wrkr are both qualified for some fraction of a job
    ;;   up to a complete g-harvest-quota, but one or the other may be
    ;;   short in some needed input requirement, even after grants are applied.
    ;; The dynamic quota is tha largest harvest possible given the resource constraints.
    let dynamic-quota g-harvest-quota

    ;; The quota for this transaction cannot exceed the per-tick quota.
    if( dynamic-quota > meus-yet-to-buy ) [ set dynamic-quota meus-yet-to-buy ]
    
    ;; Amount harvested cannot exceed available mass in field.
    if ( dynamic-quota > recycled ) [ set dynamic-quota recycled ]

    ;; Amount to be paid cannot exceed available cash on hand.
    ;; Only half of the energy comes from the wrkr, so salary is paid for half quota.
    let salary-payable floor( g-eu-price * dynamic-quota / 2 )
    if ( salary-payable > cash ) 
    [ 
      set salary-payable cash
      ;; Multiply by two for total quota.
      set dynamic-quota ( 2 * floor( salary-payable / g-eu-price ) )
    ]
    
    ;; Amount harvested cannot exceed frmr's available energy.
    f-set-available-energy  ;; Determine energy available for work.
    ;; Half comes from frmr and half comes from wrkr.
    if ( available-energy < ( dynamic-quota / 2 ) ) 
      [ set dynamic-quota ( 2 * available-energy ) ]

    ;; Ensure the dynamic quota is a multiple of two.
    set dynamic-quota ( 2 * floor( dynamic-quota / 2 ) )
    if( dynamic-quota <= 0 ) [ set b-frmr-can-continue 0 ]
       
    let b-wrkr-can-continue 1

    ;; Adjust the dynamic quota for the seller of labour (i.e.the wrkr).
    ask this-wrkr [ f-set-available-energy ]
    if ( ( [ available-energy ] of this-wrkr ) < ( dynamic-quota / 2 ) ) 
      [ set dynamic-quota ( 2 * [ available-energy ] of this-wrkr ) ]

    ;; Ensure the dynamic quota is still a multiple of two.
    ;; Two lines suppressed as redundant.
    ;; set dynamic-quota ( 2 * floor( dynamic-quota / 2 ) )
    ;; if( dynamic-quota <= 0 ) [ set b-wrkr-can-continue 0 ]

    LOG-TO-FILE      "TRANSACTION SUMMARY:"  
    LOG-TO-FILE word "    Hire # this tick - " ( no-of-hires-completed + 1 )
    LOG-TO-FILE word "            Frmr who - " who 
    LOG-TO-FILE word "        Cash on hand - " cash 
    LOG-TO-FILE word "    Available Energy - " available-energy
    LOG-TO-FILE word "            Recycled - " recycled 
    LOG-TO-FILE word "           Inventory - " inventory 
    LOG-TO-FILE word "Hold Inventory Limit - " hil
    LOG-TO-FILE word "     Meus yet to buy - " meus-yet-to-buy
    LOG-TO-FILE word "            Wrkr who - " [ who ] of this-wrkr 
    LOG-TO-FILE word "    Available Energy - " [ available-energy ] of this-wrkr 
    LOG-TO-FILE word "       Dynamic quota - " dynamic-quota 

    if ( ( b-frmr-can-continue = 1 ) and ( b-wrkr-can-continue = 1 ) )
    [ 
      ;; Increment the count of the number of hires.
      set no-of-hires-completed ( no-of-hires-completed + 1 ) 
      ;; Flag the seller of energy ( the wrkr ) as serviced.
      ask this-wrkr [ set b-can-work 0 ]
      set b-wrkr-can-continue 0
      
      ;; Increment the overall count of hires per tick.
      set g-no-of-hires-this-tick ( g-no-of-hires-this-tick + 1 )

      ;; Use wrkr's energy allotment and pay for it.
      let share-of-energy ( dynamic-quota / 2 )
      let salary ( share-of-energy * g-eu-price )
      ask this-wrkr 
      [ 
        set energy ( energy - share-of-energy )
        f-set-available-energy
        set cash ( cash + salary )
      ]

      set cash ( cash - salary )
      set g-cash-spent-this-tick ( g-cash-spent-this-tick + salary )
      set g-cash-spent-this-tick-labour ( g-cash-spent-this-tick-labour + salary )
      set energy ( energy - share-of-energy )
      f-set-available-energy
      set recycled ( recycled - dynamic-quota )
      set inventory ( inventory + dynamic-quota )
      
      set meus-yet-to-buy ( meus-yet-to-buy - dynamic-quota )

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-B ( list "HWk" ( [who] of this-wrkr ) who share-of-energy salary )
        f-write-dpx-data-B
      ]
      
      if( gb-EMgr = true )
      [
        ;; grant management: note the resources used
        set grt-mgmt-cash-used salary
        set grt-mgmt-energy-used share-of-energy
        set grt-mgmt-recycled-used dynamic-quota
        ask this-wrkr [ set grt-mgmt-energy-used share-of-energy ]
      ]

      LOG-TO-FILE word "Do-HWk:  Meus harvested - " dynamic-quota 
      LOG-TO-FILE word "Do-HWk: Hires completed - " no-of-hires-completed 
      let frmr-who who  ;; These lets are for debug logging purposes only.
      let wrkr-who [who] of this-wrkr
      LOG-WITH-AIF-CHECK ( word "Do-HWk: " dynamic-quota " meus harvested with aid of wrkr " wrkr-who "." ) frmr-who
      ask this-wrkr [ LOG-WITH-AIF-CHECK ( word "Do-HWk: " share-of-energy " hours worked for frmr " frmr-who "." ) wrkr-who ] 
    ]  ;; End of 'can continue' for frmr and wrkr.  This wrkr did the work and has been paid.
    
    ;; Return all unused grants, if any.  This is done for every transaction.
    f-frmr-returns-unused-grants "Hwk-R"
    ask this-wrkr [ f-wrkr-returns-unused-grants "Hwk-R" ]
      
    ;; Check if this completes all hires.
    ifelse ( no-of-hires-completed >= g-no-of-hires-max ) 
    [ 
      ;; Tell the frmr to stop trying to hire.
      set b-frmr-can-continue 0
      LOG-TO-FILE ""
      LOG-TO-FILE word "Do-HWk: Hires completed this tick - " no-of-hires-completed 

      ;; Flag the frmr as serviced.
      set b-can-hire-wrkrs 0
      ;; Flag the transaction as done.
      set b-transaction-completed 1
    ]
    [
      LOG-TO-FILE ""
      LOG-TO-FILE word "Do-HWk: Hires completed so far - " no-of-hires-completed 
    ]

    ;; Check if the frmr can continue.
    
    ;; Note: The following has been suppressed to allow the frmr to continue
    ;;   to work as long as there is energy available from the EMgr.
    ;; if ( available-energy <= 0 ) 
    ;; [ 
    ;;   set b-frmr-can-continue 0 
    ;;   LOG-TO-FILE word "Do-HWk: Frmr cannot continue.  Available energy is too low - " available-energy
    ;; ]
    ;; Note:  In V1.31 (141031) I activated this block of code and all frmrs died 
    ;;   at tick 14098.  It seems frmrs need generous make-work handouts in 
    ;;   order to survive.  Of course, the frmrs benefit directly, but the 
    ;;   wrkrs also benefit as they have plenty of work also.

    if ( cash <= 0 ) 
    [ 
      set b-frmr-can-continue 0 
      LOG-TO-FILE word "Do-HWk: Frmr cannot continue.  Cash too low - " cash
    ]

    ;; Note if there are no more wrkrs to try to hire.
    if ( count un-set <= 0 ) 
    [ 
      set b-frmr-can-continue 0 
      LOG-TO-FILE word "Do-HWk: Frmr cannot continue.  Wrkrs remaining in pool - " count un-set
    ]

    LOG-TO-FILE word "Do-HWk: Frmr-can-continue - " b-frmr-can-continue
  ] ;; End of while frmr can continue
end 

;;-----------------------------------------------------------------------------|
;; A customer returns unused grants to the EMgr.

to f-consumer-returns-unused-grants [ action-type ]
  ;; Frmrs and wrkrs execute this routine.
  
  ifelse( breed = "frmr" ) 
  [ f-frmr-returns-unused-grants action-type ]
  [ f-wrkr-returns-unused-grants action-type ]
end 


;;-----------------------------------------------------------------------------|
;; An agent determines how much energy is available for work.

to f-set-available-energy
  ;; Frmrs and wrkrs execute this routine.

  ;; The energy set point starts at zero and grows by one with each 'do-eat'
  ;;   step.  That amount of energy is reserved for eventual reproduction.  If
  ;;   this is not done, most agents never save enough energy to reproduce.
  set available-energy ( energy - energy-set-point )
  ;; Energy for work is never less than zero.
  if( available-energy < 0 ) [ set available-energy 0 ]
end 


;;-----------------------------------------------------------------------------|
;; A frmr returns unused grants to the EMgr.

to f-frmr-returns-unused-grants [ action-type ]
  ;; Only frmrs execute this routine – self is a frmr.

  ;; ASSERT ( g-EMgr-cash >= 0   ) ( word "EMgr: Cash grant returns Msg 001; cash = " g-EMgr-cash " " ) who
  ;; ASSERT ( g-EMgr-mass >= 0   ) ( word "EMgr: Mass grant returns Msg 002; mass = " g-EMgr-mass " " ) who
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( word "EMgr: Energy grant returns Msg 003; energy = " g-EMgr-energy " " ) who

  if( gb-EMgr = true )
  [
    ;; An agent must spend its own resources before it spends granted resources
    ;; I am handling this differently from the way I handled it in C++ to try
    ;;   to reduce the complexity of the calculations, but it is still complex.
    ;; When the grant was assigned, it was added to the agent's resource pool but
    ;;   note of it was made in the agent's grant management variables.
    
    let grant-to-return 0
    
    ;; Cash grant.
    set grant-to-return ( grt-mgmt-cash-granted - grt-mgmt-cash-used )
    if ( grant-to-return > 0 )
    [
      set cash ( cash - grant-to-return )
      set g-EMgr-cash ( g-EMgr-cash + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "frmr" "cash" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Frmr returns unused cash grant of " grant-to-return ) who
    ]
    set grt-mgmt-cash-granted 0      
    set grt-mgmt-cash-used 0        
    
    ;; Energy grant.
    set grant-to-return ( grt-mgmt-energy-granted - grt-mgmt-energy-used )
    if ( grant-to-return > 0 )
    [
      set energy ( energy - grant-to-return )
      f-set-available-energy
      set g-EMgr-energy ( g-EMgr-energy + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "frmr" "energy" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Frmr returns unused energy grant of " grant-to-return ) who
    ]
    set grt-mgmt-energy-granted 0      
    set grt-mgmt-energy-used 0        
    
    ;; Recycled grant.
    set grant-to-return ( grt-mgmt-recycled-granted - grt-mgmt-recycled-used )
    if ( grant-to-return > 0 )
    [
      set recycled ( recycled - grant-to-return )
      set g-EMgr-mass ( g-EMgr-mass + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "frmr" "recycled" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Frmr returns unused recycled grant of " grant-to-return ) who
    ]
    set grt-mgmt-recycled-granted 0      
    set grt-mgmt-recycled-used 0        
    
    ;; Inventory grant.
    set grant-to-return ( grt-mgmt-inventory-granted - grt-mgmt-inventory-used )
    if ( grant-to-return > 0 )
    [
      set inventory ( inventory - grant-to-return )
      set g-EMgr-mass ( g-EMgr-mass + grant-to-return ) 
      set g-EMgr-energy ( g-EMgr-energy + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "frmr" "inventory" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Frmr returns unused inventory grant of " grant-to-return ) who
    ]
    set grt-mgmt-inventory-granted 0
    set grt-mgmt-inventory-used 0
    
    ;; Waste grant.
    set grant-to-return ( grt-mgmt-waste-granted - grt-mgmt-waste-used )
    if ( grant-to-return > 0 )
    [
      set waste ( waste - grant-to-return )
      set g-EMgr-mass ( g-EMgr-mass + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "frmr" "waste" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Frmr returns unused waste grant of " grant-to-return ) who
    ]
    set grt-mgmt-waste-granted 0      
    set grt-mgmt-waste-used 0        
  ]

  ;; ASSERT ( g-EMgr-cash >= 0 ) ( word "EMgr: Cash grant returns Msg 004; cash = " g-EMgr-cash " " ) who
  ;; ASSERT ( g-EMgr-mass >= 0 ) ( word "EMgr: Mass grant returns Msg 005; mass = " g-EMgr-mass " " ) who
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( word "EMgr: Energy grant returns Msg 006; energy = " g-EMgr-energy " " ) who
end 

;;-----------------------------------------------------------------------------|
;; A wrkr returns unused grants to the EMgr.

to f-wrkr-returns-unused-grants [ action-type ]
  ;; Only wrkrs execute this routine – self is a wrkr.


  ;; ASSERT ( g-EMgr-cash >= 0   ) ( word "EMgr: Cash grant returns Msg 007; cash = " g-EMgr-cash " " ) who
  ;; ASSERT ( g-EMgr-mass >= 0   ) ( word "EMgr: Mass grant returns Msg 008; mass = " g-EMgr-mass " " ) who
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( word "EMgr: Energy grant returns Msg 009; energy = " g-EMgr-energy " " ) who

  if( gb-EMgr = true )
  [
    ;; An agent must spend its own resources before it spends granted resources
    ;; I am handling this differently from the way I handled it in C++ to try
    ;;   to reduce the complexity of the calculations, but it is still complex.
    ;; When the grant was assigned, it was added to the agent's resource pool but
    ;;   note of it was made in the agent's grant management variables.
    
    let grant-to-return 0
    
    ;; Cash grant.
    set grant-to-return ( grt-mgmt-cash-granted - grt-mgmt-cash-used )
    if ( grant-to-return > 0 )
    [
      set cash ( cash - grant-to-return )
      set g-EMgr-cash ( g-EMgr-cash + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "wrkr" "cash" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Wrkr returns unused cash grant of " grant-to-return ) who
    ]
    set grt-mgmt-cash-granted 0      
    set grt-mgmt-cash-used 0        
    
    ;; Energy grant.
    set grant-to-return ( grt-mgmt-energy-granted - grt-mgmt-energy-used )
    if ( grant-to-return > 0 )
    [
      set energy ( energy - grant-to-return )
      f-set-available-energy
      set g-EMgr-energy ( g-EMgr-energy + grant-to-return ) 

      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "wrkr" "energy" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Wrkr returns unused energy grant of " grant-to-return ) who
    ]
    set grt-mgmt-energy-granted 0      
    set grt-mgmt-energy-used 0        
    
    ;; Waste grant.
    set grant-to-return ( grt-mgmt-waste-granted - grt-mgmt-waste-used )
    if ( grant-to-return > 0 )
    [
      set waste ( waste - grant-to-return )
      set g-EMgr-mass ( g-EMgr-mass + grant-to-return ) 
 
      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-H 
        ( list action-type who "wrkr" "waste" grant-to-return )
        f-write-dpx-data-H
      ]
    
      LOG-WITH-AIF-CHECK ( word "EMgr: Wrkr returns unused waste grant of " grant-to-return ) who
    ]
    set grt-mgmt-waste-granted 0      
    set grt-mgmt-waste-used 0        
  ]

  ;; ASSERT ( g-EMgr-cash >= 0 ) ( word "EMgr: Cash grant returns Msg 010; cash = " g-EMgr-cash " " ) who
  ;; ASSERT ( g-EMgr-mass >= 0 ) ( word "EMgr: Mass grant returns Msg 011; mass = " g-EMgr-mass " " ) who
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( word "EMgr: Energy grant returns Msg 012; energy = " g-EMgr-energy " " ) who
end 

;;-----------------------------------------------------------------------------|
;; Compute a frmr's 'hold inventory limit' ( hil ).

to f-set-frmr-hil
  ;; Only frmrs execute this routine – self is a frmr.

  ;; HIL stands for 'hold inventory limit' and is the amount of
  ;;   inventory a frmr may hold as determined
  ;;   by the business factor g-HIF-f.  If a frmr's holding is less than
  ;;   the allowed amount, it may make enough hires 
  ;;   to take it up to this limit.

  ;; NOTE: decide whether -net-value or -real-value are best here.
  ;; With V1.31 net-value gives stable runs. (141031)
  set hil floor( g-HIF-f * fr-get-frmr-net-value / g-meu-price ) 

  if( hil < g-hil-f-min ) [ set hil g-hil-f-min ]
  
  LOG-WITH-AIF-CHECK ( word "Do-HWk: Agent: " who "; HIL: " hil " meus; Inv: " inventory " meus" ) who
end 


;;-----------------------------------------------------------------------------|
;; A frmr requests a grant from the EMgr for cash to hire wrkrs.

to f-frmr-requests-HWk-cash-grant
  ;; Only frmrs should execute this.
  
  ;; The frmr has enough unused hil to hire at least one wrkr.
  ;; The wrkr has enough available-energy to start at least one job.
  ;; If the EMgr has grants, they will be approved up to g-harvest-quota for
  ;;    both frmr and wrkr.
  
  ;; LOG-TO-FILE "" LOG-WITH-AIF-CHECK "EMgr: HWk-cash-grant msg 001 - requested" who
  if( gb-EMgr = true )
  [
    ;; LOG-WITH-AIF-CHECK "EMgr: HWk-cash-grant msg 002 - EMgr is active" who
    if( g-EMgr-cash > 0 )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: HWk-cash-grant msg 003 - EMgr has cash" who
      let cash-needed floor( g-harvest-quota * g-eu-price / 2 )
      ;; Determine if frmr is poor.
      if( cash < cash-needed )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: HWk-cash-grant msg 004 - frmr is poor" who
        ;; Determine if frmr is "deserving".
        if( cash > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: HWk-cash-grant msg 005 - frmr is deserving" who
          ;; Frmr is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out?
          let amount-granted ( cash-needed - cash )
          if( amount-granted > g-EMgr-cash )
          [
            set amount-granted g-EMgr-cash
          ]
 
          LOG-WITH-AIF-CHECK ( word "EMgr: Frmr has cash on hand - $" cash ) who

          ;; Record the grant in the frmrs variables.
          set grt-mgmt-cash-granted amount-granted
          set grt-mgmt-cash-used 0

          ;; Effect the grant.
          set cash ( cash + amount-granted )
          set g-EMgr-cash ( g-EMgr-cash - amount-granted )
 
          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            set gl-dpx-record-layout-H 
            ( list "Hwk" who "frmr" "cash" amount-granted )
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: HWk-cash grant to frmr - $" amount-granted ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-cash >= 0 ) ( "EMgr: HWk-cash grant; cash < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; A frmr requests a grant from the EMgr for energy to hire wrkrs.

to f-frmr-requests-HWk-energy-grant
  ;; Only frmrs should execute this.

  ;; The frmr has enough unused hil to hire at least one wrkr.
  ;; The wrkr has enough available-energy to start at least one job.
  ;; If the EMgr has grants, they will be approved up to g-harvest-quota for
  ;;    both frmr and wrkr.
  
  ;; Since the frmr provides only half of the energy needed for the
  ;;   harvest, divide the harvest quota by 2.
  let half-harvest-quota floor( g-harvest-quota / 2 )

  ;; LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 001 - requested" who
  if( gb-EMgr = true )
  [
    ;; LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 002 - EMgr is on" who
    if( g-EMgr-energy > 0 )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 003 - EMgr has energy" who
      ;; Determine if frmr is poor.
      if( available-energy < half-harvest-quota )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 004 - frmr is poor" who
        ;; Determine if frmr is "deserving".
        ;; Note: the following is set to -1 to allow the frmr to always be
        ;;   determined as deserving.
        ;; (141031) In V1.31 I switched this from -1 to 0.  All frmrs died 
        ;;   at 16319 ticks. Put back to -1.
        if( available-energy > -1 )  ;; Note: It is 'always deserving' is this needed? 
        [
          LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 005 - frmr is deserving" who
          ;; Frmr is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out?
          let amount-granted ( half-harvest-quota - available-energy )
          if( amount-granted > g-EMgr-energy )
          [
            set amount-granted g-EMgr-energy
          ]
 
          LOG-WITH-AIF-CHECK ( word "EMgr: Frmr has available energy on hand - " available-energy " eus." ) who

          ;; Record the grant in the frmrs variables.
          set grt-mgmt-energy-granted amount-granted
          set grt-mgmt-energy-used 0
          
          ;; Effect the grant.
          set energy ( energy + amount-granted )
          f-set-available-energy
          set g-EMgr-energy ( g-EMgr-energy - amount-granted )
 
          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            set gl-dpx-record-layout-H 
            ( list "Hwk" who "frmr" "eu" amount-granted )
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: HWk-energy-grant to frmr - " amount-granted " eus." ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( "EMgr: HWk-energy grant; energy < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; A frmr requests a grant from the EMgr for mass to hire wrkrs.

to f-frmr-requests-HWk-mass-grant
  ;; Only frmrs should execute this.

  ;; The frmr has enough unused hil to hire at least one wrkr.
  ;; The wrkr has enough available-energy to start at least one job.
  ;; If the EMgr has grants, they will be approved up to g-harvest-quota for
  ;;    both frmr and wrkr.
  
  ;; LOG-WITH-AIF-CHECK "EMgr: HWk-mass-grant msg 001 - requested" who
  if( gb-EMgr = true )
  [
    ;; LOG-WITH-AIF-CHECK "EMgr: HWk-mass-grant msg 002 - EMgr is on" who
    if( g-EMgr-mass > 0 )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: HWk-mass-grant msg 003 - EMgr has mass" who
      ;; Determine if frmr is poor but deserving.
      if( recycled < g-harvest-quota )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: HWk-mass-grant msg 004 - frmr is poor" who
        ;; Determine if frmr is "deserving".
        if( recycled > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: HWk-mass-grant msg 005 - frmr is deserving" who
          ;; Frmr is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out?
          let amount-granted ( g-harvest-quota - recycled )
          if( amount-granted > g-EMgr-mass )
          [
            set amount-granted g-EMgr-mass
          ]
 
          LOG-WITH-AIF-CHECK ( word "EMgr: Frmr has recycled mass on hand - " recycled " mus." ) who

          ;; Record the grant in the frmr's variables.
          set grt-mgmt-recycled-granted amount-granted
          set grt-mgmt-recycled-used 0

          ;; Effect the grant.
          set recycled ( recycled + amount-granted )
          set g-EMgr-mass ( g-EMgr-mass - amount-granted )

          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            set gl-dpx-record-layout-H 
            ( list "Hwk" who "frmr" "mu" amount-granted )
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: HWk-mass grant to frmr - " amount-granted " mus." ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-mass >= 0 ) ( "EMgr: HWk-mass grant; mass < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; A wrkr requests a grant from the EMgr for available-energy to work.

to f-wrkr-requests-HWk-energy-grant
  ;; Only wrkrs should execute this.

  ;; The frmr has enough unused hil to hire at least one wrkr.
  ;; The wrkr has enough available-energy to start at least one job.
  ;; If the EMgr has grants, they will be approved up to g-harvest-quota for
  ;;    both frmr and wrkr
  
  ;; Since the wrkr provides only half of the energy needed for the
  ;;   harvest, divide the harvest quota by 2.
  let half-harvest-quota floor( g-harvest-quota / 2 )

  ;; LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 001 - requested by wrkr" who
  if( gb-EMgr = true )
  [
    ;; LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 002 - EMgr is on" who
    if( g-EMgr-energy > -1 )  ;; always deserving  ;; Note: - is this needed
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 003 - EMgr has energy" who
      ;; Determine if this wrkr is poor but deserving.
      if( available-energy < half-harvest-quota )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 004 - wrkr is poor" who
        ;; Determine if this wrkr is "deserving".
        ;; Note: Do I want this wrkr to be always deserving?
        if( available-energy > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: HWk-energy-grant msg 005 - wrkr is deserving" who
          ;; This wrkr is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out?
          ;; Since the wrkr provides only half of the energy needed for the
          ;;   harvest, divide the harvest quota by 2.
          let amount-granted ( half-harvest-quota - available-energy )
          if( amount-granted > g-EMgr-energy )
          [
            set amount-granted g-EMgr-energy
          ]
 
          LOG-WITH-AIF-CHECK ( word "EMgr: Wrkr has available energy on hand - " available-energy " eus." ) who

          ;; Record the amounts in the wrkr's variables.
          set grt-mgmt-energy-granted amount-granted
          set grt-mgmt-energy-used 0

          ;; Effect the grant.
          set energy ( energy + amount-granted )
          f-set-available-energy
          set g-EMgr-energy ( g-EMgr-energy - amount-granted )
 
          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            set gl-dpx-record-layout-H 
            ( list "Hwk" who "wrkr" "eu" amount-granted )
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: HWk-energy-grant to wrkr - " amount-granted " eus." ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( "EMgr: HWk-energy grant; energy < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; D4 – sell inventory procedures( s )
;;-----------------------------------------------------------------------------|

to do-sell-inventory
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "sell-inventory" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-Sell-inventory: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-SlI" g-aif

  ;; Ensure all frmrs are flagged if available to sell supplies.
  ask frmrs 
  [ 
    ifelse( inventory > 0 )
    [ set b-can-sell-inventory 1  ]
    [ set b-can-sell-inventory 0 ]
  ]

  ;; Ensure all consumers ( both wrkrs and frmrs ) are flagged if available to buy supplies.
  ask turtles 
  [ 
    f-set-consumer-hsl  ;; This is set here, for each consumer.
    ifelse( ( cash > g-meu-price ) and ( supplies < hsl ) )
    [ set b-can-buy-supplies 1  ]
    [ set b-can-buy-supplies 0 ]
  ]

  LOG-TO-FILE ( word "Do-SlI: Consumers able to participate: " ( count turtles with [ b-can-buy-supplies = 1 ] ) )
  
  ;; Frmrs take the primary role.
  ;; OK frmrs are those with inventory to sell.
  let ok-frmrs frmrs with [ b-can-sell-inventory = 1 ]

  LOG-TO-FILE word "Do-SlI: Frmrs able to sell - " ( count ok-frmrs ) 
  LOG-TO-FILE word "Do-SlI: Who #s of able frmrs: " [who] of ok-frmrs 

  ask ok-frmrs [ f-sell-inventory-to-consumers ]  

  ;; Supressed. f-update-aggregates

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-SlI" g-aif

  LOG-TO-FILE "Do-SlI: procedure completed."
end 

;;-----------------------------------------------------------------------------|
;; Sell-inventory-to-consumers routine.

to f-sell-inventory-to-consumers
  ;; Frmrs execute this routine – self is a frmr.
  ;; The frmr sells inventory until all customers are serviced, or all inventory
  ;;   is gone.
  
  ;; Establish a list of customers who have not purchased supplies so far this 
  ;;   tick.
  let cu-set customer-set with [ b-can-buy-supplies = 1 ]

  ;; A let as declaration, used later.
  let this-customer one-of cu-set
  
  ;; Now, a needed let.
  let no-of-transactions-completed 0

  ;; And now, another needed let.
  let b-frmr-can-continue 1
  if ( inventory <= 0 )    [ set b-frmr-can-continue 0 ]
  if ( count cu-set <= 0 ) [ set b-frmr-can-continue 0 ]
 
  while [ b-frmr-can-continue = 1 ]
  [
    let b-transaction-completed 0
    ;; Pull one customer out of temporary customer-set.
    set this-customer one-of cu-set
    ask this-customer [ set cu-set other cu-set ]
 
    LOG-TO-FILE ""
    LOG-TO-FILE word "    Transaction #: " ( no-of-transactions-completed + 1 )

    ;; Check if EMgr has grants to offer.
    f-frmr-requests-SlI-meu-grant  ( [breed] of this-customer )
    ask this-customer [ f-consumer-requests-SlI-cash-grant ]
    
    let cu-who [who] of this-customer ;; For AIF purposes.
    let dynamic-quota g-supplies-purchase-quota
    ask this-customer 
    [ 
      LOG-WITH-AIF-CHECK ( word "Do-SlI: Agent: " who ": HSL " hsl " meus; Supplies: " supplies " meus; Dq: " dynamic-quota  " meus." ) cu-who
    ] 

    if( true = ( is-frmr? this-customer ) ) 
    [ 
      ;; Allow frmrs to purchase four times the supplies, as they eat four times the amount per tick.
      set dynamic-quota ( g-no-of-hires-max * dynamic-quota ) 
      ask this-customer 
      [ 
        LOG-WITH-AIF-CHECK ( word "Do-SlI: Agent: " who ": Dq raised for frmr customer = " dynamic-quota " meus." ) cu-who
      ] 
    ]
    
    ;; Amount purchased cannot exceed available inventory of frmr.
    if ( dynamic-quota > inventory ) 
    [ 
      set dynamic-quota inventory 
      ask this-customer 
      [ 
        LOG-WITH-AIF-CHECK ( word "Do-SlI: Agent: " who "; Dq reduce to available Inv = " dynamic-quota " meus." ) cu-who
      ] 
    ]
    
    ;; Price of amount purchased cannot exceed cash of customer.
    if( ( dynamic-quota * g-meu-price ) > ( [cash] of this-customer ) )
    [ 
      set dynamic-quota floor( ( [cash] of this-customer ) / g-meu-price ) 
      ask this-customer 
      [ 
        LOG-WITH-AIF-CHECK ( word "Do-SlI: Agent: " who "; Dq reduced to available cash = " dynamic-quota " meus." ) cu-who
      ] 
    ] 
    

    LOG-TO-FILE word "           FRMR WHO - " who 
    LOG-TO-FILE word "       Cash on hand - " cash 
    LOG-TO-FILE word "          Inventory - " inventory 
    LOG-TO-FILE word "       CONSUMER WHO - " [who] of this-customer 
    LOG-TO-FILE word "       Cash on hand - " [cash] of this-customer 
    LOG-TO-FILE word "           Supplies - " [supplies] of this-customer 
    LOG-TO-FILE word "Hold Supplies limit - " [hsl] of this-customer 
    LOG-TO-FILE word "      Dynamic quota - " dynamic-quota 

    ;; Transfer meus from frmr to customer.
    set inventory ( inventory - dynamic-quota )
    ask this-customer [ set supplies ( supplies + dynamic-quota ) ]
    let extended-price ( g-meu-price * dynamic-quota )
    set cash ( cash + extended-price )
    ask this-customer [ set cash ( cash - extended-price) ]
    set g-cash-spent-this-tick ( g-cash-spent-this-tick + extended-price )
    set g-cash-spent-this-tick-food ( g-cash-spent-this-tick-food + extended-price )

    ;; Process DPX data collection option
    if( gb-dpx-on = 1 )
    [
      set gl-dpx-record-layout-B ( list "SlI" who ( [who] of this-customer ) dynamic-quota extended-price )
      f-write-dpx-data-B
    ]

    if( gb-EMgr = true )
    [
      ;; Grant management: note the resources transferred.
      set grt-mgmt-inventory-used ( grt-mgmt-inventory-used + dynamic-quota )
      ask this-customer [ set grt-mgmt-cash-used ( grt-mgmt-cash-used + ( g-meu-price * dynamic-quota ) ) ]
    ]
      
    set no-of-transactions-completed ( no-of-transactions-completed + 1 )

    LOG-WITH-AIF-CHECK ( word "Do-SlI: " dynamic-quota 
      " meus sold to customer " ( [who] of this-customer ) 
      " at price $" ( g-meu-price * dynamic-quota ) "." ) who
    ask this-customer [ LOG-WITH-AIF-CHECK ( word "Do-SlI: Customer " cu-who 
        " purchased " dynamic-quota 
        " meus from frmr " ( [who] of myself ) 
        " at price $" ( g-meu-price * dynamic-quota ) "." ) cu-who ]

    ;; Return excess grants to EMgr.
    f-frmr-returns-unused-grants "SlI-R"
    ask this-customer [ f-consumer-returns-unused-grants "SlI-R" ]
      
    ;; Flag this customer for exclusion from further transactions of this type during this tick.
    ask this-customer [ set b-can-buy-supplies 0 ]

    ;; Check if frmr can continue to sell inventory.
    if ( inventory <= 0 )    
    [ 
      set b-frmr-can-continue 0 
      LOG-WITH-AIF-CHECK ( word "Do-SlI: Frmr cannot continue.  Inventory at end: " inventory " meus." ) who
    ]

    ;; Note if there are no more customers available.
    if ( count cu-set <= 0 ) 
    [ 
      set b-frmr-can-continue 0 
      LOG-WITH-AIF-CHECK ( word "Do-SlI: Frmr cannot continue.  Unused customers: " count cu-set " agents." ) who
    ]
  ]  ;; End of while frmr can continue.
end 

;;-----------------------------------------------------------------------------|
;; Compute a consumer's 'hold supplies limit' ( hsl ).

to f-set-consumer-hsl
  ;; This routine is to be executed by both frmrs and wrkrs ( i.e. consumers ).

  ;; Determine the supply allowed by the business factor g-HSF-f or g-HSF-w
  set hsl 0

  ifelse( breed = frmrs )
  [ 
    set hsl floor( g-HSF-f * fr-get-frmr-net-value / g-meu-price ) 
    if( hsl < g-hsl-f-min ) [ set hsl g-hsl-f-min ]
  ]
  [
    set hsl floor( g-HSF-w * fr-get-wrkr-net-value / g-meu-price )
    if( hsl < g-hsl-w-min ) [ set hsl g-hsl-w-min ]
  ]
  
  LOG-WITH-AIF-CHECK ( word "Do-SlI: Agent: " who "; HSL:" hsl " meus; Supplies:" supplies " meus." ) who
end 

;;-----------------------------------------------------------------------------|
;; Compute a wrkr's net value.

to-report fr-get-wrkr-net-value
  ;; Only wrkrs execute this routine – self is a wrkr.
  set net-value cash
  set net-value ( net-value + ( energy    * g-eu-price  ) )  
  set net-value ( net-value + ( supplies  * g-meu-price ) )  
  set net-value ( net-value + ( waste     * g-mu-price  ) )  
  report net-value
end 

;;-----------------------------------------------------------------------------|
;; Compute a wrkr's real value.

to-report fr-get-wrkr-real-value
  ;; Only wrkrs execute this routine – self is a wrkr.
  
  ;; Real value is the same as net value, less the cash.
  ;; This is used in finding hsl using the business factor hsf.  
  ;;   E.g HSL = ( HSF * real-value ).
  ;; When net value is used, including cash, wrkrs are too quick to take work
  ;;   and burn up energy, thereby being unable to reproduce.  This is due to 
  ;;   the fact that neither energy nor cash are controlled.  High cash assets
  ;;   cause wrkrs to take work and burn up energy.  Frmrs may suffer the 
  ;;   same problem.  I have produceD a real-value function for each type
  ;;   of agent.
  
  set real-value                ( energy    * g-eu-price  )
  set real-value ( real-value + ( supplies  * g-meu-price ) )  
  set real-value ( real-value + ( waste     * g-mu-price  ) )  
  report real-value
end 

;;-----------------------------------------------------------------------------|
;; A frmr requests a grant from the EMgr for inventory to sell.

to f-frmr-requests-SlI-meu-grant [ customer-breed ]
  ;; Only frmrs should execute this.

  ;; LOG-TO-FILE "" LOG-WITH-AIF-CHECK "EMgr: SlI-meu-grant msg 001 - requested" who
  if( gb-EMgr = true )
  [ 
    ;; LOG-WITH-AIF-CHECK "EMgr: SlI-meu-grant msg 002 - EMgr is on" who
    if( ( g-EMgr-energy > 0 ) and ( g-EMgr-mass > 0 ) )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: SlI-meu-grant msg 003 - EMgr has meus" who
      ;; Determine if this frmr is poor but deserving.
      let inventory-on-hand inventory
      if( inventory-on-hand < g-supplies-purchase-quota )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: SlI-meu-grant msg 004 - frmr is poor" who
        ;; Determine if this frmr is "deserving".
        if( inventory-on-hand > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: SlI-meu-grant msg 005 - frmr is deserving" who
          ;; This frmr is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out.
          let spq g-supplies-purchase-quota
          if( customer-breed = "frmr" ) [ set spq ( g-no-of-hires-max * spq ) ]
          
          let amount-granted ( spq - inventory-on-hand )
          ;; EMgr must grant a pair of resources to make one meu ( 1 mu + 1 eu = 1 meu ).
          if( amount-granted > g-EMgr-energy ) [ set amount-granted g-EMgr-energy ]
          if( amount-granted > g-EMgr-mass )   [ set amount-granted g-EMgr-mass ]
 
          LOG-WITH-AIF-CHECK ( word "Do-SlI: EMgr: Frmr had inventory on hand - " inventory " meus." ) who

          ;; Effect the grant.
          set grt-mgmt-inventory-granted amount-granted
          set grt-mgmt-inventory-used 0
          
          set inventory ( inventory + amount-granted )
          set g-EMgr-energy ( g-EMgr-energy - amount-granted )
          set g-EMgr-mass   ( g-EMgr-mass   - amount-granted )

          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            set gl-dpx-record-layout-H 
            ( list "SlI" who "frmr" "meu" amount-granted )
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: SlI-meu grant to frmr - " amount-granted " meus." ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-mass >= 0 ) ( "EMgr: SlI-meu grant; mass < 0 " ) who
  ;; ASSERT ( g-EMgr-energy >= 0 ) ( "EMgr: SlI-meu grant; energy < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; A consumer requests a grant from the EMgr for cash to buy supplies.

to f-consumer-requests-SlI-cash-grant
  ;; only consumers should execute this

  ;; LOG-TO-FILE "" LOG-WITH-AIF-CHECK "EMgr: SlI-cash-grant msg 001 - requested" who
  if( gb-EMgr = true )
  [ 
    ;; LOG-WITH-AIF-CHECK "EMgr: SlI-cash-grant msg 002 - EMgr is on" who
    if( g-EMgr-cash > 0 )
    [
      ;; LOG-WITH-AIF-CHECK "EMgr: SlI-cash-grant msg 003 - EMgr has cash" who
      ;; Determine if this consumer is poor but deserving.
      let cash-on-hand cash
      if( cash-on-hand < ( g-supplies-purchase-quota * g-meu-price ) )  ;; a measure of "poor"
      [
        LOG-WITH-AIF-CHECK "EMgr: SlI-cash-grant msg 004 - consumer is poor." who
        ;; Determine if this-customer is "deserving".
        if( cash-on-hand > 0 )
        [
          LOG-WITH-AIF-CHECK "EMgr: SlI-cash-grant msg 005 - consumer is deserving." who
          ;; This consumer is both poor and deserving.
          ;; Does the EMgr have suitable grants to hand out.
          let amount-granted ( ( g-supplies-purchase-quota * g-meu-price ) - cash-on-hand )
          ;; But frmrs eat more.
          if( breed = "frmr" ) [ set amount-granted ( amount-granted * g-no-of-hires-max ) ]
          if( amount-granted > g-EMgr-cash )
          [
            set amount-granted g-EMgr-cash
          ]
 
          LOG-TO-FILE word "Do-SlI: Consumer has cash on hand - " cash

          ;; Effect the grant.
          set grt-mgmt-cash-granted amount-granted
          set grt-mgmt-cash-used 0
          
          set cash ( cash + amount-granted )
          set g-EMgr-cash ( g-EMgr-cash - amount-granted )

          ;; Process DPX data collection option
          if( gb-dpx-on = 1 )
          [
            ifelse( breed = "frmr" )
            [
              set gl-dpx-record-layout-H 
              ( list "SlI" who "frmr" "cash" amount-granted )
            ] 
            [
              set gl-dpx-record-layout-H 
              ( list "SlI" who "wrkr" "cash" amount-granted )
            ] 
            f-write-dpx-data-H
          ]
          
          LOG-WITH-AIF-CHECK ( word "EMgr: SlI-cash grant to consumer - " amount-granted ) who
        ]
      ]
    ]
  ]
  
  ;; ASSERT ( g-EMgr-cash >= 0 ) ( "EMgr: SlI-cash grant; cash < 0 " ) who
end 

;;-----------------------------------------------------------------------------|
;; D5 – eat-supplies procedures( s )
;;-----------------------------------------------------------------------------|

to do-eat-supplies
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "eat-supplies" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-Eat-supplies: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-Eat" g-aif

  ;; Ensure all flags set properly.
  ;; [not needed] ask turtles [ set b-is-ready-to-die 0 ]
  
  ask frmrs [ f-frmr-eats-own-supplies ]   ;; agent eats its own supplies, if any
  ask wrkrs [ f-wrkr-eats-own-supplies ]   ;; agent eats its own supplies, if any
  ;; Supressed. f-update-aggregates

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-Eat" g-aif

  LOG-TO-FILE "Do-Eat: procedure completed."
end 

;;-----------------------------------------------------------------------------|
;; Wrkr-eats-own-supplies routine.

to f-wrkr-eats-own-supplies
  ;; Wrkrs execute this routine – self is a wrkr.
  let amount-eaten g-EPT
  set b-can-die-of-hunger 0
  if( supplies < amount-eaten ) 
  [
     set amount-eaten supplies 
     set b-can-die-of-hunger 1
  ]
  
  LOG-WITH-AIF-CHECK ( word "Do-Eat: Before -       Nrg: " energy " eus; Sup: " supplies " meus; Wst: " waste " mus." ) who
    
  ;; Eat meus; mass plus energy.
  set supplies ( supplies - amount-eaten )
  ;; Add eus and mus to energy and mass stores.
  set energy ( energy + amount-eaten )
  set waste ( waste + amount-eaten )
  ;; Increment the energy-set-point to indicate maturation/growth.
  set energy-set-point ( energy-set-point + 1 )
  ;; The energy-set-point does not need to be bigger than g-RET.
  if( energy-set-point > g-RET ) [ set energy-set-point g-RET ]
  f-set-available-energy

  ;; Process DPX data collection option
  if( gb-dpx-on = 1 )
  [
    set gl-dpx-record-layout-D 
    ( list "Eat" who amount-eaten age cash energy supplies waste HSL )
    f-write-dpx-data-D
  ]

  LOG-WITH-AIF-CHECK ( word "Do-Eat: Eaten: " amount-eaten 
    " meus; Nrg: " energy 
    " eus; Sup: " supplies 
    " meus; Wst: " waste " mus." ) who

  ifelse( b-can-die-of-hunger = 1 ) 
    [ LOG-WITH-AIF-CHECK ( word "Do-Eat: Supplies eaten/remaining - " amount-eaten "/" supplies " meus ; dying" ) who ]
    [ LOG-WITH-AIF-CHECK ( word "Do-Eat: Supplies eaten/remaining - " amount-eaten "/" supplies " meus." ) who ]
end 

;;-----------------------------------------------------------------------------|
;; Frmr-eats-own-supplies routine.

to f-frmr-eats-own-supplies
  ;; Frmrs execute this routine – self is a frmr.
  let amount-eaten ( g-no-of-hires-max * g-EPT )
  set b-can-die-of-hunger 0
  if( supplies < amount-eaten ) 
  [
     set amount-eaten supplies 
     set b-can-die-of-hunger 1
  ]
  
  LOG-WITH-AIF-CHECK ( word "Do-Eat: Before -     Nrg: " energy " eus; Sup: " supplies " meus; Wst: " waste " mus." ) who
    
  ;; Eat meus; mass plus energy.
  set supplies ( supplies - amount-eaten )
  ;; Add eus and mus to energy and mass stores.
  set energy ( energy + amount-eaten )
  set waste ( waste + amount-eaten )
  ;; Increment the energy-set-point to indicate maturation/growth.
  set energy-set-point ( energy-set-point + 1 )
  ;; The energy-set-point does not need to be bigger than g-RET.
  if( energy-set-point > g-RET ) [ set energy-set-point g-RET ]
  f-set-available-energy

  ;; Process DPX data collection option
  if( gb-dpx-on = 1 )
  [
    set gl-dpx-record-layout-F 
    ( list "Eat" who amount-eaten age cash energy recycled inventory supplies waste HRL HIL HSL )
    f-write-dpx-data-F
  ]

  LOG-WITH-AIF-CHECK ( word "Do-Eat: Eaten: " amount-eaten 
    " meus; Nrg: " energy 
    " eus; Sup: " supplies 
    " meus; Wst: " waste " mus." ) who

  ifelse( b-can-die-of-hunger = 1 ) 
    [ LOG-WITH-AIF-CHECK ( word "Do-Eat: Supplies eaten/remaining - " amount-eaten "/" word supplies " meus; dying" ) who ]
    [ LOG-WITH-AIF-CHECK ( word "Do-Eat: Supplies eaten/remaining - " amount-eaten "/" supplies "  meus." ) who ]
end 

;;-----------------------------------------------------------------------------|
;; D6 – reproduction procedures( s )
;;-----------------------------------------------------------------------------|

to do-reproduction
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "reproduction" ) )
    [ 
      set gb-debug-flow-on 1 
      LOG-TO-FILE "" 
      LOG-TO-FILE word "Do-Reproduction: Debug on; tick = " ticks 
      LOG-TO-FILE ( word "Control variables: g-RAT - " g-RAT 
                       "; g-GTT " g-GTT 
                       "; g-RET " g-RET )
    ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-Rep" g-aif

  ;; Checking must be separate from reproduction.
  ask turtles [ f-check-if-ready-to-reproduce ]
  let ok-frmrs frmrs with [ b-can-reproduce = 1 ]
  let ok-wrkrs wrkrs with [ b-can-reproduce = 1 ]

  LOG-TO-FILE word "Do-Rep: Wrkrs able to participate - " ( count ok-wrkrs ) 
  LOG-TO-FILE word "Do-Rep: Who #s of able wrkrs: " [who] of ok-wrkrs 
  LOG-TO-FILE word "Do-Rep: Frmrs able to participate - " ( count ok-frmrs ) 
  LOG-TO-FILE word "Do-Rep: Who #s of able frmrs: " [who] of ok-frmrs 

  ;; frmrs get first shot at available lots
  ask ok-frmrs [ f-reproduce-frmr ]   ;; agent reproduces, if possible
  ask ok-wrkrs [ f-reproduce-wrkr ]   ;; agent reproduces, if possible
  ;; Supressed. f-update-aggregates

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-Rep" g-aif

  LOG-TO-FILE "Do-Rep: procedure completed."
end 

;;-----------------------------------------------------------------------------|
;; F-check-if-ready-to-reproduce routine.

to f-check-if-ready-to-reproduce
  ;; frmrs and wrkrs execute this routine – self is a frmr or wrkr
  
  set b-can-reproduce 1
  if( age < age-to-reproduce ) [ set b-can-reproduce 0 ]
  if( energy < g-RET )         [ set b-can-reproduce 0 ]
end 

;;-----------------------------------------------------------------------------|
;; Reproduce-frmr routine.

to f-reproduce-frmr
  ;; Frmrs execute this routine – self is a frmr.
  ;; Reproduction is by fission.
   
  if( b-can-reproduce = 1 )
  [
    ;; This agent is old enough and healthy enough but it can only reproduce once
    ;;   per tick.

    ;; Is there a place to put a daughter?
    let available-patch-list com-area with [ ( p-no-of-frmrs <= 0 ) and ( p-no-of-wrkrs <= 0 ) ]
    LOG-TO-FILE ""
    LOG-TO-FILE word "Do-Rep: MOTHER'S WHO # - " who 
    LOG-TO-FILE word "Do-Rep: Count of available-patch-list - " count available-patch-list 
    
    ifelse ( count available-patch-list <= 0 ) [ set b-can-reproduce 0 ]
    [
      ;; Proceed with reproduction.
      ;; Select a location for daughter.
      let new-patch one-of available-patch-list
      if( gb-debug-flow-on = 1 )
      [ 
        ;; Leave condition here, though redundant.
        let x [ pxcor ] of new-patch
        let y [ pycor ] of new-patch
        LOG-TO-FILE ( word "Do-Rep: Location of new-patch - x=" x "; y=" y )
      ]
      
      ;; The mother produces a daughter by fission.
      ;; Mother stays on the patch owned by the mother.
      ;; Simply retool the mother.
      let mother self
      
      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-F 
        ( list "Rep" who 0 age cash energy recycled inventory supplies waste HRL HIL HSL )
        f-write-dpx-data-F 
      ]

      ;; Daughter is sprouted on the new patch.
      ;; So, daughter must get onto the reference sets of other agents, and 
      ;;   must establish its own reference sets.
      ask new-patch [ sprout-frmrs 1 ] 
      let daughter frmrs-on new-patch
      ask new-patch [ set p-no-of-frmrs ( count frmrs-on new-patch ) ]
    
      ;; Both mother and daughter each have half the assets of the mother.
      ;; Use temp to store half of assets, put in daughter, subtract from mother.
      ;; Temp is always integral, so non-integral assets should never happen.
      ;; Mother may have one more of any asset than daughter.
      ;; This is done to conserve total amount of assets during fission.
      let temp 0
        
      ;; BUILT-IN ATTRIBUTES
      ;; who        ;; set automatically
      set heading 0 ;; north
      ask daughter [ set heading 0 ]
        
      ;; xcor       ;; min-pxcor <= xcor < max-pxcor
      ;; ycor       ;; min-pxcor <= xcor < max-pxcor
      ;; pen-mode   ;; "up" or "down"
      ;; pen-size   ;; in pixels
      ;; size       ;; size relative to a patch, default is 1

      set age 0     ;; number of ticks since birth
      ;; Adjust the age-to-reproduce by a random amount limited
      ;;   by the 'gestation time threshold' (g-GTT).
      set age-to-reproduce fr-get-random-age-to-reproduce
      set color 25

      ask daughter [ set age 0 ]
      ask daughter [ set age-to-reproduce fr-get-random-age-to-reproduce ]
      ask daughter [ set color 25 ]
      
      ;; Note mother-daughter connection.
      set temp [who] of daughter
      set da-who fput temp da-who      ;; who numbers of daughters
      ask daughter [ set ma-who [who] of mother ]  ;; who number of mother
      ask daughter [ set da-who [-1] ] ;; who numbers of daughters

      LOG-TO-FILE ( word "Do-Rep: Ages - Mother " ( [age] of mother ) 
                       "; Daughter " ( [age] of daughter ) )
      LOG-TO-FILE ( word "Do-Rep: Repro Age - Mother " ( [age-to-reproduce] of mother ) 
                       "; Daughter " ( [age-to-reproduce] of daughter ) )
      LOG-TO-FILE word "Do-Rep: Daughter list " da-who
      LOG-TO-FILE word "Do-Rep: Daughter's who # - " [who] of daughter 

      set temp floor( cash / 2 )
      set cash ( cash - temp ) ;; amount of cash ( $ )
      ask daughter [ set cash temp ]
        
      LOG-TO-FILE "Do-Rep: Assigned values: "
      LOG-TO-FILE word "   Cash: " temp 
      
      set temp floor( energy / 2 )
      set energy ( energy - temp ) ;; amount of energy ( eu )
      ask daughter [ set energy temp ]
      LOG-TO-FILE word "   Energy: " temp

      set energy-set-point 0
      f-set-available-energy
      ask daughter [ set energy-set-point 0 f-set-available-energy ]

      set temp floor( recycled / 2 )
      set recycled ( recycled - temp ) ;; units of recycled mass ( mu )
      ask daughter [ set recycled temp ]
      LOG-TO-FILE word "   Recycled: " temp

      set temp floor( inventory / 2 )
      set inventory ( inventory - temp ) ;; units of inventory of mass-energy ( meu )
      ask daughter [ set inventory temp ]
      LOG-TO-FILE word "   Inventory: " temp

      set temp floor( supplies / 2 )
      set supplies ( supplies - temp ) ;; units of supplies of mass-energy ( meu )
      ask daughter [ set supplies temp ]
      LOG-TO-FILE word "   Supplies: " temp

      set temp floor( waste / 2 )
      set waste ( waste - temp ) ;; units of waste mass ( mu )
      ask daughter [ set waste temp ]
      LOG-TO-FILE word "   Waste: " temp

      set b-can-sell-waste 0     ;; Boolean control on participation
      set b-can-buy-recycled 0   ;; Boolean control on participation
      set b-can-hire-wrkrs 0     ;; Boolean control on participation
      set b-can-sell-inventory 0 ;; Boolean control on participation
      set b-can-buy-supplies 0   ;; Boolean control on participation
      set b-can-eat 0            ;; Boolean control on participation
      set b-can-reproduce 0      ;; Boolean control on participation
      set b-can-die 0            ;; Boolean control on participation
      set b-can-die-of-hunger 0  ;; Boolean control on participation
      set b-can-die-of-age 0     ;; Boolean control on participation
      set b-can-die-of-lownrg 0  ;; Boolean control on participation
      
      ask daughter 
      [ 
        set b-can-sell-waste 0     ;; Boolean control on participation
        set b-can-buy-recycled 0   ;; Boolean control on participation
        set b-can-hire-wrkrs 0     ;; Boolean control on participation
        set b-can-sell-inventory 0 ;; Boolean control on participation
        set b-can-buy-supplies 0   ;; Boolean control on participation
        set b-can-eat 0            ;; Boolean control on participation
        set b-can-reproduce 0      ;; Boolean control on participation
        set b-can-die 0            ;; Boolean control on participation
        set b-can-die-of-hunger 0  ;; Boolean control on participation
        set b-can-die-of-age 0     ;; Boolean control on participation
        set b-can-die-of-lownrg 0  ;; Boolean control on participation
      ]

      ;; Reset agent-sets for all turtles in affected comuting area.
      ask frmrs-on com-area [ f-claim-my-frmrs-patch ]
      ask wrkrs-on com-area [ f-claim-my-wrkrs-patch ]
    ]
  ]
end 

;;-----------------------------------------------------------------------------|
;; Reproduce-wrkr routine.

to f-reproduce-wrkr
  ;; Wrkrs execute this routine – self is a wrkr.
   
  if( b-can-reproduce = 1 )
  [
    ;; This agent is old enough and healthy enough but it can only reproduce once
    ;;   per tick.

    ;; Is there a place to put a daughter?
    let available-patch-list com-area with [ ( p-no-of-frmrs <= 0 ) and ( p-no-of-wrkrs < g-no-of-rents-max ) ]
    LOG-TO-FILE ""
    LOG-TO-FILE word "Do-Rep: MOTHER'S WHO # - " who 
    LOG-TO-FILE word "Do-Rep: Count of available-patch-list - " count available-patch-list 
    
    ifelse ( count available-patch-list <= 0 )
    [ 
      set b-can-reproduce 0
      set b-just-sprouted 0
    ]
    [
      ;; Proceed with reproduction.
      ;; Select a location for daughter.
      let new-patch one-of available-patch-list
      if( gb-debug-flow-on = 1 )
      [ 
        ;; Leave condition here, though redundant.
        let x [pxcor] of new-patch
        let y [pycor] of new-patch
        LOG-TO-FILE ( word "Do-Rep: Location of new-patch - x=" x "; y=" y )
      ]
      
      ;; The mother produces a daughter by fission.
      ;; The mother stays on her patch.
      ;; Simply retool the mother.
      let mother self
      
      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-D 
        ( list "Rep" who 0 age cash energy supplies waste HSL )
        f-write-dpx-data-D
      ]
        
      ;; Daughter is on the new patch, and must get onto the reference sets of other agents.
      ;; So, daughter must get onto lists, and must establish its own lists.
      ask new-patch 
      [ 
        sprout-wrkrs 1 [ set b-just-sprouted 1 ]
        set p-no-of-wrkrs ( p-no-of-wrkrs + 1 )
      ] 
      
      set new-patch patch-set new-patch
      let daughter wrkrs-on new-patch
      set daughter daughter with [ b-just-sprouted = 1 ]
      ask daughter [ set b-just-sprouted 0 ] ;; turn off the flag
      
      LOG-TO-FILE word "Do-Rep: Daughter's who # - " [who] of daughter 
    
      ;; Both mother and daughter each have half the assets of the mother.
      ;; Use temp to store half of assets, put in daughter, subtract from mother.
      ;; Temp is always integral, so non-integral assets should never happen.
      ;; Mother may have one more of any asset than daughter.
      ;; This is done to conserve total amount of assets during fission.
      let temp 0
        
      ;; BUILT-IN ATTRIBUTES
      ;; who        ;; set automatically
      set heading 0 ;; north
      ask daughter [ set heading 0 ]  ;; north
      ;; xcor       ;; min-pxcor <= xcor < max-pxcor
      ;; ycor       ;; min-pxcor <= xcor < max-pxcor
      ;; pen-mode   ;; "up" or "down"
      ;; pen-size   ;; in pixels
      ;; size       ;; size relative to a patch, default is 1

      set age 0     ;; number of ticks since birth
      ;; Adjust the age-to-reproduce by a random amount limited
      ;;   by the 'gestation time threshold' (g-GTT).
      set age-to-reproduce fr-get-random-age-to-reproduce

      ask daughter [ set age 0 ]
      ask daughter [ set age-to-reproduce fr-get-random-age-to-reproduce ]
      
      ;; Note mother-daughter connection.
      set temp [who] of daughter
      set da-who fput temp da-who      ;; who numbers of daughters
      ask daughter [ set ma-who [who] of mother ]  ;; who number of mother
      ask daughter [ set da-who [-1] ] ;; who numbers of daughters

      LOG-TO-FILE ( word "Do-Rep: Ages - Mother " ( [age] of mother ) 
                       "; Daughter " ( [age] of daughter ) )
      LOG-TO-FILE ( word "Do-Rep: Repro Age - Mother " ( [age-to-reproduce] of mother ) 
                       "; Daughter " ( [age-to-reproduce] of daughter ) )
      LOG-TO-FILE word "Do-Rep: Daughter list " da-who
 
      set temp floor( cash / 2 )
      set cash ( cash - temp ) ;; amount of cash ( $ )
      ask daughter [ set cash temp ]
      LOG-TO-FILE "Do-Rep: Assigned values: "
      LOG-TO-FILE word "   Cash: " temp 
      
      set temp floor( energy / 2 )
      set energy ( energy - temp ) ;; amount of energy ( eu )
      ask daughter [ set energy temp ]
      LOG-TO-FILE word "   Energy: " temp

      set energy-set-point 0
      f-set-available-energy
      ask daughter [ set energy-set-point 0 f-set-available-energy ]

      set temp floor( supplies / 2 )
      set supplies ( supplies - temp ) ;; units of supplies of mass-energy ( meu )
      ask daughter [ set supplies temp ]
      LOG-TO-FILE word "   Supplies: " temp

      set temp floor( waste / 2 )
      set waste ( waste - temp ) ;; units of waste mass ( mu )
      ask daughter [ set waste temp ]
      LOG-TO-FILE word "   Waste: " temp

      set b-can-sell-waste 0    ;; Boolean control on participation
      set b-can-buy-supplies 0  ;; Boolean control on participation
      set b-can-eat 0           ;; Boolean control on participation
      set b-can-reproduce 0     ;; Boolean control on participation
      set b-can-die 0           ;; Boolean control on participation
      set b-can-die-of-hunger 0 ;; Boolean control on participation
      set b-can-die-of-age 0    ;; Boolean control on participation
      set b-can-die-of-lownrg 0 ;; Boolean control on participation
      set b-just-sprouted 0     ;; Boolean control to find new sprout
      
      ask daughter 
      [ 
        set b-can-sell-waste 0    ;; Boolean control on participation
        set b-can-buy-supplies 0  ;; Boolean control on participation
        set b-can-eat 0           ;; Boolean control on participation
        set b-can-reproduce 0     ;; Boolean control on participation
        set b-can-die 0           ;; Boolean control on participation
        set b-can-die-of-hunger 0 ;; Boolean control on participation
        set b-can-die-of-age 0    ;; Boolean control on participation
        set b-can-die-of-lownrg 0 ;; Boolean control on participation
        set b-just-sprouted 0     ;; Boolean control to find new sprout
      ]

      ;; Reset agent-sets for all turtles in affected commuting area.
      ;; This resets lists for both daughters.
      ask frmrs-on com-area [ f-claim-my-frmrs-patch ]
      ask wrkrs-on com-area [ f-claim-my-wrkrs-patch ]
    ]
  ]
end 

;;-----------------------------------------------------------------------------|
;; Get a random value for age-to-reproduce

to-report fr-get-random-age-to-reproduce
  ;; This routine is to be executed by a wrkr or frmr.
  
  ;; Start with the Reproductive Age Threshold (g-RAT).
  let atr g-RAT 
  ;; Get a variance using the Gestation Time Threshold (g-GTT).
  set atr ( atr - ( g-GTT / 2 ) + ( random g-GTT ) )
  
  report atr
end 


;;-----------------------------------------------------------------------------|
;; D7 – death procedures( s )
;;-----------------------------------------------------------------------------|

to do-death
  ;; This routine is to be executed by the observer.
   
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "death" ) )
    [ 
      set gb-debug-flow-on 1 
      LOG-TO-FILE "" 
      LOG-TO-FILE word "Do-Death: Debug on; tick = " ticks 
      LOG-TO-FILE ( word "Control variables: g-DAT - " g-DAT 
                       "; g-DET " g-DET ) 
    ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-Die" g-aif

  ;; Check to see which agents are ready-to-die.
  ask turtles [ f-check-if-ready-to-die ]  ;; agent ready to die if starved, aged, or emaciated 
  
  ;; Isolate the agents that are ready to die into two agent sets.
  let dying-frmrs frmrs with [ b-can-die = 1 ]
  let dying-wrkrs wrkrs with [ b-can-die = 1 ]

  let b-at-least-one-agent-has-died 0
  let b-wrkr-has-died 0
  let b-frmr-has-died 0

  ;; Note the conserved assets of the dying frmrs.
  if( count dying-frmrs > 0 )
  [
    ;; Set flag for debug log dump.
    set b-at-least-one-agent-has-died 1
    set b-frmr-has-died 1
    
    ;; Cash is easy.
    set g-EMgr-cash g-EMgr-cash + sum [cash] of dying-frmrs

    ;; Now energy.
    set g-EMgr-energy g-EMgr-energy + sum [energy] of dying-frmrs
    set g-EMgr-energy g-EMgr-energy + sum [inventory] of dying-frmrs
    set g-EMgr-energy g-EMgr-energy + sum [supplies] of dying-frmrs
    
    ;; Now mass.
    set g-EMgr-mass g-EMgr-mass + sum [recycled] of dying-frmrs
    set g-EMgr-mass g-EMgr-mass + sum [inventory] of dying-frmrs
    set g-EMgr-mass g-EMgr-mass + sum [supplies] of dying-frmrs
    set g-EMgr-mass g-EMgr-mass + sum [waste] of dying-frmrs
  ]

  ;; Note the conserved assets of the dying wrkrs.
  if( count dying-wrkrs > 0 )
  [
    ;; Set flag for debug log dump.
    set b-at-least-one-agent-has-died 1
    set b-wrkr-has-died 1
   
    ;; Cash is easy.
    set g-EMgr-cash g-EMgr-cash + sum [cash] of dying-wrkrs
    ;; ASSERT ( frb-EMgr-is-valid ) ( "EMgr validity check: D-Setup" ) -1

    ;; Now energy.
    set g-EMgr-energy g-EMgr-energy + sum [energy] of dying-wrkrs
    set g-EMgr-energy g-EMgr-energy + sum [supplies] of dying-wrkrs
    ;; ASSERT ( frb-EMgr-is-valid ) ( "EMgr validity check: D-Setup" ) -1
    
    ;; Now mass.
    set g-EMgr-mass g-EMgr-mass + sum [supplies] of dying-wrkrs
    set g-EMgr-mass g-EMgr-mass + sum [waste] of dying-wrkrs
    ;; ASSERT ( frb-EMgr-is-valid ) ( "EMgr validity check: D-Setup" ) -1
  ]
  
  ;; All of the rest need be done only if someone has died.
  if( b-at-least-one-agent-has-died = 1 )
  [
    ;; Isolate the patches affected by the deaths into two agent sets.
    let patches-of-dying-frmrs patch-set [ my-patch ] of dying-frmrs 
    let patches-of-dying-wrkrs patch-set [ my-patch ] of dying-wrkrs
    
    if( b-wrkr-has-died = 1 )
    [
      LOG-TO-FILE word "Do-Die: Count dying-wrkrs: " count dying-wrkrs 
      LOG-TO-FILE word "Do-Die: Who #s of dying-wrkrs: " [who] of dying-wrkrs 
      LOG-TO-FILE word "Do-Die: Count patches-of-dying-wrkrs: " count patches-of-dying-wrkrs
    ]
    if( b-frmr-has-died = 1 )
    [
      LOG-TO-FILE word "Do-Die: Count dying-frmrs: " count dying-frmrs 
      LOG-TO-FILE word "Do-Die: Who #s of dying-frmrs: " [who] of dying-frmrs 
      LOG-TO-FILE word "Do-Die: Count patches-of-dying-frmrs: " count patches-of-dying-frmrs
    ]
    
    ;; Take reading of agent-in-focus before killing agents.
    LOG-DUMP-AIF "Do-Die" g-aif

    ;; Kill the agents.
    ask dying-frmrs 
    [
      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-F 
        ( list "Die" who 0 age cash energy recycled inventory supplies waste HRL HIL HSL )
        f-write-dpx-data-F
      ]
     
      let temp-aif g-aif
      set g-aif who
      LOG-DUMP-AIF "Do-die" g-aif
      set g-aif temp-aif
      die
    ]

    ask dying-wrkrs 
    [
      ;; Process DPX data collection option
      if( gb-dpx-on = 1 )
      [
        set gl-dpx-record-layout-D 
        ( list "Die" who 0 age cash energy supplies waste HSL )
        f-write-dpx-data-D
      ]
     
      let temp-aif g-aif
      set g-aif who
      LOG-DUMP-AIF "Do-die" g-aif
      set g-aif temp-aif
      die
    ]
    
    ;; Adjust the patch-related data.
    ask patches-of-dying-frmrs [ set p-no-of-frmrs ( count frmrs-on self ) ]
    ask patches-of-dying-wrkrs [ set p-no-of-wrkrs ( count wrkrs-on self ) ]
    ;; Reset agent-sets for all turtles in affected patch-sets.
    ask frmrs-on patches-of-dying-frmrs [ f-claim-my-frmrs-patch ]
    ask wrkrs-on patches-of-dying-frmrs [ f-claim-my-wrkrs-patch ]
    ask frmrs-on patches-of-dying-wrkrs [ f-claim-my-frmrs-patch ]
    ask wrkrs-on patches-of-dying-wrkrs [ f-claim-my-wrkrs-patch ]
    
    ;; Supressed. f-update-aggregates
  ]

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-Die" g-aif

  LOG-TO-FILE "Do-Die: procedure completed."
end 

;;-----------------------------------------------------------------------------|
;; F-check-if-ready-to-die 

to f-check-if-ready-to-die
  ;; Frmrs and wrkrs execute this routine – self is a frmr or wrkr.

  if( b-can-die-of-hunger = 1 ) [ set b-can-die 1 ]
  if( age >= g-DAT ) [ set b-can-die-of-age 1 set b-can-die 1 ]
  if( energy <= g-DET ) [ set b-can-die-of-lownrg 1 set b-can-die 1 ]
end 

;;-----------------------------------------------------------------------------|
;; D8 - f-post-tick procedure(s)
;;-----------------------------------------------------------------------------|

to do-post-tick
  ;; This routine is to be executed by the observer.
   
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "post-tick" ) )
    [ set gb-debug-flow-on 1  LOG-TO-FILE "" LOG-TO-FILE word "Do-Post-tick: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Take reading of agent-in-focus at start of routine.
  LOG-DUMP-AIF "Do-Pos" g-aif

  ;; MANUAL CHANGE FOR DEBUG.
  ;; This is a call to a debug routine which could be suppressed if all is okay.
  ;; This is one of a group of such calls, most of which are between steps in 
  ;;   the 'Go' routine.  They are suppressed there, but can be enabled again.
  ;; I have decided to leave this one active, for now.
  ;; It checks all agents, every tick, to ensure that all values are greater than
  ;;   or equal to zero.  
  if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test." ) ]
  
  ;; Enter all commands that need to be done after a tick is completed.
  ask turtles [ set age ( age + 1 ) ]
  
  ;; Write "Data Per Tick" (dpt) macro data to CSV file, if it is turned on.
  DPT-DUMP
  ;; Write "Data Per Generation" (dpg) micro data to CSV file, if it is turned on.
  DPG-DUMP
  
  ;; TODO remove this after bug in reproduction is fixed.
  ask patches
  [
    ;; This is a kludge.
    set p-no-of-frmrs ( count frmrs-on self )
    set p-no-of-wrkrs ( count wrkrs-on self )
  ]
  
  ;; Update the aggregates for display in the monitors.
  f-update-aggregates
  ;; This call requires f-update-aggregates to be completed.
  ;; This call also requires that 'reset-ticks' be called first.
  f-update-entropy-graph
  display

  ;; Take reading of agent-in-focus at end of routine.
  LOG-DUMP-AIF "Do-Pos" g-aif

  LOG-TO-FILE "Do-Pos: procedure completed."
end 

;;-----------------------------------------------------------------------------|
;; SECTION E – DRAWING AND MAINTENANCE PROCEDURE(S)
;;-----------------------------------------------------------------------------|



;;-----------------------------------------------------------------------------|
;; Update the values of global aggregate numbers.

to f-update-aggregates
  ;; This routine is to be executed by the observer.

  ;; Although this is an display-only routine, it implicitly calls the PRNG and
  ;;   so does have an effect on the trajectory of the model.  In a standard 'go'
  ;;   run it is called only once per tick, before graphs are updated.  If you
  ;;   use the one-step debug buttons, it is called once after each step, so
  ;;   debug runs that use those buttons will not replicate a real run.
  
  ;;Ensure the net values and real values are all set properly.
  let temp 0
  ask wrkrs
  [
    set temp fr-get-wrkr-net-value
    set temp fr-get-wrkr-real-value
  ]
  ask frmrs
  [
    set temp fr-get-frmr-net-value
    set temp fr-get-frmr-real-value
  ]
  
  ;; Totals:
  ;; Cash is easy.
  set g-total-cash sum [cash] of turtles
  set g-total-cash ( g-total-cash + g-EMgr-cash )
  set g-total-cash ( g-total-cash + g-MMgr-cash )
    
  ;; Mass.
  set g-total-mass sum [recycled] of frmrs
  set g-total-mass ( g-total-mass + ( sum [inventory] of frmrs ) )
  set g-total-mass ( g-total-mass + ( sum [supplies]  of frmrs ) )
  set g-total-mass ( g-total-mass + ( sum [supplies]  of wrkrs ) )
  set g-total-mass ( g-total-mass + ( sum [waste]     of frmrs ) )
  set g-total-mass ( g-total-mass + ( sum [waste]     of wrkrs ) )
  set g-total-mass ( g-total-mass + g-EMgr-mass )
  set g-total-mass ( g-total-mass + g-MMgr-mass )
    
  ;; Energy.
  set g-total-energy sum [energy] of frmrs
  set g-total-energy ( g-total-energy + ( sum [energy]    of wrkrs ) )
  set g-total-energy ( g-total-energy + ( sum [inventory] of frmrs ) )
  set g-total-energy ( g-total-energy + ( sum [supplies]  of turtles ) )
  set g-total-energy ( g-total-energy + g-EMgr-energy )
    
  ;; Frmrs:
  ;; Cash is easy.
  set g-frmr-cash sum [cash] of frmrs
    
  ;; Mass.
  set g-frmr-mass sum [recycled] of frmrs
  set g-frmr-mass ( g-frmr-mass + ( sum [inventory] of frmrs ) )
  set g-frmr-mass ( g-frmr-mass + ( sum [supplies]  of frmrs ) )
  set g-frmr-mass ( g-frmr-mass + ( sum [waste]     of frmrs ) )
    
  ;; Energy.
  set g-frmr-energy sum [energy] of frmrs
  set g-frmr-energy ( g-frmr-energy + ( sum [inventory] of frmrs ) )
  set g-frmr-energy ( g-frmr-energy + ( sum [supplies]  of frmrs ) )
    
  ;; wrkrs
  ;; cash is easy
  set g-wrkr-cash sum [cash] of wrkrs
    
  ;; Mass.
  set g-wrkr-mass sum [supplies] of wrkrs
  set g-wrkr-mass ( g-wrkr-mass + ( sum [waste] of wrkrs ) )
    
  ;; Energy.
  set g-wrkr-energy sum [energy] of wrkrs
  set g-wrkr-energy ( g-wrkr-energy + ( sum [supplies] of wrkrs ) )
    
  ;; Number of agents.
  set g-no-of-wrkrs count wrkrs
  set g-no-of-frmrs count frmrs
  set g-no-of-agents ( g-no-of-wrkrs + g-no-of-frmrs )
    
  ;; Asset classes:
  set g-frmr-cash-class       ( sum [cash]      of frmrs )  ;; frmr cash class
  set g-frmr-recycled-class   ( sum [recycled]  of frmrs )  ;; frmr recycled class
  set g-frmr-energy-class     ( sum [energy]    of frmrs )  ;; frmr energy class
  set g-frmr-inventory-class  ( sum [inventory] of frmrs )  ;; frmr inventory class
  set g-frmr-supplies-class   ( sum [supplies]  of frmrs )  ;; frmr supplies class
  set g-frmr-waste-class      ( sum [waste]     of frmrs )  ;; frmr waste class
    
  set g-wrkr-cash-class       ( sum [cash]      of wrkrs )  ;; wrkr cash class
  set g-wrkr-energy-class     ( sum [energy]    of wrkrs )  ;; wrkr energy class
  set g-wrkr-supplies-class   ( sum [supplies]  of wrkrs )  ;; wrkr supplies class
  set g-wrkr-waste-class      ( sum [waste]     of wrkrs )  ;; wrkr waste class
    
  set g-total-cash-class      ( g-wrkr-cash-class +     g-frmr-cash-class )      ;; total cash class
  set g-total-recycled-class  (                         g-frmr-recycled-class )  ;; total recycled class
  set g-total-energy-class    ( g-wrkr-energy-class +   g-frmr-energy-class )    ;; total energy class
  set g-total-inventory-class (                         g-frmr-inventory-class ) ;; total inventory class
  set g-total-supplies-class  ( g-wrkr-supplies-class + g-frmr-supplies-class )  ;; total supplies class
  set g-total-waste-class     ( g-frmr-waste-class +    g-frmr-waste-class )     ;; total waste class

;;-----------------------------------------------------------------------------|
  ;; To ensure that the PRNG is called whether or not plots are displayed, the
  ;;   calculations needed for the histogram plots are carried out here where
  ;;   they will happen every tick.

;;-----------------------------------------------------------------------------|
  ;; Setup for Plot "Sector Sizes"
    ;; A sector-size is the total value, in dollars, of the assets of a breed.
    
    ;; Wrkrs.
    set g-wrkr-sector-size 0
    set g-wrkr-sector-size ( g-wrkr-sector-size + ( g-wrkr-cash ) )
    set g-wrkr-sector-size ( g-wrkr-sector-size + ( g-wrkr-mass * g-mu-price ) )
    set g-wrkr-sector-size ( g-wrkr-sector-size + ( g-wrkr-energy * g-mu-price ) )
    
    ;; Frmrs.
    set g-frmr-sector-size 0
    set g-frmr-sector-size ( g-frmr-sector-size + ( g-frmr-cash ) )
    set g-frmr-sector-size ( g-frmr-sector-size + ( g-frmr-mass * g-mu-price ) )
    set g-frmr-sector-size ( g-frmr-sector-size + ( g-frmr-energy * g-eu-price ) )
    
    ;; MMgr.
    set g-mmgr-sector-size 0
    set g-mmgr-sector-size ( g-mmgr-sector-size + ( g-MMgr-cash ) )
    set g-mmgr-sector-size ( g-mmgr-sector-size + ( g-MMgr-mass * g-mu-price ) )
    
    ;; EMgr.
    set g-emgr-sector-size 0
    set g-emgr-sector-size ( g-emgr-sector-size + ( g-EMgr-cash ) )
    set g-emgr-sector-size ( g-emgr-sector-size + ( g-EMgr-mass * g-mu-price ) )
    set g-emgr-sector-size ( g-emgr-sector-size + ( g-EMgr-energy * g-eu-price ) )
  
;;-----------------------------------------------------------------------------|
  ;; Setup for Plot "Wealth Distribution - wrkrs"
    ;; get the min and max x values
    set g-min-wrkr-wealth 0
    set g-max-wrkr-wealth 0
    let wrkr-with-min-wealth ( min-one-of wrkrs [ net-value ] )
    if wrkr-with-min-wealth != nobody
    [
      ask wrkr-with-min-wealth [ set g-min-wrkr-wealth net-value ]
      let wrkr-with-max-wealth ( max-one-of wrkrs [ net-value ] )
      if wrkr-with-max-wealth != nobody
      [
        ask wrkr-with-max-wealth [ set g-max-wrkr-wealth ( net-value + 1 ) ]
      ]
    ]
    if( g-max-wrkr-wealth <= g-min-wrkr-wealth ) 
      [ set g-max-wrkr-wealth ( g-min-wrkr-wealth + 1 ) ]
    set g-max-wrkr-count ( count wrkrs )
    if( g-max-wrkr-count <= 0 ) [ set g-max-wrkr-count 1 ]
  
;;-----------------------------------------------------------------------------|
  ;; Setup for Plot "Wealth Distribution - frmrs"
    ;; get the min and max x values
    set g-min-frmr-wealth 0
    set g-max-frmr-wealth 0
    let frmr-with-min-wealth ( min-one-of frmrs [ net-value ] )
    if frmr-with-min-wealth != nobody
    [
      ask frmr-with-min-wealth [ set g-min-frmr-wealth net-value ]
      let frmr-with-max-wealth ( max-one-of frmrs [ net-value ] )
      if frmr-with-max-wealth != nobody
      [
        ask frmr-with-max-wealth [ set g-max-frmr-wealth ( net-value + 1 ) ]
      ]
    ]
    if( g-max-frmr-wealth <= g-min-frmr-wealth ) 
      [ set g-max-frmr-wealth ( g-min-frmr-wealth + 1 ) ]
    set g-max-frmr-count ( count frmrs )
    if( g-max-frmr-count <= 0 ) [ set g-max-frmr-count 1 ]
  
;;-----------------------------------------------------------------------------|
  ;; Setup for Plot "Age Distribution - wrkrs"
    ;; get the min and max x values
    set g-min-wrkr-age 0
    set g-max-wrkr-age 0
    let wrkr-with-min-age ( min-one-of wrkrs [ age ] )
    if wrkr-with-min-age != nobody
    [
      ask wrkr-with-min-age [ set g-min-wrkr-age age ]
      let wrkr-with-max-age ( max-one-of wrkrs [ age ] )
      if wrkr-with-max-age != nobody
      [
        ask wrkr-with-max-age [ set g-max-wrkr-age ( age + 1 ) ]
      ]
    ]
    if( g-max-wrkr-age <= g-min-wrkr-age ) 
      [ set g-max-wrkr-age ( g-min-wrkr-age + 1 ) ]
    set g-max-wrkr-count ( count wrkrs )
    if( g-max-wrkr-count <= 0 ) [ set g-max-wrkr-count 1 ]
  
;;-----------------------------------------------------------------------------|
  ;; Setup for Plot "Age Distribution - frmrs"
    ;; get the min and max x values
    set g-min-frmr-age 0
    set g-max-frmr-age 0
    let frmr-with-min-age ( min-one-of frmrs [ age ] )
    if frmr-with-min-age != nobody
    [
      ask frmr-with-min-age [ set g-min-frmr-age age ]
      let frmr-with-max-age ( max-one-of frmrs [ age ] )
      if frmr-with-max-age != nobody
      [
        ask frmr-with-max-age [ set g-max-frmr-age ( age + 1 ) ]
      ]
    ]
    if( g-max-frmr-age <= g-min-frmr-age ) 
      [ set g-max-frmr-age ( g-min-frmr-age + 1 ) ]
    set g-max-frmr-count ( count frmrs )
    if( g-max-frmr-count <= 0 ) [ set g-max-frmr-count 1 ]
  
  ;; This log entry may come from any step during debug operations.  
  LOG-TO-FILE "Do-xxx: All aggregates updated."  
end 

;;--------------------------
;; DATA CAPTURE TO CSV FILES
;;--------------------------
  
;;-----------------------------------------------------------------------------|
;; Open a dpx file.

to f-open-dpx-file
  ;; This routine is to be executed by the observer.
  
  ;; DPX stands for 'Data Per Xaction'
  ;; Ensure previous dpx file is closed.
  f-close-dpx-file
  
  set gb-dpx-on 1
  set gs-dpx-status "1 (On)"
  set gs-dpx-file-name ( fr-construct-file-name "dpx" )
  set g-dpx-recno 0
  
  file-open gs-dpx-file-name
  
  ;; Write the mast head for the file.
  file-show "Data Per Transaction (DPX) File for a ModEco (NetLogo) Model."
  file-show word "File Name: " gs-dpx-file-name
  file-show ( word "Application Version Number: "gs-Version )
  file-show ""
    
  ifelse ( file-exists? gs-dpx-file-name )
  [
    ;; Send a message directly to the command centre.
    show word gs-dpx-file-name " opened."

    ;; Write the system parameter settings to the file.
    f-write-system-settings
    
    f-write-dpx-headers
  ]
  ;; else
  [
    ;; Send a message directly to the command centre.
    show word gs-dpx-file-name " not opened."
  
    set gb-dpx-on 0
    set gs-dpx-status "0 (Off)"
    set gs-dpx-file-name "DpxDummyName"
  ]
end 

;;-----------------------------------------------------------------------------|
;; Write header recordS to the dpx data file.

to f-write-dpx-headers
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a header record for commercial transactions (RECORD TYPE B). 
  let line-out "DPX-A, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out "X-Action, " )

  set line-out ( word line-out "Seller, " )
  set line-out ( word line-out "Buyer, " )
  set line-out ( word line-out "Amount, " )
  set line-out ( word line-out "Value ($) " )

  file-print line-out
  
  ;; Write a header record for wrkr biophysical actions (RECORD TYPE D). 
  set line-out "DPX-C, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out "X-Action, " )

  set line-out ( word line-out "Actor, " )
  set line-out ( word line-out "Amount, " )
  set line-out ( word line-out "Cash, " )
  set line-out ( word line-out "Energy, " )
  set line-out ( word line-out "Supplies, " )
  set line-out ( word line-out "Waste, " )
  set line-out ( word line-out "Hold Supplies Limit " )

  file-print line-out
  
  ;; Write a header record for frmr biophysical actions (RECORD TYPE F). 
  set line-out "DPX-E, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out "X-Action, " )

  set line-out ( word line-out "Actor, " )
  set line-out ( word line-out "Amount, " )
  set line-out ( word line-out "Cash, " )
  set line-out ( word line-out "Energy, " )
  set line-out ( word line-out "Recycled, " )
  set line-out ( word line-out "Inventory, " )
  set line-out ( word line-out "Supplies, " )
  set line-out ( word line-out "Waste, " )
  set line-out ( word line-out "Hold Recycled Limit, " )
  set line-out ( word line-out "Hold Inventory Limit, " )
  set line-out ( word line-out "Hold Supplies Limit " )

  file-print line-out

  ;; Write a header record for grants (RECORD TYPE H).
  set line-out "DPX-G, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out "Event type, " )

  set line-out ( word line-out "Actor, " )
  set line-out ( word line-out "Actor type, " )
  set line-out ( word line-out "Grant type, " )
  set line-out ( word line-out "Amount " )
 
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write the data record type B (commercial transaction) for the dpx data file.

to f-write-dpx-data-B 
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a data record for X-Action. 
  set g-dpx-recno ( g-dpx-recno + 1 )
  ;; Record type
  let line-out "DPX-B, "
  ;; Record number
  set line-out ( word line-out g-dpx-recno ", " )
  ;; Ticks
  set line-out ( word line-out ticks ", " )
  ;; Transaction type
  set line-out ( word line-out ( item 0 gl-dpx-record-layout-B ) ", " )
  ;; Seller
  set line-out ( word line-out ( item 1 gl-dpx-record-layout-B ) ", " )
  ;; Buyer
  set line-out ( word line-out ( item 2 gl-dpx-record-layout-B ) ", " )
  ;; Amount sold
  set line-out ( word line-out ( item 3 gl-dpx-record-layout-B ) ", " )
  ;; Extended price
  set line-out ( word line-out ( item 4 gl-dpx-record-layout-B ) )

  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write the data record type D (wrkr biophysical action) for the dpx data file.

to f-write-dpx-data-D 
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a data record for X-Action. 
  set g-dpx-recno ( g-dpx-recno + 1 )
  ;; Record type
  let line-out "DPX-D, "
  ;; Record number
  set line-out ( word line-out g-dpx-recno ", " )
  ;; Ticks
  set line-out ( word line-out ticks ", " )
  ;; Action type
  set line-out ( word line-out ( item 0 gl-dpx-record-layout-D ) ", " )
  ;; Actor
  set line-out ( word line-out ( item 1 gl-dpx-record-layout-D ) ", " )
  ;; Amount (for "Eat"; 0 for birth and death)
  set line-out ( word line-out ( item 2 gl-dpx-record-layout-D ) ", " )
  ;; Cash
  set line-out ( word line-out ( item 3 gl-dpx-record-layout-D ) ", " )
  ;; Energy
  set line-out ( word line-out ( item 4 gl-dpx-record-layout-D ) ", " )
  ;; Supplies
  set line-out ( word line-out ( item 5 gl-dpx-record-layout-D ) ", " )
  ;; Waste
  set line-out ( word line-out ( item 6 gl-dpx-record-layout-D ) ", " )
  ;; HSL
  set line-out ( word line-out ( item 7 gl-dpx-record-layout-D ) )

  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write the data record type F (frmr biophysical action) for the dpx data file.

to f-write-dpx-data-F 
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a data record for X-Action. 
  set g-dpx-recno ( g-dpx-recno + 1 )
  ;; Record type
  let line-out "DPX-F, "
  ;; Record number
  set line-out ( word line-out g-dpx-recno ", " )
  ;; Ticks
  set line-out ( word line-out ticks ", " )
  ;; Action type
  set line-out ( word line-out ( item 0 gl-dpx-record-layout-F ) ", " )
  ;; Actor
  set line-out ( word line-out ( item 1 gl-dpx-record-layout-F ) ", " )
  ;; Amount (for "Eat"; 0 for birth and death)
  set line-out ( word line-out ( item 2 gl-dpx-record-layout-F ) ", " )
  ;; Cash
  set line-out ( word line-out ( item 3 gl-dpx-record-layout-F ) ", " )
  ;; Energy
  set line-out ( word line-out ( item 4 gl-dpx-record-layout-F ) ", " )
  ;; Recycled
  set line-out ( word line-out ( item 5 gl-dpx-record-layout-F ) ", " )
  ;; Inventory
  set line-out ( word line-out ( item 6 gl-dpx-record-layout-F ) ", " )
  ;; Supplies
  set line-out ( word line-out ( item 7 gl-dpx-record-layout-F ) ", " )
  ;; Waste
  set line-out ( word line-out ( item 8 gl-dpx-record-layout-F ) ", " )
  ;; HRL
  set line-out ( word line-out ( item 9 gl-dpx-record-layout-F ) ", " )
  ;; HIL
  set line-out ( word line-out ( item 10 gl-dpx-record-layout-F ) ", " )
  ;; HSL
  set line-out ( word line-out ( item 11 gl-dpx-record-layout-F ) )

  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write the data record type F (frmr biophysical action) for the dpx data file.

to f-write-dpx-data-H 
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a data record for X-Action. 
  set g-dpx-recno ( g-dpx-recno + 1 )
  ;; Record type
  let line-out "DPX-H, "
  ;; Record number
  set line-out ( word line-out g-dpx-recno ", " )
  ;; Ticks
  set line-out ( word line-out ticks ", " )
  ;; Action type
  set line-out ( word line-out ( item 0 gl-dpx-record-layout-H ) ", " )
  ;; Actor 
  set line-out ( word line-out ( item 1 gl-dpx-record-layout-H ) ", " )
  ;; Agent type
  set line-out ( word line-out ( item 2 gl-dpx-record-layout-H ) ", " )
  ;; Grant type
  set line-out ( word line-out ( item 3 gl-dpx-record-layout-H ) ", " )
  ;; Amount 
  set line-out ( word line-out ( item 4 gl-dpx-record-layout-H ) )

  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Close the dpx file.

to f-close-dpx-file
  ;; This routine is to be executed by the observer.
  
  ;; DPX stands for 'Data Per Xaction'
  if ( Is-string? gs-dpx-file-name )
  [
    if ( file-exists? gs-dpx-file-name )
    [
      ;; Select the file
      file-open gs-dpx-file-name
      ;; Close it.
      file-close
    ]
  ]
  set gb-dpx-on 0
  set gs-dpx-status "0 (Off)"
  set gs-dpx-file-name "DpxDummyName"
  set g-dpx-recno 0
end 

;;-----------------------------------------------------------------------------|
;; Close and reopen the dpx file, it is too full.

to f-reopen-dpx-file
  ;; This routine is to be executed by the observer.
  
  f-close-dpx-file
  f-open-dpx-file
end 

;;-----------------------------------------------------------------------------|
;; Write a pair of records for the system settings.

to f-write-system-settings
  ;; This routine is to be executed by the observer.

  ;; A file must already be selected.
  ;; These system setting records are meant to be writtin right after the
  ;;   mast head lines.
  
  ;; Write a header record for system parameters.  
  let line-out "SYS-A, "
  set line-out ( word line-out "Scenario, " )
  set line-out ( word line-out "PRNG-Seed, " )
  
  set line-out ( word line-out "g-DAT (ticks), " )
  set line-out ( word line-out "g-DET (eu), " )
  set line-out ( word line-out "g-RAT (ticks), " )
  set line-out ( word line-out "g-GTT (ticks), " )
  set line-out ( word line-out "g-RET (eu), " )
  set line-out ( word line-out "g-EPT (meu), " )
  
  set line-out ( word line-out "g-HRF-f, " )
  set line-out ( word line-out "g-HIF-f, " )
  set line-out ( word line-out "g-HSF-f, " )
  set line-out ( word line-out "g-HSF-w, " )
  
  set line-out ( word line-out "g-HRL-f-min (mu), " )
  set line-out ( word line-out "g-HIL-f-min (meu), " )
  set line-out ( word line-out "g-HSL-f-min (meu), " )
  set line-out ( word line-out "g-HSL-w-min (meu), " )
  
  set line-out ( word line-out "g-no-of-rents-max (#), " )
  set line-out ( word line-out "g-no-of-hires-max (#), " )
  set line-out ( word line-out "g-no-of-waste-xactions-max (#), " )
  
  set line-out ( word line-out "g-waste-sales-quota (mu), " )
  set line-out ( word line-out "g-recycled-purchase-quota (mu), " )
  set line-out ( word line-out "g-harvest-quota (meu), " )
  set line-out ( word line-out "g-supplies-purchase-quota (meu), " )
  
  set line-out ( word line-out "g-mu-price ($), " )
  set line-out ( word line-out "g-eu-price ($), " )
  set line-out ( word line-out "g-meu-price ($), " )
  
  set line-out ( word line-out "gb-MMgr (0/1), " )
  set line-out ( word line-out "gb-MMgr-debt (0/1), " )
  
  set line-out ( word line-out "g-MMgr-cash-at-setup ($), " )
  set line-out ( word line-out "g-MMgr-mass-at-setup (mu), " )
  
  set line-out ( word line-out "gb-EMgr (0/1), " )
  set line-out ( word line-out "g-EMgr-cash-at-setup ($), " )
  set line-out ( word line-out "g-EMgr-mass-at-setup (mu), " )
  set line-out ( word line-out "g-EMgr-energy-at-setup (eu) " )

  file-print line-out
  
  ;; Write a data record for system parameters.  
  set line-out "SYS-B, "
  set line-out ( word line-out gs-scenario ", " )
  set line-out ( word line-out g-use-this-seed ", " )
  
  set line-out ( word line-out g-DAT ", " )
  set line-out ( word line-out g-DET ", " )
  set line-out ( word line-out g-RAT ", " )
  set line-out ( word line-out g-GTT ", " )
  set line-out ( word line-out g-RET ", " )
  set line-out ( word line-out g-EPT ", " )
  
  set line-out ( word line-out g-HRF-f ", " )
  set line-out ( word line-out g-HIF-f ", " )
  set line-out ( word line-out g-HSF-f ", " )
  set line-out ( word line-out g-HSF-w ", " )
   
  set line-out ( word line-out g-HRL-f-min ", " )
  set line-out ( word line-out g-HIL-f-min ", " )
  set line-out ( word line-out g-HSL-f-min ", " )
  set line-out ( word line-out g-HSL-w-min ", " )
  
  set line-out ( word line-out g-no-of-rents-max ", " )
  set line-out ( word line-out g-no-of-hires-max ", " )
  set line-out ( word line-out g-no-of-waste-xactions-max ", " )
  
  set line-out ( word line-out g-waste-sales-quota ", " )
  set line-out ( word line-out g-recycled-purchase-quota ", " )
  set line-out ( word line-out g-harvest-quota ", " )
  set line-out ( word line-out g-supplies-purchase-quota ", " )
  
  set line-out ( word line-out g-mu-price ", " )
  set line-out ( word line-out g-eu-price ", " )
  set line-out ( word line-out g-meu-price ", " )
  
  set line-out ( word line-out gb-MMgr ", " )
  set line-out ( word line-out gb-MMgr-debt ", " )  
  set line-out ( word line-out g-MMgr-cash-at-setup ", " )
  set line-out ( word line-out g-MMgr-mass-at-setup ", " )
  
  set line-out ( word line-out gb-EMgr ", " )
  set line-out ( word line-out g-EMgr-cash-at-setup ", " )
  set line-out ( word line-out g-EMgr-mass-at-setup ", " )
  set line-out ( word line-out g-EMgr-energy-at-setup " " )

  file-print line-out
  
  ;; Now, write instructions on how to process the data.
  set line-out ( word "INSTRUCTIONS:" )
  file-print line-out
  set line-out ( word " - Copy the above rows of meta-data to a fresh sheet." )
  file-print line-out
  set line-out ( word " - Then delete the rows of meta-data and instructions." )
  file-print line-out
  set line-out ( word " - Then sort all columns and all rows of headers and data using Column A as sort key." )
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Dump "Data Per Tick" data to dpt file, if open.

to DPT-DUMP
  ;; This routine is to be executed by the observer.

  ;; Activate only if the dpt file is open and ready to receive data.
  if( gb-dpt-on = 1 )
  [
    ;; If the file is full, close it.  MS Excel can handle 1,048,000 records.
    ;; Terminate the file at 1,000,000 records.
    ifelse( g-dpt-recno > g-recno-max ) [ f-reopen-dpt-file ]
    [
      ;; Activate once per tick.  Take a reading.
      ;; This collects macro-economic data of various kinds.
      f-write-dpt-macro-data 
    ]
  ]
end 

;;-----------------------------------------------------------------------------|
;; Open a dpt file.

to f-open-dpt-file
  ;; This routine is to be executed by the observer.
  
  ;; DPT stands for 'Data Per Tick'
  ;; Ensure previous dpt file is closed.
  f-close-dpt-file
  
  set gb-dpt-on 1
  set gs-dpt-status "1 (On)"
  set gs-dpt-file-name ( fr-construct-file-name "dpt" )
  set g-dpt-recno 0
  
  file-open gs-dpt-file-name
 
  ;; Write the mast head for the file.
  file-show "Data Per Transaction (dpt) File for a ModEco (NetLogo) Model."
  file-show ( word "Application Version Number: "gs-Version )
  file-show word "File opened at:" date-and-time
  file-show ""
    
  ifelse ( file-exists? gs-dpt-file-name )
  [
    ;; Send a message directly to the command centre.
    show word gs-dpt-file-name " opened."

    ;; Write the system parameter settings to the file.
    f-write-system-settings
    
    ;; Write header records to the file.
    f-write-dpt-headers
  ]
  ;; else
  [
    ;; Send a message directly to the command centre.
    show word gs-dpt-file-name " not opened."
  
    set gb-dpt-on 0
    set gs-dpt-status "0 (Off)"
    set gs-dpt-file-name "DptDummyName"
  ]
end 

;;-----------------------------------------------------------------------------|
;; Write the header records for the dpt data file.

to f-write-dpt-headers
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a header record for aggregates by materiel type. 
  let line-out "DPT-A, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  
  set line-out ( word line-out "T-Agents (#), " )
  set line-out ( word line-out "T-Wrkrs (#), " )
  set line-out ( word line-out "T-Frmrs (#), " )
  set line-out ( word line-out "T-Cash ($), " )
  set line-out ( word line-out "T-Mass (mu), " )
  set line-out ( word line-out "T-Energy (eu), " )
  
  set line-out ( word line-out "W-Cash ($), " )
  set line-out ( word line-out "W-Mass (mu), " )
  set line-out ( word line-out "W-Energy (eu), " )
  
  set line-out ( word line-out "F-Cash ($), " )
  set line-out ( word line-out "F-Mass (mu), " )
  set line-out ( word line-out "F-Energy (eu), " )
  
  set line-out ( word line-out "M-Cash ($), " )
  set line-out ( word line-out "M-Mass (mu), " )
  
  set line-out ( word line-out "E-Cash ($), " )
  set line-out ( word line-out "E-Mass (mu), " )
  set line-out ( word line-out "E-Energy (eu)" )

  file-print line-out
  
  ;; Write a header record for aggregates by stock type.
  set line-out "DPG-C, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  
  set line-out ( word line-out "T-Cash ($), " )
  set line-out ( word line-out "T-Energy (eu), " )
  set line-out ( word line-out "T-Recycled (mu), " )
  set line-out ( word line-out "T-Inventory (meu), " )
  set line-out ( word line-out "T-Supplies (meu), " )
  set line-out ( word line-out "T-Waste (mu), " )
  
  set line-out ( word line-out "W-Cash ($), " )
  set line-out ( word line-out "W-Energy (eu), " )
  set line-out ( word line-out "W-Supplies (meu), " )
  set line-out ( word line-out "W-Waste (mu), " )
  
  set line-out ( word line-out "F-Cash ($), " )
  set line-out ( word line-out "F-Energy (eu), " )
  set line-out ( word line-out "F-Recycled (mu), " )
  set line-out ( word line-out "F-Inventory (meu), " )
  set line-out ( word line-out "F-Supplies (meu), " )
  set line-out ( word line-out "F-Waste (mu), " )
  
  set line-out ( word line-out "M-Cash ($), " )
  set line-out ( word line-out "M-Mass (mu), " )
  
  set line-out ( word line-out "E-Cash ($), " )
  set line-out ( word line-out "E-Mass (mu), " )
  set line-out ( word line-out "E-Energy (eu)" )
  
  file-print line-out

  ;; Write a header record for aggregates by flow type.
  set line-out "DPG-E, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  
  set line-out ( word line-out "T-Labour (#), " )
  set line-out ( word line-out "T-Hires (#), " )
  
  set line-out ( word line-out "T-Recycled ($), " )
  set line-out ( word line-out "T-Labour ($), " )
  set line-out ( word line-out "T-Food ($), " )
  set line-out ( word line-out "T-Waste ($) " )
  
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write the data records for the dpt data file.

to f-write-dpt-macro-data
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a data record for aggregates by materiel type. 
  set g-dpt-recno ( g-dpt-recno + 1 )
  let line-out "DPT-B, "
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  set line-out ( word line-out g-no-of-agents ", " )
  set line-out ( word line-out g-no-of-wrkrs ", " )
  set line-out ( word line-out g-no-of-frmrs ", " )
  set line-out ( word line-out g-total-cash ", " )
  set line-out ( word line-out g-total-mass ", " )
  set line-out ( word line-out g-total-energy ", " )
  
  set line-out ( word line-out g-wrkr-cash ", " )
  set line-out ( word line-out g-wrkr-mass ", " )
  set line-out ( word line-out g-wrkr-energy ", " )
  
  set line-out ( word line-out g-frmr-cash ", " )
  set line-out ( word line-out g-frmr-mass ", " )
  set line-out ( word line-out g-frmr-energy ", " )
  
  set line-out ( word line-out g-MMgr-cash ", " )
  set line-out ( word line-out g-MMgr-mass ", " )
  
  set line-out ( word line-out g-EMgr-cash ", " )
  set line-out ( word line-out g-EMgr-mass ", " )
  set line-out ( word line-out g-EMgr-energy " " )

  file-print line-out
  
  ;; Write a header record for aggregates by stock type.
  set g-dpt-recno ( g-dpt-recno + 1 )
  set line-out "DPG-D, "
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  set line-out ( word line-out g-total-cash-class ", " )
  set line-out ( word line-out g-total-energy-class ", " )
  set line-out ( word line-out g-total-recycled-class ", " )
  set line-out ( word line-out g-total-inventory-class ", " )
  set line-out ( word line-out g-total-supplies-class ", " )
  set line-out ( word line-out g-total-waste-class ", " )

  set line-out ( word line-out g-wrkr-cash-class ", " )
  set line-out ( word line-out g-wrkr-energy-class ", " )
  set line-out ( word line-out g-wrkr-supplies-class ", " )
  set line-out ( word line-out g-wrkr-waste-class ", " )
  
  set line-out ( word line-out g-frmr-cash-class ", " )
  set line-out ( word line-out g-frmr-energy-class ", " )
  set line-out ( word line-out g-frmr-recycled-class ", " )
  set line-out ( word line-out g-frmr-inventory-class ", " )
  set line-out ( word line-out g-frmr-supplies-class ", " )
  set line-out ( word line-out g-frmr-waste-class ", " )

  set line-out ( word line-out g-MMgr-cash ", " )
  set line-out ( word line-out g-MMgr-mass ", " )
  
  set line-out ( word line-out g-EMgr-cash ", " )
  set line-out ( word line-out g-EMgr-mass ", " )
  set line-out ( word line-out g-EMgr-energy " " )
  
  file-print line-out

  ;; Write a header record for aggregates by flow type.
  set g-dpt-recno ( g-dpt-recno + 1 )
  set line-out "DPG-F, "
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  set line-out ( word line-out g-no-of-agents ", " )
  set line-out ( word line-out g-no-of-hires-this-tick ", " )
  
  set line-out ( word line-out g-cash-spent-this-tick-recycled ", " )
  set line-out ( word line-out g-cash-spent-this-tick-labour ", " )
  set line-out ( word line-out g-cash-spent-this-tick-food ", " )
  set line-out ( word line-out g-cash-spent-this-tick-waste " " )
  
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Close the dpt file.

to f-close-dpt-file
  ;; This routine is to be executed by the observer.
  
  ;; DPT stands for 'Data Per Tick'
  if ( Is-string? gs-dpt-file-name )
  [
    if ( file-exists? gs-dpt-file-name )
    [
      ;; Select the file
      file-open gs-dpt-file-name
      ;; Close it.
      file-close
    ]
  ]
  set gb-dpt-on 0
  set gs-dpt-status "0 (Off)"
  set gs-dpt-file-name "DptDummyName"
  set g-dpt-recno 0
end 

;;-----------------------------------------------------------------------------|
;; Close and reopen the dpt file, it is too full.

to f-reopen-dpt-file
  ;; This routine is to be executed by the observer.
  
  f-close-dpt-file
  f-open-dpt-file
end 

;;-----------------------------------------------------------------------------|
;; Dump "Data Per Generation" data to dpg file, if open.

to DPG-DUMP
  ;; This routine is to be executed by the observer.

  ;; Activate only if the dpg file is open and ready to receive data.
  if( gb-dpg-on = 1 )
  [
    ;; If the file is full, close it.  MS Excel can handle 1,048,000 records.
    ;; Terminate the file at 1,000,000 records.
    ifelse( g-dpg-recno > g-recno-max ) [ f-reopen-dpg-file ]
    [
      ;; Activate once per generation (I.e. once per g-RAT ticks).
      ;; Take a base-line reading at the end of tick 1.
      ;; Test to see if ticks is a multiple of g-RAT.
      let test-ticks ( g-RAT * floor( ticks / g-RAT ) )
      if( ( ticks <= 1 ) or ( test-ticks = ticks ) )
      [
        ;; Take a reading for each agent.
        ask wrkrs [ f-write-dpg-wrkr-data ]
        ask frmrs [ f-write-dpg-frmr-data ]
      ]
    ]
  ]
end 

;;-----------------------------------------------------------------------------|
;; Open a dpg file.

to f-open-dpg-file
  ;; This routine is to be executed by the observer.
  
  ;; DPG stands for 'Data Per Generation'
  ;; Ensure previous dpg file is closed.
  f-close-dpg-file
  
  set gb-dpg-on 1
  set gs-dpg-status "1 (On)"
  set gs-dpg-file-name ( fr-construct-file-name "dpg" )
  set g-dpg-recno 0
  
  file-open gs-dpg-file-name
  
  ;; Write the mast head for the file.
  file-show "Data Per Transaction (dpg) File for a ModEco (NetLogo) Model."
  file-show ( word "Application Version Number: "gs-Version )
  file-show word "File opened at:" date-and-time
  file-show ""
    
  ifelse ( file-exists? gs-dpg-file-name )
  [
    ;; Send a message directly to the command centre.
    show word gs-dpg-file-name " opened."

    ;; Write the system parameter settings to the file.
    f-write-system-settings
    
    f-write-dpg-headers
  ]
  ;; else
  [
    ;; Send a message directly to the command centre.
    show word gs-dpg-file-name " not opened."
  
    set gb-dpg-on 0
    set gs-dpg-status "0 (Off)"
    set gs-dpg-file-name "DpgDummyName"
  ]
end 

;;-----------------------------------------------------------------------------|
;; Write the record headers for the dpg data file.

to f-write-dpg-headers
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpg-file-name
  
  ;; Write a header record for wrkrs.
  let line-out "DPG-A, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out "Who, " )
  set line-out ( word line-out "Xcor, " )
  set line-out ( word line-out "Ycor, " )
  set line-out ( word line-out "Age, " )
  set line-out ( word line-out "Age-To-Reproduce, " )
  set line-out ( word line-out "Cash, " )
  set line-out ( word line-out "Energy, " )
  set line-out ( word line-out "Supplies, " )
  set line-out ( word line-out "Waste, " )
  set line-out ( word line-out "Net-Value, " )
  set line-out ( word line-out "Real-Value, " )
  set line-out ( word line-out "Hold-Supplies-Limit (HSL), " )
  set line-out ( word line-out "Energy-Set-Point, " )
  set line-out ( word line-out "Available-Energy " )
  file-print line-out
  
  ;; Write a header record for frmrs.
  set line-out "DPG-C, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out "Who, " )
  set line-out ( word line-out "Xcor, " )
  set line-out ( word line-out "Ycor, " )
  set line-out ( word line-out "Age, " )
  set line-out ( word line-out "Age-To-Reproduce, " )
  set line-out ( word line-out "Cash, " )
  set line-out ( word line-out "Energy, " )
  set line-out ( word line-out "Recycled, " )
  set line-out ( word line-out "Inventory, " )
  set line-out ( word line-out "Supplies, " )
  set line-out ( word line-out "Waste, " )
  set line-out ( word line-out "Net-Value, " )
  set line-out ( word line-out "Real-Value, " )
  set line-out ( word line-out "Hold-Recycled-Limit (HRL), " )
  set line-out ( word line-out "Hold-Inventory-Limit (HIL), " )
  set line-out ( word line-out "Hold-Supplies-Limit (HSL), " )
  set line-out ( word line-out "Energy-Set-Point, " )
  set line-out ( word line-out "Available-Energy " )
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write a data record a wrkr into the dpg data file.

to f-write-dpg-wrkr-data
  ;; This routine is to be executed by a wrkr.

  ;; Select the file
  file-open gs-dpg-file-name
  
  set g-dpg-recno ( g-dpg-recno + 1 )
  
  ;; Write the data record.
  let line-out "DPG-B, "
  set line-out ( word line-out g-dpg-recno ", "  )
  set line-out ( word line-out ticks ", "  )
  set line-out ( word line-out who ", "  )
  set line-out ( word line-out Xcor ", "  )
  set line-out ( word line-out Ycor ", "  )
  set line-out ( word line-out age ", "  )
  set line-out ( word line-out age-to-reproduce ", "  )
  set line-out ( word line-out cash ", "  )
  set line-out ( word line-out energy ", "  )
  set line-out ( word line-out supplies ", "  )
  set line-out ( word line-out waste ", "  )
  set line-out ( word line-out net-value ", "  )
  set line-out ( word line-out real-value ", "  )
  set line-out ( word line-out HSL ", "  )
  set line-out ( word line-out energy-set-point ", "  )
  set line-out ( word line-out available-energy )
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Write a data record a frmr into the dpg data file.

to f-write-dpg-frmr-data
  ;; This routine is to be executed by a frmr.

  ;; Select the file
  file-open gs-dpg-file-name
  
  set g-dpg-recno ( g-dpg-recno + 1 )
  
  ;; Write the data record.
  let line-out "DPG-D, "
  set line-out ( word line-out g-dpg-recno ", "  )
  set line-out ( word line-out ticks ", " )
  set line-out ( word line-out who ", "  )
  set line-out ( word line-out Xcor ", "  )
  set line-out ( word line-out Ycor ", "  )
  set line-out ( word line-out age ", "  )
  set line-out ( word line-out age-to-reproduce ", "  )
  set line-out ( word line-out cash ", "  )
  set line-out ( word line-out energy ", "  )
  set line-out ( word line-out recycled ", "  )
  set line-out ( word line-out inventory ", "  )
  set line-out ( word line-out supplies ", "  )
  set line-out ( word line-out waste ", "  )
  set line-out ( word line-out net-value ", "  )
  set line-out ( word line-out real-value ", "  )
  set line-out ( word line-out HRL ", "  )
  set line-out ( word line-out HIL ", "  )
  set line-out ( word line-out HSL ", "  )
  set line-out ( word line-out energy-set-point ", "  )
  set line-out ( word line-out available-energy )
  file-print line-out
end 

;;-----------------------------------------------------------------------------|
;; Close the dpg file.

to f-close-dpg-file
  ;; This routine is to be executed by the observer.
  
  ;; DPG stands for 'Data Per Generation'
  if ( Is-string? gs-dpg-file-name )
  [
    if ( file-exists? gs-dpg-file-name )
    [
      ;; Select the file
      file-open gs-dpg-file-name
      ;; Close it.
      file-close
    ]
  ]
  set gb-dpg-on 0
  set gs-dpg-status "0 (Off)"
  set gs-dpg-file-name "DpgDummyName"
  set g-dpg-recno 0
end 

;;-----------------------------------------------------------------------------|
;; Close and reopen the dpg file, it is too full.

to f-reopen-dpg-file
  ;; This routine is to be executed by the observer.
  
  f-close-dpg-file
  f-open-dpg-file
end 

;;-----------------------------------------------------------------------------|
;; Construct a CSV data file name.

to-report fr-construct-file-name [ type-string ]
  ;; This routine is to be executed by the observer.
  ;;
  ;; Date-string format "01:19:36.685 PM 19-Sep-2002"
  let date-string date-and-time
  let file-name ( word "ModEco_" type-string "_" )
  ;; Append the year as yy.
  set file-name word file-name ( substring date-string 25 27 )
  ;; Append the month as Mmm.
  set file-name word file-name fr-convert-mmm-mm ( substring date-string 19 22 )
  ;; Append the day as dd.
  set file-name word file-name ( substring date-string 16 18 )
  ;; Append a dash.
  set file-name word file-name "_"

  ;; Append the hour as hh.
  set file-name word file-name fr-convert1224 ( substring date-string 0 2 ) ( substring date-string 13 15 )
  ;; Append the minute as mm.
  set file-name word file-name ( substring date-string 3 5 )
  ;; Append the second as ss.
  set file-name word file-name ( substring date-string 6 8 )
  ;; Append the .csv extension.
  set file-name word file-name ".csv"

  report file-name
end 



;;-----------------------------------------------------------------------------|
;; DEBUG AND DEBUG LOG FILE MANAGEMENT FUNCTIONS
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; Open a log file for debug output.

to f-open-log-file
  ;; This routine is to be executed by the observer.
  
  ;; Ensure previous log file is closed.
  if ( is-string? gs-log-file-name )
  [
    if ( file-exists? gs-log-file-name )
    [
      file-close-all
    ]
  ]
  
  ;; Date-string format "01:19:36.685 PM 19-Sep-2002"
  let date-string date-and-time
  set gs-log-file-name "ModEco_Log_"
  ;; Append the year as yy.
  set gs-log-file-name word gs-log-file-name ( substring date-string 25 27 )
  ;; Append the month as Mmm.
  set gs-log-file-name word gs-log-file-name fr-convert-mmm-mm ( substring date-string 19 22 )
  ;; Append the day as dd.
  set gs-log-file-name word gs-log-file-name ( substring date-string 16 18 )
  ;; Append a dash.
  set gs-log-file-name word gs-log-file-name "_"

  ;; Append the hour as hh.
  set gs-log-file-name word gs-log-file-name fr-convert1224 ( substring date-string 0 2 ) ( substring date-string 13 15 )
  ;; Append the minute as mm.
  set gs-log-file-name word gs-log-file-name ( substring date-string 3 5 )
  ;; Append the second as ss.
  set gs-log-file-name word gs-log-file-name ( substring date-string 6 8 )
  ;; Append the .txt extension.
  set gs-log-file-name word gs-log-file-name ".txt"

  file-open gs-log-file-name
  file-show "Log File for a ModEco (NetLogo) Model."
  file-show word "File Name: " gs-log-file-name
  file-show word "File opened at:" date-and-time
  file-show ""
  
  ;; Send a message directly to the command centre.
  ifelse ( file-exists? gs-log-file-name )
  [
    show word gs-log-file-name " opened."
  ]
  [
    show word gs-log-file-name " not opened."
  ]
end 

;;-----------------------------------------------------------------------------|
;; Convert month in text form to digital form.

to-report fr-convert-mmm-mm [ mmm ]
  ;; This routine is to be executed by the observer.
  ;; It converts a string in the form mmm ( alpha text ) to the form mm ( digit-text ).
  
  let mm "00"
  if( mmm = "Jan" ) [ set mm "01" ]
  if( mmm = "Feb" ) [ set mm "02" ]
  if( mmm = "Mar" ) [ set mm "03" ]
  if( mmm = "Apr" ) [ set mm "04" ]
  if( mmm = "May" ) [ set mm "05" ]
  if( mmm = "Jun" ) [ set mm "06" ]
  if( mmm = "Jul" ) [ set mm "07" ]
  if( mmm = "Aug" ) [ set mm "08" ]
  if( mmm = "SeP" ) [ set mm "09" ]
  if( mmm = "Oct" ) [ set mm "10" ]
  if( mmm = "Nov" ) [ set mm "11" ]
  if( mmm = "Dec" ) [ set mm "12" ]
  report mm
end 

;;-----------------------------------------------------------------------------|
;; Convert hour in 12 format to 24 hour format.

to-report fr-convert1224 [ hh ampm ]
  ;; This routine is to be executed by the observer.
  ;; It converts a string in 12 hour format to 24 hour format.
  
  let hour read-from-string hh
  if( ampm = "PM" ) [ set hour ( hour + 12 ) ]
  
  let dd ( word "00" hour )
  let d2 last dd
  set dd but-last dd
  let d1 last dd
  set dd ( word d1 d2 )
  report dd
end 

;;-----------------------------------------------------------------------------|
;; Close a log file for debug output.

to f-close-log-file
  ;; This routine is to be executed by the observer.
  
  let b-filename-exists 0
  if ( is-string? gs-log-file-name ) 
  [
    if ( file-exists? gs-log-file-name )
    [
      set b-filename-exists 1
    ]
  ] 

  ifelse( b-filename-exists = 1 )
  [
    ;; Ensure the file is selected.
    file-open gs-log-file-name
      
    ;; Stanp it.
    LOG-TO-FILE word "File closed at: " date-and-time
      
    ;; Flush the buffers.
    file-flush 
      
    ;; Close it.
    file-close-all
      
    ;; Note sent to command centre.
    show word gs-log-file-name " closed."
    
    ;; Revert to dummy name.
    set gs-log-file-name "dummyname"
  ]
  [
    if( gs-log-file-name = "dummyname" )
      [ show "No log file is open.  Cannot close it." ]
  ]
end 

;;-----------------------------------------------------------------------------|
;; Select an already opened log file.

to f-select-log-file
  ;; This routine is to be executed by the observer.
  
  ifelse ( file-exists? gs-log-file-name )
  [
    ;; Ensure the file is selected.
    file-open gs-log-file-name
    
    ;; Ensure it is open for writing.
    LOG-TO-FILE ""
    LOG-TO-FILE "SELECTED"    
  ]
  [
    show word gs-log-file-name " is not open.  Cannot select it."
  ]
end 

;;-----------------------------------------------------------------------------|
;; Change the debug mode from on to off, or vice versa.

to f-toggle-debug
  ;; This routine is to be executed by the observer, and is activated by a 
  ;;   button.
  
  ifelse( gb-debug-on = 1 )
  [
    ;; Debug is On, turn it Off.
    ;; Close the file before turning debug logging off.
    f-close-log-file
    set gs-debug-status "0 (Off)"  ;; This appears in the monitor.
    set gb-debug-on 0              ;; But this controls the debug feature.
  ]
  [
    ;; Debug is Off, turn it On.
    set gs-debug-status "1 (On)"   ;; This appears in the monitor.
    set gb-debug-on 1              ;; But this controls the debug feature.
    ;; The switches, if needed, are reset manually by the user.
    ;; Open the log file after turning debug logging on.
    f-open-log-file
  ]
end 

;;-----------------------------------------------------------------------------|

to f-regulate-debug-switches
  ;; This routine is to be performed by the observer.

  ;; There are certain combinations of debug switch settings which are meaning-
  ;;   less when in debug mode.  Rather than placing this logic here and there
  ;;   throughout the application, this routine has the logic to ensure that
  ;;   the debug switches remain in a meaningful configuration.
  
  if(gb-debug-on = 0 )
  [
    ;; The debug feature is turned off.  All switches should be set to default
    ;;   positions, which is 'Off', or zero, or false.
    set gb-debug-show-steps false
    set gb-debug-aif-on false
    set gb-debug-tog-on false
    set gb-debug-show-aif false
  ]
  
  ;; Things are more complicated if the debug feature is turned on.
  if(gb-debug-on = 1 )
  [
    ;; It is assumed that the debug log file is open.  I have not implemented a 
    ;;   check here.  It is therefore assumed that, for one or all steps, data is 
    ;;   being sent to the log file.  That data may or may not be also sent to 
    ;;   the command centre.  gb-debug-show-steps therefore does not need to be
    ;;   adjusted, as it may properly be a false or a true here.
    
    ;; The variables gb-debug-tog-on and gb-debug-show-aif can only be on if
    ;;   gb-debug-aif-on is true.  But if it is off, they must be off.
    if( gb-debug-aif-on = false )
    [
      set gb-debug-tog-on   false
      set gb-debug-show-aif false
    ]
  ]
end 

;;-----------------------------------------------------------------------------|
;; Dump the contents of an agent to the debug file.

to LOG-DUMP-AIF [ s-do-step aif-number ]
  ;; This routine is to be executed by an agent.  s-do-step is a string with 
  ;;   the name of the calling do step.  This routine should only be called when 
  ;;   debug is on for the calling do-step.  I.e. the do- function must conditon 
  ;;   a call with if( gb-debug-flow-on = 1 ).
  
  f-regulate-debug-switches
  
  ;; Only execute if the debug feature is on.
  if ( gb-debug-on = 1 )
  [
    ;; Only execute if the debug flow is on for this do-step.
    if ( gb-debug-flow-on = 1 )
    [
      ;; Only execute if the AIF feature is on.
      if ( gb-debug-aif-on = true )
      [
        if( NOBODY = turtle aif-number  ) 
        [ 
          set aif-number [ who ] of one-of turtles 
          set g-aif aif-number
        ]
        
        ;; Process wrkrs and frmrs separately.
        ifelse( ( is-wrkr? turtle aif-number ) = true )
        [
          ;; Aif is a wrkr.
          ask wrkr aif-number
          [
            let lineout ( word 
              "AIF "
              s-do-step
              "; Tic: " ticks
              "; Who: " who
              "; Age: " age
              "; $: " cash
              "; Nrg " energy
              "; Sup: " supplies
              "; Wst: " waste 
              "; Net: " fr-get-wrkr-net-value
              "; Real: " fr-get-wrkr-real-value
              )
            file-show lineout
            if(gb-debug-show-aif = true )
            [
              show lineout
            ]
            if( gb-debug-tog-on = true )
            [
              set lineout ( word 
                "AIF "
                s-do-step
                "; Tic: " ticks
                "; Who: " who
                "; Can-slw: " b-can-sell-waste 
                "; Can-wrk: " b-can-work 
                "; Can-bys: " b-can-buy-supplies 
                "; Can-eat: " b-can-eat 
                "; Can-rep: " b-can-reproduce 
                "; Is-new:  " b-just-sprouted 
                "; Can-die: " b-can-die 
                "; Can-doh: " b-can-die-of-hunger 
                "; Can-doa: " b-can-die-of-age 
                "; Can-dol: " b-can-die-of-lownrg 
                )
              file-show lineout
              if(gb-debug-show-aif = true )
              [
                show lineout
              ]
            ]
          ]  ;; End of ask
        ]  ;; End of is a wrkr.
        [
          ;; Aif is a frmr.
          ask frmr aif-number
          [
            let lineout ( word 
              "AIF "
              s-do-step
              "; Tic: " ticks
              "; Who: " who
              "; Age: " age
              "; $: " cash
              "; Nrg " energy
              "; Rec: " recycled
              "; Inv: " inventory
              "; Sup: " supplies
              "; Wst: " waste 
              "; Net: " fr-get-frmr-net-value
              "; Real: " fr-get-frmr-real-value
              )
            file-show lineout
            if(gb-debug-show-aif = true )
            [
              show lineout
            ]
            if( gb-debug-tog-on = true ) 
            [
              set lineout ( word 
                "AIF "
                s-do-step
                "; Tic: " ticks
                "; Who: " who
                "; Can-slw: " b-can-sell-waste 
                "; Can-ByR: " b-can-buy-recycled 
                "; Can-HWk: " b-can-hire-wrkrs 
                "; Can-sli: " b-can-sell-inventory 
                "; Can-bys: " b-can-buy-supplies 
                "; Can-eat: " b-can-eat 
                "; Can-rep: " b-can-reproduce 
                "; Can-die: " b-can-die 
                "; Can-doh: " b-can-die-of-hunger 
                "; Can-doa: " b-can-die-of-age 
                "; Can-dol: " b-can-die-of-lownrg 
                )
              file-show lineout
              if(gb-debug-show-aif = true )
              [
                show lineout
              ]
            ]
          ]  ;; End of ask.
        ]  ;; End of is a frmr.
      ]  ;; End of if feature on.
    ]  ;; End if flow is on.
  ]  ;; End of debug is on.
end 

;;-----------------------------------------------------------------------------|
;; 'Show' a string in a debug log.

to LOG-TO-FILE [ log-this-string ]
  ;; This routine may be executed by observer, wrkr, or frmr.
  ;; It should be invoked as a debug routine only, and would not be used for 
  ;;    normal output.  It sends output to the debug log file, or, optionally,
  ;;    also to the command centre.
  
  
  f-regulate-debug-switches
  
  ;; gb-debug-on is a global Boolean and has value 1 (true) or 0 (false).
  if( gb-debug-on = 1 )
  [
    ;; gb-debug-flow-on is declared as a global Boolean variable, and its value 
    ;;   is 0 ( false ) or 1 ( true ) and is set on or off at the beginning of each 
    ;;   function ( each do-step ).  It is controlled by the chooser that selects 'all' 
    ;;   or a specific do-function.
    ;; 
    ;; When it is 'on' you can assume the debug log file exists and is open for
    ;;   write.
    
    if( gb-debug-flow-on = 1 )
    [
      file-show log-this-string
      if( gb-debug-show-steps = true )
      [
        show log-this-string
      ]
    ] 
  ]
end 

;;-----------------------------------------------------------------------------|
;; 'Show' a string in a debug log for the 'agent-in-focus' ( aif ).

to LOG-WITH-AIF-CHECK [ log-this-string test-who ]
  ;; This routine may be executed by wrkr, or frmr only
  ;; It should be invoked as a debug routine only, and would not be used for 
  ;;   normal output.  It sends output to the command centre or to a log file.
  
  f-regulate-debug-switches
  
  ;; gb-debug-on is a global Boolean and has value 1 (true) or 0 (false).
  if( gb-debug-on = 1 )
  [
    ;; gb-debug-flow-on is declared as a global Boolean variable, and its value is 
    ;;   0 ( false ) or 1 ( true ) and is set on or off at the beginning of each 
    ;;   function ( do-step ).  It is controlled by the chooser that selects 'all' or 
    ;;   a specific do-function.
    ;; When it is on you can assume the debug log file exists and is open for write.
    
    if( gb-debug-flow-on = 1 )
    [
      ;; Default is log normally, with optional show in command centre
      ifelse( ( gb-debug-aif-on = true ) and ( test-who = g-aif ) )
      [
        ;; This section is for the 'agent-in-focus' (AIF) debug feature.  The 
        ;;   variable g-aif is the who number of the aif.  The contents of that
        ;;   agent's variables are dumped to the log file and to the command
        ;;   centre window, independantly (and possibly redundantly) of the
        ;;   other debug data reporting.
        ;;
        file-show ( word "AIF " log-this-string )
        if( gb-debug-show-aif = true )
        [
          show ( word "AIF " log-this-string )
        ]
      ]
      [
        ;; This is default action.
        ;; The string can be sent to the log file.
        file-show log-this-string
        if( gb-debug-show-steps = true )
        [
          show log-this-string
        ]
      ]

      ;; In addition, the aif output is conditional upon the 'agent-in-focus'   
      ;;   feature being turned on.  gb-debug-aif-on is a Boolean global variable, 
      ;;   and its value is false or true.
      
    ] 
  ]
end 

;;-----------------------------------------------------------------------------|
;; This replicates the effect of an 'ASSERTION' in C++

to ASSERT [ error-test error-string error-who ]
;; This routine can be run by any of observer, wrkr or frmr (I think).

if( error-test = false )
[
  show ( word error-test " " error-string " " error-who )
  ;; Cause a run-time error and display a message.
  error ( word "Agent: " error-who " - " error-string )
]
end 


;;-----------------------------------------------------------------------------|
;; Check whether the agents are all valid.

to-report frb-agents-are-all-valid 
;; This routine can be run by the observer.

  let b-agents-are-all-valid true
  
  if( gb-debug-on = 1 )
  [
    ;; Do the check only if debug is on.
    
    ;; The MMgr is always valid.
    ;; Check the EMgr.
    if( frb-EMgr-is-valid = false ) [ set b-agents-are-all-valid false ]
    
    ;; Check the wrkrs.
    ask wrkrs
    [
      if( frb-wrkr-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
    
    ;; Check the frmrs.
    ask frmrs
    [
      if( frb-frmr-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
  ]
  
  report b-agents-are-all-valid
end 

;;-----------------------------------------------------------------------------|
;; Check whether the EMgr is valid.

to-report frb-EMgr-is-valid 
;; This routine can be run by any of observer, wrkr or frmr (I think).

  let b-EMgr-is-valid true
  if( g-EMgr-cash < 0 ) 
  [ 
    set b-EMgr-is-valid false 
    LOG-TO-FILE ( word "g-EMgr-cash = " g-EMgr-cash "; at tick = " ticks )
  ]
  
  if( g-EMgr-mass < 0 ) 
  [ 
    set b-EMgr-is-valid false 
    LOG-TO-FILE ( word "g-EMgr-mass = " g-EMgr-mass "; at tick = " ticks )
  ]
  
  if( g-EMgr-energy < 0 ) 
  [ 
    set b-EMgr-is-valid false 
    LOG-TO-FILE ( word "g-EMgr-energy = " g-EMgr-energy "; at tick = " ticks )
  ]

  report b-EMgr-is-valid
end 

;;-----------------------------------------------------------------------------|
;; Check whether a frmr is valid.

to-report frb-frmr-is-valid 
;; This routine can be run by a frmr.

  let b-frmr-is-valid true
  if( cash < 0 ) 
  [ 
    set b-frmr-is-valid false 
    LOG-TO-FILE ( word "cash = " cash "; at tick = " ticks )
  ]
  
  if( energy < 0 ) 
  [ 
    set b-frmr-is-valid false 
    LOG-TO-FILE ( word "energy = " energy "; at tick = " ticks )
  ]
  
  if( recycled < 0 ) 
  [ 
    set b-frmr-is-valid false 
    LOG-TO-FILE ( word "recycled = " recycled "; at tick = " ticks )
  ]
  
  if( inventory < 0 ) 
  [ 
    set b-frmr-is-valid false 
    LOG-TO-FILE ( word "inventory = " inventory "; at tick = " ticks )
  ]
  
  if( supplies < 0 ) 
  [ 
    set b-frmr-is-valid false 
    LOG-TO-FILE ( word "supplies = " supplies "; at tick = " ticks )
  ]
  
  if( waste < 0 ) 
  [ 
    set b-frmr-is-valid false 
    LOG-TO-FILE ( word "waste = " waste "; at tick = " ticks )
  ]

  report b-frmr-is-valid
end 

;;-----------------------------------------------------------------------------|
;; Check whether a wrkr is valid.

to-report frb-wrkr-is-valid 
;; This routine can be run by a frmr.

  let b-wrkr-is-valid true
  if( cash < 0 ) 
  [ 
    set b-wrkr-is-valid false 
    LOG-TO-FILE ( word "cash = " cash "; at tick = " ticks )
  ]
  
  if( energy < 0 ) 
  [ 
    set b-wrkr-is-valid false 
    LOG-TO-FILE ( word "energy = " energy "; at tick = " ticks )
  ]
  
  if( supplies < 0 ) 
  [ 
    set b-wrkr-is-valid false 
    LOG-TO-FILE ( word "supplies = " supplies "; at tick = " ticks )
  ]
  
  if( waste < 0 ) 
  [ 
    set b-wrkr-is-valid false 
    LOG-TO-FILE ( word "waste = " waste "; at tick = " ticks )
  ]

  report b-wrkr-is-valid
end 

;;-----------------------------------------------------------------------------|
;; ENTROPY COMPUTATION MECHANISM
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; Update the entropy graph.

to f-update-entropy-graph
  ;; The observer executes this routine.
  
  ;; An entropy reading is a list containing:
  ;;   - Item 0 - ticks value
  ;;   - Item 1 - a computed entropic index for wrkrs
  ;;   - Item 2 - the associated scaling factor g-K-w
  ;;   - Item 3 - a computed entropic index for frmrs
  ;;   - Item 4 - the associated scaling factor g-K-f
  ;;   - Item 5 - a computed entropic index for all together
  ;;   - Item 6 - the associated scaling factor g-K-a
  
  set g-entropic-index-w fr-compute-entropic-index-w
  set g-entropic-index-f fr-compute-entropic-index-f
  set g-entropic-index-a fr-compute-entropic-index-a
  
  ;; Construct a reading of entropies with scaling factors.
  set gl-ent-reading 
    ( 
      list
      ticks 
      g-entropic-index-w g-K-w 
      g-entropic-index-f g-K-f 
      g-entropic-index-a g-K-a
    )
  
  ifelse ( g-no-of-ent-readings >= g-no-of-ent-readings-max )
  [
    ;; The time series already has a maximum number of readings.
    ;; Drop the oldest reading, and add the newest to the end.
    set gl-ent-time-series ( lput gl-ent-reading ( but-first gl-ent-time-series ) ) 
  ]
  ;; else
  [
    ;; Add this reading to the list.
    ifelse ( g-no-of-ent-readings > 0 )
    [
      ;; The time series has not yet reached full length.
      ;; Add the newest reading to the end.
      set gl-ent-time-series ( lput gl-ent-reading gl-ent-time-series )
    ]
    ;; else
    [
      ;; The time series is empty.
      ;; Create a list with one reading.
      set gl-ent-time-series ( list gl-ent-reading ) 
    ]
    set g-no-of-ent-readings ( g-no-of-ent-readings + 1 )
  ]
end 

;;-----------------------------------------------------------------------------|
;; Compute the entropy of the wrkrs.

to-report fr-compute-entropic-index-w
  ;; The observer executes this routine.
  
  ;; Note: g-min-wrkr-wealth and g-max-wrkr-wealth are global variables of 
  ;;   which the value is computed
  ;;   each tick in the 'f-update-aggregates' function.  This routine assumes 
  ;;   that they have been updated in that function.
  
  ;; Compute the lower end of the range of each histogram.
  let first-bin-start-w ( g-ent-bin-width-w * floor( g-min-wrkr-wealth / 
      g-ent-bin-width-w ) )
  
  ;; Compute the upper end of the range of each histogram.
  let last-bin-end-w ( g-ent-bin-width-w * floor ( ( g-max-wrkr-wealth + 
        g-ent-bin-width-w ) / g-ent-bin-width-w ) )
  
  ;; Compute the range of each histogram.
  let range-w ( last-bin-end-w - first-bin-start-w )
  
  ;; Compute K, the scaling factor, equal to the number of bins.
  set g-K-w ( range-w / g-ent-bin-width-w )
  
  ;;  Select the wealth data out of the agents.
  let wealth-data-w [ net-value ] of wrkrs
  
  ;; Create the empty bins for the two histograms.
  let bin-content 0
  let wealth-bins-w ( n-values g-K-w [bin-content] ) 
  
  ;; Load the wealth data into the bins for wrkrs.
  ;; g-no-of-wrkrs is given a current value in f-update-aggregates.
  let wealth-index 0
  let agent-wealth 0
  let bin-index 0
  while [ wealth-index < g-no-of-wrkrs ]
  [
    ;; Get the net-value of the next agent.
    set agent-wealth ( item wealth-index wealth-data-w )

    ;; Compute the index into the histogram bins.
    set agent-wealth ( agent-wealth - first-bin-start-w )
    set bin-index floor( agent-wealth / g-ent-bin-width-w )
    
    ;; Get the previous count.
    set bin-content ( item bin-index wealth-bins-w )
    ;; Increment the count in the appropriate bin.
    set bin-content ( bin-content + 1 )
    set wealth-bins-w ( replace-item bin-index wealth-bins-w bin-content )
    
    ;; Increment the index.
    set wealth-index ( wealth-index + 1 )
  ]
  
  ;; Now, using the bins, calculate the surprisals, and add them up.
  let entropic-measure-w 0
  let surprisal 0
  let probability 0
  set bin-index 0
  while [ bin-index < g-K-w ]
  [
    set bin-content ( item bin-index wealth-bins-w )
    set probability ( bin-content / g-no-of-wrkrs )
    ifelse ( probability = 0 )
    [
      set surprisal 0
    ]
    ;; else
    [
      ;; Use Sterling's approximation for the surprisal.
      ;; TODO - replace with better approximation for small counts.
      set surprisal ( probability * ln( 1 / probability ) )
    ]
    
    set entropic-measure-w ( entropic-measure-w + surprisal )
    
    set bin-index ( bin-index + 1 )
  ]

  let entropic-index-w 0
  ;; Convert the entropic measure into an entropic index.
  ifelse ( g-K-w <= 1 )
  [
    set entropic-index-w 0
  ]
  ;; else
  [
    set entropic-index-w ( entropic-measure-w / ln( g-K-w ) )
  ]

  report entropic-index-w
end 

;;-----------------------------------------------------------------------------|
;; Compute the entropy of the frmrs.

to-report fr-compute-entropic-index-f
  ;; The observer executes this routine.
  
  ;; Note: g-min-frmr-wealth and 
  ;;   g-max-frmr-wealth are global variables of which the value is computed
  ;;   each tick in the 'f-update-aggregates' function.  This routine assumes 
  ;;   that they have been updated in that function.
  
  ;; Compute the lower end of the range of each histogram.
  let first-bin-start-f ( g-ent-bin-width-f * floor( g-min-frmr-wealth / 
      g-ent-bin-width-f ) )
  
  ;; Compute the upper end of the range of each histogram.
  let last-bin-end-f ( g-ent-bin-width-f * floor ( ( g-max-frmr-wealth + 
        g-ent-bin-width-f ) / g-ent-bin-width-f ) )
  
  ;; Compute the range of each histogram.
  let range-f ( last-bin-end-f - first-bin-start-f )
  
  ;; Compute K, the scaling factor, equal to the number of bins.
  set g-K-f ( range-f / g-ent-bin-width-f )
  
  ;;  Select the wealth data out of the agents.
  let wealth-data-f [ net-value ] of frmrs
  
  ;; Create the empty bins for the two histograms.
  let bin-content 0
  let wealth-bins-f ( n-values g-K-f [bin-content] ) 
  
  ;; Load the wealth data into the bins for frmrs.
  ;; g-no-of-frmrs is given a current value in f-update-aggregates.
  let wealth-index 0
  let agent-wealth 0
  let bin-index 0
  while [ wealth-index < g-no-of-frmrs ]
  [
    ;; Get the net-value of the next agent.
    set agent-wealth ( item wealth-index wealth-data-f )

    ;; Compute the index into the histogram bins.
    set agent-wealth ( agent-wealth - first-bin-start-f )
    set bin-index floor( agent-wealth / g-ent-bin-width-f )
    
    ;; Get the previous count.
    set bin-content ( item bin-index wealth-bins-f )
 
    ;; Increment the count in the appropriate bin.
    set bin-content ( bin-content + 1 )
    set wealth-bins-f ( replace-item bin-index wealth-bins-f bin-content )
    
    ;; Increment the index.
    set wealth-index ( wealth-index + 1 )
  ]
  
  ;; Now, using the bins, calculate the surprisals, and add them up.
  let entropic-measure-f 0
  let surprisal 0
  let probability 0
  set bin-index 0
  while [ bin-index < g-K-f ]
  [
    set bin-content ( item bin-index wealth-bins-f )
    set probability ( bin-content / g-no-of-frmrs )
    ifelse ( probability = 0 )
    [
      set surprisal 0
    ]
    ;; else
    [
      ;; Use Sterling's approximation for the surprisal.
      ;; TODO - replace with better approximation for small counts.
      set surprisal ( probability * ln( 1 / probability ) )
    ]
    
    set entropic-measure-f ( entropic-measure-f + surprisal )
    
    set bin-index ( bin-index + 1 )
  ]

  ;; Convert the entropic measure into an entropic index.
  let entropic-index-f 0
  ifelse ( g-K-f <= 1 )
  [
    set entropic-index-f 0
  ]
  ;; else
  [
    set entropic-index-f ( entropic-measure-f / ln( g-K-f ) )
  ]

  report entropic-index-f
end 


;;-----------------------------------------------------------------------------|
;; Compute the entropy of all turtles.

to-report fr-compute-entropic-index-a
  ;; The observer executes this routine.
  
  ;; Note: g-min-wrkr-wealth, g-min-frmr-wealth, g-max-wrkr-wealth and 
  ;;   g-max-frmr-wealth are global variables of which the value is computed
  ;;   each tick in the 'f-update-aggregates' function.  This routine assumes 
  ;;   that they have been updated in that function.
  
  let min-wealth g-min-frmr-wealth
  if( g-min-wrkr-wealth < g-min-frmr-wealth ) [ set min-wealth g-min-wrkr-wealth ]

  let max-wealth g-max-frmr-wealth
  if( g-max-wrkr-wealth > g-max-frmr-wealth ) [ set max-wealth g-max-wrkr-wealth ]
  
  ;; Compute the lower end of the range of each histogram.
  let first-bin-start-a ( g-ent-bin-width-a * floor( min-wealth / 
      g-ent-bin-width-a ) )
  
  ;; Compute the upper end of the range of each histogram.
  let last-bin-end-a ( g-ent-bin-width-a * floor ( ( max-wealth + 
        g-ent-bin-width-a ) / g-ent-bin-width-a ) )
  
  ;; Compute the range of each histogram.
  let range-a ( last-bin-end-a - first-bin-start-a )
  
  ;; Compute K, the scaling factor, equal to the number of bins.
  set g-K-a ( range-a / g-ent-bin-width-a )
  
  ;;  Select the wealth data out of the agents.
  let wealth-data-a [ net-value ] of turtles
  
  ;; Create the empty bins for the two histograms.
  let bin-content 0
  let wealth-bins-a ( n-values g-K-a [bin-content] ) 
  
  ;; Load the wealth data into the bins for frmrs.
  ;; g-no-of-frmrs is given a current value in f-update-aggregates.
  let wealth-index 0
  let agent-wealth 0
  let bin-index 0
  
  while [ wealth-index < g-no-of-agents ]
  [
    ;; Get the net-value of the next agent.
    set agent-wealth ( item wealth-index wealth-data-a )

    ;; Compute the index into the histogram bins.
    set agent-wealth ( agent-wealth - first-bin-start-a )
    set bin-index floor( agent-wealth / g-ent-bin-width-a )
    
    ;; Get the previous count.
    set bin-content ( item bin-index wealth-bins-a )
 
    ;; Increment the count in the appropriate bin.
    set bin-content ( bin-content + 1 )
    set wealth-bins-a ( replace-item bin-index wealth-bins-a bin-content )
    
    ;; Increment the index.
    set wealth-index ( wealth-index + 1 )
  ]
  
  ;; Now, using the bins, calculate the surprisals, and add them up.
  let entropic-measure-a 0
  let surprisal 0
  let probability 0
  set bin-index 0
  while [ bin-index < g-K-f ]
  [
    set bin-content ( item bin-index wealth-bins-a )
    set probability ( bin-content / g-no-of-agents )
    ifelse ( probability = 0 )
    [
      set surprisal 0
    ]
    ;; else
    [
      ;; Use Sterling's approximation for the surprisal.
      ;; TODO - replace with better approximation for small counts.
      set surprisal ( probability * ln( 1 / probability ) )
    ]
    
    set entropic-measure-a ( entropic-measure-a + surprisal )
    
    set bin-index ( bin-index + 1 )
  ]

  ;; Convert the entropic measure into an entropic index.
  let entropic-index-a 0
  ifelse ( g-K-a <= 1 )
  [
    set entropic-index-a 0
  ]
  ;; else
  [
    set entropic-index-a ( entropic-measure-a / ln( g-K-a ) )
  ]

  report entropic-index-a
end 

;;-----------------------------------------------------------------------------|
;; LORENZ CURVE AND GINI COEFFICIENT COMPUTATION MECHANISMS
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; NOTE: This routine has been copied directly from the model "Wealth 
;;   Distribution" written by Uri Wilensky, and found on the NetLogo Modeling 
;;   Commons website.  A few changes to variable names have been made to
;;   make it work in this context.

;; This procedure recomputes the value of gini-index-reserve
;;   and the points in lorenz-points for the Lorenz and Gini-Index plots.

to f-update-lorenz-and-gini
  ;; This routine is executed by the observer.
  
  ;; First, address all agents together.
  let sorted-wealths sort [net-value] of turtles
  let total-wealth sum sorted-wealths
  let wealth-sum-so-far 0
  let index 0
  set g-gini-index-reserve-a 0
  set gl-lorenz-points-a []

  ;; Now actually plot the Lorenz curve.  Along the way, we also
  ;;   calculate the Gini index.
  ;;   (see the Info tab for a description of the curve and measure)
  repeat g-no-of-agents [
    set wealth-sum-so-far (wealth-sum-so-far + item index sorted-wealths)
    set gl-lorenz-points-a lput ((wealth-sum-so-far / total-wealth) * 100) gl-lorenz-points-a
    set index (index + 1)
    set g-gini-index-reserve-a
    g-gini-index-reserve-a +
    (index / g-no-of-agents) -
    (wealth-sum-so-far / total-wealth)
  ]

  ;; Second, address the wrkrs as a group.
  set sorted-wealths sort [net-value] of wrkrs
  set total-wealth sum sorted-wealths
  set wealth-sum-so-far 0
  set index 0
  set g-gini-index-reserve-w 0
  set gl-lorenz-points-w []

  ;; Now actually plot the Lorenz curve.  Along the way, we also
  ;;   calculate the Gini index.
  ;;   (see the Info tab for a description of the curve and measure)
  repeat g-no-of-wrkrs [
    set wealth-sum-so-far (wealth-sum-so-far + item index sorted-wealths)
    set gl-lorenz-points-w lput ((wealth-sum-so-far / total-wealth) * 100) gl-lorenz-points-w
    set index (index + 1)
    set g-gini-index-reserve-w
    g-gini-index-reserve-w +
    (index / g-no-of-wrkrs) -
    (wealth-sum-so-far / total-wealth)
  ]

  ;; Third, address the frmrs as a group.
  set sorted-wealths sort [net-value] of frmrs
  set total-wealth sum sorted-wealths
  set wealth-sum-so-far 0
  set index 0
  set g-gini-index-reserve-f 0
  set gl-lorenz-points-f []

  ;; Now actually plot the Lorenz curve.  Along the way, we also
  ;;   calculate the Gini index.
  ;;   (see the Info tab for a description of the curve and measure)
  repeat g-no-of-frmrs [
    set wealth-sum-so-far (wealth-sum-so-far + item index sorted-wealths)
    set gl-lorenz-points-f lput ((wealth-sum-so-far / total-wealth) * 100) gl-lorenz-points-f
    set index (index + 1)
    set g-gini-index-reserve-f
    g-gini-index-reserve-f +
    (index / g-no-of-frmrs) -
    (wealth-sum-so-far / total-wealth)
  ]
end 

There is only one version of this model, created about 7 years ago by Garvin Boyle.

Attached files

File Type Description Last updated
01 ModEco V1.39.png preview Preview for '01 ModEco V1.39' about 7 years ago, by Garvin Boyle Download
110427 PPR The Distribution of Wealth 2Cols Draft R5.pdf pdf An unpublished paper examining the distribution of wealth in the model about 7 years ago, by Garvin Boyle Download
130108 Reflections on Sustainability V2.0.pdf pdf Some thoughts about the nature of sustainable economies about 7 years ago, by Garvin Boyle Download
130111 Model Economy Design Document V2.03A R4.pdf pdf A high-level technical description of the model. about 7 years ago, by Garvin Boyle Download
130507 ModEco Presentation At MABS 2013 R7 Full Set In Order.pptx powerpoint A presentation made at MABS 2013 - A Workshop for modelers about 7 years ago, by Garvin Boyle Download
130523 PPR - Boyle - MABS - A Sustainable Model Economy V11.pdf pdf An unpublished paper prepared for the MABS 2013 workshop about 7 years ago, by Garvin Boyle Download
140405 ModEco Pricing Issues V2.04A R5.pdf pdf A technical paper discussing the price/value problem and seeking ways to fix it. about 7 years ago, by Garvin Boyle Download
141129 NTF - NetLogo Stds for OrrerySW R2.pdf pdf A diary note setting out programming standards for Orrery Software respecting NetLogo projects. about 7 years ago, by Garvin Boyle Download
141129 ODD Description of PMM (NetLogo) R8.pdf pdf A description of ModEco using the ODD protocol (Overview, Design concepts, Details). about 7 years ago, by Garvin Boyle Download
141216 ModEco (NetLogo) - Change diary V1.39.pdf pdf The most recent change diary. about 7 years ago, by Garvin Boyle Download

This model does not have any ancestors.

This model does not have any descendants.