因此笔者放弃任何(可能会有的)权力,一切权力属于Bob Nystroms。
英文原文在此:Rooms and Mazes: A Procedural Dungeon Generator。
本文生成地牢所用的脚本在这里,点击链接下载,里面有附使用说明。还提供了两个在线生成器在文章最后。
在电脑端阅读以取得最好的阅读体验。
没什么前言,我只是觉得生成一个迷宫真是太他妈酷了,想想看一个个房间被放置、走廊和墙壁填满每一寸土地,然后想象你的角色走在其中,得到宝藏。
所以不多废话。这是一个示例,点击它可以再运行一遍2:
红色方格表示房间的“门”,蓝色方格表示走廊相连形成回路的地方。
不同于迷宫,地牢作为一种不“纯粹”的谜题3,它更多的在于“探索”这一过程而不仅仅是找到出口这么简单4。因此地牢比迷宫多了一项元素:房间。你可以在房间里布置一个真正的迷宫或是别的什么其它谜题,也可以什么都不布置,只是单纯的放一个宝箱5在那里。
除此之外,地牢通常是有回路的,它不像完美迷宫那样严格要求所有路径可达且没有环路。
另一个不同的点在于:地牢通常不会有死胡同6。
那么,地牢究竟是什么样的?
Bob Nystroms认为:
除此之外,从技术上来说,一个地牢生成程序应该:
很简单,对不对?尤其是以现在机器的性能78,几乎不需要考虑生成所需要的时间,只要大胆发挥自己的创意就好了,让我们开始吧!
第一步是放置房间。为了确保房间不覆盖,我们在每次生成一个新房间的时候,如果发现它跟其它房间有重合,那就丢弃掉。不过这样可能会造成无限循环,所以限制了生成房间的总次数是很有用的一种方法。
这是尝试200次的结果。下面是尝试2000次的结果:
虽然确实比200次尝试所产生的房间要多,但是远远没有我们所预想的那么多,对吧?这是因为随着成功放置的房间越来越多,剩余空间越来越小,满足新房间的概率也就越小。所以越是尝试放置新房间,失败的概率就越大;到最后,由于房间最小是2*2且互不相连邻,已经不可能再放置新房间了。
这是最难的一部分,你可能想到了不少其它的方法,不过我仍然建议你来看看这个:
请注意,当我们执行第二步的时候,不需要将所有死胡同都堵起来9,而是随机的填充一部分。
不过对于第4步,就像我们上面所说的那样,你可能没办法将房间放在你想要的地方,甚至你可能连一个房间都放不下。所以我们不妨换位思考,先放置房间,再布置迷宫,就像下面这样:
这里需要另外提一嘴它是怎么工作的:
这样我们就能保证所有区域都会有迷宫到达,即使放置房间使它们之间不再相连。
我们已经有了房间,也有了走廊,那么只剩下连接它们了。遍历房间和房间、房间和走廊、走廊和走廊,寻找潜在的连接点,同时还要注意两个连接点不能相邻。考虑所有条件后,这些连接点看起来像是这样11:
死胡同是很讨厌的,除非你放一个巨大的宝箱在它的尽头。
我们遍历每一个走廊,如果一个走廊3面都是墙,那么我们就把它删掉;如果这个死胡同连接着某个房间的门,那就连门也一同删掉。
下面是一个演示。为了凸显效果,我提高了出现死胡同的概率。
这是一个非常大的地牢:
以及你可能想自己试试各种参数,看看下面这两个页面:
文中所有展示都是为了使读者看清而故意放慢的。实际上地牢迷宫的生成过程是这样(点击它):
这里还有另外一篇文章,它采用”扩散式“的思路来创建迷宫。
简单概括就是:
看起来就像这样:
以及其它因为种种原因没能添加到这篇文章里的文章: