Just lately, I’ve had reason to mock up a couple of simple models of opinion dynamics, and have spent some time working on new NetLogo code,1 which I always find to be a joy. The models are from Thurner et al.2 and Mathias et al.3
Before I go any further, here’s the obligatory NetLogo citation:
Wilensky U. 1999. NetLogo. Center for Connected Learning and Computer-Based Modeling, Northwestern University, Evanston, IL.
It doesn’t much matter what these models are about. What I’m interested in here is why NetLogo is a great platform for a situation where, as in these examples, I’ve just read about a model, and perhaps I don’t quite get it. Or I want to know more. Or I want to know what would happen if I changed something. For that, I need to build it. It might be my engineering background (my first degree) that means I learn by building, or maybe I just enjoy the process. Either way, there really isn’t a better tool than NetLogo for exploring these kinds of systems.
Thinking about this question is useful more generally for thinking about what makes any programming language useful, and why you might pick one over another in different cases.
Before I get to that, some personal backstory. If you just want to know why NetLogo is great jump to that section, I won’t be offended.
My NetLogo journey
I wrote a lot of Java for a tool I called GraphCA for my PhD4—in fact,cloc informs me thus:
----------------------------------------------------
Language files blank comment code
----------------------------------------------------
HTML 128 4350 1591 47599
Java 101 3035 4232 8634
Text 2 4 0 19
CSS 1 8 8 13
----------------------------------------------------
SUM: 232 7397 5831 56265
----------------------------------------------------
8634 lines of actual code (not comments, but over 4200 lines of those too). Thankfully, all that HTML was generated by javadoc.
While I was labouring over all that Java code and building my own GUI and plotting tools, and so on, my advisor Mike Batty spent much of the time churning out interesting models (and papers) using something called StarLogo. Needless to say, I thought I was the future and Mike was a crazy old man messing about with a weird child’s toy.
StarLogo was an evolution of Logo a Lisp-like programming language. Logo is a ‘proper’ programming language, which is probably best known for its turtle graphics, which is computer graphics based on issuing instructions to a ‘turtle’ to move around the screen (forward 100, right 90, that kind of thing) and draw stuff (pen-up, pen-down, set color red, and so on). This lets you make drawings like this:
In essence, StarLogo is what you get if you ask (then answer) the question, “what about if there were many turtles?”, and supplementary question, “what about if they could interact with each other?” StarLogo, was originally developed by Mitch Resnick and is nicely described in his Turtles, Termites, and Traffic Jams5 Since its original development StarLogo has stuck close to its educational mission and evolved into a building block based programming environment aimed squarely at early education settings.
Developed at the Center for Connected Learning at Northwestern, NetLogo started as a clone of StarLogo. There was a period in the late 1990s into the early 2000s when several *Logo variants were competing for attention. I’m not really sure what their beef was with one another, although an immediate advantage of NetLogo was that being written in Java it could be run on a PC. Whatever the reason for competing *Logos, eventually NetLogo won out in the application I’m interested in of building models of distributed systems.
But it still took years for me to see what Mike Batty saw in it. I stuck with Java well past the point where I had time to write Java,6 and persisted with building agent-based models using Repast.7 Although I had used NetLogo quite a bit, including in teaching a graduate class at Penn State, I still had a nagging sense that it’s not a serious tool. My moment of clarity arrived on sabbatical in 2008 at the National Centre for Geocomputation in Ireland. I planned to use GraphCA to support some arguments I was making in a talk. But when I tried to run it the day before, it wouldn’t work.8 After trying and failing for several hours, panic set in, and I decided to reimplement GraphCA using NetLogo.
Well… 250 or so lines of NetLogo code later and I was back in business.
From 8600 lines of Java to 250 lines of NetLogo! The NetLogo version doesn’t do everything my Java code did.9 But I suspect another 250 lines would do the trick. Of course, I use other languages than NetLogo (R and Python) all the time, but for building simulations, and more generally for interactively exploring dynamic spatial models, I turn to NetLogo.
What makes NetLogo great
So what’s so great about NetLogo?
It’s turtles (and patches) all the way down
The primitives of NetLogo, other than the usual numbers and strings are turtles and patches. It also has links (between turtles) and lists, but turtles and patches are the core. When you open NetLogo there is a square View which on closer inspection is a 33×33 grid of patches.10 Into this ‘world’ you add turtles by issuing a create-turtles command. You can then ask the turtles to do stuff. The commands
ask patches [ set pcolor random 3 ]
create-turtles 500 [ forward random-float 15 ]
will produce this picture in the View:
The central iteration command in NetLogo is not a for loop (although it has those if you need them). Instead, it is politely asking patch-sets and turtle-sets (collectively agent-sets) to do things. The default collection of all turtles in a model is called turtles, and all the patches are called, well… patches. So
ask patches [ set pcolor random 3 ]
gets all the patches to set a colour specified by one of the values 0, 1, or 2, chosen at random. In the example above the block of code after create-turtles [...] is executed by each turtle on creation. If it’s not clear, the turtles spawn at the centre of the view, facing in random directions, and the forward random-float 15 command causes them to move forward by a random distance. ask iterates over sets in random order. At first this is confusing if you’re accustomed to iteration using for loops,11 but you get used to it. It’s an important feature in simulation contexts, where always having patches or turtles execute in the same order can produce undesirable artifacts.
In addition to built-in properties (like colour, size, coordinate location) turtles and patches can have properties assigned to them, and thus can be used to represent mobile entities (the turtles) or fixed locations (the patches) with a range of characteristics. If you only want some of the turtles or patches do something, then you use a with conditional to filter the set:
create-turtles 500 [ set color one-of [orange blue] ]
ask turtles [forward 5]
ask turtles with [color = blue] [forward 5]
forward 5 and only those with [color = blue] moved forward 5 again.
This isn’t the place to learn NetLogo, so I won’t get into more details than this. Turtles and patches as language primitives are great because they come for free. It’s no work at all to create, visualize, and manipulate mobile entities and grid cells. Agents and grids are not included out of the box in other languages, and representing them graphically is more work again. The closest analogue I know to this in another language is processing, which bills itself as “a flexible software sketchbook”, and NetLogo shares many of the desirable features of that platform.
Visualization and GUI for free
Because turtles and patches are immediately graphically represented in the view, as your model runs, you see it evolve, without additional effort. The following is all the NetLogo code needed for a voter model:
to setup
clear-all
ask patches [ set pcolor one-of [red yellow blue] ]
end
to go
ask patches [ set pcolor [pcolor] of one-of neighbors4 ]
end
Initialise patches to one of three possible colours. Then each iteration (go) get them to change their colour to match that of a neighbour.
NetLogo also has GUI elements for free: buttons, sliders, drop-downs, switches, and so on. Functions (called procedures and reporters) can be associated with GUI elements. So if we add setup and go buttons to the GUI, then we end up with a model like this one (did I mention it also has the option to export models to web pages?)
It’s the semantics, stupid
It takes a while for it to seep in, but while the features I’ve already discussed (other than ask) are platform advantages, not language advantages per se, it’s how NetLogo feels to write that really makes it stand out. The semantics of the language initially seem strange, a bit wonky, but after a while writing quite complicated statements feels a lot like writing sentences in a natural language.
ask turtles [
face one-of other turtles in-radius 4 with [color = [color] of myself]
forward 1
]
I am not a computer scientist steeped in the theory of language design, but I can see that there is something subtle going on here. That long run-on line of code face... is functional programming without the distracting ugliness in R of |> pipes or in Python of chained . operators.12 It’s how the functions are defined that makes this work.
face agentcauses the turtle calling it to change itsheadingtowards the supplied agent (i.e., to face it);one-of setreturns one member of the supplied agent-set at random;other setreturns the supplied agent-set with the calling agent removed;set in-radius xfilters the supplied agent-set returning a set of agents within distance x of the calling agent;set with [condition]applies a selection filter to the supplied agent-set.
The clever ordering of how arguments are passed to functions does all the work that allows compound statements to be chained together like this. From time to time you need parentheses to disambiguate which operation should be applied first, but most of the time, you can simply construct compound statements as long run on statements. For clarity, you may want to assign some intermediate steps to variables, but there’s a peculiar satisfaction to be found in constructing these phrases. It was when this landed with me that I really started to enjoy writing NetLogo code. Before you get into the rhythm of the language, on first encountering the ordering of parameters passed to functions, they can seem awkward. It’s when you start chaining functions together that you see why they are ordered the way they are.
This elegance in the language syntax is clearly not accidental and speaks to the care with which it has been designed. It takes a little longer to sink in than the immediacy of Python, but it has a similar quality once absorbed: statements like the one above just seem obvious. This structure also subliminally encourages an approach to programming based on small procedures and reporters that can themselves be chained together in the language’s governing style.13 This is not unique to NetLogo, but it’s a good habit to develop and regularly programming in NetLogo made it natural for me.
Thinking like a turtle
In the same vein, many built-in functions in NetLogo are turtle- or patch-centric, and run from the perspective of those entities. This is an extension of the way that turtle graphics is expressed from the perspective of the turtle. Operators such as neighbors and in-radius distance are examples. This leads naturally to thinking about spatial problems from the perspective of the turtles and patches.14 When you are building agent-based models this is exactly the head-space you need to be in.
This turtle-centric perspective is reminiscent of a wonderful article by Dana Tomlin about the worm’s eye view that map algebra calls for.15 It’s also why I recommended to Matt Duckham that he use NetLogo for the examples in his fantastic book Decentralized Spatial Computing16. Algorithms for distributed sensor networks demand a strictly local perspective. Matt was understandably skeptical as I raved, slightly wild-eyed, that NetLogo was exactly what he needed for this project, during one of the breaks at (I think it was) GeoComputation 2009. But he was listening, and it’s reassuring to me that someone as smart as Matt clearly respects NetLogo too!
NetLogo made me a better programmer
Another language feature, very much a product of NetLogo’s roots via Logo in Lisp are its primitives for dealing with lists. A list in NetLogo is an ordered collection of things. It’s all very well asking to do things in random order all the time but sometimes you need a bit more control than that. A list is a sequence of values
let lst [3 1 4 1 5 9]
The values need not all be the same type and you can nest lists within lists. There are a bunch of built-in reporters you can apply like min, max, mean, and so on, and also things like reverse, sort, and remove-duplicates. You can iterate over lists using foreach
let squares nobody
foreach values [ x ->
set squares lput x ^ 2 squares
]
x -> binds each element in the list to the name x in the scope of the foreach block of code. We can also iterate over multiple lists in parallel:
(foreach (sort-on [size] turtles) (sort patches) [ [t p] ->
ask t [ move-to p ]
])
sort and sort-on report the input turtles and patches as ordered lists. Again, the [t p] -> construct gives the paired elements we are iterating over local names in the scope of the foreach block of code, and we ask each turtle t to move-to patch p.
Granted, the syntax here is a little weird. No argument there. It’s a good idea to get used to it because the real joy of lists is in the map, filter, and reduce operations, which use the same notation to apply anonymous functions to list elements.
map [x -> x ^ 2] [1 2 3 4 5]
[1 4 9 16 25]
Here the x -> ... notation defines an anonymous function. filter uses the same method to make a new list from only those elements that match some conditional:
filter [x -> x mod 2 = 0] [1 2 3 4 5]
[2 4 6]
Finally, reduce, a bit of a mind-bender, applies an anonymous function to consecutive pairs of elements in the supplied list accumulating a single result as it goes.
reduce [[a b] -> a + b] [1 2 3 4 5]
15
In a simple case like that, it’s easy enough to see that the output is the sum of elements in the supplied list, but more complicated cases can be a puzzle to figure out. Here’s a cumulative sum17
reduce [[a b] -> lput (last a + b) a] (fput [0] lst)
The joys of figuring out how to do something mildly complicated with a reduce statement notwithstanding, the map function is the real magic here.
sum (map [[a b] -> a * 10 ^ (- b)] [3 1 4 1 5] range 5)
3.1415
These are the fundamental elements of functional programming and that’s why NetLogo made me a better programmer. It’s often been said that all programmers should learn Lisp. NetLogo, as a descendant of Logo, itself a descendant of Lisp, was my soft entry point to at least some aspects of that experience, and I’m pretty sure it’s why my programming has improved through working with NetLogo.
It’s a fun way to make generative art
If it’s not obvious from the foregoing, you can make cool pictures with NetLogo without breaking sweat. As an example, readers of Geographical Analysis might recognise the recent cover redesign, which originated from a prototype mocked up in NetLogo in about half an hour.18
Downsides
Alright, so we all agree that NetLogo is great. What’s not so great? Honestly, I can only really think of a couple of actual things.
Some missing stuff
NetLogo’s extensions architecture has added quite a few things that might be considered lacking in the core language. csv makes reading and writing text files a lot easier, and there’s even a gis extension (hardly a core requirement, but handy all the same).
As my NetLogo programming matured, I found its list and text processing a bit light and often found myself reimplementing functions that I use all the time in Python. That’s why I’ve written netlogo-utils for handling lists and strings. Also included are some probability distributions that NetLogo doesn’t provide natively. This isn’t an extension, just some NetLogo source code files that can easily be added to any model and provide things like cumulative sums of lists19 and a speedy random-binomial reporter.
Development tools
It’s been 20 years since Railsback et al.’s20 mostly favourable assessment of NetLogo relative to other agent-based simulation platforms, and sadly, their major concern remains valid:
Experienced programmers, however, could be uncomfortable with NetLogo’s simplified programming environment. [… It] can be cumbersome for large models. NetLogo provides an error checker and makes it easy to develop and try code in small steps, but lacks IDE features such as a stepwise debugger.21
This is why, right at the top, I noted that it’s always a joy to write new models in NetLogo. As models grow, which they tend to do, the lack of development tools does tend to take away from the fun of the experience. But hey, nobody’s perfect.
People don’t take it seriously
NetLogo’s other problem is not NetLogo’s fault, and is partly why I’ve written this post. The kid’s toy delusion, which I laboured under for several years, persists. All I can say is that NetLogo is a whole lot more than a toy. This was recognised by Railsback et al.22. In that paper they weigh up the relative merits of a number of agent-based modelling platforms. It’s obvious reading it that they included NetLogo a little reluctantly. It’s also obvious reading the code examples as they worked through the stages of the ‘stupid model’ they developed for the evaluation process that they did not initially ‘get’ NetLogo. Clearly though, at some point it clicked and they conclude:
It is easy to recommend NetLogo for models that are (i) compatible with its paradigm of short-term, local interaction of agents and a grid environment and (ii) not extremely complex. We also strongly recommend NetLogo for prototyping models that may later be implemented in lower-level platforms: starting to build a model in NetLogo can be a quick and thorough way to explore design decisions.23
That’s pretty much my jam, but it also covers a lot of ground in agent-based models of complex systems. For ‘serious’ models built with NetLogo, check out these examples from my own research:
- Spatial model of COVID 19
- Model of gene-drives as a possible mechanism for control of invasive wasps in New Zealand
- A model to explore catchment-level change in farm management practices
It’s also worth mentioning here that since Railsback et al.’s evaluation, NetLogo has added several extensions for doing linear algebra, colour management, and integration with R and Python, which together with a pre-existing tool for conducting parameter sweeping model evaluation experiments, have further beefed up its scientific credibility.
But never mind all that: what’s so wrong with toys anyway?!
Finally
Reflecting on all of the above, as I searched around the topic in writing this post, I came across this post from Nathan Toups, which puts it perfectly:
One of the beautiful things about living at this time in human history is that there is no end to the strange and beautiful things you might find. NetLogo is one of those things I’ve discovered recently, and I thought I’d share a little bit about it.
Minus the “recently”—it’s been 25+ years for me—that pretty much hits the nail on the head: a strange and beautiful thing indeed.
Footnotes
New is important here, but I’ll get to that.↩︎
Thurner S, M Hofer, and J Korbel. 2025. Why more social interactions lead to more polarization in societies. Proceedings of the National Academy of Sciences 122(44) e2517530122.↩︎
Mathias J-D, JM Anderies, J Baggio, J Hodbod, S Huet, MA Janssen, M Milkoreit, and M Schoon. 2020. Exploring non-linear transition pathways in social-ecological systems. Scientific Reports 10(1) 4136. Although it’s worth noting that Challis KJ. 2026. An aggregate potential landscape description of an agent-based exploitation-perception model for social-ecological tipping-point dynamics. Ecological Modelling 513 111433 describes the model better.↩︎
I’d link to my doctoral thesis here, but you’re not going to read it, so instead I’ll just say you can find it on the publications section of this website if you’re really keen.↩︎
Resnick M. 1994. Turtles, Termites, and Traffic Jams: Explorations in Massively Parallel Microworlds. MIT Press.↩︎
What they say is true: you’ll never have as much time to dig into things once you start an academic job as you did when you were doing your PhD.↩︎
George Perry has never really forgiven me for persuading him to write a model of fish population dynamics using Repast. See Perry GLW and NR Bond. 2009. Spatially explicit modeling of habitat dynamics and fish population persistence in an intermittent lowland stream. Ecological Applications 19(3) 731–746.↩︎
In fairness to Java this was several years and several computers after the last time I’d run it, and I have since run it successfully, so I don’t really know what was wrong.↩︎
I didn’t need it to.↩︎
I should also make clear that you can change the size of the size and resolution of the view…↩︎
A norm so strong that Python goes out of its way to guarantee order when iterating over ostensibly unordered collections like its dictionary objects.↩︎
Disclaimer: I also love coding in R and Python.↩︎
Based on the little I’ve read on the subject, I think this might be (Net)Logo’s Lisp-lineage showing through.↩︎
See Tomlin CD. 2017. The bird’s-eye view from a worm’s-eye perspective. Pages 21-31 in Advances in Geocomputation DA Griffith, Y Chun, DJ Dean (eds). Springer International Publishing.↩︎
See Tomlin CD. 2017. The bird’s-eye view from a worm’s-eye perspective. Pages 21-31 in Advances in Geocomputation DA Griffith, Y Chun, DJ Dean (eds). Springer International Publishing.↩︎
Duckham M. 2013. Decentralized Spatial Computing: Foundations of Geosensor Networks. Heidelberg ; New York: Springer.↩︎
At this point, you might want to lie down, and yes, I’ve got a bit carried away.↩︎
Although the final version was rendered in R which allowed a bit more flexibility in output formats.↩︎
So you don’t have to figure out how to use
reduce.↩︎Railsback SF, SL Lytinen and SK Jackson. 2006. Agent-based simulation platforms: review and development recommendations. Simulation 82(9) 609–623.↩︎
ibid., page 621↩︎
ibid.↩︎
ibid. page 621↩︎








