Step 7. Add seasons
1. Winter is coming
Now that you have worked on the important bases for the Game of Thrones model, it's time to have some fun with seasons and the inevitable whitewalkers that come with winter.
​
In this step, you will change the landscape a bit by adding snow north of the wall (which will reduce the productivity of the patches), as well as introduce erratic seasons using random values.
​
You will then create a breed of whitewalkers who kill any living being they encounter and transform them into new whitewalkers (yes, I know, technically, they would be wights, but remember... this is a model). In unchecked environments, they can multiply quickly. Will the realm survive? For how long?
​
First step first: Create a new global variable for season and set it to "summer" in the setup procedure.
globals [
max-sheep ; don't let the sheep population grow too large
land-patches ; keeps track of the patches that are on land
players ; records who will play the prisoner's dilemma
average-household-strength ; calculates the average throne score
season ; record the current season
]
globals [
max-sheep
land-patches
players
average-household-strength
season
]
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
setup-houses ; call the setup-houses procedure to identify the kingdom in which each patch falls
setup-cities ; call the setup-cities procedure to create cites
setup-roads ; call the setup-road procedure to create roads
set season "summer" ; the model starts in summer, like the books
to setup
clear-all
setup-world
setup-wall
setup-houses
setup-cities
setup-roads
set season "summer"
2. Reporter to change seasons
Create a reporter procedure called change-season that changes the season. Here, fall fill follow summer, and winter will follow fall, but spring will never come because... well, we're still waiting for that book!
​
Every time the season changes, the grass will take longer to regrow to show reduced productivity of the land.
​
After writing that reporter, go to the Interface and create a slider called season-change-rate with values 0-100.
​
Then, in the code, call the reporter you just created at a random time with max value set by the season-change-rate slider. This means that seasons will change at a random rate, controlled by that slider.
to-report change-season [ current-season ] ; observer procedure
; if the current season is summer, it becomes fall and the grass takes longer to regrow
ifelse current-season = "summer" [
set grass-regrowth-time ( grass-regrowth-time + 10 )
print "Fall is here. Winter is coming."
report "fall" ; changes season to fall
][ ; if it is currently fall, it becomes winter and the grass takes even longer to regrow
ifelse current-season = "fall" [
set grass-regrowth-time ( grass-regrowth-time + 10 )
print "Winter is here."
report "winter" ; changes season to winter
][ ; if it's already winter, it stays winter, but the grass does not change anymore
report "winter"
]
]
end
to-report change-season [ current-season ]
ifelse current-season = "summer" [
set grass-regrowth-time ( grass-regrowth-time + 10 )
print "Fall is here. Winter is coming."
report "fall" ; changes season to fall
][
ifelse current-season = "fall" [
set grass-regrowth-time ( grass-regrowth-time + 10 )
print "Winter is here."
report "winter"
][
report "winter"
]
]
end
to go
[ ... ]
​
ask land-patches [ grow-grass ]
if random season-change-rate < 1 [ ; roll the dice with max set by slider
set season change-season season ; if the value is below, this calls the reporter that changes the season
]
to go
[ ... ]
​
ask land-patches [ grow-grass ]
if random season-change-rate < 1 [
set season change-season season
]
3. Let it snow!
While adding seasons is great, we know that the land north of the wall is usually pretty wintery already.
​
So, let's now set the land north of the wall to be snowy, with lower resources for sheep and men.
​
To do so, create a new snow? patch variable and add some code to the setup procedure so that patches north of the wall have snow and set their color to white.
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
road? ; identify if the patch is part of a road
border? ; identify if a patch is at the border between two house territories
resources ; records how much resources there are on patch
snow? ; records the presence or absence of snow on the patch
]
patches-own [
countdown
land?
wall?
house
house-color
road?
border?
resources
snow?
]
to setup
[ ... ]
​
ask land-patches [ ; ask only land patches to do what's between the square brackets
set snow? false ; by default, patches do not have snow
ifelse road? = true [
set pcolor black ; roads are black and do not have resources
][
set road? false ; default value
ifelse house = "Wildlings" [ ; quick way to identify patches north of the wall
set snow? true
set pcolor white
set countdown grass-regrowth-time * 1.5 ; grass takes longer to regrow
set resources sheep-gain-from-food / 2 ; grass also has less nutritious
][
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 resources sheep-gain-from-food ; each grassy patch starts with enough resources to feed one sheep
][
set countdown random grass-regrowth-time ; initialize grass regrowth clocks randomly for brown patches
set resources 0 ; brown patches have no resources
]
] ; closes the ifelse Wildlings statement
]
]
to setup
[ ... ]
​
ask land-patches [
set snow? false
ifelse road? = true [
set pcolor black
][
set road? false
ifelse house = "Wildlings" [
set snow? true
set pcolor white
set countdown grass-regrowth-time * 1.5
set resources sheep-gain-from-food / 2
][
set pcolor one-of [ green brown ]
ifelse pcolor = green [
set countdown grass-regrowth-time
set resources sheep-gain-from-food
][
set countdown random grass-regrowth-time
set resources 0
]
]
]
]
4. Make the appropriate changes everywhere
If you click setup now, you should see that the land beyond the wall is all white. Isn't that neat?!
​
But what happens when you click go? Automatically, the patches change to green as if nothing you coded actually happened. Why is that?
​
Well, you haven't yet integrated how snow affects the way that grass grows back and how that affects the patches colors. To do so, you need to make a few changes to the grow-grass and the go procedures as seen below.
​
to grow-grass ; patch procedure
; countdown on brown patches: if you reach 0, grow some grass
if resources = 0 [ ; if there are no more resources
ifelse countdown <= 0 [ ; and the countdown reached 0
ifelse snow? [
set resources sheep-gain-from-food / 2 ; if the patch has snow, it has less resources ...
set countdown grass-regrowth-time * 1.5 ; ... and the countdown is longer to regrowth
][
set pcolor green
set resources sheep-gain-from-food ; regain resources
set countdown grass-regrowth-time
]
][
set countdown countdown - 1
]
]
end
to grow-grass
if resources = 0 [
ifelse countdown <= 0 [
ifelse snow? [
set resources sheep-gain-from-food / 2
set countdown grass-regrowth-time * 1.5
][
set pcolor green
set resources sheep-gain-from-food
set countdown grass-regrowth-time
]
][
set countdown countdown - 1
]
]
end
to go
[ ... ]
​
ifelse display-house-ownership? [
ask land-patches [ ; Only the land patches
set pcolor house-color ; Change their colors to the house that just conquered it
]
][
ask land-patches [
ifelse snow? [
set pcolor white ; snowy patches remain white
][
ifelse resources = 0 [
set pcolor brown ; depleted patches are brown
][
set pcolor green ; patches with grass are green
]
]
]
]
to go
[ ... ]
​
ifelse display-house-ownership? [
ask land-patches [
set pcolor house-color
]
][
ask land-patches [
ifelse snow? [
set pcolor white
][
ifelse resources = 0 [
set pcolor brown
][
set pcolor green
]
]
]
]
5. It's a winter wonderland. But, is it?
While I do love snow as it is peaceful and quiet, I also know that snow is not a good omen in Westeros. You know what comes with the cold and the snow: Whitewalkers and their army of wights!
​
In the next step, you will create a new breed of whitewalkers. But, as this model was originally designed to teach our students to work with NetLogo, you will do so in a slightly different way this time.
​
Here, you will use an nls file, which is a way to keep parts of models on separate physical documents.
​
To do so, open the text editor that is available on your operating system, save an empty file with the name "Whitewalkers.nls" and place it in the same folder as your model. Pay close attention to the extension, it has to be "nls" to work. If you cannot save the file directly in that format, simply save it as a .txt and change the extension manually in Finder/File Explorer.
​
Then, in your model, go to the code tab and add a call to that file at the top of the code, using the lines shown below.
__includes [
"Whitewalkers.nls"
]
extensions [ gis nw rnd profiler ] ; load the gis, nw, and rnd extensions to the model
__includes [
"Whitewalkers.nls"
]
extensions [ gis nw rnd profiler ]
6. Using nls files
If you click on the checkmark, it will show a new tab in the window or it will call an error and open a new tab called "Whitewalkers.nls" with some text in it. If that is the case, simply delete all text in that tab and save. This should fix the error.
​
The nls file allows you to keep some code in separate files. Every line of code you write in this new tab within NetLogo will be saved to the text file you created (only if you save it manually, however, so keep that in mind).
​
In nls files, you can write your own additional new variables as well as new procedures.
​
Let's start this process: in the Whitewalker.nls tab, create the new breed of Whitewalkers.
​
Then, create a new procedure that create icy blue white walkers North of the wall when winter is here.
​
You will need to set the turtle shape to "whitewalkers," which is a shape we created. You can import it from this model.
​
Finally, let's call that new procedure from the go procedure, when the season changes from fall to winter.
breed [ Whitewalkers whitewalker ] ; breed of whitewalkers, as they are not human
breed [ Whitewalkers whitewalker ]
to winter-is-here ; observer procedure
; at the beginning, there are only 10 whitewalkers
ask n-of 10 patches with [ snow? = true ][ ; only snowy patches can create whitewalkers
sprout-whitewalkers 1 [
set size 6 ; they are slightly bigger than humans
set heading 180 ; as soon as they start, they are heading south
set shape "whitewalker"
set color 98
]
]
end
to winter-is-here
ask n-of 10 patches with [ snow? = true ][
sprout-whitewalkers 1 [
set size 6
set heading 180
set shape "whitewalker"
set color 98
]
]
end
to go
[ ... ]
​
if random season-change-rate < 1 [ ; roll the dice with max set by slider
if season = "fall" [ ; if it is fall, but about to change to winter, this triggers the creation of whitewalkers
winter-is-here
]
set season change-season season ; if the value is below, this calls the reporter that changes the season
]
to go
[ ... ]
​
if random season-change-rate < 1 [
if season = "fall" [
winter-is-here
]
set season change-season season
]
7. The march of the dead
Congratulations on creating your own whitewalkers. You can make sure the procedure works by pressing setup and then writing winter-is-here in the command center to call the procedure even if it's still summer. Do you see icy blue scary creatures in north of the wall now?
​
Now, you need to make them start their southern march. They are already all facing South, and just need a move procedure to start marching towards it.
​
Spoiler alert: As whitewalkers will eventually start walking past the wall, they should bring snow with them. So any patch a whitewalker walks on should become snowy and thus less productive.
to others-move ; whitewalkers procedure
rt random 10 ; they wiggle a bit (turning right by up to 10 degree)
lt random 10 ; they wiggle a bit (turning left by up to 10 degree)
; same as for other agents: they stay on land
ifelse patch-ahead 1 != nobody [
ifelse [ land? ] of patch-ahead 1 = true [
fd 1
][
rt 20 ; when they encounter a patch that is not land, they turn 20 degrees to their right
]
][
rt 20 ; when they encounter the boundary of the World, they turn 20 degrees
]
; when they step on a patch that does not have snow, it becomes snowy
if snow? = false [
set snow? true
]
end
to others-move
rt random 10
lt random 10
ifelse patch-ahead 1 != nobody [
ifelse [ land? ] of patch-ahead 1 = true [
fd 1
][
rt 20
]
][
rt 20
]
if snow? = false [
set snow? true
]
end
8. Integrating the march to the rest
As before, you have now created a move procedure, but it is not called anywhere, so the whitewalkers will not start walking just yet. To make sure they do, you have to create a new procedure that will call the others-move procedure, but will also allow whitewalkers to kill any other living beings they encounter.
​
After you create that procedure, edit the go procedure to call it.
​
Finally, just for fun, let's add a user message in the go procedure. If the whitewalkers are the only agents left on the land (remove "turtles" as is shown in red italics below and replace it with the temporary turtle-set), the model stops and it prints "The Night King has won!" Let's just hope this never actually happens...
to winter-advance ; observer procedure
ask whitewalkers [
others-move ; calls the others-move procedure
let living-things ( turtle-set wolves sheep humans ) ; agentset of all living beings
if any? living-things in-radius 1 [ ; if there are any living beings on the same patch
ask living-things in-radius 1 [ die ] ; they are killed and
hatch-whitewalkers 1 ; a new whitewalker takes its place
]
]
end
to winter-advance
ask whitewalkers [
others-move
let living-things ( turtle-set wolves sheep humans )
if any? living-things in-radius 1 [
ask living-things in-radius 1 [ die ]
hatch-whitewalkers 1
]
]
end
to go
[ ... ]
​
if random season-change-rate < 1 [ ; roll the dice with max set by slider
if season = "fall" [ ; if it is fall, but about to change to winter, this triggers the creation of whitewalkers
winter-is-here
]
set season change-season season ; if the value is below, this calls the reporter that changes the season
]
if season = "winter" [
winter-advance ; during winter, whitewalkers move and kill
]
to go
[ ... ]
​
if random season-change-rate < 1 [
if season = "fall" [
winter-is-here
]
set season change-season season
]
if season = "winter" [
winter-advance
]
to go
; stop the model if there are no more wolves, sheep or humans
let living-things ( turtle-set wolves sheep humans )
if not any? turtles living-things [
user-message "The Night King has won!"
stop
]
to go
let living-things ( turtle-set wolves sheep humans )
if not any? turtles living-things [
user-message "The Night King has won!"
stop
]
9. Congratulations!
Congratulations on completing another step in the creation of your own Game of Thrones ABM! You now have most of the elements necessary to study the dynamics of Westeros politics as well as their potential impact on the success of the whitewalkers' conquest of the land.
​
Right now, whitewalkers cannot be killed. They do not need to eat, so their level of energy never goes down and they never die. But, they do turn everyone they encounter into whitewalkers. This is pretty scary.
​
If you want, you can play around with running the model using different parameter settings and see which ones delay the whitewalkers' march and which ones help them. For example, is conflict useful in resisting the dead or not? Have fun with it and don't despair too much with the fact that whitewalkers always win because in the next step, you'll introduce a weapon that men can create and exchange to kill the Night King and his associates.
See you there! If you want to see the finished model for this step, download it here​​.