This post takes into account that you read and exercise my first and second (posts on Agent-Base Models & Insight maker. In this post, the focus is the action primitive. We’ll use it to depict the same functionality that we did in the previous post. Then we will use the action primitive to add more logic.
Create a new model. Add 3 new State primitive. Head with yellow borders, Will with red borders, and Heart with green borders. Then select them and create a folder to group them. Name the folder “Person” and set it Behavior property to “Agent”.
Add agent population and name it Associates. Change the population to 200, Agent Base to “Person”, and “Placement Method” to Grid. As defined in the first post, configure the simulation to display a grid.
Add a new variable and name it “Rand Agent personality” and set the value to Floor(Rand(1,4)). Place it between Will and Hart states (inside of the folder) and connect it to both of them. To make the model more readable, we will create a ghost variable. Control & right-click on the new variable and select “Ghost Primitive” from the drop-down menu. Drag it to the left side of the Head, inside of the Person folder. The “Ghost Primitive” will have the same value as the original one, it just prevents lines crossing each other.
Now let’s follow the same logic (1 – Will, 2 – Head, 3 Heart) to set the default states. You can refer to previous posts for step-by-step instructions. This is the code for Head : IfThenElse([Rand Agent personality] = 2, 1, 0). The model should look like that: (Image 1).

When you’ll run it, you should see random personalities.
Let’s add the variables that count #of personalities per type around the agent. You can see the details in the previous post. We need one per personality. Connect each variable to the relevant state and to the Associates “agent population” primitive.
Each one of those variable’s value is the same as we used before, except for the fix function we need to add. “# of Hart Neighbors” value will look like = Fix([Associates].FindNearest(Self, 8)).FindState([Hart]).Count(). You can run the simulation to validate that you didn’t miss any link. Fix force dynamic value to be fixed over a period of the simulation.
So far, we created the same model. Before moving forward, let’s define the logic of this model. In this model, we want to see what happened if we will run the same logic between personalities for three and two personalities. We should see that three personalities increase the longevity of a group. To accomplish that, we will add a logic that after X (we’ll use 9) amount of attempts to find the right personality due to unfitness to the personality rules, the system will quit trying to find the right personality.
To achieve the above, the first thing that we want is to enable users to choose between 2 or 3 personalities. To do that, we need to create a new variable outside of the folder. We’ll name it “# of Personalities”. Set the default “Value” to 2. Turn “Show value slider” to yes, Slider max to 3, Slider Min to 2, and Slider step to 1. (Image 2)

When “# of Personalities” is 2, we will take Heart out of the equations. Therefore, we need to modify the “Start Active” property of Heart state and “Rand Agent personality”. We are going to change the Haert so it will set the state. just if the value of “# of personalities” is 3:
if [# of Personalities] = 3 then
if [Rand Agent personality] = 3 then
1
end if
End if
We need to change the Rand Agent personality to generate the right random range based on the user selection:
if [# of Personalities] = 3 then
Floor(Rand(1,4))
else if [# of Personalities] = 2 then
Floor(Rand(1,3))
end if
If you don’t see the slide bars in the property window, use the right round right button to collapse and them expand it back. You can try to run the model with 2 or 3 types and see the differences.
Before we can start working with Action, there is another data point that we need to keep. It’s the number of times the system replaced an agent with a new random personality. We will use this data to determine when we want to remove the agent from the model. Create a Stock inside the Folder and named it “# of attempts”, and place it on the right side of the folder.
Now it’s the time to add the Action Primitive. Control & Right Click and choose “Create Action”. Name it “Change & Leave”. Link all the following primitive to the Action:
- Associates
- Head
- Will
- Heart
- # of attempts
- The 3 “Number of XXXX Neighbors”
- # of properties, you can create a ghost to make the model easier
It should look like that: (Image 3)

If you’ll run the model, the agents will move because of the default action. We will replace it with ours. We will touch the agents movement in our next post.
Open the Action edit box and remove the default text. Expand the box, we are going to add some logic.
There is a logic that we’ll repeat for each state. Therefore, we’ll create a function that will implement the logic and we’ll call it every time we need it. The logic is simple. If the # of attempts per the current agent (Self) bigger than 9, remove it from the model. As long as the number didn’t reach 9, we want to:
1) increase the “# of attempts” in 1
2) Set all states to false
3) Get a random number between 1 to 3
4) Based on the random number set the current agent (Self) to a new state.
We use Self.SetValue() to reach the same of what we achieved with transition lines. As I mentioned before, with this approach, you can deal with more connected states.
When we have 2 personalities, we need to deal with fewer states, so I added another if condition to deal with this option.
This is the function that needs to be the first in the text editor (the code as the text is below):

(image 4)
The rest is the logic that calls the function based on the # of neighbors.
The entire content of Action should look like that:
Function RemoveAgentAddNewWithRandomState() If PastValues([Will]).Length() > 1 Then
If [# of attempts] > 9 then
self.Remove()
Else
if [# of Personalities] = 3 then
self.SetValue([# of attempts], [# of attempts]+1)
self.SetValue([Will], false)
self.SetValue([Head], false)
self.SetValue([Heart], false)
RndNumber <- Floor(Rand(1,4))
If RndNumber = 1 then
self.SetValue([Will], true)
else if RndNumber = 2 then
self.SetValue([Head], true)
else
self.SetValue([Heart], true)
end if
else if [# of Personalities] = 2 then
self.SetValue([# of attempts], [# of attempts]+1)
self.SetValue([Will], false)
self.SetValue([Head], false)
RndNumber <- Floor(Rand(1,3))
If RndNumber = 1 then
self.SetValue([Will], true)
else if RndNumber = 2 then
self.SetValue([Head], true)
end if
end if
End if
End If
End Function
if [Head] = true then
if [# of Head Neighbors] >= 3 and [# of Will Neighbors] >= 3 then
RemoveAgentAddNewWithRandomState()
end if
end if
if [# of Personalities] = 2 then
If [Heart] = true then
If [# of Head Neighbors] >=4 then
RemoveAgentAddNewWithRandomState()
End If
End If
end if
If [Will] = True Then
If [# of Will Neighbors] >= 4 then
RemoveAgentAddNewWithRandomState()
End If
End If
Run the model with 3 types and watch the behavior. Then run it with 2 types of personalities.
Diversity is important!