Netlogo 让海龟在一个区域内随机行走

Netlogo let turtles random walk within an area

假设我有一片海滩和一片海洋,分别用灰色和青色色块表示。我有一些海龟(鱼),我将它们的起始位置随机限制在海洋中的某个地方。现在,每一次滴答,鱼都会按照正态分布(均值=0,标准差=1)的步长进行随机游动。从逻辑上讲,鱼在移动时应该留在海洋中而不是移动到海滩上。我尝试了与我用来将鱼的起始位置限制在海洋中相同的 while [],但这似乎在这里不起作用,即鱼根本不动。有什么想法吗?

编辑:除了水中有 2 条鱼外,我在陆地上还有另外 2 只乌龟(例如牛和羊),它们与鱼类似,cannot/shouldn在它们进入水中时不会进入水中移动(事实上,我总共有 3 个 'habitats' 海龟不应该离开它们开始的栖息地)。当我将 LeirsW 的解决方案用于鱼和 cows/sheep 时,我的 Netlogo 冻结,我不得​​不强制退出。对此有什么想法吗?

编辑 2:x0 和 y0 没有错误,需要保留在代码中。

更新了以下代码:

breed [ fishes fish ]

fishes-own
[
  x0 y0 xcur ycur
]

to setup

  clear-all
  reset-ticks

  ask patches [set pcolor gray]
  ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]

  create-fishes 4
    [
      setxy random-xcor random-ycor
      set x0 xcor
      set y0 ycor

      ifelse who <= ( 3 * 0.5 )      
        [ set shape "fish" set size 2 ]
        [ set shape "fish" set size 3 ]

      set color white

      while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]                  
    ]

  create-fishes 4
    [
      setxy random-xcor random-ycor
      set x0 xcor
      set y0 ycor

      ifelse who <= ( 4 - 1 + 4 * 0.5 )
        [ set shape "sheep" set size 2 set color yellow ]
        [ set shape "cow" set size 2  set color yellow]

      ;set color white

      while [ pcolor != gray ] [ setxy random-xcor random-ycor ]                          ]

end

to go

  fish-move

  tick

end

to fish-move

  ask fishes with [pcolor = cyan]
    [

          ifelse (random-float 1) < 0.95
            [
              let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)

              while [ [pcolor] of destination != cyan ]
                [
                  set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
                ]
              move-to destination

              set xcur xcor
              set ycur ycor
            ]
            [
              let destination patch random-xcor random-ycor

              while [ [pcolor] of destination != cyan ]
                [
                  set destination patch random-xcor random-ycor
                ]
              move-to destination

              set xcur xcor
              set ycur ycor
            ]

          ]

  ask fishes with [pcolor = gray]
    [


          ifelse (random-float 1) < 0.95
            [
              let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)

              while [ [pcolor] of destination != gray ]
                [
                  set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
                ]
              move-to destination

              set xcur xcor
              set ycur ycor
            ]
            [
              let destination patch random-xcor random-ycor

              while [ [pcolor] of destination != gray ]
                [
                  set destination patch random-xcor random-ycor
                ]
              move-to destination

              set xcur xcor
              set ycur ycor
            ]
        ]


end

你的代码的问题是你要求你的鱼只在 non-cyan 方块上移动。因为它们都是从青色瓷砖开始的,所以它们都不会移动。

解决此问题的第一种方法是简单地让他们移动一次,然后只要他们在灰色上就再次移动

to fish-move

  ask fishes
    [
      setxy (x0 + random-normal 0 1 ) (y0 + random-normal 0 1 )
      while [ pcolor != cyan ]
        [
          setxy (x0 + random-normal 0 1 ) (y0 + random-normal 0 1 )
        ]
    ] 
  
end

现在这带来了它自己的一系列问题,因为这意味着靠近灰色的鱼可能会移动到它上面并移动很长的距离,最后再次以青色结束。这就是为什么我更愿意将问题分为三个部分:选择目的地、评估目的地、移动到目的地。 为此,您可以使用 let 创建一个创造性地命名为“目的地”的局部变量:

let destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )

然后我们继续评估目的地是否是一个可行的补丁,如果有必要,选择一个新的目的地:

while [ [pcolor] of destination != cyan ] [ set destination <...> ]

然后最后,在找到令人满意的目的地之后,移动到它:

move-to destination

现在我也注意到你给每条鱼一个 x0y0 并且你从不更新它们。这些鱼是不是要不断地在同一块地方盘旋?我假设不是,所以我删除了它们,让鱼根据它们当前的位置确定它们的目的地(xcorycor

breed [ fishes fish ]

to setup

  clear-all
  reset-ticks

  ask patches [set pcolor gray]                                           
  ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]        
 
  create-fishes 4
    [
      setxy random-xcor random-ycor

      set shape "fish" set size 2.5 set color white 

      while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]                   
    ]

end

to go
  
  fish-move
  
  tick
 
end

to fish-move
  
  ask fishes
    [let destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
  
     while [ [pcolor] of destination != cyan ]
       [
         set destination patch (xcor + random-normal 0 1 ) (ycor + random-normal 0 1 )
       ]
     move-to destination
    ] 

 end

最后一点,您也可以使用

let destination patch-at (random-normal 0 1) (random-normal 0 1)

这是一种略短的写法。

注意:由于问题已经更改,我觉得需要一个新的答案而不是编辑之前的答案,它本身仍然正确。但是,由于我最近才加入 Whosebug,如果需要,我会按照别人的判断将其附加到我之前的 post。

在您的新版本中,x0y0 造成了您的问题。在将海龟洗牌以找到一个好的初始位置之前,您可以定义它们。这意味着一条鱼可以将其 x0y0 设置为陆地。由于您的代码让他们在那个点附近寻找目的地,拒绝所有灰色目的地,您将陷入无休止的搜索。将 x0y0 移动到 create-fishes 块的末尾解决了这个问题。

 create-fishes 4
  [
    setxy random-xcor random-ycor
    
    ifelse who <= ( 3 * 0.5 )       ; Set proportion of fishes in lagoon determined by slider
      [ set shape "fish" set size 2 ]
    [ set shape "fish" set size 3 ]
    
    set color white
    
    while [ pcolor != cyan ] [ setxy random-xcor random-ycor ]   
    
    set x0 xcor
    set y0 ycor
 ]

现在进一步提出一般性建议

  • 我添加了一个名为 habitat 的 fishes-own 变量。此变量在创建鱼时设置为一种颜色,并确定它们可以移动到哪种颜色的斑块。通过将其设为绑定到海龟的变量,您不需要为每种新类型的海龟设置新的移动代码。

  • 我添加了 Matteo 的建议,即让他们 move-to one-of patches with [pcolor = [habitat] of myself].

    更有效地选择他们的初始补丁
  • 我将所有初始移动组合在一个单独的代码块中,只是为了不必为您要添加的每种不同类型的海龟重写它。

  • xcurycur有什么具体的目标吗?您已经可以在所有海龟上访问 xcorycor,因此我看不到对它们的任何特定需求。

  • 鱼种有什么具体的目标吗?否则,您可以只使用通用代理集 turtles,并定义 turtles-own 而不是 fishes-own。即使您有多个品种,定义为 turtles-own 的任何变量也可用于您的品种,因此您不必为每个品种分别定义它们。

     breed [ fishes fish ]
    
     fishes-own
     [
       x0 y0 xcur ycur habitat
     ]
    
     to setup
    
       clear-all
       reset-ticks
    
       ask patches [set pcolor gray]
       ask patches with [ pycor < (max-pycor / 2) ] [ set pcolor cyan ]
    
       create-fishes 4 ;create the water animals
       [
         ifelse who <= ( 3 * 0.5 )       
           [ set shape "fish" set size 2 ]
         [ set shape "fish" set size 3 ]
    
         set color white
         set habitat cyan
       ]
    
       create-fishes 4 ;create the land animals
       [
         ifelse who <= ( 4 - 1 + 4 * 0.5 )
           [ set shape "sheep" set size 2 ]
         [ set shape "cow" set size 2 ]
    
         set color yellow
         set habitat gray
       ]
    
       ask fishes [   ;move all animals to their prefered habitat
         move-to one-of patches with [pcolor = [habitat] of myself]
    
         set x0 xcor
         set y0 ycor
       ]
    
     end
    
     to go
    
       fish-move
    
       tick
    
     end
    
     to fish-move
    
       ask fishes
         [
    
           ifelse (random-float 1) < 0.95
             [
               let destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
    
               while [ [pcolor] of destination != habitat ]
                 [
                   set destination patch (x0 + random-normal 0 1) (y0 + random-normal 0 1)
               ]
               move-to destination
    
               set xcur xcor
               set ycur ycor
           ]
           [
             let destination patch random-xcor random-ycor
    
             while [ [pcolor] of destination != habitat ]
               [
                 set destination patch random-xcor random-ycor
             ]
             move-to destination
    
             set xcur xcor
             set ycur ycor
           ]
    
       ]
    
     end
    

在NetLogo中,补丁是用整数坐标来标识的。也就是说,patch 0.4 0.4patch 0 0 相同。 NetLogo 在定位补丁时将给定的坐标四舍五入到最接近的整数。因此,如果您的代码涉及向补丁的每个坐标添加 0 到 1 之间的随机值,则新计算的坐标很可能指的是同一个旧补丁。这也许可以解释为什么给定新计算的目的地的海龟似乎仍留在原来的地方。

解决您的问题的另一种方法是让海龟向前移动一段距离。这是一个例子,我告诉海龟检查它的前进方向,并在必要时改变路线:

ask turtles with [pcolor = cyan] [
  let dist random-normal 0 1 
  while ([pcolor] of patch-at-heading-and-distance heading dist) != cyan [
    set heading random-float 360
  ]
  fd dist
]

在上面的代码中,变量dist定义为移动的距离(负值表示向后移动),heading是海龟的属性,表示它们的方向, fd 是 NetLogo 函数,告诉海龟朝它们前进的方向前进。

附带说明一下,random-normalrandom-float 是两个不同的函数。具体来说,请注意 random-normal 0 1 从均值为 0 且标准差为 1 的正态分布中抽取随机数,而 random-float 1 给出介于 0 和 1 之间的随机数。