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.
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!
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 ]
]
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
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 ]
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
]
]
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.