避免访问补丁netlogo

时间:2014-09-01 11:47:18

标签: netlogo

先生,我正在研究一个项目,我不时会在这里发布与此问题相关的问题。我已经创建了一个模拟场景,其中海龟(机器人)在空间中移动,并且每个机器人都跟踪其访问过的补丁。在patch-ahead 1访问补丁的运动中,我需要将机器人向左转45度并再次检查patch-ahead,直到它检查所有8个邻居,如果8个中的任何一个是UN访问的那么它应该转移到那个补丁并继续探索。但是如果所有8个都被访问过,那么它应该在检查所有8个邻居之后移动到当前标题前面的补丁,无论它是否被访问。 这是我正在使用的一段代码。

breed [robots robot ]
robots-own[ state memory ]
patches-own [ is-obstacle? ]

to setup

__clear-all-and-reset-ticks
create-robots num [ 
set memory (list patch-here)
]
draw-obstacles
  ask patches [if pxcor = 0 and pycor = 0  [ set pcolor black ]]
end   

to draw-obstacles
   ask patches with [ pxcor mod 6 = 0 and pycor mod 6 = 0 ] [set pcolor red set is-obstacle? true]
  ; set pcolor red
  ask patches [ ifelse pcolor = red [ set is-obstacle? true ][ set is-obstacle? false ] ]
  ask patches with [ count neighbors != 8 ] [ set pcolor red set is-obstacle? true ]
end


to make-obstacle
 if mouse-down?
 [ ask-concurrent patches
   [ if ((abs (pxcor - mouse-xcor)) < 1) and ((abs (pycor - mouse-ycor)) < 1)
     [set pcolor red]]
 ]
end
to remove-obs
 if mouse-down?
 [ ask-concurrent patches
   [ if ((abs (pxcor - mouse-xcor)) < 1) and ((abs (pycor - mouse-ycor)) < 1)
     [set pcolor black]]
 ]
end

to go
  ask patches [if ( pcolor = red )[set is-obstacle? true]]
  ask patches [if ( pcolor = black )[set is-obstacle? false]]
  ask-concurrent robots ; wanderers instructions
  [
   rt random-float rate-of-random-turn 
   lt (rate-of-random-turn  / 2)
   set-state
   move-robots
  ]
  tick 
end

to move-robots ;;turtle proc
 if (not member? state ["disperse" "explore"]) [
    error "Unknown state"
  ]
  if (state = "disperse") [
    disperse
  ]
  if (state = "explore") [
    explore
  ]
end

to set-state ;;turtle proc
  ifelse (any? other turtles in-radius 1) [
    set state "disperse"
  ] [
    set state "explore"
  ]
end
to disperse ;;turtle proc
 avoid-obstacle
 move1

 ; move-to one-of patch-set [neighbors] of neighbors
end

to explore
  move
  ;search-open-room
  avoid-obstacle
  ;move-to one-of neighbors
end

to move
 fd speed
 set memory lput patch-here memory
 if ( (member? patch-ahead 1 memory) or ([is-obstacle?] of patch-ahead 1 ) )
  [ lt random 45

     ]

end

to move1
fd speed
end

to avoid-obstacle
  set memory lput patch-here memory
      if ([is-obstacle?] of patch-ahead 1 )
    [
        ifelse [is-obstacle?] of patch-at-heading-and-distance (heading - 5) 1
        [
           ifelse [is-obstacle?] of patch-at-heading-and-distance (heading + 5) 1
            [ 
                ifelse random 1 = 0
                [ rt 40 ]
                [ lt 40 ]
            ]
            [ rt 60 ]
        ]
        [lt 60]
    ]

end
to search-open-room
  ask robots[
    ifelse ([is-obstacle?] of patches in-cone 2 150 )
      [  rt 45 ] [ move ]

    ]

end

但在move程序中我只能lt random 45。如何根据上述场景进行更改。我用while循环和repeat语句尝试了很多但是代码似乎对我不起作用。

1 个答案:

答案 0 :(得分:2)

您可以使用whilerepeat执行此操作,但我认为这是recursion效果良好的情况。

我们的想法是让一个程序继续自我调用,直到达到所需的状态:

to turn-until-free [ n ]
  let target ifelse-value (patch-ahead 1 = patch-here)
    [ patch-ahead 2 ]
    [ patch-ahead 1 ]
  let seen? member? target memory
  let obstacle? [ is-obstacle? ] of target
  if-else n < 8
    [ if seen? or obstacle? [ lt 45 turn-until-free n + 1 ] ]
    [ if obstacle? [ lt 45 turn-until-free n + 1 ] ]
end

n参数表示我们已对该过程进行的调用次数(或者,换句话说,我们到目前为止已检查过的邻居数)。当您第一次调用该过程时,请从n = 0开始:

to move
  turn-until-free 0
  fd 1
  set memory lput patch-here memory
  ask patch-here [ set pcolor black + 2 ] ; just to show what's visited
end

一些不符合原始规范的事情:

  • 可能会发生patch-ahead 1与机器人已经在的补丁相同的补丁。贴片的边长为1,但其对角线稍长(√2)。因此,如果机器人位于左下角,并且面向右上方,patch-ahead 1 = patch-here将为真。在这些情况下,我们会进一步了解并将目标设置为patch-ahead 2

  • 在检查完所有8个邻居之后,你可能会遇到障碍。如果是这种情况,你需要继续转动直到你清除障碍物。事实上,这样做可以很好地避免障碍,并且您可以摆脱代码中的avoid-obstacle过程。

修改

以下是完整工作示例所需的代码(除上述两个步骤外):

breed [ robots robot ]
robots-own [ memory ]
patches-own [ is-obstacle? ]

to setup
  ca
  ask patches [ set is-obstacle? false ]
  ask patches with [ pxcor mod 6 = 0 and pycor mod 6 = 0 ] [
    set is-obstacle? true
    set pcolor red
  ]
  ask n-of 5 patches with [ not is-obstacle? ] [
    sprout-robots 1 [ set memory [] ]
  ]
  reset-ticks
end

to go
  ask robots [ move ]
  tick
end

如果您遇到运行时错误或其他不需要的行为问题,我建议您从此开始,并一次性添加您在模拟中的任何其他内容。然后,您可以确切地看到问题的来源。

我还在上面的if-else n < 7程序中更改了if-else n < 8的{​​{1}}。这样,如果探索所有邻居而不是向右转,机器人会回到原来的标题。这可以避免在探索整个领土后进入圈内。