Nicola Nicoli

Computer Science and Simulation for Economics

Project work on

"Hotelling model."

 

The applet requires Java 1.4.1 or higher. It will not run on Windows 95 or Mac OS 8 or 9. Mac users must have OS X 10.2.6 or higher and use a browser that supports Java 1.4. (Safari works, IE does not. Mac OS X comes with Safari. Open Safari and set it as your default web browser under Safari/Preferences/General.) On other operating systems, you may obtain the latest Java plugin from Sun's Java site.


powered by NetLogo

view/download model file: hotelling_model.nlogo

WHAT IS IT?

This model represents an extension of the Hotelling spatial competition model by considering two dimensions.


HOW IT WORKS

A certain number of consumers feel like buying a product that is sold by two firms (duopolist1 and duopolist2).

If the switch "only-if-near?" is set off, at each time unit, all consumers buy the product from the "nearest" duopolist, without abandoning its original place: only the progress of time units allows the consumers to move or stay according to the rules established by the observer by selection of a behaviour criterion; but if the switch is set on, the consumers are allowed to take the product from the nearest duopolist only if he is at a distance lesser than the limit distance selected by the observer, so that, at certain times, maybe some consumers are not able to take no product at all (they take the color "pink - 1").

Both duopolists may stay or move around the world to attract new consumers, following some behaviour criteria arranged for them.

The most interesting rules are:
a) those by which a duopolist reacts to the competitor's situation, that is, he reacts to the better price or the shorter distance boasted by the competitor by moving in the world in order to contrast his antagonist in the same market or escape from his neighbourhood in search of a less "difficult" market, and
b) those by which the consumers address themselves towards the duopolist showing the cheapest price or the less distance to them: it deals with situations capable to uncork persevering, very hard price- or position war between suppliers.


HOW TO USE IT

"Setup" creates a certain number of consumers randomly spread around the world and two firms: duopolist1 (turquoise) and duopolist2 (orange).

"Go" makes duopolists move or stay in the world accordingly to the criteria set by the observer, with the goal to gain new consumers or defend his market share. The same for the consumers, that, according to the behavioural criteria dedicated to them, may stay in the world, or wander around it, or reach the nearest duopolist, or the cheapest one (with a rate of knowledge representing, in percentage terms, the probability to really reach the cheapest duopolist).

"Go once" makes the same of "go" in a single time unit.

By the slider "number-of-consumers" one can select how many people will act in the world demanding the good furnished by the duopolists.

The sliders "initial-price1" and "initial-price2" makes possible to set different initial price levels for the duopolists; alternatively, one can let the program establish randomly the initial price levels, by setting on the switch "randomize-initial-prices".

The sliders "price-cut-made-by-duopolist1" and "price-cut-made-by-duopolist2" allow to diversify the discount policies followed by the duopolist; in particular, if one or both sliders are set on zero, the corrisponding price policy doesn't trend to practice discounted prices, but to practice only the best price between the market ones.

Acting on the slider "knowledge rate" it is possible to select the probability for a consumer desiring to be supplied from the cheapest duopolist to have success in being satisfied.

Finally, the slider "lim-distance" makes one be able to set the distance under which the consumers can searching for the duopolist that is, to his respect, "nearest" than the other.


THINGS TO NOTICE

When the "Setup" buttton is pushed, the consumers are put randomly on the world, and are not provided by any duopolist; but after clicking of "Go", they begin to compare their distance from the nearest duopolist, and the prices fixed by the competitors.

If their area is not the best - and the chooser "behaviour-of-consumers" is not set on "stay" - the consumers begin to move out till they will find out a new "best" area.

The flow of simulations is affected primarily by the initial distribution of consumers in the world and by the initial price levels: in fact, the behaviour of duopolist depends mostly by earns gained in each time unit and by possible price difference, the latter orienting the preferences conferred by consumers to each competitor. After that, it will be the price-policies, the behavioural criteria of consumers and duopolist, and the price trends that determine what kind of results will be obtained during the simulations.


THINGS TO TRY

It could be very interesting to test various combinations of sets for switches and choosers; particularly, if the former ones were set on their extreme levels (e.g. for the max-willingness-to-discount, try setting on levels 0% and 100%: it could be highlighted the effects of agents' interactions in case of absolute unwillingness by one or both duopolists to practice any discount and, on the contrary, in case of perpetual and complete willingnes to practice discounts).


EXTENDING THE MODEL

To make the model more complete, one might introduce some balance constrain for the consumers, differentiate them with respect to tastes, or, finally, differentiate the products furnished by the duopolists. One could, also, try to remove the absumption that the consumers always buy from the nearest duopolist, while the price is able, eventually, only to address them along a path that makes them approaching to the cheapest duopolist.


CREDITS AND REFERENCES

For a friendly introduction to the classical Hotelling model, it may be useful to look at Roberta Capello - Economia regionale (63 - 68) - Il Mulino, Bologna, 2004 (in italian language).


PROCEDURES

breed [consumers]
breed [duopolists duopolist]

duopolists-own [earns] 
globals [duopolist1 duopolist2 nearest price1 price1-best price2 price2-best price-of-nearest]

to setup
  ca
  set-default-shape consumers "person"
  set-default-shape duopolists "truck"
  create-consumers number-of-consumers [set color white
; a trigger allowing all consumers showing a label for prices taken: if the price taken not discounted, the label stays empty, ...
; ... but if there is some discount in accordance to following price policy rules, the label is filled with the discounted price; ...
; ... this trigger permits us to divide consumers, for the purposes of programming technique, between those taking discounts ... 
; ... and those paying full prices    
                                        set label ""
                                        setxy random-xcor random-ycor]
  
; the following little ploy allows the model working with sense even in case the price policies are "best for customers so far served ...
; ... by competitor" or "best for faithfuls" for both duopolists (see ahead); otherwise, there would be no modifications ...
; ... in those cases, as the starting livery of all consumers would be neither turquoise nor orange, but only white: it's like ...
; ... there would be a little group of consumers that, at the beginning of simulation, already showed their tendency ...
; ... to one duopolist rather than to the other  
  ask n-of (number-of-consumers / 10) consumers [set color orange]
  ask n-of (number-of-consumers / 10) consumers with [color != orange] [set color turquoise] 
  
  create-duopolists 2 [set earns 0
                       set color orange
                       set label-color white
                       setxy random-xcor random-ycor
; the consumers are specified through all the who-numbers from 0 to "number-of-consumers" - 1; ...
; ... the first duopolist, taking now turquoise color, is specified through the who-number equal to the "number of consumers" ...
; ... planned by the observer; finally, the other duopolist is specified through the who-number of the former, increased by one                        
                       set duopolist1 number-of-consumers
                       set duopolist2 (number-of-consumers + 1)
                       ask duopolist duopolist1 [set color turquoise]]

; both prices can initially be at randomized levels, 1 to 20 inclusive: maybe they are on the same level, or not; ...
; ... or, instead, they can be set at certain levels planned by the observer by switching in the interface  
  ifelse randomize-initial-prices?
     [set price1 (1 + random 20)                                        
      set price2 (1 + random 20)]
     [set price1 initial-price1
      set price2 initial-price2]                                                                   
end

to go
  label-duopolists-with-prices
  send-consumers-to-take-right-price                                                                                                                                                                             
  calculate-earns                           
  behave-like-a-consumer
  behave-like-a-duopolist
  move-prices
  tick                                                                                       
  update-plots
end

to label-duopolists-with-prices
; for both duopolists, the price labelling begins here, so the labels are updated after each time unit
  ask duopolist duopolist1 [set label price1]
  ask duopolist duopolist2 [set label price2]
end

to send-consumers-to-take-right-price
; the consumers lying at a smaller distance to a duopolist than to the other take the price policy (and the color, ...
; ... via the "take-price-policy" procedures) of the former; ...
; ... notice that the color changing happens only after the price policy taking: otherwise, there may be some deviation ...
; ... from the right process: a consumer obtains a discount if he already wears a certain livery color , and then, ...
; ... if that color is not the same of that of the discounter, he takes the latter's color                     
  ask consumers with [distance duopolist duopolist1 < distance duopolist duopolist2][take-price-policy1]                                       
  ask consumers with [distance duopolist duopolist1 > distance duopolist duopolist2][take-price-policy2] 

; if the distance of a consumer to a duopolist is the same than to the other, then ...
; ...the consumer takes (or maintains) a price policy and a livery color based on the following rules; ...
; notice that, if some consumer changes his livery color to "pink - 1", he remains, for a tick, "hesitant", ...
; ... i.e. he doesn't take any price policy  
  ask consumers with [(distance duopolist duopolist1 = distance duopolist duopolist2) 
        and (color = turquoise or color = turquoise - 0.5 or color = turquoise - 1 or color = turquoise - 1.5)]           
                                                                                         [ifelse random 100 < 35 
                                                                                             [set color pink - 1
                                                                                              calculate-earns]
                                                                                             [ifelse (random 100 >= 35 and random 100 < 50) 
                                                                                                 [take-price-policy2]
                                                                                                 [take-price-policy1]]]  
  ask consumers with [(distance duopolist duopolist1 = distance duopolist duopolist2) 
        and (color = orange or color = orange - 0.5 or color = orange - 1 or color = orange - 1.5)]           
                                                                                         [ifelse random 100 < 35 
                                                                                             [set color pink - 1
                                                                                              calculate-earns]
                                                                                             [ifelse (random 100 >= 35 and random 100 < 50) 
                                                                                                 [take-price-policy1]                                                                                                     
                                                                                                 [take-price-policy2]]]
  ask consumers with [(distance duopolist duopolist1 = distance duopolist duopolist2) and color = white]           
                                                                                         [ifelse random 100 < 25 
                                                                                             [take-price-policy1]
                                                                                             [ifelse (random 100 >= 25 and random 100 < 50) 
                                                                                                 [take-price-policy2]                                                                                                           
                                                                                                 [set color pink - 1
                                                                                                  calculate-earns]]]     
 ask consumers with [(distance duopolist duopolist1 = distance duopolist duopolist2) and color = pink - 1]           
                                                                                         [ifelse random 100 < 25 
                                                                                             [take-price-policy1]
                                                                                             [ifelse (random 100 >= 25 and random 100 < 50) 
                                                                                                 [take-price-policy2]                                                                                                           
                                                                                                 [calculate-earns]]]
end

; here are now the settings made through selection of a price policy: ...
; ... - if the best price is allowed for any set of fresh-captured customers, they pay a price surely cheaper than the full ones ...
; ... (with the exception of the case that the cut made is equal to zero, so that the price allowed equals the minimum ...
; ... of the full ones), and then take the color of their serving duopolist ...;
; ... - if the best price is allowed only for customers keeping the same supplier for three times (as happens ...
; ... when "better for faithfuls" is selected), the effects are the same as described above; but note, in that case, ...
; ... how the progress of customers' "confirmation of faithfulness" is shown: it is represented by color changings - the turquoise ...
; ... and orange colors darken at each time unit in which the consumers keep supplied by the same duopolist -, we're about changings ...
; ... that are permitted only once in a time unit by means of "calculate-earns" procedure - quite a true ...
; ... "goto"-flavoured procedure!..); ...
; ... note, also: in case of price discrimination, the price labelled on a consumer is not the same labelled ...
; ... on his furnisher - the duopolists always show their full prices; the consumers show, if at all, the discounted ones; ...
; ... and pay attention, finally, to the fact that the price policy "best for customers so far not served by anyone" obviously ...
; ... takes sense only if the switch "only-if-near?" is on: otherwise, there would never be consumers not served by a duopolist! 
to take-price-policy1
  if price1-policy = "no discrimination"
                   [set color turquoise
                    calculate-earns]
                                                                                         
  if (price1-policy = "best for all new customers" 
         and (color != turquoise or color != turquoise - 0.5 or color != turquoise - 1 or color != turquoise - 1.5) 
              and random 100 < max-willingness-to-discount1)      
                   [set price1-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist1) 2)                        
                    set label price1-best
                    set label-color yellow - 1
                    set color turquoise
                    calculate-earns]

  if (price1-policy = "best for customers so far not served by anyone" 
         and (color = pink - 1 or color = white) and random 100 < max-willingness-to-discount1)
                   [set price1-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist1) 2)
                    set label price1-best
                    set label-color yellow - 1
                    set color turquoise
                    calculate-earns]
                                                                                              
  if (price1-policy = "best for customers so far served by competitor" and random 100 < max-willingness-to-discount1)
                   [ask consumers with [color = orange or color = orange - 0.5 or color = orange - 1 or color = orange - 1.5]
                          [set price1-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist1) 2)
                           set label price1-best
                           set label-color yellow - 1
                           set color turquoise
                           calculate-earns]]
                                                                                                                                                                                                                                                                                       
  if price1-policy = "best for faithfuls" and random 100 < max-willingness-to-discount1 
                   [ask consumers with [color = turquoise][set color turquoise - 0.5
                                                           calculate-earns]
                    ask consumers with [color = turquoise - 0.5][set color turquoise - 1
                                                                 calculate-earns]
                    ask consumers with [color = turquoise - 1][set color turquoise - 1.5
                                                               calculate-earns]
                    ask consumers with [color = turquoise - 1.5]
                          [set price1-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist1) 2)
                           set label price1-best
                           set label-color yellow - 1
                           calculate-earns]]   
end

to take-price-policy2
  if price2-policy = "no discrimination"
                   [set color orange
                    calculate-earns]
  
  if (price2-policy = "best for all new customers" 
         and (color != orange or color != orange - 0.5 or color != orange - 1 or color != orange - 1.5) 
              and random 100 < max-willingness-to-discount2)
                   [set price2-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist2) 2) 
                    set label price2-best
                    set label-color magenta - 1
                    set color orange
                    calculate-earns]
                                                                                              
  if (price2-policy = "best for customers so far not served by anyone" 
         and (color = pink - 1 or color = white) and random 100 < max-willingness-to-discount2)
                   [set price2-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist2) 2) 
                    set label price2-best
                    set label-color magenta - 1
                    set color orange
                    calculate-earns]
                                                                                              
  if (price2-policy = "best for customers so far served by competitor" and random 100 < max-willingness-to-discount2)  
                   [ask consumers with [color = turquoise or color = turquoise - 0.5 or color = turquoise - 1 or color = turquoise - 1.5]
                           [set price2-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist2) 2)
                            set label price2-best
                            set label-color magenta - 1
                            set color orange
                            calculate-earns]]       
                                                                                              
  if price2-policy = "best for faithfuls" and random 100 < max-willingness-to-discount2
                   [ask consumers with [color = orange][set color orange - 0.5
                                                        calculate-earns]
                    ask consumers with [color = orange - 0.5][set color orange - 1
                                                              calculate-earns]
                    ask consumers with [color = orange - 1][set color orange - 1.5
                                                            calculate-earns]
                    ask consumers with [color = orange - 1.5]
                           [set price2-best max (list 0 precision (min (list price1 price2) - price-cut-made-by-duopolist2) 2)
                            set label price2-best
                            set label-color magenta - 1
                            calculate-earns]]
end

to calculate-earns
; if a consumer is distant to a duopolist less than to the other, then the former and his price become the "nearest" ones; ...
; ... moreover, if the switch "only-if-near?" is on, and, at the same time, the distance of the closer duopolist ...
; ... is smaller than the limit distance planned by the observer, then the earns gained by that duopolist ...
; ... increase by a quantity equal to his price; but if the aforesaid switch is, instead, off, ...  
; ... the earns increase occurs anyhow, with no consideration at all of distance data
  ask consumers with [label = ""][if (distance duopolist duopolist1 != distance duopolist duopolist2)
                                     [ifelse (distance duopolist duopolist1 < distance duopolist duopolist2) 
                                         [set nearest duopolist1                                             
                                          set price-of-nearest price1]                                                            
                                         [set nearest duopolist2                                             
                                          set price-of-nearest price2]]                                                                                                              
                                  ifelse only-if-near?
                                     [if (distance duopolist nearest < lim-distance)
                                         [ask duopolist nearest [set earns earns + price-of-nearest]]]
                                     [ask duopolist nearest [set earns earns + price-of-nearest]]]                

  ask consumers with [label = price1-best][if (distance duopolist duopolist1 != distance duopolist duopolist2)
                                             [ifelse (distance duopolist duopolist1 < distance duopolist duopolist2) 
                                                 [set nearest duopolist1                                             
                                                  set price-of-nearest price1-best]                                                            
                                                 [set nearest duopolist2                                             
                                                  set price-of-nearest price2]]                                                                                                              
                                           ifelse only-if-near?
                                             [if (distance duopolist nearest < lim-distance)
                                                 [ask duopolist nearest [set earns earns + price-of-nearest]]]
                                             [ask duopolist nearest [set earns earns + price-of-nearest]]]

  ask consumers with [label = price2-best][if (distance duopolist duopolist1 != distance duopolist duopolist2)
                                             [ifelse (distance duopolist duopolist1 < distance duopolist duopolist2) 
                                                 [set nearest duopolist1                                             
                                                  set price-of-nearest price1]                                                            
                                                 [set nearest duopolist2                                             
                                                  set price-of-nearest price2-best]]                                                                                                               
                                           ifelse only-if-near?
                                             [if (distance duopolist nearest < lim-distance)
                                                 [ask duopolist nearest [set earns earns + price-of-nearest]]]
                                             [ask duopolist nearest [set earns earns + price-of-nearest]]]

; the consumers whose distance to the nearest duopolist is greater than the limit distance planned by the observer...
; ...take the color "pink - 1"
  if only-if-near?                                                                                        
       [ask consumers with [distance duopolist nearest > lim-distance] [set label ""
                                                                        set color pink - 1]]
end

to behave-like-a-consumer            
  if behaviour-of-consumers = "wander" [ask consumers [do-random-walk]]

; if the behavioural criterion is set on "go to nearest", the consumers always move towards the closest duopolist  
  if behaviour-of-consumers = "go to nearest" [ask consumers [if (distance duopolist duopolist1 != distance duopolist duopolist2)
                                                                 [ifelse (distance duopolist duopolist1 < distance duopolist duopolist2)
                                                                     [set heading towards duopolist duopolist1 fd 1]
                                                                     [set heading towards duopolist duopolist2 fd 1]]]] 

; if the behavioural criterion is set on "go always to cheapest", the consumers always move towards the low-pricing duopolist   
  if (behaviour-of-consumers = "go always to cheapest" and price1-policy = "no discrimination" and price2-policy = "no discrimination" 
                                               and price1 != price2)
                                                   [ifelse (price1 < price2)
                                                       [ask consumers [set heading towards duopolist duopolist1 fd 1]]
                                                       [ask consumers [set heading towards duopolist duopolist2 fd 1]]]

  if (behaviour-of-consumers = "go always to cheapest" and price1-policy != "no discrimination" and price2-policy != "no discrimination") 
                                                                 [ask consumers with [label = price1-best]
                                                                     [if price1-best != price2-best
                                                                         [ifelse (price1-best < price2-best)
                                                                             [set heading towards duopolist duopolist1 fd 1]
                                                                             [set heading towards duopolist duopolist2 fd 1]]]
                                                                  ask consumers with [label = price2-best]
                                                                     [if price1-best != price2-best
                                                                        [ifelse (price2-best < price1-best)
                                                                            [set heading towards duopolist duopolist2 fd 1]
                                                                            [set heading towards duopolist duopolist1 fd 1]]]     
                                                                  ask consumers with [label = ""]
                                                                     [if (price1 != price2)    
                                                                         [ifelse (price1 < price2)
                                                                             [set heading towards duopolist duopolist1 fd 1]
                                                                             [set heading towards duopolist duopolist2 fd 1]]]]  
                                                                
  if (behaviour-of-consumers = "go always to cheapest" and price1-policy = "no discrimination" and price2-policy != "no discrimination")
                                                                 [ask consumers with [label = price2-best]
                                                                        [set heading towards duopolist duopolist2 fd 1]
                                                                  ask consumers with [label = ""]
                                                                        [if price1 != price2    
                                                                            [ifelse (price1 < price2)
                                                                                [set heading towards duopolist duopolist1 fd 1]
                                                                                [set heading towards duopolist duopolist2 fd 1]]]]

  if (behaviour-of-consumers = "go always to cheapest" and price1-policy != "no discrimination" and price2-policy = "no discrimination")
                                                                 [ask consumers with [label = price1-best]
                                                                        [set heading towards duopolist duopolist1 fd 1]
                                                                  ask consumers with [label = ""]
                                                                        [if price1 != price2    
                                                                            [ifelse (price1 < price2)
                                                                                [set heading towards duopolist duopolist1 fd 1]
                                                                                [set heading towards duopolist duopolist2 fd 1]]]]

; if the behavioural criterion is set on "go to cheapest only if well-known", the consumers wilfully move towards ...
; ... the low-pricing duopolist, but only with a probability equal to the knowledge rate planned by the observer, divided by a hundred ... 
; ... (e.g. if the knowledge rate is planned to be 100%, that is equivalent to a probability of 100/100 = 1 - the certainty -; ...
; ... if the same rate is, on the other hand, planned to be 0%, that is equivalent to a probability of 0 - the impossibility! - ...
; ... that the consumer intentionally move towards the cheapest duopolist... 
; ... But he can still move towards the cheapest one without intention, of course!) 
  if (behaviour-of-consumers = "go to cheapest if well-known" and price1-policy = "no discrimination" 
                                                   and price2-policy = "no discrimination")
                                                              [ifelse (random 100 <= knowledge-rate) 
                                                                  [ifelse price1 != price2 
                                                                      [ifelse (price1 < price2)
                                                                          [ask consumers [set heading towards duopolist duopolist1 fd 1]]
                                                                          [ask consumers [set heading towards duopolist duopolist2 fd 1]]]
                                                                      [ask consumers [set heading towards one-of duopolists fd 1]]]
                                                                  [ask consumers [set heading towards one-of duopolists fd 1]]]
                                                                      

if (behaviour-of-consumers = "go to cheapest if well-known" and price1-policy != "no discrimination" 
                                                   and price2-policy != "no discrimination")
                                                              [ifelse (random 100 <= knowledge-rate)
                                                                  [ask consumers with [label = price1-best]
                                                                      [if price1-best != price2-best
                                                                          [ifelse (price1-best < price2-best)
                                                                              [set heading towards duopolist duopolist1 fd 1]
                                                                              [set heading towards duopolist duopolist2 fd 1]]]
                                                                   ask consumers with [label = price2-best]
                                                                      [if price1-best != price2-best
                                                                          [ifelse (price2-best < price1-best)
                                                                              [set heading towards duopolist duopolist2 fd 1]
                                                                              [set heading towards duopolist duopolist1 fd 1]]]     
                                                                   ask consumers with [label = ""]
                                                                      [if price1 != price2    
                                                                          [ifelse (price1 < price2)
                                                                              [set heading towards duopolist duopolist1 fd 1]
                                                                              [set heading towards duopolist duopolist2 fd 1]]]]
                                                                  [ask consumers [set heading towards one-of duopolists fd 1]]] 
                                                                                                                                         
if (behaviour-of-consumers = "go to cheapest if well-known" and price1-policy = "no discrimination" 
                                                                   and price2-policy != "no discrimination")
                                                                      [ifelse (random 100 <= knowledge-rate)
                                                                          [ask consumers with [label = price2-best]
                                                                              [set heading towards duopolist duopolist2 fd 1]
                                                                           ask consumers with [label = ""]
                                                                              [if price1 != price2    
                                                                                  [ifelse (price1 < price2)
                                                                                      [set heading towards duopolist duopolist1 fd 1]
                                                                                      [set heading towards duopolist duopolist2 fd 1]]]]
                                                                          [ask consumers [set heading towards one-of duopolists fd 1]]]

if (behaviour-of-consumers = "go to cheapest if well-known" and price1-policy != "no discrimination" 
                                                                   and price2-policy = "no discrimination")
                                                                      [ifelse (random 100 <= knowledge-rate)
                                                                          [ask consumers with [label = price1-best]
                                                                              [set heading towards duopolist duopolist1 fd 1]
                                                                           ask consumers with [label = ""]
                                                                              [if price1 != price2    
                                                                                  [ifelse (price1 < price2)
                                                                                      [set heading towards duopolist duopolist1 fd 1]
                                                                                      [set heading towards duopolist duopolist2 fd 1]]]]
                                                                          [ask consumers [set heading towards one-of duopolists fd 1]]]  
end                                                                                                                                                                                                                                                       

to behave-like-a-duopolist
; if the behavioural criterion is set on "stay at centre", both duopolists stay at one step away from the true centre ...
; ... of the world (0,0), so that it is always possible for the consumers to compare their distance from the duopolists and, ...
; ... consequently, to decide by which of them being provided   
  if behaviour-of-duopolist1 = "stay at centre"                                     
       [ask duopolist duopolist1 [home rt random 45 lt random 45 fd 1]]
       
  if behaviour-of-duopolist2 = "stay at centre"                                     
       [ask duopolist duopolist2 [home rt random 45 lt random 45 fd 1]]                                        

; if the behavioural criterion is set on "go far from competitor", the duopolist with the lesser income flees from the competitor ...
; ... if the latter is too close to him  
  if (behaviour-of-duopolist1 = "go far from competitor" and ([earns] of duopolist duopolist1 < [earns] of duopolist duopolist2))
       [ask duopolist duopolist1 [if (distance duopolist duopolist2 <= 5) 
                                                 [bk (1 + random 15)]]]                                                        
 
  if (behaviour-of-duopolist2 = "go far from competitor" and ([earns] of duopolist duopolist2 < [earns] of duopolist duopolist1))
       [ask duopolist duopolist2 [if (distance duopolist duopolist1 <= 5) 
                                                 [bk (1 + random 15)]]]                                              

; if the behavioural criterion is set on "go randomly", the duopolist gaining the lesser income starts moving randomly in the world ...
; ... to meet new selling opportunities  
  if (behaviour-of-duopolist1 = "go randomly" and ([earns] of duopolist duopolist1 < [earns] of duopolist duopolist2))          
       [ask duopolist duopolist1 [do-random-walk]]                                
          
  if (behaviour-of-duopolist2 = "go randomly" and ([earns] of duopolist duopolist2 < [earns] of duopolist duopolist1))          
       [ask duopolist duopolist2 [do-random-walk]]       

; if the behavioural criterion is set on "go towards competitor", the duopolist gaining the lesser income starts moving ...
; ...towards his competitor
  if (behaviour-of-duopolist1 = "go towards competitor" and ([earns] of duopolist duopolist1 < [earns] of duopolist duopolist2))            
       [ask duopolist duopolist1 [set heading towards duopolist duopolist2 fd 1]]    
     
  if (behaviour-of-duopolist2 = "go towards competitor" and ([earns] of duopolist duopolist2 < [earns] of duopolist duopolist1))            
       [ask duopolist duopolist2 [set heading towards duopolist duopolist1 fd 1]]  

; if the behavioural criterion is set on "go towards consumers", each duopolist starts moving towards the consumers actually lying ...
; ... at a smaller distance to him than to the competitor; that is intended to show a situation in which a duopolist ...
; ... tries to tighten his client to his neighbour against competitor's expansion aims   
  if behaviour-of-duopolist1 = "go towards consumers"                                     
       [ask duopolist duopolist1 [set heading towards max-one-of patches 
           [count consumers with [distance myself < distance duopolist duopolist2]] fd 1]]                                                           

  if behaviour-of-duopolist2 = "go towards consumers"                                     
       [ask duopolist duopolist2 [set heading towards max-one-of patches 
           [count consumers with [distance myself < distance duopolist duopolist1]] fd 1]]
end

to do-random-walk
   rt random-float 360              
   forward 1
end

to move-prices
; if the price trend for the turquoise duopolist is set: ... 
; ... - on "fluctuation", the pricing fluctuates in a little range, with sinusoidal corrections; ...
; ... - on "growth", the pricing increases with a sinusoidal trend; ...
; ... - on "fall", the pricing decreases with a sinusoidal trend, until it sinks under 1, where it begins fluctuating randomly ...
; ... from 1 to 5 inclusive    
  if price1-trend = "fluctuation" [ifelse price1 >= 1 
                                      [set price1 precision (price1 + sin (random (pi / 2)) - sin (random (pi / 2))) 2]
                                      [set price1 price1 + 1]]  
  if price1-trend = "growth" [ifelse price1 >= 1
                                 [set price1 precision (price1 + sin (random (pi / 2))) 2]
                                 [set price1 price1 + 1]]
  if price1-trend = "fall" [ifelse price1 >= 1
                               [set price1 precision (price1 - sin (random (pi / 2))) 2]
                               [set price1 price1 + 1 + random 5]]
    
; if the price trend for the orange duopolist is set: ... 
; ... - on "fluctuation", the pricing fluctuates in a little range, with cosinusoidal corrections; ...
; ... - on "growth", the pricing increases with a "parasigmoidal" trend; ...
; ... - on "fall", the pricing decreases with a cosinusoidal trend, until it sinks under 1, where it begins fluctuating randomly ...
; ... from 1 to 5 inclusive                                                          
  if price2-trend = "fluctuation" [ifelse price2 >= 1 
                                      [set price2 precision (price2 + cos (random (pi / 2)) - cos (random (pi / 2))) 2]
                                      [set price2 price2 + 1]]
  if price2-trend = "growth" [ifelse price2 >= 1
                                 [set price2 precision (price2 + 2 / (1 + e) ^ (ticks / price2)) 2]
                                 [set price2 price2 + 1]]
  if price2-trend = "fall" [ifelse price2 >= 1
                               [set price2 precision (price2 - cos (random (pi / 2))) 2]
                               [set price2 price2 + 1 + random 5]]
end

to update-plots
  set-current-plot "earns"
  set-current-plot-pen "duopolist 1"
  plot [earns] of duopolist duopolist1
  set-current-plot-pen "duopolist 2"
  plot [earns] of duopolist duopolist2  
  set-current-plot "consumers provided"
  set-current-plot-pen "by duopolist 1"
  plot count consumers with [color = turquoise or color = turquoise - 0.5 or color = turquoise - 1 or color = turquoise - 1.5]
  set-current-plot-pen "by duopolist 2"
  plot count consumers with [color = orange or color = orange - 0.5 or color = orange - 1 or color = orange - 1.5]
  set-current-plot-pen "by no one"
  plot count consumers with [color = pink - 1] 
  set-current-plot "distance traveled"
  ifelse only-if-near?
     [set-current-plot-pen "max"
      plot max [distance duopolist nearest] of consumers with [distance duopolist nearest < lim-distance]
      set-current-plot-pen "mean"
      plot mean [distance duopolist nearest] of consumers with [distance duopolist nearest < lim-distance]
      set-current-plot-pen "min"
      plot min [distance duopolist nearest] of consumers with [distance duopolist nearest < lim-distance]]
     [set-current-plot-pen "max"
      plot max [distance duopolist nearest] of consumers
      set-current-plot-pen "mean"
      plot mean [distance duopolist nearest] of consumers
      set-current-plot-pen "min"
      plot min [distance duopolist nearest] of consumers]
end