我正在尝试用Netlogo模拟2048游戏。我已经实现了由权重参数确定的三个启发式函数,并想使用行为空间运行模拟,检查赢得这场游戏的最佳策略是什么。
过程search使用导出/导入世界原语来搜索可能的移动,并选择启发式函数值最高的移动。
问题是这个过程非常慢(由于每次回合都调用了四次import-world函数)。你有什么想法可以实现这一点而不需要频繁地导出和导入世界吗?
这是我的AI入门课程的一个项目。几天后就要交了,我似乎找不到任何解决方案。
相关代码部分如下。过程move-(direction)都正常工作,如果方块可以朝该方向移动,则变量moveable?为真,否则为假。这在由move-(direction)调用的过程moveable-check中进行检查。
我非常感谢你的帮助。:)
to search let x 0 let direction "down" export-world "state.csv" move-up ifelse not any? squares with [moveable?] [set h-value -5000] [set x h-value set direction "up" import-world "state.csv"] export-world "state.csv" move-down ifelse not any? squares with [moveable?] [set h-value -5000] [if h-value > x [set x h-value set direction "down"] import-world "state.csv"] export-world "state.csv" move-left ifelse not any? squares with [moveable?] [set h-value -5000] [if h-value > x [set x h-value set direction "left"] import-world "state.csv"] export-world "state.csv" move-right ifelse not any? squares with [moveable?] [set h-value -5000] [if h-value > x [set x h-value set direction "right"] import-world "state.csv"] ifelse direction = "up" [move-up print "up"] [ifelse direction = "down" [move-down print "down"] [ifelse direction = "right" [move-right print "right"] [move-left print "left"]]] if not any? squares with [moveable?] [ ask squares [set heading heading + 90] moveable-check if not any? squares with [moveable?] [ask squares [set heading heading + 90] moveable-check if not any? squares with [moveable?] [ask squares [set heading heading + 90] moveable-check if not any? squares with [moveable?] [stop]]] ]end
回答:
你需要能够保存和恢复的最重要且最困难的信息是方块。这在没有使用import-world
和export-world
的情况下做起来相当容易(请注意,以下使用的是NetLogo 6语法;如果你还在使用NetLogo 5,你需要在foreach
中使用旧的任务语法):
to-report serialize-state report [(list xcor ycor value)] of squaresendto restore-state [ state ] clear-squares foreach state [ [sq] -> create-squares 1 [ setxy (item 0 sq) (item 1 sq) set heading 0 ;; 或者其他 set value item 2 sq ] ]end
上面的value
只是展示如何存储方块的任意变量。我不确定你与它们相关联的数据或需要恢复的数据是什么。这个代码背后的想法是你将方块的信息存储在一个列表的列表中,其中每个内部列表包含一个方块的数据。然后你使用它的方式是:
let state serialize-state;; 对你想要调查的状态进行更改restore-state state
你可能还需要存储一些全局变量等。它们可以存储在本地变量中,或者存储在state
列表中(这更通用,但实现起来更困难)。
其他一些想法:
- 现在看起来你只向前看一个状态,并且只查看将要放置的新方块的一个可能位置(确保你没有通过知道新方块的确切位置来作弊)。最终,你可能想要使用一种树搜索来进行任意前瞻。这棵树会很快变得非常大。如果你这样做,你将想要使用剪枝策略,例如:https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning。另外,这使得状态恢复变得更加困难,但仍然可行。你将存储一堆状态而不是单个状态。
- 你可以用
right 90
或rt 90
代替set heading heading + 90
。