Agents not following movement rules based on territories

Hi,
I am trying to create a model where the agents should set up territory on patches they have occupied and avoid patches that have been occupied by other agents.
To do this I decided to assign each patch the “who” of the agent that occupied it and then have the agents check if the patch has not been occupied previously. Assigning patches to agents seem to work, but recognising occupied patches does not.

When I ask the agents to print if the patch they are facing is safe or not, they often report it being usafe even if it has not previously been occupied or is within their own territory. When I run the code with only one agent I do not get false reports of patches being unsafe. I think the issue might be in the " [ifelse ([territory] of patch-ahead 1 = [who] of myself) or ([territory] of patch-ahead 1 = nobody)" statement but I cannot see what it could be. I would greatly apprechiate any feedback on what the issue might be!

There is also an issue that agents sometimes enter patches not within their own territory. I have setup the code so that agents should not move when the patch-ahead is “unsafe”, only turn, but they still enter them. Does it have anything to do with the angle the agent is facing?

Code:

to setup
ca ;clear environment

setup-habitat
setup-mammal

reset-ticks

end ;end of setup procedure

;
;
;
;PATCH SETUP

to setup-habitat

ask patches [
set pcolor black
set territory nobody ;all patches start as unclaimed territory
]

end

;
;
; AGENT SETUP

to setup-mammal

create-mammals n.mammals
[ set size 1
setxy random-pxcor random-pycor
set label who ;track individuals
]

ask mammals [
mark-territory
]

end ;of mammal setup

;
;
; GO PROCEDURES

to go

ask mammals [
set at-edge false ;reset edge checker
check-territory
move ;forage or travel

]

tick
if ticks >= 100 [stop]

end

to check-territory

ask mammals [
ifelse patch-ahead 1 = nobody ;check if at edge of world
[
show(“at edge - turn”) ;defensive code
set at-edge true ;set patch ahead to unsafe, for using in move procedure
]
[ifelse ([territory] of patch-ahead 1 = [who] of myself) or ([territory] of patch-ahead 1 = nobody) ;check if patch is part of own territory or not part of a territory yet
[
set patch-safe true ;patch is safe if this is true
show (“patch safe”) ;defensive code
]
[set patch-safe false ;patch is unsafe if this is false
show (“too close to other territory - patch unsafe”) ;defensive code
]
]
]

end

to move
pd
ask mammals [
ifelse at-edge = true
[right 90 fd 0 ;turn away from edge
]
[ifelse patch-safe = true ;check if patch ahead is safe to move to
[
fd 1 ;move to patch
mark-territory ;mark patch as territory if unclaimed
right random-normal 0 120 ;change turning angle
]
[right 90 fd 0] ;if patch is unsafe turn and check if new patch is safe
]
]

end

to mark-territory

ask mammals [
if [territory] of patch-here = nobody [ ;check if patch has not been claimed
ask patch-here [set territory [who] of myself] ;set territory to own ID

]

]

end

Hi @MKlaussen,

If I’m reading your code correctly, it seems like you’re using myself to refer to the current agent. This is likely where your bug is occurring, because myself refers to the agent that asked the current agent, not the current agent itself. To refer to the current agent, you can use self, or you can just say who on its own to implicitly get the current agent’s who number. Let me know if that doesn’t solve the problem!

Isaac B.

Hi @MKlaussen,

Thank you for posting your question here.

Apart from the confusion between self and myself (you are not the first one to encounter this), I see some other pitfalls.

Before I go into those aspects, some other advice.
It is important to include breeds and variables as well when asking questions about your code. (Or add the model file to the message…)
From the code, I distilled that we need the following declarations at the top of the code:

(To make a code block like this, start with three backticks ```. It also avoids conversion of quotes to ‘smart quotes’) .
And I guess that m.mammals is a slider?
I included the first procedure as well. As you see, indentation is still correct.

For anybody reading your code, please use blank lines sparingly. There is no need to put a blank line after to or before end or around square brackets.

Then about your coding question.
You use nobody as well as who numbers. However, who is just a number, while nobody is a special reference, not a number. For referring to any agent, who numbers are usually not the best (safest) way – did you realize that 0 could mean “unitialized” or “the first agent created”? To refer to an agent, you can use self instead of who. Then agent references and nobody are really comparable (same type in programming language terminology).

After copying your code into an empty NetLogo model and making the necessary adjustments, I noticed that the model is terribly slow.
This is another issue I encountered frequently as a teacher. The problem is that your agents (mammals) execute procedures (check-territory, move, mark-territory) that start with ask mammals again.
The first convention to avoid this kind confusion is to mark each procedure with a ‘context’ that indicates which kind of agents are meant to execute the code. That would look something like this in your model:

Then, inside a “mammals procedure”, don’t say ask mammals again. The procedure is already executed by (one or more) mammals. If you repeat the ask mammals all mammals ask all mammals (others and themselves) to execute the nested code. So instead of 100 times (for example) the code will be execute 10k times. With another level of nesting, it gets even worse!

I hope this helps getting your model working.
Good luck,
Mark

Hi! Thank you both for your replies the code works now!
And thank you for clarifying how to present the code and the improvements that could be done to the code to make it better.

Mari

2 Likes