Step 3. Add Westeros

1. Get the GIS extension

In this tutorial, you will add the GIS extension to your NetLogo model and import raster and vector maps to situate your humans-wolves-sheep model into a "realistic" Westeros landscape. You will learn how to change the size of the World window and how those changes impact the visibility and behavior of your agents. 

In NetLogo, extensions are pretty simple to set up. While some extensions are created by users and need to be downloaded, you will not need to do so for the extensions used for this model, as they are already part of the NetLogo package. You just need to activate them at the beginning of your code. Place that line of code before everything else.

extensions [ gis ]   ; activates the gis extension

 

globals [ max-sheep ]  ; don't let the sheep population grow too large

extensions [ gis ]   

 

globals [ max-sheep ]  

2. Download the GIS data

The GIS data you will be using were originally created by cadaei based on ser MountainGoats' map. Both of these datasets are under license CC BY-NC-SA 3.0.

We made a few changes to the GIS dataset to insure that it would work well in NetLogo. You should download that updated GIS data here.

 

**Important: Make sure to place the files in the same folder as your ABM, not in a subfolder.

3. Prepare the World window and patches

In the original Wolf Sheep Predation model, you may have noticed that when the agents move through any 'wall', they reappear on the other side. For example, if a sheep walks to the right limit of the window, it does not bounce back but rather goes through and reappears on the left. This is because the World window is set as a torus, so there are no limits. 

Given that we do not know what lies west of Westeros, but we know that it probably is not Essos, we need to add boundaries to our map.

In the Interface, click on the top right 'Settings' button. This will open the World window settings.

Change the Location of Origin for "Corner" and make sure the corner is the Bottom Left one.

Unclick both boxes that say "World wraps..." You will see that the world now has red lines on all sides. This shows that they are boundaries.

While you are in this settings window, change the Patch size to 3, as the map you will import has a lot more patches than the Wolf-Sheep model, but we want to keep the whole window visible.

And to change the model so that each tick represents a day, change the Tick counter label to "days". This will not change how ticks are called within the code, but will make your Interface more informative.

Then, go to the Code tab. Within the patches-own brackets, add the following variables: value, land?, wall?, house, and house-color. Those variables will take on values from the GIS maps you will import.

WorldWindow.png

patches-own [ 

  countdown   ; used to trigger grass regrowth

  land?  ; boolean that identifies is a cell is land

  wall?  ; boolean that identifies if the cell overlaps the wall (and thus is part of the wall)

  house   ; identifies which house owns the cell

  house-color  ; to show the extent of each house's territory

]

patches-own [ 

  countdown   

  land? 

  wall?  

  house  

  house-color  

]

4. Import the GIS raster data

Before importing the maps, let's explore how adding patch variables changes the patches. Go to the Interface and press Setup. Then, right click on any patch you see, and select "Inspect patch ..." Note that the two numbers following that text indicate the XY coordinates of the patch. This will open a window that focuses on that patch and shows the values to each of its variables. You should be able to see the variables you just added in there. Notice that by default, any new variable is set to 0.

You can inspect any patch or agent in the same way. Inspecting them is a great way to learn about how a model functions and changes during a simulation. It also helps troubleshooting problems.

To import the raster data, you will create a new procedure called setup-world that calls primitives from the gis extension. To call those, you always have to precede the primitive's name by the extension name and one colon.

In the setup-world procedure, you will distinguish between land and water patches, and make the water patches blue.

After creating the procedure, make sure to add setup-world at the top of your setup procedure, so it is called during setup.

While you make changes to the setup procedure, delete the line of code that relates to netlogo-web? (see red italics). We will not need this.

;;; OBSERVER PROCEDURE ;;;

 

to setup-world

  ; Set up a virtual world using GIS raster base maps

  let basemap gis:load-dataset "Land_raster.asc"  ; Loads the GIS data to temp variable basemap

  let world-wd gis:width-of basemap  ; Identifies the width of the GIS raster

  let world-ht gis:height-of basemap  ; Identifies the height of the GIS raster

  resize-world 0 ( world-wd - 1 ) 0 ( world-ht - 1 )  ; Sets the dimensions of the World window to fit the GIS raster

  gis:set-world-envelope gis:envelope-of basemap  ; Transforms the World window based on the GIS raster

  gis:set-sampling-method basemap "NEAREST_NEIGHBOR" ; makes sure resampling is by nearest neighbor

  

  ask patches [ 

    let myX pxcor  ; temp variable to record the X coordinate

    let myY pycor  ; temp variable to record the Y coordinate

    let myCoor ( list myX myY )  ; xy coordinates as a list for the next line

    set house-color gis:raster-sample basemap myCoor  ; Each patch querries the value from the raster at its location

  ]

  ; Identify land patches (house-color >= 0) (water patches have house-color -9999 in the raster)

  ask patches [ 

    ifelse house-color >= 0 [

      set land? true  ; patches with house-color >= 0 are land

    ][  ; closing the if statement

      set land? false  ; patches that have house-color < 0 (-9999 in this case) are water

      set pcolor blue   ; thus they are blue

    ]  ; closing the else statement

  ]  ; closing the "ask patches" statement

 

end

;;; OBSERVER PROCEDURE ;;;

 

to setup-world

 

  let basemap gis:load-dataset "Land_raster.asc" 

  let world-wd gis:width-of basemap

  let world-ht gis:height-of basemap

  resize-world 0 ( world-wd - 1 ) 0 ( world-ht - 1 )

  gis:set-world-envelope gis:envelope-of basemap

  gis:set-sampling-method basemap "NEAREST_NEIGHBOR"

  

  ask patches [ 

    let myX pxcor

    let myY pycor 

    let myCoor ( list myX myY ) 

    set house-color gis:raster-sample basemap myCoor ion

  ]

  

  ask patches [ 

    ifelse house-color >= 0 [

      set land? true 

    ][ 

      set land? false 

      set pcolor blue  

    ] 

  ] 

 

end

to setup

  clear-all

  ifelse netlogo-web? [ set max-sheep 10000 ] [ set max-sheep 30000 ]

 

  setup-world   ; call the setup-world procedure to import GIS data

to setup

  clear-all

  ifelse netlogo-web? [ set max-sheep 10000 ] [ set max-sheep 30000 ]

 

  setup-world 

5. Fix the issues with water patches

Now, you should be able to see some changes to the World window when pressing setup. Try it! What happens? If everything was coded properly, you should now have a taller World window. However, while we coded that water patches should be blue, we do not see them here. All patches still have grass or dirt. Why?

This is simply because of the piece of setup code that follows the setup-world call. That piece of code asks all patches to choose a green/brown color, so this basically overwrites the code that sets water patches to blue.

To fix this, you need to ask only land patches to choose a green/brown color. To do so, you will create a new global variable that will record which patches are land patches. Note that variable names should never have spaces between words, which is why you will call this variable land-patches.

Then change the setup code to ask only land patches to choose a color (replace the code in red by the code in blue). Then, press setup again and see Westeros appear!

Westeros_noWesteros.png

globals [ 

  max-sheep     ; don't let the sheep population grow too large

  land-patches   ; keeps track of the patches that are on land

]  

globals [ 

  max-sheep    

  land-patches 

]  

  setup-world  ; call the setup-world procedure to import GIS data

  

  set land-patches patches with [ land? = true ]  ; Creates a patchset that comprises only land patches

 

  ask land-patches [   ; ask only land patches to do what's between the square brackets

  ask patches [   ; ask all patches to do what's between the square brackets

    set pcolor one-of [ green brown ]   ; each patch chooses a color between the two

    ifelse pcolor = green   ; if they chose green...

      [ set countdown grass-regrowth-time ]   ; they need to set their countdown for when they'll get eaten

      [ set countdown random grass-regrowth-time ]   ; initialize grass regrowth clocks randomly for brown patches

  ]

  setup-world 

  

  set land-patches patches with [ land? = true ] 

 

  ask land-patches [ 

  ask patches [  

    set pcolor one-of [ green brown ] 

    ifelse pcolor = green  

      [ set countdown grass-regrowth-time ]  

      [ set countdown random grass-regrowth-time ] 

  ]

Westeros_wtWesteros.png

6. Can sheep swim?

Alright, you should now see the outline of Westeros, which is great, but what do you notice in terms of the position of sheep, wolves, and people? They are set on land but also on water. That's problematic. 

Next step will be to make sure that agents are positioned on land only, and that they also do not walk on water. This will require a few changes here and there in the code (this shows you how making one small change to a model may have important impacts for the rest of the model).

First, you will need to change how sheep, wolves, and humans are created. See below, remove the lines in red and add the lines in blue. Change the size of humans to 5 to make them more visible.

  create-sheep initial-number-sheep  ; create the sheep, then initialize their variables

  ask n-of initial-number-sheep land-patches [ ; asks n (n from the slider) patches to prout one sheep.

    sprout-sheep 1 [

      set shape "sheep"

      set color white

      set size 1.5  ; easier to see

      set label-color blue - 2

      set energy random (2 * sheep-gain-from-food)

    ]

    setxy random-xcor random-ycor

  ]

 

  create-wolves initial-number-wolves  ; create the wolves, then initialize their variables

  ask n-of initial-number-wolves land-patches [ ; asks n (n from the slider) patches to sprout one wolf.

    sprout-wolves 1 [

      set shape "wolf"

      set color black

      set size 2  ; easier to see

      set energy random (2 * wolf-gain-from-food)

      setxy random-xcor random-ycor

      set domesticated? false    ; by default, wolves are wild

    ]

  ]

  create-sheep initial-number-sheep  ; create the sheep, then initialize their variables

  ask n-of initial-number-sheep land-patches [

    sprout-sheep 1 [

      set shape "sheep"

      set color white

      set size 1.5 

      set label-color blue - 2

      set energy random (2 * sheep-gain-from-food)

    ]

    setxy random-xcor random-ycor

  ]

 

  create-wolves initial-number-wolves  ; create the wolves, then initialize their variables

  ask n-of initial-number-wolves land-patches [

    sprout-wolves 1 [

      set shape "wolf"

      set color black

      set size 2  

      set energy random (2 * wolf-gain-from-food)

      setxy random-xcor random-ycor

      set domesticated? false  

    ]

  ]

to add-humans

  ; Create as many humans as the slider

  ask n-of initial-number-humans land-patches [  ; This way of creating humans prevents having to give them coordinates

  sprout-humans 1 [   ; Create humans, then initialize their variables

    set shape "person"   ; humans are "person" shaped

    set size 5   ; a bit bigger than turtles and wolves

    set color blue   ; people will be blue for now

    set energy random (2 * wolf-gain-from-food)   ; the initial energy is up to the gain that wolves get * 2

    ]

  ]

 

end

to add-humans

 

  ask n-of initial-number-humans land-patches

  sprout-humans 1 [  

    set shape "person"  

    set size 5 

    set color blue  

    set energy random (2 * wolf-gain-from-food) 

    ]

  ]

 

end

6. Fixing movement

You fixed the setup procedure, and now all agents are positioned on land rather than water. But, what happens when you click Go? Agents walk on water now..., of course! 

In the next step, you will change the move procedure so that agents turn around when they encounter the edge of the window as well as water. 

to move  ; turtle procedure

  rt random 50   ; turn right by a randon angle up to 50

  lt random 50   ; turn left by a random angle up to 50

  

  ifelse patch-ahead 1 != nobody [   ; checks if the patch in front of the agent is something (to turn at the edges) 

    ifelse [ land? ] of patch-ahead 1 = true   ; if the patch in front of the agent is land

    [ fd 1 ]   ; if it is land, the agent move one step ahead

    [ rt 180 ]   ; if the patch is water, the agent turns 180 degrees 

  ][ rt 180 ]   ; if the patch is nothing (edge), the agent turns 180 degrees

  

  fd 1

end

to move

  rt random 50

  lt random 50

  

  ifelse patch-ahead 1 != nobody [ 

    ifelse [ land? ] of patch-ahead 1 = true

    [ fd 1 ] 

    [ rt 180 ]

  ][ rt 180 ]

  

  fd 1

end

Wall.png

7. Building the wall

Now that you adapted agents' setup and mobility, let's add a few more Westerosy things to the model. The first thing is the most important to guard the realm of men: The Wall!

In the GIS data you downloaded, there is a shapefile for a wall vector. It is a line that covers the rough extent of the wall. Create a new procedure that imports that line and asks all patches that intersect with it to become the wall.

The wall should be white as it is made of ice, and will be labelled as "water" so that agents cannot walk through it.

Make sure to call setup-wall in the setup procedure, right after setup-world, and before defining land-patches, because you want to make sure that land-patches do not include wall patches.

to setup-wall   ; observer procedure

  ; load the vector dataset of the wall into the temporary variable wall-basemal

  let wall-basemap gis:load-dataset "Wall.shp"

  ; ask patches that intersect with the wall line to set their wall? variable to true

  ask patches gis:intersecting wall-basemap [

    set land? false   ; Wall patches should not be walked on. This excludes them from the land-patches set

    set wall? true   ; to keep track of which patches are part of the wall

    set pcolor white   ; The wall is white as it is made of ice

  ]

  

end

to setup-wall 

 

  let wall-basemap gis:load-dataset "Wall.shp"

 

  ask patches gis:intersecting wall-basemap [

    set land? false 

    set wall? true

    set pcolor white

  ]

  

end

to setup

  clear-all

 

  setup-world  ; call the setup-world procedure to import GIS data

  setup-wall   ; call the setup-wall procedure to import the Wall vector

to setup

  clear-all

 

  setup-world

  setup-wall

8. Separating the kingdoms

Westeros has 7 kingdoms, so you need to separate them and have humans take on the identity of the house to which they pledged their allegiance.

To do so, you will import a new shapefile that has polygons covering each kingdom. The polygons hold the identity of the house they are claimed by. You will use these data to set humans' color to their respective house.

Create a new procedure that will be called in the setup, right after setup-wall.

Change the setup-humans procedure so that humans set their color based on the house-color of the patch on which they are created.

Finally, remove the Go statement that stops the model if all wolves die. This will allow your model to run even if the animal settings are not well calibrated.

to setup-houses   ; observer procedure

  ; load the vector dataset of houses  to the temporary houses-basemap variable

  let houses-basemap gis:load-dataset "W_political_revised.shp"

  ; set the min and max threshold for patches to decide if they are part of the polygon or not

  ; to be a part, a patch has to be covered at least 50% by a polygon

  gis:set-coverage-minimum-threshold 0.5

  gis:set-coverage-maximum-threshold 1

  ; ask patches to set their house variable based on the claimbedBy variable of the polygon they fall on

  gis:apply-coverage houses-basemap "CLAIMEDBY" house

  ; some cleaning necessary as the polygons do not fit perfectly with the raster

  let list-houses remove-duplicates ([ house ] of patches with [ land? = true ])

  set list-houses remove "no one" list-houses      ; removes the name associated with water

  ask patches [

    if land? = false and member? house list-houses   ; houses that fall within a polygon but are water...

    [ set house "no one" ]   ; ... change their house to "no one" (water)

  ]

  

end

to setup-houses 

  let houses-basemap gis:load-dataset "W_political_revised.shp"

  

  

  gis:set-coverage-minimum-threshold 0.5

  gis:set-coverage-maximum-threshold 1

  

  gis:apply-coverage houses-basemap "CLAIMEDBY" house

 

  let list-houses remove-duplicates ([ house ] of patches with [ land? = true ])

  set list-houses remove "no one" list-houses    

  ask patches [

    if land? = false and member? house list-houses 

    [ set house "no one" ] 

  ]

  

end

to setup

  clear-all

 

  setup-world    ; call the setup-world procedure to import GIS data

  setup-wall    ; call the setup-wall procedure to create the wall

  setup-houses    ; call the setup-houses procedure to identify the kingdom in which each patch falls

to setup

  clear-all

 

  setup-world

  setup-wall 

  setup-houses 

to add-humans   ; observer procedure

  ; Create as many humans as the slider

  ask n-of initial-number-humans land-patches [  ; This way of creating humans prevents having to give them coordinates

  sprout-humans 1 [   ; Create humans, then initialize their variables

    set shape "person"   ; humans are "person" shaped

    set size 5   ; a bit bigger than turtles and wolves

    set color house-color   ; humans take the house color of the patch on which they are created

    set energy random (2 * wolf-gain-from-food)   ; the initial energy is up to the gain that wolves get * 2

    ]

  ]

 

end

to add-humans 

 

  ask n-of initial-number-humans land-patches [ 

  sprout-humans 1 [ 

    set shape "person" 

    set size 5 

    set color house-color 

    set energy random (2 * wolf-gain-from-food)

    ]

  ]

 

end

to go

  ; stop the model if there are no wolves and no sheep

  if not any? turtles [ stop ]

  ; stop the model if there are no wolves and the number of sheep gets very large

  if not any? wolves and count sheep > max-sheep [ user-message "The sheep have inherited the earth" stop ]

to go

  

  if not any? turtles [ stop ]

  ; stop the model if there are no wolves and the number of sheep gets very large

  if not any? wolves and count sheep > max-sheep [ user-message "The sheep have inherited the earth" stop ]

NewPerson.png

9. Find the proper attire

Now that the simulation is set in Westeros, it would be nice to have humans dressed in the proper attire. We already created a shape to take care of that. Download the model that holds it here.

 

Then, in your Westeros model, go to Tools -> Turtles Shapes Editor. You can see here all the shapes that are included by default. To add the one we created, click the Import from Model button and browse to the HumansShape model you just downloaded. Select the "Person" shape. Replace the old one with this one. This will apply only for this model. 

 

You do not need to change the code; it will automatically choose this new version of the "person" shape.

10. Final clean up

At this point, we will not need the model version that deals only with wolves and sheep anymore. So, we should remove all mentions of that version in the Interface and the code (first in Setup, then in Go). Do not forget to delete the "model-version" chooser completely.

  if model-version = "sheep-wolves-humans-grass" ; Check model switch. If applicable, create humans

  [ add-humans ]    ; call the add-humans procedure

  if model-version = "sheep-wolves-humans-grass" ; Check model switch. If applicable, create humans

  [ add-humans ]   

  if model-version = "sheep-wolves-humans-grass" [     ; checks the version. If there are humans, ask them to do stuff

    ask humans [    ; human actions, almost all the same as sheep and wolves

      move     ; calls the "move" procedure

      set energy energy - 1     ; humans also lose energy as they move

      humans-eat    ; Humans eat some of the sheep that are on their patch or the grass if available

      domesticate-wolves    ; Humans domesticate some of the wolves they encounter

      humans-feed-animals    ; humans feed their domesticated wolves

      death    ; humans die when they run out of energy

      reproduce humans-reproduce    ; humans reproduce at a random rate governed by a slider

    ]

  ]

  if model-version = "sheep-wolves-humans-grass" [     ; checks the version. If there are humans, ask them to do stuff

    ask humans [    

      move  

      set energy energy - 1 

      humans-eat 

      domesticate-wolves 

      humans-feed-animals 

      death

      reproduce humans-reproduce 

    ]

  ]

Final.png

11. Success!

If you press Setup at this point, you should see Westeros with humans colored by the house to which they pledge allegiance. Humans who are created at the wall are in black (Night's watch), whereas humans created north of the wall are in light grey (wildlings). 

Congratulations on importing GIS data to create a model of Westeros!

If you want to see the finished model for this step, download it here.

In the next step, you will create networks between castles/establishments, and see which ones may be the most influential places.