寻路中的态势感知


11

假设您必须找到穿过地牢的最短路径,其中只有在收集到某些物品(例如,锁着的门和钥匙)之后才打开某些通道。

单词“最短路径”的正常肠道反应显然是A *。但是A *在这种环境下会失败,因为我看到许多定义可靠启发式方法的问题,此外,很有可能必须多次访问一个节点,这在常规A *中也是不可能的,并且使启发式变得更困难。

我想到的只是在寻找一条从地牢开始到末尾的道路,而忽略任何被阻塞的门。找到此路径后,对于每扇阻碍我们前进的门,在到达门之前,都将寻找并遍历一条寻找适当钥匙并返回门的附加路径。将使用完全相同的系统来处理以下情况:打开门所需的钥匙路径再次被另一扇门阻塞,该门需要首先打开。

我在解决方案中看到的一个大问题是,在找到所有路径(包括用于物品获取的路径)之后,代理可能行进的总距离可能不是最小的,因为可能还有其他被挡住的门离目标更远但更容易获得其适当的密钥。在第一次通过时,A *会忽略这些门,而只是简单地忽略了被阻塞的门。

我确定我不是第一个尝试解决此问题的人,并且希望您对此问题有所投入。


我不知道常规A *的实现方式,但是我看到具有不同路径的实现具有“权重”比例,这将改变各种路径的吸引力。您不能计算所有可能的路径,然后将穿过一扇锁着的门的路径的“权重”设置为正无穷大吗?这将导致该路径看起来无限长,因此永远不会被使用。如果您预先计算路径而不是对每个实体在每次更新时都进行计算,那么这当然适用。
William Mariager

感谢您的答复,但是您忘记的是开门可能是通向目标节点的唯一途径,在这种情况下,您提到的算法将找不到路径。或者,如果阻塞路径的权重仅仅是无限的,它将选择一条阻塞路径并站在我的原始问题之前。
马克·穆勒

Answers:


8

使用简单的A *来最佳处理这种情况的方法是扩大搜索空间。也就是说,假设角色可能携带的每种物品组合都有一个单独的副本。

在地牢的每个副本中,可通过的门正好是可以使用相应项目集通过的门。从一种地牢副本传递到另一种副本的唯一方法是站在物品的位置并捡起它。

您可以扩展此技巧以包括其他状态更改,例如可以打开和/或关闭门的开关。您甚至可以允许玩家放置物品,尽管这可能会变得很复杂,因为状态必须随后包含每个放置物品的位置,从而极大地增加了潜在的搜索空间。

一个非常有用的优化方法是,假设所有门都已锁定,则预先计算从每个门(实际上是每个门的每一侧)和物品到每个其他可到达的门/物品的最短路径。一旦有了这些路径,就可以将它们中的每一个视为将这些重要位置相互连接的图形中的加权边,而忽略所有其他位置。

例如,假设您的地牢有十个门和五个钥匙。然后将有2 * 10 + 5 = 25个重要位置,以及2 ^ 5 = 32个可能的项目组合,在整个搜索空间中总共有25 * 32 = 800个节点。这是一个非常适中的数字,尤其是考虑到很多搜索空间可能无法到达。


5

从现实世界的角度来看:如果您从A到B的方向找到了被锁着的门D,您将意识到必须找到钥匙D。因此,如果您的AI像典型的人一样不为人知,这将涉及寻找密钥,这本身就是一组微小的寻路步骤。另一方面,您甚至可能希望AI甚至在尝试路径之前都知道该路线上的门已锁定,在这种情况下,它也可能会知道在哪里找到钥匙。

无论哪种方式,问题都是两个级别的连通性之一。在“地面”级别上,您知道您始终可以在一个未划分的区域内安全移动……也就是说,没有被锁着的门划分的区域。您可以在这里自由使用当前的A *寻路实现。(在一个简单的例子中,您可以将一个区域视为一个房间。如果不打开门就无法进入任何其他房间。实际上,它可能是您的地牢的整个区域。)这是您的地牢的基础。实体移动,但这有点像眼睛向下垂走动,而不是先调查周围的区域-您可能会走进路灯柱。或者在这种情况下,请锁定门。因此,运行A *的地面地图必须限制玩家只能在当前区域内移动。

接下来,有一个更高级别的地图,其本质上比拓扑结构更具拓扑性。它实际上并不关心障碍物的地面细节,仅关注区域之间的连通性。由于该拓扑图显示了地牢中所有区域的理想连通性,因此它们之间甚至存在当前之间已锁定门的区域之间的连接。在它的边缘(每个代表区域之间的一扇门)中,它存储打开该门所需的钥匙(如果有的话),否则认为是打开的。因此,在此图中搜索最短路径时,在搜索运行时检查边缘数据,从而将找到的路径限制为仅已打开的路径。这里的连通性并不意味着开放,而是潜在的开放。

当您想移至单独区域内的某个点时,请先搜索更高级别的地图以查找路径。(在此级别上可以使用A *或任何其他最短路径算法。)找到路径后,该更高级别的地图还应提供有关从当前区域到另一个区域需要使用哪扇门的信息。现在,您可以在本地区域执行地面AI导航到该门。一旦到达门,您的角色便可以通过该门/门。他现在位于区域B中。如果这是目标区域,则可以使用地面导航转到关键点。如果不是,那么您需要重复第一步,直到到达目标区域。

所寻找的钥匙本身可能位于锁着的门后面……而该门的钥匙也同样存在……等等。这本质上是一个依赖关系解决问题,有几种方法可以解决此问题,其中之一就是Petri Nets。看到这篇优秀的论文。

PS。如果您要按程序创建地牢,那么在您已经知道播放器的起始位置的情况下,可以存储有关依存顺序的信息。


2

单词“最短路径”的正常肠道反应显然是A *。但是A *在这种环境下会失败,因为我看到许多定义可靠启发式方法的问题,此外,很有可能必须多次访问一个节点,这在常规A *中也是不可能的,并且使启发式变得更困难。

首先,可允许的启发式方法不一定是完美的。它只是被低估了,它总比没有好。假设您使用的是实际距离,似乎A *至少会有所帮助,即使启发式搜索没有太大改进,它仍然可能比标准的广度优先搜索更好或类似。

其次,A *可以根据需要多次访问节点。请记住,A *不是寻路算法,而是搜索算法。它搜索状态。在游戏中,我们经常将状态等同于位置,因为我们不在乎您如何达到该状态-只是到达目标的路径有多短。但是,在这样的问题中,状态是位置加上任何其他相关状态(例如,保持的键)的组合。

但是,这些并发症确实会使A *从“非常有效”的领域转移到“将会成功,但可能不会在我要求的时间范围内”。您需要什么时间范围?实际上,为什么需要这样做-您是否真的需要最短的路径,或者任何合理的路径都足够?

我想到的只是在寻找一条从地牢开始到末尾的道路,而忽略任何被阻塞的门。找到此路径后,对于每扇阻碍我们前进的门,在到达门之前,都将寻找并遍历一条寻找适当钥匙并返回门的附加路径。

很容易证明这样的系统将不是最佳的。您将从何处开始附加路径?如果从一开始,那么您就浪费了时间来绘制通往门的原始路径。如果从头开始,则在起点附近放置一个键,这意味着该路径两次遍历地图(一次就足够)。如果您尝试计算往返于门和原始路径的路径的最佳合并点,这将产生最佳结果,但是由于排列的数量和形成启发式方法以简化搜索的难度,因此将占用大量资源。如果您将多个密钥添加到问题中,那么您将遇到不容易有效解决的旅行商问题。

如果可以放宽“最短路径”标准,我将尝试做的是:

  • 创建一个仅包含重要位置的高级图形-关键位置,门位置,锁定区域内的位置,并记下它们之间的直线距离。如果您的地图已经划分为房间或其他离散位置,那就太好了。
  • 使用A *查找从头到尾贯穿此图的路径。正常的笛卡尔距离试探法应足以使其易于管理。
  • 现在,借助这些路径点之间的简化路径,再次使用A *绘制从一个路径点到下一个路径点的低级路径。
  • 将这些低级路径连接在一起,形成整个路径。

一旦我开始工作,我会考虑一些小的优化-例如。较宽松地对具有密钥的区域进行加权,以使低级别路径更有可能绕道绕行以收集密钥。


0

根据您提供的信息,我认为您只需稍加修改即可使用A *。在普通的A *算法中,当您经过每个节点时会对其进行标记,以确保不会再通过它。那正是使项目出现问题的确切部分。关键的更改是记住您先前从节点传递时的物品。这是一个sudo代码,说明我的意思:

if (nodestoCheck.notempty())
    newNode = nodeToCheck.first;
    if (notpassed(newNode.pos, newNode.items))
        if (room(newNode).containItem)
            add NewNode + room(NewNode).items 
        else
            do normal A* algorithm for new Node

使用这种算法,您首先要检查所有没有项目的节点。您的第一个搜索组很可能最终被一些门所挡住。但它会在搜索所有房间之前找到该门的钥匙。从该键开始,进行具有该特定键的新搜索。这次,当您到达门口时,您可能会通过它。继续执行相同的例程,直到您找到离开地牢的路为止。唯一的问题可能是每当有许多门和钥匙时都会消耗内存。尽管至少有10或15个键不会有问题。


0

您为什么不只使用普通的A *,并将锁门建模为无法通过的区域?一旦拿起钥匙(在钥匙砖上走动了吗?),那把特定的锁着的门就会变成通行区域。

这意味着您的路径查找器将采用最短的无钥匙路径,并且如果在此过程中找到了钥匙,则会在有帮助的情况下将其合并到其路径中。

对我来说,这似乎很合理。这不是完美的,但这是解决问题的简单方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.