Netlogo:如何让一只乌龟朝着一个独特的补丁目标移动?

Netlogo: How to make a turtle move towards an unique patch target?

我有乌龟(病人),每只只能用一张床(白斑)。由于患者是在候诊室中随机生成的(绿色补丁),有时他们中的两个或更多人会到达相同的距离,因此他们会找到与目标相同的补丁。我试图向贴片添加一个属性,目的是将特定床位分配给特定患者。这个想法是这样的(请沉迷于丑陋的代码,我正在学习:P):

globals [
  waitxmax
  waitxmin
  waitymax
  waitymin
  box
]

breed [ patients patient ]
patients-own [ target ]
patches-own [ assigned ]

to setup-wait-room
  set waitxmax -15
  set waitxmin 15
  set waitymax 11
  set waitymin 15
  ask patches with [
    pxcor >= waitxmax and
    pxcor <= waitxmin and
    pycor >= waitymax and
    pycor <= waitymin
  ] [ set pcolor green ]
end

to setup-beds

  let cmy 7
  let cmx 15
  let dst 3
  let nbox 7

  ask patch cmx cmy [ set pcolor white ]
   
  let i 1
  while [ i < nbox ] [ 
    ask patch (cmx - dst) cmy [ set pcolor white ]
    
    set i i + 1
    set cmx cmx - dst
  ]
  ask patches with [ pcolor = white ] [ set assigned false ]
  
  set box patches with [ pcolor = white ]
end

to setup-patients
  create-patients start-patients [ 
    set shape "person" 
    set target nobody
    move-to one-of patches with [ pcolor = green ] ]
end

to setup [
  clear-all
  setup-wait-room
  setup-beds
  reset-ticks
]

to go
  ask patients [ go-to-bed ]
  tick
end

to go-to-bed
  let _p box with [ self != [ patch-here ] of myself ]

  if target = nobody [
    set target min-one-of _p [ distance myself ]
    ask target [ set assigned myself ]
  ] 
  
  ;;; FIXME
  if ([ assigned ] of target) != self [ show "not true" ]

  if target != nobody [
    face target
    fd 1 
  ]

end

当我在 FIXME 下面打印比较的两侧时,从命令中心我实际上得到了预期的结果。例如:患者 0 和患者 1 都具有相同的 target(补丁 -3 7),但该补丁是 assigned 到(患者 0)。我本以为比较会迫使患者 1 获得新目标,因为床上没有他的名字(我还没有编写该代码),但它总是评估为真。这更臭名昭著,因为我增加了更多可用床位的患者(如果没有可用床位,他们应该在有空位时立即等待)。

通过界面检查时,我还看到补丁 -3 7 显示(患者 0),所以我不知道发生了什么。指挥中心示例:

observer> show [ assigned ] of patch -3 7
observer: (patient 0)
observer> if ([ assigned ] of patch -3 7) = [self] of patient 0  [ show "true" ]
observer: "true"
observer> if ([ assigned ] of patch -3 7) = [self] of patient 1  [ show "true" ]
;;;; SETUP AND GO
(patient 0): (patch -3 7)
(patient 0): (patient 0)
(patient 0): "true"
(patient 2): (patch 12 7)
(patient 2): (patient 2)
(patient 2): "true"
(patient 1): (patch -3 7)
(patient 1): (patient 1)
(patient 1): "true"

也许我只是想多了,有一种更简单的方法可以为病人分配床位,反之亦然?

上面的代码中似乎缺少一两个块(我不能 copy-paste 和 运行),所以请查看下面的选项。

这个版本的工作原理是在 turtle 变量中有一个地方存储 'claimed' 个床位。由于海龟变量可以使用 of 作为列表查询,bed-less 海龟可以检查是否有任何床不在该列表中,如果有,则声明一个。

turtles-own [ owned-bed ]

to setup
  ca
  ask n-of 5 patches [
    set pcolor green
  ]
  crt 10 [
    set owned-bed nobody
    claim-unclaimed-bed
    if owned-bed != nobody [
      print word "I own the bed " owned-bed
    ]    
  ]
  reset-ticks
end

to claim-unclaimed-bed
  ; If I have no bed
  if owned-bed = nobody [
    ; Pull the current owned beds for comparison
    let all-owned-beds [owned-bed] of turtles
    
    ; Pull those beds that are green AND are not found in 'all-owned-beds'
    let available-beds patches with [ 
      pcolor = green and not member? self all-owned-beds    
    ]
    
    ; If there are any beds available, claim one
    ifelse any? available-beds [
      set owned-bed one-of available-beds
    ] [
      ; If there are none available, print so
      print "There are no available beds."
    ]
  ]  
end

编辑: 忘记了实际的问题标题 - 在上面的示例中实际移动到他们的 owned-bed(如果他们有的话),他们只是 face 它并移动你喜欢的方式-例如:

to go
  ask turtles with [ owned-bed != nobody ] [
    ifelse distance owned-bed > 1 [
      face owned-bed
      fd 1
    ] [
      move-to owned-bed
    ]
  ]
  tick
end

编辑:增加了复杂性

好的,对于 severity 的添加元素,您可能希望避免使用多个 with [ ... = x 语句,而是使用一个名为 min-one-of 的原语 returns 具有某些报告者最小值的代理。然后,你想告诉 NetLogo 继续询问下一个最严重的和下一个最严重的,等等。一种方法是使用 while 循环,它基本上说“当满足这个条件时,继续评估以下代码。” 小心 while 循环 - 如果您忘记编写代码,最终条件不再是 truewhile 循环将只是继续 运行ning 直到你最终将工具 > 停止你的模型(或者,就像我遇到的大型模型一样,NetLogo 崩溃)。

我修改了代码(上面的大部分内容没有改变)以包含这样一个 while 循环。还要注意的是,由于模型需要多次检查哪些床可用,我将该代码制作成 to-report 块以压缩/简化。

turtles-own [ owned-bed severity ]

to setup
  ca
  ask n-of 5 patches [
    set pcolor green
  ]
  crt 10 [
    set owned-bed nobody
    set severity random-float 10
  ]
  let current-available-beds report-available-beds
  
  while [any? current-available-beds] [
    ; From the turtles with no bed, ask the one with the lowest severity number to 
    ; claim an unclaimed bed. Then, reset the current-available-beds
    ask min-one-of ( turtles with [owned-bed = nobody] ) [ severity ]  [
      claim-unclaimed-bed
      if owned-bed != nobody [
        show ( word "I have a severity of " severity " so I am claiming the bed " owned-bed )
      ]
    ]
    set current-available-beds report-available-beds
  ]
  reset-ticks
end

to-report report-available-beds 
  let all-owned-beds [owned-bed] of turtles
  report patches with [
      pcolor = green and not member? self all-owned-beds
  ]
end

to claim-unclaimed-bed
  ; If I have no bed
  if owned-bed = nobody [
    let available-beds report-available-beds

    ; If there are any beds available, claim one
    ifelse any? available-beds [
      set owned-bed one-of available-beds
    ] [
      ; If there are none available, print so
      print "There are no available beds."
    ]
  ]
end