Another student in my ICPSR ABM workshop wanted to generate countries and have them interact via trade, conflict, assimilation, and splitting. He was new to Netlogo and only had enough time to build the behavior part of the model and couldn’t visualize the behaviors so I created this foundation for him. It provides basic functionality for those capabilities as well as a few others. It occurs to me that many people might need some basic country setup to get their IR model going. You can download my Voronoi Countries code example and use that to freely steal my code for your own use.

This code was written in Netlogo version 4.0.2 and should work without alteration in 4.1 versions as well. The code is not totally without some weird behavior, which might mean bugs, but it also might mean that simple splitting and joining dynamics are capable of producing patterns that I didn't expect. Like many code examples there are methods in the code that can be used with little alteration to accomplish a basic task. However this might be better used as a base model for building your own international relations behavior on top of. The only breed is "countries" and the only country-own variable is "neighbor?" (which is only used in the find neighboring countries method). But it does make some substantive assumption about where countries are located and how much land goes to each one when they split and these are things that people are likely to change. However there will need to be some such rule for every model involving splitting countries so one might as well alter this technique rather than start from scratch.

You can start the countries off in random locations if you want, but you might have another scheme in mind to start. However you decide, after you create the countries and give them x and y coordinates you just call the method "assign-countries" to give each country a unique color and divide up the space to each country according to the Voronoi technique (which is min distance).

to assign-countries
   foreach sort countries [
      ask ? [ set color generate-color ]
   foreach sort patches [
      ask ? [
         set pcolor ( [color] of one-of (countries with-min [distance myself]) ) ]

There are two basic methods to start: splitting and joining. As mentioned earlier, splitting a country creates a new country (agent) on one of the patches of the old country and then uses the Voronoi technique to re-divide the land of the old country to the two countries. This means that the surrounding countries' land is not affected and countries with just one patch can't divide (nothing happens if requested). You will likely want to change the rule for where the new capital arises for your substantive model, but maybe not if your question isn't sensitive to this (e.g. no resources on patches). You'll also need the code to generate a unique color for each country because the methods below use this unique color feature to perform many of their functions.

to split-country [dividing-country]
   ask dividing-country [
      let old-country patches with [pcolor = [color] of myself]
      if any? patches with [pcolor = [color] of myself and not any? turtles-here] [
      let new-capital one-of patches with [pcolor = [color] of myself and not any? turtles-here ]
         hatch 1 [
            setxy ([pxcor] of new-capital) ([pycor] of new-capital)
            set color generate-color
         foreach sort old-country [
            ask ? [
               set pcolor ( [color] of one-of (countries with-min [distance myself]) )
    ] ] ] ]

to-report generate-color
    let new-color ((10 * random 13) + (3 + random 5))
    while [any? countries with [color = new-color] ]
        [ set new-color generate-color ]
    report new-color

Joining countries is much easier. Actually it's more like one country becomes assimilated into another...and in the command call it's the second one that gets assimilated into the first one. You input two countries and it gives all the patches from the second to the first and then kills the second country. If resources etc. are involved in your model then you'll need to deal with that stuff too, but I haven't included anything like that in this code example.

to join-countries [country-A country-B]
    if country-B != nobody [
        ask patches with [pcolor = [color] of country-B] [
            set pcolor [color] of country-A
        ask country-B [die]

If you have resources off and let it GO for a while you'll get a probabilistically even number of splits and joins and so the countries shuffle around quite a bit over time and come to resemble something very dissimilar to the original Voronoi distribution. It's easy to understand why considering the constrained randomness in assigning where new capitals form. Sometimes there are weird islands of one country inside another and I've not looked close enough to know under what circumstances that is happening, but it probably has something to do with capitals being equidistant to some patches. If you don't like that aspect in your model then you'll need to make some assumption and change the code to eliminate it.

What's left is a number of other helping codes that do specific tasks that are likely to be useful to anybody having countries interact. The first is an obviously necessary technique that, like "neighbors" and "link-neighbors", takes a specified country and returns an agentset of countries that share a border with that country. In the picture below you can see that when the orangish-tan colored country on the bottom is asked the four surrounding countries' ring gets large. That's in the button as a demo and not a feature of the following method.

to-report neighboring-countries [target-country]
    ask countries [set neighbor? false]
    let my-neighboring-countries no-turtles
    let my-country patches with [pcolor = [color] of target-country]
    let my-border my-country with [any? neighbors with [pcolor != [color] of target-country]]
    foreach sort my-border [
        ask ? [
            let foreign-neighbors neighbors with [pcolor != [pcolor] of myself]
            foreach sort foreign-neighbors [
                ask ? [
                    ask countries with [color = [pcolor] of myself] [set neighbor? true]
    set my-neighboring-countries countries with [neighbor? = true]
    report my-neighboring-countries

The next methods have to do with borders. The first takes in two countries and returns the patches of the first country that border the second country. You can see that (as in the button in the code) if you ask these border patches to set their plabel to "X" then you get something like the picture above.

to-report border-with [country-A country-B]
    let my-border-with-B patches with [pcolor = [color] of country-A and any? neighbors with [pcolor = [color] of country-B]]
    report my-border-with-B

Using that method we can go one step further and measure the length of the border between two countries. This method takes in two countries and returns the number of patches that the first has that border the second. Note that switching the countries' order will often provide different numbers because how patch neighbors work. They are not symmetric because one patch in country-A can be a neighbor to up to seven patches of country-B (even eight if you decide not to fix the mild weirdness currently in there). Depending on your model you'll want those number sot be the same, but that's for you to figure out.

to-report calculate-border-size [country-A country-B]
    let border-with-B-size count border-with country-A country-B
    report border-with-B-size

Those are the major requests that I got for this base capability. Obviously I have lots of ideas of other things to add, but this isn't my research topic and I've got to spend time on that. So if you have a specific request for another capability then let me know and if it's something that I think is generally useful I will add it here. Otherwise I'll just help you with it. And as always, if you do anything especially cool with the code or ideas found here please let me know because I love to hear about such things.