使用 Clingo 优化关卡生成器的难度
Optimizing difficulty with a level generator using Clingo
我正在使用 Clingo 制作拼图关卡生成器(推箱子),但在尝试创建具有特定移动限制的关卡时遇到了困难。这个想法是使用移动限制来控制一个级别的难度。这就是我创建生成器的方式:
- 指定有效外观水平的规则(所有可行走的瓷砖都连接,正确的可推动桶和目标平台等)
- 指定移动和推动桶的规则。
- 指定获胜条件。
我的第一个迭代是通过要求在 0..N
步中满足获胜条件来简单地要求一个级别可以在 N 步中解决。这导致了有效的关卡,但无法控制难度。
我的第二次迭代是尽量减少满足获胜条件所需的移动。这导致了一步完成的水平。
我的第三次迭代是声明一个级别不能在少于 M 步的时间内完成。这导致逻辑做不必要的动作只是为了达到最小值,仍然没有对难度进行有意义的控制。
我的第四次迭代是为了防止相同的游戏状态再次出现,以避免不必要的“填充”动作,但这仍然导致解决关卡的逻辑非常不理想,只是为了达到最低要求。
现在我真的不知道该怎么办了。我想我想做的是最大化所需的最小移动量(达到极限),但我不确定这是否有意义。我希望能够说明完成此级别的最小移动量应该是 M
.
应该如何解决这个问题?
所以换句话说:您正在寻找一个可以在 N
步中解决的谜题,但在 N-1
步中解决它会 return 无法满足。这两个部分陈述了互补的问题(“至少找到一个”与“找到 none/all”)并且很难放在一个程序中,并且组合会增加问题的复杂性(参见 polynomial hierarchy)。这里有三个建议通过枚举来解决它:
枚举与区别:对于N
和N-1
枚举所有答案。当出现 N
而不是 N-1
时,一个谜题可以精确地 N
步解决。这需要某种 post 处理,例如脚本或整洁的文本编辑。
枚举和不可满足:在脚本中为当前N
一一枚举所有答案集。对于当前的谜题,尝试解决 N-1
个问题:如果它有 return 个 0
个答案,那么您就有了自己的谜题。这需要某种形式的 data-handling,我建议使用 python.
枚举避免双打:在脚本中,为N-1
生成所有答案集。将每个答案集转换为约束并将其添加到程序中。示例:图块 m(1..4,l). m(1..4,r)
大致定义了您的拼图,您当前的答案集是 m(1,l). m(2,l). m(3,r).
,添加以下约束以避免再次生成此拼图。然后求解 N
.
的更新程序
:- m(1,l), m(2,l), m(3,r), not m(1,r), not m(2,r), not m(3,l), not m(4,l), not m(4,r).
如您所见,这三种方法都可以解决您的问题,但需要 clingo 之外的额外努力。
我正在使用 Clingo 制作拼图关卡生成器(推箱子),但在尝试创建具有特定移动限制的关卡时遇到了困难。这个想法是使用移动限制来控制一个级别的难度。这就是我创建生成器的方式:
- 指定有效外观水平的规则(所有可行走的瓷砖都连接,正确的可推动桶和目标平台等)
- 指定移动和推动桶的规则。
- 指定获胜条件。
我的第一个迭代是通过要求在 0..N
步中满足获胜条件来简单地要求一个级别可以在 N 步中解决。这导致了有效的关卡,但无法控制难度。
我的第二次迭代是尽量减少满足获胜条件所需的移动。这导致了一步完成的水平。
我的第三次迭代是声明一个级别不能在少于 M 步的时间内完成。这导致逻辑做不必要的动作只是为了达到最小值,仍然没有对难度进行有意义的控制。
我的第四次迭代是为了防止相同的游戏状态再次出现,以避免不必要的“填充”动作,但这仍然导致解决关卡的逻辑非常不理想,只是为了达到最低要求。
现在我真的不知道该怎么办了。我想我想做的是最大化所需的最小移动量(达到极限),但我不确定这是否有意义。我希望能够说明完成此级别的最小移动量应该是 M
.
应该如何解决这个问题?
所以换句话说:您正在寻找一个可以在 N
步中解决的谜题,但在 N-1
步中解决它会 return 无法满足。这两个部分陈述了互补的问题(“至少找到一个”与“找到 none/all”)并且很难放在一个程序中,并且组合会增加问题的复杂性(参见 polynomial hierarchy)。这里有三个建议通过枚举来解决它:
枚举与区别:对于
N
和N-1
枚举所有答案。当出现N
而不是N-1
时,一个谜题可以精确地N
步解决。这需要某种 post 处理,例如脚本或整洁的文本编辑。枚举和不可满足:在脚本中为当前
N
一一枚举所有答案集。对于当前的谜题,尝试解决N-1
个问题:如果它有 return 个0
个答案,那么您就有了自己的谜题。这需要某种形式的 data-handling,我建议使用 python.枚举避免双打:在脚本中,为
的更新程序N-1
生成所有答案集。将每个答案集转换为约束并将其添加到程序中。示例:图块m(1..4,l). m(1..4,r)
大致定义了您的拼图,您当前的答案集是m(1,l). m(2,l). m(3,r).
,添加以下约束以避免再次生成此拼图。然后求解N
.:- m(1,l), m(2,l), m(3,r), not m(1,r), not m(2,r), not m(3,l), not m(4,l), not m(4,r).
如您所见,这三种方法都可以解决您的问题,但需要 clingo 之外的额外努力。