Search code examples
loopsnetlogoagentset

How to make a turtle able to save other turtles ID in Netlogo?


Here is what I want to do:

  1. I want a team consists of 3 turtles in a group.

  2. All turtles need to store their own ID and teammatesID inside the variable called teammatesID. (Imagine you want to create a group, you will put your name and your friends' name in a list, that's why this variable need to store ownID, I am bad in explaning things..)

  3. Instead of just showing (agentset,3 turtles), I need them to be able to show all teammates ID.

  4. After they have gathered all 3 members, they will get teamID.

The problem here is I don't know how to make these turtles store their own ID and teammatesID in variable called teammatesID. In a group, they supposed to have 3 different members. These teammates are not supposed to be from the same group. And how to give them teamID after they get all members.

Here is my coding:

global
[ teamID]

turtles-own
[
  myID
  teammatesID
]

to setup
  clear-all
  set-default-shape turtles "arrow"
  create-turtles 10

  ask turtles [ set myID who]
  reset-ticks
  setup-group
end

to setup-group

   set teamID []
   let agent one-of other turtles
   let  nearestNeighbor one-of other turtles in-radius 1 
   set teamID = 0
   ask agent with [ teammatesID < 3]
   [ ask nearestNeighbor with [teammatesID < 3]
     [ ;set teammatesID = myID ; here is the problem, I need to make sure they did not save the same turtle in one group.
       show teammatesID]]

       ask agent with [teammatesID > 3]
       set teamID fput teamID teamID
        end

I appreciate your extra time here. Thank you.


Solution

  • If teams are random, I don't think you need a loop for this as ask will call the turtles in a random order anyway.

    I think you should still make use of agentsets here as it makes certain things easier. For example, once turtles know their (agentset,3 turtles), you can easily query that agentset for the myIDs or whatever variable you're after.

    I'm not entirely clear on the purpose of teamID so I may be off base here, but I don't think you want it as a global variable if the teamIDs are to be unique to each group of three turtles. You'll probably want it to be a turtles-own variable as well.

    Here is an example that incorporates the above ideas. With this setup:

    turtles-own [ myteamset teamID myID teammatesID ]
    
    to setup 
      ca
      crt 10 [
        set myID who
        set myteamset nobody 
        set teammatesID [ ]
      ]
      setup-groups
      print remove-duplicates [teammatesID] of turtles
      print sort [teamID] of turtles
      reset-ticks
    end
    

    And the setup-groups procedure (more detail in comments):

    to setup-groups
      ask turtles [
        ; If you don't have a team yet
        if myteamset = nobody [
          ; Make a temporary agent-set out of all other turtles that
          ; are also not yet part of a team
          let possible-teammates other turtles with [ myteamset = nobody ]
    
          ; If there are at least two more turtles, make a new team:
          ifelse count possible-teammates > 1 [
            ; Make a team out of myself and two possible teammates
            set myteamset ( turtle-set self n-of 2 possible-teammates )
    
            ; Make a temporary variable to pass on to my entire team
            ; (yourself included) for the team ids and the team members.
            ; Also, assign a random teamID to the whole team
            let ids sort [myID] of myteamset
            let teammmembers myteamset
            let tempteam random 1000
            ask myteamset [
              set teammatesID ids
              set myteamset teammmembers
              set teamID tempteam
            ]
          ] [
            ; If there aren't enough turtles to form a new team, 
            ; print a warning to the console.
            show "Not enough turtles to make a new team!"
          ]
        ]
      ]
    end
    

    Let me know if that's kind of what you're after, hope it helps.

    Edit- As per your comments:

    To get sequential team numbers, you can make use of a simple counter that gets assigned to a team and then incremented for the next one- modified setup-groups would look like:

    to setup-groups
      ; Create a temporary variable to use as a counter
      let teamCounter 1
      ask turtles [
        if myteamset = nobody [
          let possible-teammates other turtles with [ myteamset = nobody ]
          ifelse count possible-teammates > 1 [
            set myteamset ( turtle-set self n-of 2 possible-teammates )
            let ids sort [myID] of myteamset
            let teammmembers myteamset
    
            ; Assign the current teamCounter as team number, then 
            ; increment it by one for the next team
            let tempteam teamCounter
            set teamCounter teamCounter + 1
            ask myteamset [
              set teammatesID ids
              set myteamset teammmembers
              set teamID tempteam
            ]
          ] [
            show "Not enough turtles to make a new team!"
          ]
        ]
      ]
    end
    

    The second question may be worth a new question on its own, depending on how in depth you're hoping to get, but here is one very simplistic approach where you just get all unique team IDs and have one turtle with that ID have their team move together:

    to move-in-groups
      ; Get the unique team IDs
      let teamNumbers remove-duplicates [teamID] of turtles 
    
      ; Get one member of each team to ask all members
      ; of its team (itself included) to move 
      foreach teamNumbers [
        tn ->
        ask one-of turtles with [ teamID = tn ] [
          let newHeading heading + random 60 - 30
          if myteamset != nobody [
            ask myteamset [
              set heading newHeading
              fd 1
            ]
          ]
        ]
      ]
    end
    

    Edit 2: NetLogo 5-friendly version

    to move-in-groups
      ; Get the unique team IDs
      let teamNumbers remove-duplicates [teamID] of turtles
    
      ; Get one member of each team to ask all members
      ; of its team (itself included) to move
      foreach teamNumbers [
        ask one-of turtles with [ teamID = ? ] [
          let newHeading heading + random 60 - 30
          if myteamset != nobody [
            ask myteamset [
              set heading newHeading
              fd 1
            ]
          ]
        ]
      ]
    end