NetLogo Programming: An Introduction


Alan G. Isaac


American University






This introduction is written for Netlogo 6. Before reading these notes, please read NetLogo Basics You may also find it useful to read [janssen-2012-openabm].



Learning Outcomes

After mastering this material, you will be able to:

  • Understand the basic structure of a NetLogo program.

  • Find NetLogo “Code examples” to simplify your own programming tasks.

  • Create command procedures and reporter procedures, and explain the uses of each.

  • Use NetLogo’s branching and looping constructs.

  • Modify an existing NetLogo model.

  • Build a new NetLogo model.

NetLogo Models: Basic Structure

Building Models: First Steps

Steps toward Making Your Own Models

  1. Experiment with existing models via GUI

  2. Modify existing models

  3. Roll your own

Modifying Models

Find a model that does something close to what you want:

  • make sure your intended use complies with the copyright

  • save it under a new name

  • add appropriate attribution to the header

  • modify the model to suit your needs

  • update the model documentation to match your changes

  • make sure all borrowed code is clearly and appropriately attributed

Structured and Commented Code

  • use help names for variables and procedures

  • create a procedure for any repeated code blocks (DRY)

  • turn your procedures into pure functions when possible

  • structure and comment your code for readability

This will be:

– helpful to others who read your code – helpful to you in both writing and understanding your code

Simple Modifications: World Settings

You might want to change the World settings:

  • size

  • location of 0, 0

  • torus or rectangle

  • patch size (this and size determine size of world screen)

New Model: Key Decisions

  • system to be modeled

  • what do the agents represent?

  • what are the rules of action and interaction?

  • how will you approximate these rules in the modeling environment?

  • if your model repeatedly runs a schedule, how much time is represented by one iteration (e.g., by 1 tick)?

Basic Model

A basic model will have:

  • setup procedure

  • go procedure

For example:


  • initialize global variables

  • initialize any agents (e.g., the properties of patches and turtles)

  • initialize output files


  • run one interation of the model

  • update output files

Basic GUI Elements: Graphs

A simple model may add:


  • graphs can dynamically monitor a single value (plot), pairs of values (plotxy), or collections of values (histogram)

  • easy to add in NetLogo GUI

Basic GUI Elements: Sliders, Choosers, and Switches

A simple model may also add:

sliders, choosers, and switches:

  • sliders, choosers, and switches provide users with GUI control over model parameters (e.g., the number of agents in the model)

startup procedure:

If you name a procedue startup, it will be run when your model first loads in the GUI. This is the right place to set default values for your sliders (and other interface globals). Do not set code-tab globals in startup: unlike interface globals, code-tab globals will be reset by clear-all.


For experiements using BehaviorSpace, startup runs only once:

Using Sliders and Choosers

Global variables can be declared in the Interface (instead of in the Code tab). We call these interface globals.

NetLogo allows using a “right click” on the Interface window to produce a context menu that can add GUI elements.

Interface globals (set in sliders, switches, and choosers) are a convenience feature with downsides as well as upsides.

Sliders and Choosers: Some Upsides

  • Allow easy experimentation with a model.

  • Designed to interact well with BehaviorSpace (as we will see later).

Sliders and Choosers: Some Downsides

  • Interface variables are not declared in the Code tab, so while you are coding they are less visible. (However, if you code with a text editor, they are visible in the .nlogo file, as plain text.)

  • An Interface variable does not include a default value, so if a user resets the slider and then saves your model, it saves a different value than you intended. (So it is a good idea to use NetLogo’s special startup procedure to set default values, perhaps by calling a reset-defaults procedure.)

Code Tab

Basic Structure

The Code tab can contain

  • comments

  • declarations

  • procedures (commands and reporters)


  • a semicolon (;) begins a comment for remainder of line

  • be sure to state the author and date in a comment at the beginning of each program

Declarations Section

The declarations section precedes the procedures section.

The two most common declarations are global variables and agent attributes.

Declaration of Global Variables

declared globals:

In the Code tab, globals [...] declares a list of global variables.

interface globals

Note: other variables with global scope may be declared in the GUI (e.g., in sliders).

  • each global variable must be declared

  • a global variable can be declared in the declarations section or in the GUI (e.g., in a slider or chooser)

  • every agent can access or set a global variable

  • values are assigned (or reassigned) with the set command


NetLogo has the concept of an observer: a world-governing agent that owns the global state, receives our (NetLogo) commands, and passes commands to other agents (patches, turtles, and links).

The globals declaration might have instead been named observer-owns. (In a slight complication, the observer also owns the interface globals.)

image of Uatu the Watcher

Declaration of Instance Attributes

  • patches-own [...]: list of patch attributes

  • turtles-own [...]: list of turtle attributes

  • links-own [...]: list of link attributes

  • can also declare breed attributes

Procedures Section

The procedures section only contains procedures (user-written commands and reporters). It comes after the declarations section.

command procedure

  • to my-procedure ... end

  • body contains NetLogo commands

reporter procedure

  • to-report my-reporter ... end

  • returns a value

  • must use the report command

Review: Procedures

Enter the following in the Code window:

globals [ nHeads ]

to setup

to go
  set nHeads (nHeads + fairCoinFlip)

to-report fairCoinFlip
  report ifelse-value (random-float 1 < 0.5) [1] [0]

Review: Procedures ...

Next, return to the Command Center and enter the following lines:

show nHeads
show nHeads

Note: clear-all calls clear-globals, which sets all global variables to their default value. The default value of variables declared with globals is 0.


When you are writing code, you may wish to refer to a procedure you have not written yet. If you do not define a procedure with this name, the NetLogo syntax checker will complain.

The solution is to define an empty procedure or a procedure that warns you that it needs to be written.

Such placeholders and warnings are sometimes called “scaffolding”. The idea is that assist you in construction of your model, but you intend to remove them from the final product.

Code Tab: Basic Structure

In the Code tab, outside of code blocks, we should only find:

  • comments

  • NetLogo keywords (see below)

  • <instances>-own (see below)

Comment: many of the NetLogo documentation examples are slightly misleading on this score. E.g.,


NetLogo Source (.nls) Files

In support of DRY programming, NetLogo allows a model to load a .nls file declaring variables, breeds, and (most importantly) procedure definitions.

The process for creating a new .nls file in the Code tab is a bit awkward.

  • at the top of the Code tab add __includes [], and then press Check.

  • a new chooser named Included Files appears; from it pick New Source File

  • add some code and then File » Save As, being sure to include the .nls extension!

  • note this this does not save your model file; it just saves your .nls file. To save your model file, first return to one of the three main tabs.

Code Analysis

  • scaffolding (print statements)

  • inline tests (if tests with error statements)

  • test procedures (e.g., test-setup and test-go)

  • procedure timing (e.g., reset-timer myproc print timer)

  • profiling (see the profiler`` extension)

Program Structure

Code Examples

The NetLogo Models Library includes a collection of code examples. Be sure to look at these for hints whenever you get stuck.

Basic Program Structure

Even the simplest NetLogo programs traditionally include the following structure:


declaration of global variables using the globals keyword


a procedure named setup that initializes the global varaibles and does other setup operations


a procedure that runs one iteration of the model; this holds the “schedule” for your program

Expressions and Statements

Programmers use the term expression for a piece of code that will produce a value. (An example is 1 + 2, an expression involving addition.) Programmers use the term statement to refers to an instruction telling a computer to carry our some action. A NetLogo statement will not return a value, but it will cause some action to take place. (An example is print "this", a print statement.)

We say an expression is evaluated. We say a statement is executed. The action produced by a statement is sometimes called a side effect of the statement.

We build statements from NetLogo command primitives, which are the basic verbs on the NetLogo language. We will be particularly interested in the ask command, which allows us to control our NetLogo agents.

Procedures: Review

Recall that there are two basic types of procedures: reporter procedures, and command procedures.

Reporter procedure stub:

to-report <reporter-name>
  report <return-value>

Command procedure stub:

to <command-name>
  report <return-value>

By convention, reporter names are nouns, and command names are verbs.


Example: Minimal Program Structure

globals [ gvar01 gvar02 ]

to setup

to go

to do-stuff

Program Structure: Setup

As soon as you add any complexity to your model, you will want to break the model set up into parts:

  • the global variables,

  • the patches

  • the turtles

So your model set up procedure will often look like:

to setup

Note: NetLogo already has a setup-plots command, which in turn is called by reset-ticks. If you want to set up your plots in the Code tab, use the name setupPlots or init-plots instead.

Application: Minimal Program Structure

globals [ nHeads ]

to setup
  clear-all  ;sets nHeads to 0

to go
  repeat 50 [
    set nHeads (nHeads + fairCoinFlip01)

to-report fairCoinFlip01
  ;; fill in procedure body

Parameters for Functions and Procedures

Functions and procedures may be defined in terms of parameters. Parameters are variables, not values. A parameter is an abstract representation of any possible input. Later, after our definition is complete, the function or procedure can be applied to a value (which may be stored in a variable). This actual input value is called an input argument, or just an argument.

NetLogo Functions

Recall that NetLogo offers two ways to create a function: as a reporter procedures, and as a function literal. Function literals are also called anonymous functions, lambdas, or tasks. Here we focus on reporter procedures, which are often just called reporters.

Create reporter procedures in the procedures section of the Code tab, using the to-report and end primitives. The reporter name must immediately follow to-report, and the body must come before end. The body must use the report primitive to return a value. (NetLogo uses report rather than the more familiar return.) Here is an example of a reporter procedure with no parameters.

to-report always0 ;reporter name is always0

report 0 ;reporter body incldues report


Documentation resource:

Functions and Parameters

Mathematics provides the basic notion of a function as a mapping of input values to output values. Permissible input values are called the domain of the function; the associated output values are calle the range of the function. The terms map and transformation are often used as synonyms for the term function. Related to this, a NetLogo function is a rule for transforming inputs into outputs.

In order to define a function, we need to be able to represent the inputs. When defining a NetLogo procedure, we can provide a list of parameter names in brackets immediately after the procedure name.

to-report identity [#param01]
  report [#param01]

We use the term “formal parameters” for the names we give to the inputs. We cannot refer to a parameter from outside of the procedure body—it is strictly local to the procedure.


A useful convention is to begin the names of formal parameters begin with an octothorpe (#). We generally follow this convention, but it is not required by NetLogo.

Function Arguments

We use the term “arguments” for the actual values we provide as inputs to a function. Note that you do not put the arguments in brackets, even though you must bracket the parameters in a procedure definition. For example, once you include the identity function above in your Code tab, you can do the following at the command line:

print identity 1

Pay careful attention to the difference between function parameters and function arguments. Function parameters are variables used during function defintion to represent any possible argument that might be provided to the function. Once we have defined a function, we can apply it to actual arguments in order to report an output.

Arity: Some Examples

The number of formal parameters in a function definition is the arity of the function. The arity of a function is therefore the number of arguments that the function consumes when executed. A function that consumes one argument is called a unary function. Here is an example.

to-report logistic375 [#x]
  report 3.75 * #x * (1 - #x)

A function that consumes two arguments is called a binary function.

to-report logistic [#x #r]
  report #r * #x * (1 - #x)

A function that consumes three arguments is called a ternary function.

to-report production [#a #x #y]
  report (#x ^ #a) * (#y ^ (1-#a))

Note that each of these functions return a single value (a number). In every case, the names of these variables have meaning the is strictly internal to the procedure we are defining. We say that these variables are local to the procedure. There is no problem that we reused the name #x in the definitions of three different procedures. These uses are entirely independent. The use of this name in one procedure definition cannot in any way seen by any other procedure.

Partial Function Application

One user defined procedure can call another user defined procedure. For example, instead of defining logistic375 as above, we can use partial function application to define it in terms of logistic.

to-report logistic375 [#x]
  report logistic #x 3.75

Partial Function Application (Redux)

One user defined procedure can call another user defined procedure. For example, we could define incremented in terms of added.

to-report added [#x #y]
  report (#x + #y)

to-report incremented [#x]
  report added #x 1

Similarly, we can turn a function of three variables into a function of two variable. Let us set the parameter in the production function (defined above) to 0.33, thereby producing a function of two variables.

to-report production33 [#x #y]
  report production #x #y 0.33

In these two examples, we use a function of larger arity to produce use a function of smaller arity. This is called partial function application.

Write Once Use Anywhere

Here is a silly reporter that illustrates the use of parameters. This time, instead of returning a number, the function returns a boolean value (true or false).

to-report is-equal? [#x #y]
  report (#x = #y)

Copy is-equal? into your Code tab. You can use it elsewhere in your code. You can even use it in the Command Center. E.g., go to the Command Center and type in:

show is-equal? 2 3

The observer will show you the value false. Note how the reporter "consumes" two arguments (the 2 and the 3), because we defined it to do so.


Parameters for Procedures (another example)

Suppose we want to simulate a coin flip with a specified probability.

to-report bernoulli [#p]
  report ifelse-value (random-float 1 < #p) [1] [0]

Once you copy that to your Code tab, you can use it like this:

show bernoulli 0.3

This example is different than our earlier examples. The bernoulli function is not pure: even if you call it with the same argument, if produces a different output. The output is a random variable.

Procedures Calling Procedures

Once again, you can define new procedures in terms of existing procedures.

to-report fairCoinFlip01
  report bernoulli 0.5

Looping: repeat

The repeat primitive allows you to repeat a command block as many times as you wish. E.g., enter the following at the Command Center.

let %ct 0 repeat 50 [show %ct set %ct (%ct + 1)]

In the Command Center, the observer shows you the whole numbers up 0-49. As another example, at the Command Center enter:

repeat 50 [set nHeads (nHeads + fairCoinFlip) ]
show nHeads

Note: clear-all sets all global variables to their default value of 0.

Exiting a Loop: stop

At the Command Center enter:

let %ct 0 repeat 50 [show %ct set %ct (%ct + 1) stop]

The stop command exits the loop, so in the Command Center, the observer only shows 0.

Exiting a Procedure: stop

We can use stop to exit a procedure, but stop only exits the procedure that executes it. To illustrate, add the following to the Code tab:

to test
  show 0  stop-me  show 2

to stop-me
  stop  show 1

Go to the Command Center and enter test. You will see 0 and 2 printed.

Looping: loop

Run a list of commands repeatedly (potentially forever):

loop [ commands ]

This is obviously a hazardous construct, but if one of the commands eventually calls stop, you will exit the loop.

loop [if (ticks > 100) [stop] tick]

Use of loop is not quite like use of a forever button. In NetLogo, we usually use a forever button in order to repeat something forever. We can click again on a forever button to exit the loop. If the button calls a procedure that executes the stop command, that will also exit the forever-button loop. However, procedures do not pass on the stop command to loop: to break out of loop, stop must be called by a command directly in the loop body.

Stopping Forever Buttons

NetLogo models often have a go command that is called by a forever button. If you want to stop on a condition, rather than by again clicking the button, use stop conditionally at the top of your procedure:

to go
  if condition? [ stop ]

This prevents the user from forcing additional step in the model by repeatedly pressing the button.

Style Guide

Currently there is no official NetLogo style guide. The NetLogo Models Library is stylistically fairly consistent, so it can serve as a guide by example.

A course-related guide is available at

Contrary to that style guide, I recommend:

  • do not use spaces in your file names

  • use camel-case instead of hyphenated long names, beginning with a lower-case letter

While hyphenated names are a convention in Lisp derived languages, they are not possible in many other languages.


Remember that NetLogo is case insensitive, so case conventions are purely for reader convenience.

Common Styles: Naming

Here are some style guidelines that reflect some fairly common practices, some of which we will violate on a regular basis.

  • do not use underscores in names (but, we will instead begin local variable names with an underscore)

  • name boolean variables with a question mark: attempted-task? (but, we will instead begin boolean variable names with is or has, as in hasAttemptedTask.)

  • name command procedures with nouns and reporter procedures with verbs

  • breed names should be obviously plural

We consider the following convention helpful, but it is nonstandard.

  • start parameter names with a hash and local variable names with an underscore:

    to-report sq [#x]
      let _xsq (#x * #x)
      report _xsq

Common Styles ...

  • indent code blocks by 2 spaces per level, including procedure and reporter bodies;

  • do not use tab characters (except possibly in output)

  • declare variables (globals, patches-own, etc.) one per line, with an explanatory comment for each variable

  • identify procedure context with a comment:

    to move ;; turtle procedure
      right random-float 360
      forward 1

Common Styles ...

  • avoid using who numbers

  • put branching conditions in parentheses

  • open code-block brackets at the end of a line; close them on their own line, except between the if and else clauses, e.g.,

    ifelse (this?) [

Plotting: First Steps

Types of Plots

NetLogo builds in the following plot types:


you provide the y value; the x values are automatically incremented.


you provide the x and y values


you provide a collection of values as a list

Exercise: Simple plot

In the Interface tab, add a plot with the pen update command plot nHeads.

In the Code tab, create a coin-flipping program that has the following go procedure:

to go
  set nHeads 0
  repeat 50 [set nHeads (nHeads + flipCoin)]

Clearly this is not the complete program: you need to declare nHeads as a global variable, define a flipCoin reporter procedure, and define an appropriate setup procedure.

In the Command Center, run your setup procedure, and then run your go procedure 100 times.

Basic Concepts: Plots

Review plots in NetLogo Basics.

For the moment, we will only change the pen update commands.

pen update commands

commands to be executed when the plot updates


NetLogo primitive to initialize all plots. Often comes at the end of our setup procedure. (However, it is more common to use reset-ticks, which calls setup-plots.)


NetLogo primitive to update all plots. Often comes at the enf of our go procedure. (However, it is more common to use tick, which calls update-plots.)

In the NetLogo Models Library, under Code Examples, see Plotting Example.

Temporary Plot Pens

If you want to add background features (like a 45 degree line) to a plot, you can use a temporary plot pen during setup.

;;plot 45 degree line from (0,0) to (1,1)
create-temporary-plot-pen "equal"
plotxy 0 0 plotxy 1 1


The export-plot command writes a comma-separated values file. There data written includes the x and y values of all points plotted by all the plot pens in the plot.

Specify the plotname as a string: it is the same as whatever you entered as the name in the plot dialogue (which is used as the title of your plot).

The data is written to an external file. You specify the filename as a string. Use forward slashes.


Plot Commands

most-used plot commands:

histogram plot plotxy set-current-plot set-current-plot-pen set-plot-pen-mode

often-used plot commands:

set-histogram-num-bars set-plot-pen-color set-plot-x-range set-plot-y-range

autoplot (automatic axes range adjustemnts):

autoplot? auto-plot-off auto-plot-on

clear-plot related commands:

clear-all-plots clear-plot plot-pen-reset

other plot commands:

Simplest Histogram

A histogram plots the frequency of occurence of items in a list. Add a new plot in the Interface tab and replace the default pen update commands with histogram [1 2 2 3 3 3]. Click OK then then in the Command Center enter ca update-plots.

Note that by default histogram produces a line plot. For the corresponding bar chart, you need to change the pen-mode. At the Command Center, you can enter set-plot-pen-mode 1. But you can set the pen mode in NetLogo's plot dialogue.

Dynamic Histogram

If we have a histogram of turtle colors, we would like our histogram to be redrawn when our turtles change colors.

In the NetLogo Models Library, under Code Examples, see Histogram Example.

Note that the tick command calls update-plots. Note that the x-axis is not autoscaled; you must scale in appropriately be histogramming your data.

Simple Histogram

Suppose we have turtles classified by color: red, green, or blue. After using the GUI to create a plot titled "Class Histogram", we can:

to update-class-histogram
  set-current-plot "Class Histogram"
  histogram map
    [position ? [red green blue]]
    ([color] of turtles)

Custom Histogram

If we would like to color-code our bars, we cannot use histogram. Instead we plot a bar for each value.

to update-class-histogram
  set-current-plot "Class Histogram"
  set plot-pen-mode 1     ;; bar mode
  set-plot-pen-color red
  plot count turtles with [color = red]
  set-plot-pen-color green
  plot count turtles with [color = green]
  set-plot-pen-color blue
  plot count turtles with [color = blue]


Parameter Sweep

A parameter sweep is a systematic variation of parameter values to explore the effects of on model outcomes.

range sweep

specify a range of values (start, stop, increment) for a parameter

enumerated sweep

specify specific values (e.g., as a list) for a parameter

BehaviorSpace is part of the NetLogo toolkit. It makes it simple to do a parameter sweep.

  • standard method for exploring the parameter space

  • systematic variation of scenarios


a NetLogo tool for easily implementing a parameter sweep

Using BehaviorSpace

  • Tools > Behavior Space > New

  • give your experiment a name

  • specify multiple values of parameters for your experiment

    • list the values explicitly, or use a range [start increment end]

    • ["myparam" 0 1 2 3], or ["myparam" [0 1 3]]

    • you can vary the world size! (not a parameter in an ordinary sense)

  • fill in the experiment information

  • click “ok” when you are done

  • save your NetLogo model (this will save your experiment settings)

  • run the experiment by pressing the Run button

    • you will be prompted for how to save your data before the experiment runs; usually you should “table” output.

    • be sure to include the .csv filename extension if you enter a filename; NetLogo does not add it for you.

    • it runs much more quickly if you uncheck “update graphics” and “update plots and monitors”.

BehaviorSpace (Components)


the number of replicates for each scenario (i.e., for each parameter combination)


One reporter per line, for each value you want to record.

Setup commands:

often just your setup procedure, but you may need to add random-seed behaviorspace-run-number

Go commands:

the command(s) to run one step of your model; usually just go or step, but sometimes e.g. repeat 10 [go]. (Your recording reporters are called after each step.)

Stop condition:

a reporter that reports true when the run should stop (or just set the number of steps as a Time Limit)

BehaviorSpace Cautions

  • BehaviorSpace sets the values of global variables before executing its setup and go commands. So if your setup commands set the value of these variables, the BS values will no longer apply.

    Example: if you use clear-all in your setup, you will reset to 0 all the non-interface globals that BehaviorSpace has set. (Note: clear-all does not reset your sliders or choosers, so BehaviorSpace works well with these.)

  • If you set the value of random-seed in BehaviorSpace, it is reset to that value before each run (not once per experiment). Workaround: set the value during setup as a function of behaviorspace-run-number. As a simplest example: random-seed behaviorspace-run-number. (You can include this in the setup box of the BehaviorSpace dialogue.)

BehaviorSpace Output Formats

spreadsheet format

written at the end of the experiment (data held in memory)

tries to be more “human readable”

table format

written as the data is generated (data not held in memory)

use this for experiments generating large datasets

The NetLogo Programming Language

Language Basics

Review of Language Basics

  • reassignment: set a b

  • use parentheses to control order of operations

  • use brackets [ ] for code blocks

  • white space ignored after initial space

  • procedures (commands and reporters; see above)

Basic Data Types


all numbers are floating point (as in Javascript)


ordered, immutable collection of objects; concatenate with sentence


immutable sequence of characters; create with double quotes; concatenate with word


true or false; reported by comparisons


  • turtlesets

  • patchsets

  • linksets

Extension Data Types

  • tables

  • arrays

Language Surprises

  • use (- numbername), not -numbername

  • case-insensitive

  • necessary white space: set a (3 * b)

Recent Changes

  • see the Transition Guide:

  • reset-ticks: as of version 5, you must explicitly call reset-ticks to initialize the ticks counter; it is no longer called by clear-all

  • NetLogo 5: can no longer concatenate strings with +; use word

  • random-one-of was renamed one-of

Language Conventions

  • Logical variables end in ?

  • procedure body indented

  • two semicolons to start comment ;;


NetLogo includes a built-in tick counter:

print ticks  ;; display current value of ticks
tick         ;; increment ticks (by 1)
print ticks  ;; display current value of ticks
reset-ticks  ;; reset ticks to 0
print ticks  ;; display current value of ticks

Booleans and Comparisons: Numerical Issues

Be careful with numerical comparisons when you are not working with integers. Computers must work with approximations of fractions. The value of (0.1 + 0.2) is 0.30000000000000004, so the value of (0.1 + 0.2 = 0.3) is false, and the value of (0.1 + 0.2 > 0.3) is true.

Control Flow: Conditional Branching

A boolean expression has a value of either true or false. We can use such expressions to determine the flow of control in a NetLogo program. This is called conditional branching. NetLogo has three basic constructs for conditional branching: if, ifelse, and ifelse-value.

if <condition> [<commands>]
ifelse <condition> [<commands4true>] [<commands4false>]
ifelse-value <condition> [<reporter4true>] [<reporter4false>]

Here we use angle brackets to indicate where NetLogo code must be substituted. For example, you need to replace <condition> with a boolean expression (that is, an expression that evaluates to true or false).

Documentation resource:

Booleans and Conditional Branching

E.g., noting that random-float 1 is between zero and one:

if (random-float 1 < 0.5) [show "heads"]

We might also like the observer to print “tails” for larger outcomes. We can use the ifelse construct to do this.:

ifelse (random-float 1 < 0.5)
  [show "heads"]
  [show "tails"]

Note that to create a string, we bracket a sequence of characters with double quotes.

Example: Conditional Setting of Global Variables

  • start NetLogo

  • In the Code window enter globals [nHeads nTails]

  • Go to the Command Center and enter the following code:

ifelse (random-float 1 < 0.5)
  [set nHeads (nHeads + 1)]
  [set nTails (nTails + 1)]
show nHeads
show nTails


NetLogo also provides the unusual ifelse-value primitive, which allows condition determination of a value.

ask turtles [
  set color ifelse-value (wealth < 0) [red] [blue]

Example of Switching

We can nest ifelse-value expressions to discriminate between cases.

let x random 10000
show ifelse-value (x < 10) ["One digit"] [
     ifelse-value (x < 100) ["Two digits"] [
     ifelse-value (x < 1000) ["Three digits"] [
     "Many digits"

Control Flow: Looping

  • ask <agentset> [<commands>]

  • foreach <list> <command>

  • repeat

  • stop

  • while

  • loop (forever!)

Control Flow: Other

  • ask-concurrent

  • carefully (and error-message)

  • every

  • run runresult

  • to to-report

  • wait

  • with-local-randomness

  • without-interruption

Operators: Math, Logic and Comparison

  • +, -, /, ^

  • white space delimited (e.g., 3 + 2 not 3+2)

  • all are binary, but can write (- x) for 0 - x

logical operators (operate on booleans)
  • and, not, or, xor

  • >, >=, <, <=, =, !=

Operator Precedence (high to low)

  • with, at-points, in-radius, in-cone

  • (all other primitives and user-defined procedures)

  • eponentiation: ^

  • *, /, mod

  • +, -

  • inequality comparisons: <, >, <=, >=

  • equality comparisons: =, !=

  • logical operators: and, or, xor

Note that primitives have higher precedence than other operators. E.g., sin 0 + 1 evaluates to 1.

Documentation resource:

Global Variables

  • have global scope (i.e., are available anywhere in the program)

  • must be declared before used

    • in the declarations section, or

    • by adding a button

  • use set a b to change the value of variable a

Local Variables

Local variable can be created with let inside a procedure body. They are invisible outside their code block. 1 Suppose that insider a procedure body, a and b have already been defined, but c has not. Then

  • let c a declares a new local variable c and assigns it the value of a.

  • set c b changes the value of c to be the value of b.

  • The scope of c is restricted to code block in which it was declared. In particular, the variable c is invisible outside of this procedure body.

A procedure’s formal parameters are also local to the procedure.


However, see the discussion below in Tasks Are Closures.


NetLogo Lists: Basic Concepts

NetLogo lists can contain a variety of items in a fixed order.

Lists are:

  • ordered

  • immutable

  • potentially heterogeneous (e.g., numbers and strings)


let lst00 []                 ;; empty list
let lst01 [0 1]              ;; list of numbers
let lst02 ["zero" "one"]     ;; list of strings
let lst03 [0 1 "zero" "one"] ;; list of numbers and strings

Zero-Based Indexing

Because lists are ordered, it makes sense to ask what item is at a particular location. We do this with the item primitive.

Indexing is zero-based: the first index is 0.

item index list

return item index of list (e.g., item 0 [3 2 1] is 3)

Constructing Lists

The list primitive provides a general list constructor (with parentheses):

(list )               ;;emtpy list
(list 0 "one" myvar)  ;;list of three items

A shorter bracket notation can be used when all list items are literals. (But you cannot use bracket notation to build lists from variables.):

[]         ;; emtpy list
[0 "one"]  ;; list of two items
let x 0 let y 1 show [x y]  ;;ERROR

List Length

The length of a list is the number of items in the list.

length lst

reports the length of lst

empty? lst

reports true if lst is empty

Adding Items to a List

fput <item> <list>

prepends item to list (e.g., fput 1 [2 3])

lput <item> <list>

appends item to list (e.g., lput 3 [1 2])

sentence <list1> <list2>

concatenates list1 and list2 (e.g., (sentence [1 2] [3]))

Note: in each case, a new list is returned, which we can represent as [1 2 3].

List Members

member? value list

report true if value is in list

first list

report first list item


report last list item

item index list

report item at (zero-based) index

one-of list

report a random item of list

position item list

report the index of item in list

Creating Lists with range

The simplest way to create a long list of values is with range, which generates list of numbers from a starting point, an open stopping point, and a step size.

(range <start> <stop> <step>)

The step size may be omitted; its default value is \(1\). The starting point may additionally be omitted; its default value is \(0\). (In this last case, parentheses become optional.)

(range <start> <stop>)
range <stop>

Mapping over Ranges

Many of the needs for basic list creation can be met by mapping over ranges. For example,

map [[x] -> x * x] (range 10)

Creating Lists with n-values

An alternative to mapping over ranges is to use n-values, which does not require buidling the range list.

Newcomers to NetLogo often find it puzzling to use n-values. Read the documentation carefully. The general syntax is

n-values <number> <reporter block>

The n-values primitive takes two inputs and produces one output. The inputs are the number of values to produce, and a reporter. The output is a list, where each item is a function of its index.

Remember that NetLogo indexes start at zero. Consider the command n-values 5 [[?] -> ?]. This say to produced a list of 5 values using the reporter [[?] -> ?]. The question mark is just an ordineary variable name, which stands for the index. (You can use any other valid name.) The result is therefore [0 1 2 3 4]: a list of 5 successive values, starting at 0.

Note again that n-values takes two arguments: an integer size (here 5), and a “reporter” (here [[?] -> ?]).

Documentation Resource:

Question Mark: n-values

The question mark in the reporter is an ordinary NetLogo variable name used by convention. (NetLogo allows many names that would be illegal in other languages.) The values taken by this variable depend on the command.

When we use the n-values command, the variable will take on successive integer values, starting at 0. (The number of values is determined by the size argument.) That is, when we use n-values, the reporter parameter stands for the index of the list item.

For example, to produce a list of 5 items where each item equals its index, we can use

n-values 5 [[?] -> ?]
n-values 5 [[x] -> x]
n-values 5 [[my-favorite-name] -> my-favorite-name]

As another example, to produce a list of 5 items where each item equals half of its index, we can use

n-values 5 [[?] -> ? / 2]

Here is another example: to produce a list of the squares of \(0\) through \(9\), we can use

n-values 10 [[?] -> ? * ?]

You are not required to use a reporter parameter if you do not need it. For example,

n-values 5 [random 2]

Iterating over a List with foreach

We can use foreach to run commands for each item of a list, using the items in the commands. The general syntax is:

foreach <list> <command>

where, as usual, we use angle brackets to indicate a needed substitution. Here is a simple example:

foreach [0 1 2] print

Here is a slightly more complex example, where we use range to generate the list, and then use foreach to process that list item by item.

foreach (range 3) [[?] -> print ? * ?]

Note: ? is an ordinary name that is a somewhat common convention for naming parameters in NetLogo tasks. The name is local to the task for which it is a parameter, so two uses in two different tasks do not collide. To illustrate, let us produce the list with n-values instead of with range.

foreach (n-values 3 [[?] -> ?]) [[?] -> print ? * ?]

The n-values reporter provides sequential nonnegative integers to its reporter task. The foreach command provides sequential elements of its list to its command task.

Documentation Resource:

Cumulative Sum using foreach

to-report partialSums [#nums]
  let total 0
  let result []
  foreach #nums [[?] ->
    set total total + ?
    set result lput total result
  report result

First Function Plot with foreach

To plot a function \(f(x)\), we need to decide which \(x\) values to consider. Then we need to pair each \(x\) value with a \(y\) value. Then we can use plotxy to do the actual plotting.

Suppose we have a set of \(x\) values named domain and a function (of a single input) named f. Then we can use foreach to plot the \((x,y)\) pairs as follows:

foreach domain [[?] -> plotxy ? f ?]

Exercise: Explain how the following code works:

foreach [1 2 3] [[?] -> plotxy ? (? * ?)]

Note how a straight line is drawn between each specified point \((x,f(x))\).

Second Function Plot with foreach

Suppose we want to plot \(f(x)\) on the interval \([0,1]\). To get a smooth looking curve often requires a It takes 101 points to delimit 100 equal sized intervals. So we can proceed as follows:

let domain n-values 101 [[?] -> ? / 100]
foreach domain [[?] -> plotxy ? f ?]

Exercise: Enter the following function in your Code tab and plot it.

to-report f [#x]
  report 3.75 * #x * (1 - #x)

Creating a Domain for Function Plotting

To plot a function \(f(x)\), we need to decide on a domain over which to plot it. Commonly, we choose an interval \([x_\text{min},x_\text{max}]\). But of course, we cannot literally plot every point in an interval, which contains an infinity of points. So we create a subset of these points on which to actually evaluate our function. Commonly, we do this by deciding how many points we wish to plot and then dividing the interval up evenly.

to-report linspace [#xmin #xmax #npts]
  let _len (#xmax - #xmin)
  report n-values #npts [#xmin + _len * (? / (#npts - 1))]

foreach Example: Multiple Lists

The foreach command can be used with multiple lists of identical length. The first result is computed from the first elements of the arguments. The second result is computed from the second elements of the arguments. For example:

(foreach [1 2] [3 4] [5 6] [[?1 ?2] -> print ?1 + ?2 + ?3])

Note the required parentheses.

Note: ?1, ?2, and ?3 are ordinary names that are sequentially assigned to each item in the first, second, and third foreach sequence.

Operating on Lists

  • sublist, remove-duplicates

  • remove item list, remove-item int list

  • but-first, but-last

  • n-of int list

new lists
  • replace-item int list

  • fput, lput, sentence

  • n-values int [reporter]

rearranged lists
  • reverse, shuffle

  • sort, sort-by


  • NetLogo lists are immutable: you construct new lists based on old lists.

  • if you want an extant variable to refer to a new list, use set.

set mylist replace-item 0 mylist 99
; mylist's first element is now 99
set mylist lput 100 mylist
; appends the value 100 to mylst
set mylist fput -1 mylist
; mylist now has a new first element

Creating Lists from Agentsets with of

use of with an agentset:

[color] of turtles

[pcolor] of patches

[(list self pcolor)] of patches

[(list self color size)] of turtles

Note that lists can contain lists!

Lists to Agentsets

patch-set lst

creats a patch set from any patches in lst (or its sublists)

turtle-set lst

creats a turtle set from any turtles in lst (or its sublists)

Introduction to Functional Programming

map reporter list

Apply a reporter to a list and produce a new list.

E.g., map [[?] -> ? * ?] [0 1 2] reports [0 1 4].

filter boolean-reporter list

Report a list of criterion-satsifying members of the input list. (See discussion below.)

reduce two-input-reporter list

Combine the items of a list into a single result by repeatedly applying a binary operation.

Suppose op is an infix binary operation then reduce op [a b c] will report ((a op b) op c)

E.g., reduce + [1 2 3] reports 6 while reduce - [1 2 3] reports -4.

sort-by reporter list

Sort a list based on pairwise comparisons.

E.g., sort-by > [3 1 4 2] reports [4 3 2 1]

Using n-values for Mapping

to-report string-to-digits [#s]
  report n-values (length #s) [[?] -> read-from-string item ? #s]


Sometimes we want a sublist of elements that meet a certain criterion. We can use filter for this. E.g.,

filter [[?] -> ? < 3] [1 2 1 3]

reports [1 2 1].

Using Filter to Tally

to-report tally [
  #x   ;the item to search for
  #lst ;the list of items
  ] ;-> (int): the frequency of #x in #lst
  report length filter [[?] -> ? = #x] #lst

Note: This is an inefficient way to tally, because it constructs a list when we only need the count. (A good way to tally is to use table:counts, provided by the table extension.)

Filtering Agentsets

If you want to filter an agentset s based on an attribute w, you would have to convert it to a list ([self] of myagentset) before your could apply filter. E.g.,

filter [? -> [w] of ? < 3] [self] of patches

However, the better way is usually to use with to create an agentset.

patches with [w < 3]

Note that filter consumes and list and reports a list, while with requires an agentset and a reporter block, and reports an agentset. It follows that with can remove an agent a from an agentset:

set myset myset with [self != a]
Documentation resources:

Lists: Contrast with Agentsets


  • an unordered, mutable, homogeneous collection of agents

  • traverse with ask

    • ask agentset [ list of commands ]


  • an ordered, immutable, possibly heterogeneous collection of objects

  • traverse the list items sequentially with foreach

    E.g., foreach [1.1 2.2 2.6] [[?] -> print round ?]

Advanced List Use

Some example of advanced list use:

nested foreach

Here we illustrate nested foreach loops by producing the two-dimensional offsets needed to construct a box (Moore) neighborhood of arbitrary radius.

to-report moore-offsets [#r]
  let _dxdy (list )  ;; empty list
  let offsets (range (- #r) (1 + #r) 1)
  foreach offsets [?dy ->
    foreach offsets [?dx ->
      set _dxdy lput (list ?dx ?dy) _dxdy
  report _dxdy

Permutations via Nested foreach

NetLogo supports recursion, which we use here to produce all the permutations of a list.

to-report permutations [#lst] ;Return all permutations of `lst`
  let n length #lst
  if (n = 0) [report #lst]
  if (n = 1) [report (list #lst)]
  if (n = 2) [report (list #lst reverse #lst)]
  let result []
  let idxs n-values n [?]
  ;use each item as a first item, permuting remaining items
  foreach idxs [[?] ->
    let xi item ? #lst
    foreach (permutations remove-item ? #lst) [[?] ->
      set result lput (fput xi ?) result
  report result


Simple Reduction of a List

reduce reporter list

repeatedly apply a binary operation to a list from left to right, using the binary operation supplied by reporter.

Use ?1 and ?2 in your reporter to refer to the two objects being combined.

For example, we can sum the items in [1 2 3] as follows:

reduce [?1 + ?2] [1 2 3]
reduce + [1 2 3]  ;; short form

How reduce Works

Consider the following:

reduce [?1 + ?2] [1 2 4]

Remember, reduce works through the list from left to right. Here ?1 refers to the first argument, and ?2 refers to the second argument.

Step 1:

set ?1 to the first item (e.g., 1) and set ?2 to the second item (e.g., 2)

Step 2:

add ?1 and ?2; if there are any more list items go to Step 3, otherwise report the result of the addition.

Step 3:

set ?1 to the result of addition (e.g., 3), and then set ?2 to the next item in the list (e.g., 4). Go to Step 2.

So the following would produce the same result:

to-report sum-list [lst]
  let arg1 first lst
  foreach butfirst lst [[?] ->
    let arg2 ?
    set arg1 (arg1 + arg2)
  report arg1

Factorial via reduce

We can use reduce with n-values to produce the factorial of any positive integer.

to-report factorial [#n]
  report reduce * n-values #n [? + 1]

Binary to Integer via reduce

Suppose we have a list of zeros and ones representing a binary number.

to-report binary-to-integer [bits]
  report reduce [?1 * 2 + ?2] bits

Item Count via reduce

to-report tally [
  #x   ;the item whose occurences we tally
  #lst ;(list): list of items
  ] ;-> (int): the multiplicity of #x in #lst
      [[?1 ?2] -> ifelse-value (?2 = #x) [?1 + 1] [?1]]
      (fput 0 #lst)
;Attribution: see NetLogo documentation of `reduce`

All and Any

NetLogo does not provide all and any for lists. But they are easily implemented for list of booleans with reduce. For example:

to-report allTrue [#lst]
  report reduce and #lst

to-report anyTrue [#lst]
  report reduce or #lst

With just a little more effort, we can improve these functions so that they appropriately handle empty lists.

to-report allTrue [#lst]
  report ifelse-value (empty? #lst) [true] [reduce and #lst]

to-report anyTrue [#lst]
  report ifelse-value (empty? #lst) [false] [reduce or #lst]

flatten via reduce

Recall we can use sentence to concatenate lists. We can therefore use reduce with sentence to concatenate all the sublists in a list of lists.

to-report catenate [#lstlst]
  report reduce sentence #lstlst

Example: catenate [[0] [1 1] [2 2 2]]

Reversing a List with reduce

To reverse a list using reduce, we use a useful trick: we modify our input argument by inserting an empty list at the front (with fput). This is the first value seen by reduce, so we can use it to successively accumulate items.

reduce [ fput ?2 ?1 ] (fput [] lst)

Note: since NetLogo has a reverse primitive, this exercise is simply to illustrate the capabilities of reduce.

Parial Sums using reduce

Given a list lst, list of its partial sums is often called the cumulative sum of lst. To produce these partial sums, we reuse the trick of reducing an input list after inserting an initial list as the first item in our input, using fput. This allows us to construct to use reduce to construct our new list.

Challenge: carefully explain how this code works.

Computations for a Lorenz Curve

We can use partial sums to produce cumulative shares. For example, using our partialSums procedure above,

to-report cumulativeShares [
  _ws ;(list) : a list of nonnegative numbers
  ];-> (list): the cumulative shares
  ;; caclulate normalized sorted cumulative wealths
  let _cumsumWeatlhs partialSums (sort _ws)
  let _total last _cumsumWeatlhs
  report map [[?] -> ? / _total] _cumsumWeatlhs

Computing Gini Coefficient

Use the shares you computed for the Lorenz curve.

to-report shares2gini [
  #cumShares ;(list) : sorted numbers in (0,1]
  ];-> (number): the Gini coefficient of inequalty
  let _n length #cumShares
  let _popShares n-values _n [[?] -> (? + 1) / _n]
  let _gaps (map [[?1 ?2] -> ?1 - ?2] _popShares #cumShares)
  report sum _gaps * 2 / _n

Plotting Lorenz Curve ...

  plot 0
  let _shares cumulativeShares [wealth] of turtles
  let _n length _shares
  set-plot-pen-interval (1 / _n)
  foreach _shares [[?] -> plot ?]


Tasks vs. Procedures

NetLogo 6 introduces lambdas, which are also perhaps unfortunately called “anonymous procedures”. (This is perhaps unfortunate, because a lambda can be named by assigning it to a variable.) We will call these “tasks” (which was a similar NetLogo 5 terminology). Like procedures, tasks store code for later execution. Like procedures, tasks may be commands or reporters. We can ask which type of task we are dealing with with the is-anonymous-command? and is-anonymous-reporter? primitives.

Unlike procedures, tasks are values, and they can be passed around like any other values. This is a very powerful facility and can be quite useful.

We declare a task with the -> primitive. Analogously to procedures, we can have command tasks and reporter tasks. The syntax to create and report command lamda or a reporter task is

[[<args>] -> <commands>]
[[<args>] -> <reporter>]

As usual, the angle-bracketed text needs to be replaced. For example, replace <args> with a list of formal parameter names. Analogously to procedures, a task can accept arguments. The formal parameters are named in a block. If there are no arguments, use empty brackets.

Command Tasks: Simple Example

A command task is used to run code without returning a value. We use the run primitive to run a command task. Consider the following.

globals [x xpp]

to setup
  set x 0
  set xpp [[] -> set x (x + 1)]

Here xpp is just an global-variable name, but we assign a command task to it. Now the execution run xpp to add 1 to x.

Surprising Need for Parentheses


If your task takes input arguments, it must be run with parentheses.

The parenthesis determine what is considered to be an input to the task. (Extra inputs are simply ignored.)

Command Tasks: Stack Example

A command task is used to run code without returning a value. Recall that we use the run primitive to execute a command task. Consider the following.

globals [stack push]

to setup
  set stack []
  set push  [[item] -> set stack lput item stack]

Now we can (run push 1) to push a 1 on our stack. Recall that the parentheses are required. The code (run push 1) is correct, but the code run push 1 (without parentheses) is an error.

An Even More Surprising Need for Parentheses

let biggest [[?1 ?2] -> ifelse-value (?1 >= ?2) [?1] [?2]]
show reduce [[?1 ?2] -> (runresult biggest ?1 ?2)] [1 2 3 4 3 2 1]
show reduce biggest [1 2 3 4 3 2 1]  ;shorthand for the same thing

Reporter Tasks

A reporter task is used to run code and return a value. We use the runresult primitive to execute a reporter task. For example:

let square [[?] -> ? * ?] print (runresult square 5)

Again, tasks with arguments must be run with parentheses. While (runresult square 5) is correct, runresult square 5 (without the parentheses is an error.

Reporter Tasks as Function Literals

In NetLogo, there are two different ways to create functions. The traditional way is to declare a reporter procedure in the procedures section of a NetLogo Model. If we want to create a function elsewhere, such as inside a procedure or at the command line, we use a `function literal`_, also called lambda expressions or tasks. Each approach can be useful.

A function literal is an expression whose value is a function. Here is an example of a function literal in NetLogo.

[?x -> ?x + 0.03 * ?x * (1 - ?x)]

The bracketed expression is a function literal; the brackets are required. Here we follow an optional NetLogo convention of beginning the parameter names with a question mark. It is worth noticing the close relationship between the syntax for function literals and the mathematical syntax \(x \mapsto x + 0.03 * x * (1 - x)\).

In NetLogo programming, function literals are often called anonymous reporters, since we need not associate them with a name. (For historical reasons, it is also common to refer to a function literal as a lambda expression.) Function literals enable us to create functions inside a NetLogo procedure or at the command line. As we will see, this can be very useful.

In NetLogo, function literals must be called with the help of the runresult command. For example, enter the following at the command line. (The parentheses are required.)

print (runresult [?x -> ?x + 0.03 * ?x * (1 - ?x)] 2)

Here, the print command needs a value to print. This value is provided by the runresult command, which applies our function literal (in brackets) to the value of our number literal (2).

Sometimes the use of anonymous functions can become hard to read. In this case, we may prefer to introduce a variable to refer to our function. In NetLogo, we may use the let command to introduce a new variable. For example, enter the following at the command line. (The parentheses are required.)

let f [?x -> ?x + 0.03 * ?x * (1 - ?x)] print (runresult f 2)

Plotting Exercise: Simple Function Plot

Add a plot named functionPlot to your Interface.

Add the following command procedure to your Code tab (along with the linspace function defined above).

to plotFunction [#fn #xl #xr #npts]
  let _xs linspace #xl #xr #npts
  let _ys map #fn _xs
  (foreach _xs _ys [[?x ?y] -> plotxy ?x ?y])

Here #fn is a reporter task that accepts one argument. The arguments #xl and #xr are the left and right boundaries of the plot domain. The argument #npts is the number of points to plot.

Exercise: On the interval [0,1], plot the logistic map with an amplitude parameter of 3.5.


Tasks Are Closures

Tasks reported by procedures close over variables local to the procedure. For example, consider the following reporter procedure, which reports a task.

to-report modnum [#divisor]
  report [[?] -> ? mod #divisor]

Now we can do the following:

let mod3 modnum 3 show (runresult mod3 17)
let mod4 modnum 4 show (runresult mod4 17)

We see that our modnum function returns a task that is a `function closure`_. That is, each task keep track of its own value of #divisor (i.e., the value of #divisor when the task was created). Recall that NetLogo requires the use of runresult to invoke a reporter task.

Tasks in the Models Library

  • State Machine Example

  • Termites 3D

File-Based IO


Before experimenting with the file commands, create a new NetLogo model instance and save it to a directory where it is safe to overwrite and delete files.

Open and Close File

When doing modeling and simulation, we often export some of the data produced by our simulations to files. At times, we also read into our simulations data that is stored in files. In this section we explore how to read and write text files with NetLogo.

Before we can write to or read from a file, we must open it. We use file-open <string> to open a file, where you substitute a file path for <string>. Once finished with an open file, you should always close it with file-close.

file-open "temp.txt"
file-close  ;;close the last opened file

The the argument to file-open is a string; it must be in quotes. In contrast, file-close does not take an argument; it will close the last opened file.


The argument to file-open can just be a file name, if the file is in your current directory. You can also use a fully qualified file path. In path names, even on Windows, use forward slashes (not backslashes).

Open a File

Unlike many languages, NetLogo does not ask you to specify upon opening whether you will read from or write to the file. That is determined by the first file primitive you use on the open file.

For example, if you use file-read then the file can only be read. On the other hand, if you use file-write then it can only be written.

file-open "temp.txt"     ;open the file for reading or writing
file-print "output text" ;file can now be written, NOT read
file-close               ;close the last opened file

file-open "temp.txt"     ;open the file for reading or writing
print file-read-line     ;file can now be read, NOT written
file-close               ;close the last opened file


NetLogo does not offer access to explicit file handles.

Open a File for Writing

If you open an existing file and write to it, you will append to that file. If you want to replace the content of an existing file, you will have start with a file-delete. In order to open a file for writing and close it afterwards, you need the following commands:

file-delete <string>

delete the file designated by <string>

file-open <string>

open a file for reading or appending (but not both)


close an open file

Using carefully with file-delete

To replace the content of a file, begin by deleting the existing file. However, trying to delete a file that does not exist is a runtime error. Suppose you do not know ahead of time whether the file exists? The simplest solution is to use carefully. For example, try the following at the command line. (Caution: this will delete temp.txt if it exists!)

carefully [file-delete "temp.txt"] []
file-open "temp.txt"
file-print "write this line to temp.txt"


When you write information to a file, your operating system may well not write the information immediately. Use of file-close (or file-flush) forces the operating system to write to file immediately.

Documentation resource:

Caution: you should ask before file-delete

If you are absolutely sure that it is safe to delete an existing file, you can use carefully with file-delete.

You can never be sure it is ok to delete a file that someone else might have created. So models that you share should not use this approach.

You can check whether the file exists with file-exists, which returns a boolean. You can then ask the user of your code whether it is acceptible to delete the file. Here we use NetLogo’s user-yes-or-no? primitive.

if (file-exists? "temp.txt") [
  ifelse (user-yes-or-no? "OK to delete temp.txt?") [
    file-delete "temp.txt"
    error "temp.txt already exists"

If the user says not to delete a file, this code provides a pretty primitive response: it raises an error, so that program execution stops. It would be nicer to ask the user for an alternative filename, which can be done with user-new-file.

Documentation resources:

File Output Commands

NetLogo provides an unusual collection of commands for writing to files. Note that file-print and file-show append a carriage return (CR).

file-type value

write value to file

strings are written without quotes; backslashes escape control characters

file-write value

write a space, and then write value,

strings are written quote delimited; backslashes are literal

file-print value

write value, followed by a newline.

file-show value

first write the agent description, then write value, followed by CR

Comment: Windows-centric text editors may not display CR as an end-of-line. For example, Notepad will not display then at all.

Example: Export Attribute (Agentset)

This produces a single column of output:

carefully [file-delete "temp.csv"] []
file-open "temp.csv"
ask patches [
  file-print pcolor

Example: Write a List to File

This produces a single column of output:

to writeListToFile [#mylist #fname]
  carefully [file-delete #fname] []
  file-open #fname
  foreach #mylist [[?] ->
    file-print ?

For example:

writeListToFile [1 2 3] "/temp/temp.csv"

Example: Write Space-Separated Values (SSV)

Try this in the command center:

carefully [file-delete "temp.txt"] []
file-open "temp.txt"
file-print "minimum mean maximum"
file-type 10 file-write 15 file-write 20
file-print ""  ;;terminate line with CR

Example: Write Comma-Separated Values (CSV)

Ordinarily we use the csv extension to write CSV files. However, we can do it by hand. In the Code tab, create the following command procedure:

to writeCSVrow [#fname #vals]
  file-open #fname
  file-type first #vals
  foreach but-first #vals [[?] ->
    file-type "," file-type ?
  file-print ""  ;;terminate line with CR

Here we illustrate how to write a header line and a line of data. At the command center, enter the following:

carefully [file-delete "temp.csv"] []
writeCSVrow "temp.csv" ["minimum" "mean" "maximum"]
writeCSVrow "temp.csv" [10 15 10]

Writing subsequent lines is identical.

List to CSV Row with reduce

The reduce primitive can be useful to concatenate a list with a separator.

to-report stringRiffle [#lst #sep]
  report reduce [[x y] -> (word x #sep y)] #lst

This allows us to readily produce a CSV row from a list of values.

stringRiffle [1 2 3] ","

Multiple Open Files

You must always use file-open to specify what file you want to interact with. E.g.,

file-open "log1.txt"
file-open "log2.txt"
file-write "this goes in log2.txt"
file-open "log1.txt"  ;;required!
file-write "this goes in log1.txt"

File-Based Input

In order to read external information into a program, the following commands are often useful.


read the next line and return it as a string (without terminators)


read the next "constant" (e.g., number, list, or string) and return it


report true if last character of file has been read

Of course we will still need to open and close our files.

file-open string:

open a file for reading or appending (but not both)


close an open file

Example: file-read-line

Try this in the command center:

file-open "temp.txt"
print file-read-line

Note use forward slashes in your paths.

Example: File-Based Input

Suppose the nldata01.txt looks like:

pxcor pycor n-turtles
0 0 5
1 0 3

You could handle this (in a procedure, in the Code tab) as follows:

file-open "nldata01.txt"
let trash file-read-line ;; discard header line
while [not file-at-end?] [
  ask patch file-read file-read [sprout file-read]

Example: More File-Based Input

Assume a 20x10 world of patches.

Suppose patches have a foo attribute. Suppose you have created foo.txt as:

1 2 3 4 ... 200

Suppose patches also have a bar attribute. Suppose you have created bar.txt as:

200 199 198 197 ... 1

Give each patch one of these values for its foo and bar attributes as follows:

to setupPatches
  let patch-list sort patches
  file-open "foo.txt"
  foreach patch-list [[?] ->ask ? [set foo file-read]]
  file-open "bar.txt"
  foreach patch-list [[?] ->ask ? [set bar file-read]]

Comment: patches are sorted in a fixed order: left to right, top to bottom.

Example: File-Based Input (Python)

fin = open('nldata01.txt', 'r')
trash = next(fin)
data = dict()
for line in fin:
    x, y, n = map(int, line.split())
    data[(x,y)] = n

CSV Extension

The NetLogo CSV extension simplifies reading and writing data in the CSV format. CSV stands for comma-separated values. The CSV extension accommodates some common deviations from the CSV standard. For example, it allows specification of a different delimiter than the comma. However, the standard for scientific data exchange is a comma as the field delimiter and a point as the decimal separator.

Declaring and Using the CSV Extension

You must declare your intention to use the csv extension at the top of your Code tab.

extensions [csv]

You can write a list of lists to myFile.csv like this:

csv:to-file "myFile.csv" [[1 2] [3 4] [5 6]]

Try this at the command line. (Warning: this will overwrite any existing file named myFile.csv!) You can append a row to myFile.csv like this:

file-open "myFile.csv"
file-print csv:to-row [7 8]

Example: File-Based Input (CSV)

extensions [csv]

to setup
  file-open "c:/temp/temp.csv"
  ;;if there is a header line, use it or discard it
  let _trash file-read-line

to get-one-line
  file-open "c:/temp/temp.csv"
  if file-at-end? [ stop ]
  let _line file-read-line      ;; read the line into a string
  let _data csv:from-row _line  ;; convert the string to a list of numbers
  ;;now do whatever you want with the data

Example: File-Based Output (CSV)

extensions [csv]

to setup
  carefully [file-delete "temp.csv"] []
  file-open "c:/temp/temp.csv"
  file-print "x,y,z"

to write-one-line
  let _mylist (list x y z)
  file-open "c:/temp/temp.csv"
  let _mystr csv:to-row _mylist
  file-print _mystr

BehaviorSpace and File Output

If you want to make a unique output file for each BehaviorSpace run, use the behaviorspace-run-number primitive to make a unique filename. Alternatively, produce filenames based on parameter values.

For example, suppose that in BehaviorSpace you specify the parameter sweep:

["globalA" 1 2 3]
["gloablB" 4 5 6]

Then you can

file-open (word "myfile-" globalA "-" globalB ".txt")

Of course you can combine these two approaches.

If you needs even more flexibility, consider Charles Staelin's pathdir extension. It might still be here:


Bundled Extensions

See: Help > NetLogoUser Manual > Extensions

A standard NetLogo installation bundles a few extensions, which are located in Extensions subfolder of the NetLogo installation folder. These include:

vid Extension

Record 100 ticks of a simulation:

repeat 100 [
vid:save-recorder "my-movie.mp4"


Alternatives to vid Extension

There have been reports that the vid extensions produces videos that do not play reliably under Windows.

An alternative is to export the view every tick and then combine the exported .png files into a movie.

to make-frames
  setup  ;must call reset-ticks
  repeat 100 [
    go  ; (must call tick)
    export-view (word "frame" (1000 + ticks) ".png")

This will produce 100 files with names frame1001.png to frame1100.png.

To combine the PNG files, use any software capable of doing so. For example,

  • ffmpeg -f image2 -r 1/5 -i frame%04d.png -vcodec mpeg4 -y movie.mp4

  • avconv -f image2 -i frame%04d.png -r 76 -s 800x600 foo.avi

  • Mathematica's Export function.

  • Python's pillow library.

  • GIF Construction Set Professional.


What is an Array?

A NetLogo array is a fixed-length collection of objects, such as a collection of 100 numbers. Let us make an array of length 100, full of zeros.

array:from-list n-values 100 [0]

Indexing is zero-based. That is, as with lists, the first item has index 0. The second item has index 1. And so on.


Arrays Are Mutable

School-Lockers Analogy:

You can think of an array as a bit like a row of school lockers. Each student has an assigned locker, where s/he stores stuff. The stuff in a locker can change. Similarly, we can change the corresponding item in the array. Let us change the first value of myarray to 999.

array:set myarray 0 999

Increment a Single Item

Let us increment the first value of myarray by 1.

array:set myarray 0 (array:item myarray 0 + 1)

Let us decrement the second value of myarray by 1.

array:set myarray 1 (array:item myarray 1 - 1)

When array items represent the values of an attribute of agents, then a transfer can be represented as a decrement of one item combined with an increment in another.

This is a bit like taking something out of one student's locker and putting it in another student's locker.

Arrays vs Lists

NetLogo uses the term "array" substantially differently than many languages. In particular, a NetLogo array is a fixed length container of objects, which need not be of a common type. (E.g., they need not all be numbers.) Array items can be quickly accessed or replaced, using their indexes.

array:set myarr 0 (array:item myarr 0 + 1)

Since lists are immutable, the equivalent operation on lists is a bit more awkward.

set mylst replace-item 0 mylst (item 0 mylst + 1)

Array Limitations

While arrays can be useful when one needs a fixed-length container with changing contents, they are limited. For example, to copy an array, you need a list intermediary:

let acopy array:from-list array:to-list myarr

(See for details on array:to-list.)

Similarly, max and min work only on lists, so you will again have to use array:to-list if you want to use these commands.

Array Limitations: Filtering

We can only apply filter to lists. So if you want to filter an array a, you need to convert it first:

filter [? < 3] array:to-list a


What is a Table?

A NetLogo array is a mapping from keys to values.


Tables Are Mutable

to-report counts [#lst]
  let _t table:make
  foreach #lst [[?] ->
    let _k ?
    ifelse table:has-key? _t _k [
      table:put _t _k (1 + table:get _t _k)
      table:put _t _k 1
  report _t

Odds and Ends

Colors Are Numbers

When we show the color of an agent, the result is a number. NetLogo represents colors by numbers in [0 .. 140).

The command random-float 140 picks a random number in this range.

As a matter of convenience, NetLogo also defines named aliases for some colors. (E.g., white = 9.9.)

So the following are equivalent:

ask mypatch [set pcolor white]
ask mypatch [set pcolor 9.9]

(You can see this equivalent by entering show white at the command line.)

Advanced Topics

NetLogo File Format

NetLogo files use a plain text file format. This means that all the widgets in the Interface tab can be edited with a text editor. Ordinarily you will adjust the locations of widgets (such as sliders, monitors, or plots) with a mouse in the Interface GUI. However, sometimes finer adjusted is desirable. In this case, since the file format is plain text, we can simply edit the .nlogo file directly. There is helpful informal file-format documentation online.

Monitor Widget Example

Defining a monitor takes 10 lines, as follows. First comes the MONITOR declaration, on its own line. Next comes a specification of the top left \((x1,y1)\) and bottom right \((x2,y2)\) corners of the monitor, measured in pixel offsets from the top left of your graphic window. Unfortunately, y2 is ignored: the monitor height depends of the font-size you specify in the tenth line. Next you specify the display name for your monitor and the reporter expression (e.g., global variable name) you are monitoring. The next line specifies the precision of the numer displayed (i.e., the number of decimal places). The ninth line appears to be reserved for future use, and the last line specifies the font-size (in points).

Display Name

Format Stability

The NetLogo file format is not stable across major revisions, and newer versions only support import of one previous version.

There are many interesting models in NetLogo 4. The following link is helpful if you want to convert a NetLogo 4 model to NetLogo 6.


Axtell, R., Axelrod, R., Epstien, J. M., and Cohen, M. D. (1996). Aligning simulation models: A case study and results. Computational and Mathematical Organization Theory, 1:123–141.

Resnick, M. (1997). Turtles, Termites, and Traffic Jams: Explorations in Massively Parallel Microworlds. MIT Press.


Janssen, Marco A. (2012) Introduction to Agent-Based Modeling. : .


Thiele, Jan C, and Volker Grimm. 2010. NetLogo meets R: Linking agent-based models with a toolbox for their analysis. Environmental Modeling and Software , 972--974.


Copyright © 2016 Alan G. Isaac. Some rights reserved. This document is licensed under the Creative Commons Attribution 4.0 International Public License.