Step 8. Add obsidian

1. Help Westerosi defend the realm

If you run the model at the moment, the Night King will always win, simply because the whitewalkers kill everything they touch and they themselves never die.

It's time to introduce a new weapon to help balance the scale a bit: obsidian! 

Obsidian, or dragonglass, is the only weapon known to men that can kill whitewalkers (apart from dragons, but they're not here yet). Here, you will have people mining obsidian from Dragonstone (only known source to date as Sam lost most of the points he found at the Fist of the First Men). There will be different ways in which the setup of the obsidian will take place: through location, network, or territory.

1. Location: Only Dragonstone will have a cache of obsidian. Anybody that walks by Dragonstone (i.e., the closest patch on the shore next to the Dragonstone island) will obtain obsidian.

2. Network: Dragonstone and the cities that can be reached from it via the

networks will get caches of obsidian. This takes into consideration the direction of the links. If links are directed, only the linked cities that can be reached from Dragonstone (or intermediary cities) will get obsidian caches. If links are undirected, all linked cities will get some.

3. Territory: All cities that are held by the house holding Dragonstone and the people who identify with that house will automatically get obsidian. This may change over time if conflict? is ON and Dragonstone gets taken over by a new house.

People will gain obsidian when they travel to a location that has a cache or when they encounter someone who has enough pieces to share. 

To set all this up, add a human variable called obsidian, a city variable called obsidian-cache, and an Interface chooser that shows all setup possibilities.

Chooser.png

humans-own [ obsidian ]  ; determines how much obsidian the human has to kill whitewalkers

 

cities-own [

  city-name   ; the name of the city or castle

  city-size   ; size of the city (taken from the shapefile)

  centrality   ; will take the centrality measure of the city when we create networks with roads

  obsidian-cache?   ; if the city has obsidian

]

humans-own [ obsidian ] 

 

cities-own [

  city-name   

  city-size  

  centrality  

  obsidian-cache?  

]

2. Update the network

When we created the network in step 4, we used the road to show us which castles should be linked with which. Dragonstone being on an island, it was not included. However, to get obsidian to the main land, we need to add it to the network.

Change the setup-directed-networks and setup-undirected-networks procedures to create a link between Dragonstone and King's Landing. In the directed networks, the link should be from Dragonstone to King's Landing (arbitrary choice based on the fact that goods usually travel to the bigger city).

to setup-undirected-network   ; observer procedure

  ; Hardcoding those temp variables so that they can be called below (shorter code below)

  let castle-black one-of cities with [ city-name = "Castle Black" ]

  let winterfell one-of cities with [ city-name = "Winterfell" ]

  let moat-cailin one-of cities with [ city-name = "Moat Cailin" ]

  let crossroad-inn one-of cities with [ city-name = "Crossroads Inn" ]

  let lannisport one-of cities with [ city-name = "Lannisport" ]

  let eyrie one-of cities with [ city-name = "The Eyrie" ]

  let kings-landing one-of cities with [ city-name = "King's Landing" ]

  let maidenpool one-of cities with [ city-name = "Maidenpool" ]

  let highgarden one-of cities with [ city-name = "Highgarden" ]

  let storms-end one-of cities with [ city-name = "Storm's End" ]

  let oldtown one-of cities with [ city-name = "Oldtown" ]

  let dragonstone one-of cities with [ city-name = "Dragonstone" ]

  ; These roads are an oversimplification of the roads in Westeros and focus on cities connected by the big roads only

  ask castle-black [ create-link-with winterfell ]  ; Road between Castle Black and Winterfell

  ask winterfell [ create-link-with moat-cailin ]  ; Road between Winterfell and Moat Cailin

  ask moat-cailin [ create-link-with crossroad-inn ]  ; Road between Moat Cailin to the Inn at the crossroads

  ask lannisport [ create-link-with highgarden ]  ; Road between Lannisport and Highgarden

  ask highgarden [ create-link-with oldtown ]  ; Road between Highgarden and Old Town

  ask crossroad-inn [

    create-link-with lannisport  ; Road between the inn and Lannisport

    create-link-with eyrie  ; Road between the inn and the Eyrie

    create-link-with kings-landing  ; Road between the inn and King's Landing

  ]

  ask kings-landing [

    create-link-with maidenpool  ; Road between King's Landing and Maidenpool

    create-link-with lannisport  ; Road between King's Landing and Lannisport

    create-link-with highgarden  ; Road between King's Landing and Highgarden

    create-link-with storms-end  ; Road between King's Landing and Storm's End

    create-link-with dragonstone ; Road between King's Landing and Dragonstone (maritime "road")

  ]

 

end

to setup-undirected-network  

 

  let castle-black one-of cities with [ city-name = "Castle Black" ]

  let winterfell one-of cities with [ city-name = "Winterfell" ]

  let moat-cailin one-of cities with [ city-name = "Moat Cailin" ]

  let crossroad-inn one-of cities with [ city-name = "Crossroads Inn" ]

  let lannisport one-of cities with [ city-name = "Lannisport" ]

  let eyrie one-of cities with [ city-name = "The Eyrie" ]

  let kings-landing one-of cities with [ city-name = "King's Landing" ]

  let maidenpool one-of cities with [ city-name = "Maidenpool" ]

  let highgarden one-of cities with [ city-name = "Highgarden" ]

  let storms-end one-of cities with [ city-name = "Storm's End" ]

  let oldtown one-of cities with [ city-name = "Oldtown" ]

  let dragonstone one-of cities with [ city-name = "Dragonstone" ]

  

  ask castle-black [ create-link-with winterfell ] 

  ask winterfell [ create-link-with moat-cailin ]  

  ask moat-cailin [ create-link-with crossroad-inn ]

  ask lannisport [ create-link-with highgarden ] 

  ask highgarden [ create-link-with oldtown ] 

  ask crossroad-inn [

    create-link-with lannisport  

    create-link-with eyrie  

    create-link-with kings-landing  

  ]

  ask kings-landing [

    create-link-with maidenpool 

    create-link-with lannisport 

    create-link-with highgarden 

    create-link-with storms-end 

    create-link-with dragonstone 

  ]

 

end

to setup-directed-network   ; observer procedure

  ; Hardcoding those temp variables so that they can be called below (shorter code below)

  let castle-black one-of cities with [ city-name = "Castle Black" ]

  let winterfell one-of cities with [ city-name = "Winterfell" ]

  let moat-cailin one-of cities with [ city-name = "Moat Cailin" ]

  let crossroad-inn one-of cities with [ city-name = "Crossroads Inn" ]

  let lannisport one-of cities with [ city-name = "Lannisport" ]

  let eyrie one-of cities with [ city-name = "The Eyrie" ]

  let kings-landing one-of cities with [ city-name = "King's Landing" ]

  let maidenpool one-of cities with [ city-name = "Maidenpool" ]

  let highgarden one-of cities with [ city-name = "Highgarden" ]

  let storms-end one-of cities with [ city-name = "Storm's End" ]

  let oldtown one-of cities with [ city-name = "Oldtown" ]

  let dragonstone one-of cities with [ city-name = "Dragonstone" ]

  ; These roads are an oversimplification of the roads in Westeros and focus on cities connected by the big roads only.

  ; For directed networks, the direction of the links is arbitrary and does not follow any ASOIAF data

  ask castle-black [ create-link-from winterfell ]     ; Road to Castle Black from Winterfell (Brothers of the watch can't go back home)

  ask winterfell [

    create-link-from moat-cailin

    create-link-to moat-cailin   ; Bidirectional road between Winterfell and Moat Cailin

  ]

  ask moat-cailin [ create-link-to crossroad-inn ]  ; Road from Moat Cailin to the Inn at the crossroads

  ask crossroad-inn [

    create-link-to lannisport  ; Road from the inn to Lannisport

    create-link-from eyrie  ; Road to the inn from the Eyrie

    create-link-from kings-landing  ; Road to the inn from King's Landing

  ]

  ask kings-landing [

    create-link-from maidenpool  ; Road to King's Landing from Maidenpool

    create-link-from lannisport  ; Road to King's Landing from Lannisport

    create-link-from highgarden  ; Road to King's Landing from Highgarden

    create-link-from storms-end  ; Road to King's Landing from Storm's End (all roads lead to King's Landing)

    create-link-from dragonstone ; Road from Dragonstone to King's Landing

  ]

  ask lannisport [ create-link-to highgarden ]  ; Road from Lannisport to Highgarden

  ask highgarden [ create-link-from oldtown ]  ; Road to Highgarden from Oldtown

 

end

to setup-directed-network  

 

  let castle-black one-of cities with [ city-name = "Castle Black" ]

  let winterfell one-of cities with [ city-name = "Winterfell" ]

  let moat-cailin one-of cities with [ city-name = "Moat Cailin" ]

  let crossroad-inn one-of cities with [ city-name = "Crossroads Inn" ]

  let lannisport one-of cities with [ city-name = "Lannisport" ]

  let eyrie one-of cities with [ city-name = "The Eyrie" ]

  let kings-landing one-of cities with [ city-name = "King's Landing" ]

  let maidenpool one-of cities with [ city-name = "Maidenpool" ]

  let highgarden one-of cities with [ city-name = "Highgarden" ]

  let storms-end one-of cities with [ city-name = "Storm's End" ]

  let oldtown one-of cities with [ city-name = "Oldtown" ]

  let dragonstone one-of cities with [ city-name = "Dragonstone" ]

 

  

  ask castle-black [ create-link-from winterfell ]    e)

  ask winterfell [

    create-link-from moat-cailin

    create-link-to moat-cailin  

  ]

  ask moat-cailin [ create-link-to crossroad-inn ]  

  ask crossroad-inn [

    create-link-to lannisport  

    create-link-from eyrie 

    create-link-from kings-landing 

  ]

  ask kings-landing [

    create-link-from maidenpool 

    create-link-from lannisport

    create-link-from highgarden

    create-link-from storms-end 

    create-link-from dragonstone 

  ]

  ask lannisport [ create-link-to highgarden ] 

  ask highgarden [ create-link-from oldtown ] 

 

end

3. Set up the initial sources

Import the "person with obsidian" turtle shape from this model.

Create a new setup procedure that will add caches of obsidian to Dragonstone and to any other cities and people involved, depending on the obsidian-distribution method chosen in the Interface. Integrate it to the setup procedure.

Integrate this new procedure to the main setup procedure, but make sure that you call it after creating the networks, or else the network distribution will not work.

Then, add a few lines of code to change the go procedure to update who has control over Dragonstone if obsidian-distribution is set to "territory" as a new house might take take it over by winning the prisoner's dilemma game, and thus inherit its obsidian.

to setup-obsidian   ; observer procedure

 

  ask cities [

    set obsidian-cache? false   ; by default, cities do not have obsidian

  ]

 

  let dragonstone one-of cities with [ city-name = "Dragonstone" ]

  ask dragonstone [

    set obsidian-cache? true   ; but Dragonstone has a cache

  ]

 

  if obsidian-distribution = "network" [  ; if the distribution is based on network

    ask cities with [ any? my-links ][   ; focuses only on connected cities

      ask dragonstone [

        if nw:distance-to myself != false [   ; identifies the cities that can be reached by Dragonstone

          ask myself [   ; those connected cities get caches of obsidian

            set obsidian-cache? true 

          ]

        ]

      ]

    ]

  ]

  if obsidian-distribution = "territory" [  ; if the distribution is based on territory

    ask cities with [ house-color = [ house-color ] of Dragonstone ][   ; all cities from the same house...

      set obsidian-cache? true   ; ... get a cache

    ]

  ]

 

end

to setup-obsidian   

 

  ask cities [

    set obsidian-cache? false  

  ]

 

  let dragonstone one-of cities with [ city-name = "Dragonstone" ]

  ask dragonstone [

    set obsidian-cache? true  

  ]

 

  if obsidian-distribution = "network" [ 

    ask cities with [ any? my-links ][  

      ask dragonstone [

        if nw:distance-to myself != false [  

          ask myself [  

            set obsidian-cache? true 

          ]

        ]

      ]

    ]

  ]

  if obsidian-distribution = "territory" [ 

    ask cities with [ house-color = [ house-color ] of Dragonstone ][  

      set obsidian-cache? true  

    ]

  ]

 

end

to setup

  [ ... ]

 

  ifelse link-type = "undirected" [  ; check which link type is chosen in the Interface

    setup-undirected-network  ; create the undirected network

  ][

    setup-directed-network  ; create the directed network

  ]

  

  setup-obsidian   ; call the setup-obsidian procedure to distribute obsidian

to setup

  [ ... ]

 

  ifelse link-type = "undirected" [ 

    setup-undirected-network

  ][

    setup-directed-network  

  ]

  

  setup-obsidian  

  if conflict? [   ; if conflict? switch is ON (same as "if conflict? = true"), houses will fight using the prisoner's dilemma

    update-players    ; update the list of possible players

    if length players > 1 [   ; the houses fight only if there are more than one house left

      houses-fight-for-territory

    ]

  ]

  ; Updates the distribution of obsidian if Dragonstone changes owner

  if obsidian-distribution = "territory" [

    let dragonstone one-of cities with [ city-name = "Dragonstone" ]

    let dragonstone-color [ color ] of dragonstone

    ask cities with [ color = dragonstone-color ][

      set obsidian-cache? true   ; mimics if a different house takes over and distributes obsidian to all its people

    ]

  ]

  if conflict? [   

    update-players  

    if length players > 1 [  

      houses-fight-for-territory

    ]

  ]

  

  if obsidian-distribution = "territory" [

    let dragonstone one-of cities with [ city-name = "Dragonstone" ]

    let dragonstone-color [ color ] of dragonstone

    ask cities with [ color = dragonstone-color ][

      set obsidian-cache? true 

    ]

  ]

4. Allow people to pick up obsidian

To insure that as most people as possible can get obsidian, you will allow people to pick up 10 obsidian tools (arbitrary number, why not?) if they walk by a city with obsidian. Given that Dragonstone is on an island, you will need to have a special statement where one person picks up obsidian when within 10 patches of that particular city.

Create a new procedure for this and integrate it to the go procedure.

In this procedure, you will see that every human who picks up obsidian prints a statement in the Command Center. Here, we use the primitive show, which prints the ID of the human doing the action first, followed by the text we added. This will slow down the model a bit, but it is useful if you want to inspect a human with obsidian (to see its cool design... or make sure they actually have 10 tools in their kit). If you do not want those print statements, simply comment this line out. Print statements are very useful for debugging, so do not be afraid to use them.

to pick-up-obsidian   ; human procedure

  

  let picking-obsidian false   ; temp variable to keep track of who is picking up obsidian

  ; For Dragonstone

  let dragonstone one-of cities with [ city-name = "Dragonstone" ] in-radius 10

  if dragonstone != nobody [  ; if Dragonstone is within 10 patches

    set picking-obsidian true   ; the human remembers that it is picking up obsidian

  ]

  ; For other cities with caches

  let city-with-obsidian cities-here with [ obsidian-cache? ]

  if any? city-with-obsidian [  ; if the city visited has a cache

    set picking-obsidian true 

  ]

  

  if picking-obsidian [   ; if the human is picking up

    show "picking up"  ; the human prints its ID and the text here

    set shape "person with obsidian"   ; changes its shape to show its weapon

    set obsidian 10   ; adds 10 tool to its toolkit

  ]

  

end

to pick-up-obsidian  

  

  let picking-obsidian false  

 

  let dragonstone one-of cities with [ city-name = "Dragonstone" ] in-radius 10

  if dragonstone != nobody [  

    set picking-obsidian true   

  ]

  

  let city-with-obsidian cities-here with [ obsidian-cache? ]

  if any? city-with-obsidian [  

    set picking-obsidian true 

  ]

  

  if picking-obsidian [  

    show "picking up" 

    set shape "person with obsidian"  

    set obsidian 10  

  ]

  

end

to go

  [ ... ]

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

    ifelse territorial-movement [

      move-humans     ; calls the "move-humans" procedure if there is territorial movement

    ][

      move     ; calls the "move" procedure

    ]

    pick-up-obsidian   ; every move, humans will try to pick up obsidian if they can

    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    ; wolves reproduce at a random rate governed by a slider

  ]

to go

  [ ... ]

  ask humans [   

    ifelse territorial-movement [

      move-humans  

    ][

      move   

    ]

    pick-up-obsidian  

    set energy energy - 1  

    humans-eat  

    domesticate-wolves  

    humans-feed-animals  

    death  

    reproduce humans-reproduce   

  ]

5. Exchange obsidian

Let's now allow people who have more than 1 obsidian tool to give one of their tools to people they encounter, if those people don't already have a tool. 

If we wanted to be fancy, we could allow trade only between people of the same house, but we will let you think about how you could implement that part for now.

Create a new procedure that tells people to check if the person they meet already have tools, and if they don't, give them one, until they only have one left.

Then call that procedure in the go procedure.

HumanWithObsidian.png

to exchange-obsidian   ; human procedure

  

  if obsidian > 1 [   ; if the human doing the action has more than 1 tool in its kit

    let friends humans-here with [ obsidian = 0 ]  ; checks if there are people without obsidian on the same patch

    if any? friends [

      set obsidian obsidian - 1   ; take one tool from my inventory

      ask friends [

        set obsidian 1   ; give it to the people who do not have any

        set shape "person with obsidian"  ; who can change their appearance

      ]

    ]

  ]

  

end

to exchange-obsidian 

  

  if obsidian > 1 [

    let friends humans-here with [ obsidian = 0 ] 

    if any? friends [

      set obsidian obsidian - 1

      ask friends [

        set obsidian 1 

        set shape "person with obsidian"

      ]

    ]

  ]

  

end

to go

  [ ... ]

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

    ifelse territorial-movement [

      move-humans     ; calls the "move-humans" procedure if there is territorial movement

    ][

      move     ; calls the "move" procedure

    ]

    pick-up-obsidian   ; every move, humans will try to pick up obsidian if they can

    exchange-obsidian   ; every move, humans can exchange obsidian if they have some to give

    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

  ]

to go

  [ ... ]

  ask humans [  

    ifelse territorial-movement [

      move-humans  

    ][

      move 

    ]

    pick-up-obsidian 

    exchange-obsidian 

    set energy energy - 1 

    humans-eat  

    domesticate-wolves  

    humans-feed-animals 

    death 

    reproduce humans-reproduce  

  ]

6. Fight the whitewalkers

Now that you have a good trading program, it is time to use the obsidian to kill whitewalkers. 

In the Whitewalker.nls file, add some code to the winter-advance procedure where people with obsidian can try to kill the whitewalkers they encounter. You will need to make sure that the living-things turtle-set now only includes sheep and wolves. Let's assume that killing them destroys the obsidian tool, however.

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

    ]

    ; If the whitewalker falls upon someone with obsidian, it's game over

    let my-opponents humans-here with [ obsidian > 0 ]

    if any? my-opponents [   ; if there is someone with obsidian on the same patch

      ask one-of my-opponents [ 

        set obsidian ( obsidian - 1 )   ; the tool breaks

      ]

      show "..."  ; whitewalkers don't speak

      die 

    ]

    ; If the whitewalker runs into a human without obsidian tools, the human dies

    if any? humans-here with [ obsidian = 0 ][

      ask humans-here [ die ] 

      hatch-whitewalkers 1 

    ]

  ]

end

to winter-advance  

  

  ask whitewalkers [

    others-move ; calls the others-move procedure

    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  

    ]

   

    let my-opponents humans-here with [ obsidian > 0 ]

    if any? my-opponents [  

      ask one-of my-opponents [ 

        set obsidian ( obsidian - 1 )  

      ]

      show "..." 

      die 

    ]

    

    if any? humans-here with [ obsidian = 0 ][

      ask humans-here [ die ] 

      hatch-whitewalkers 1 

    ]

  ]

end

7. You did it again!

Congratulations on adding obsidian to the model. Now, you can run the model under different settings and see which one allows people to kill whitewalkers the fastest. For example, does conflict help or not? What type of obsidian distribution works best?

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

The next step is also the final one. There, you will add a new breed of dragons to the model, to provide more help to deal with the advance of whitewalkers. 

See you there!

Final.png