五子棋AI循序渐进【0】引言——认识“引擎”
刚刚完善了评价函数,这真是一个痛苦的过程。当然,所谓完善是现阶段的,因为它已经可以正常工作了,才称之为完善。从今天开始进行这个连载,当第三部分(基石)发布之后,我会把以前发的两篇删除。
首先,我们来认识一下“引擎”。实际上,这是一种人工智能,在国际象棋等等一些“信息完毕”的游戏中,早就实现了“计算机下棋的程序“,这些程序可以称之为”引擎“。也就是说,我们的连载的目标是实现一个五子棋的AI。实际上,网络上有很多这样或那样的”引擎“,但是我可以非常负责的告诉大家,用VB.NET写的、国内的、各种棋类的几乎没有开源的,估计不开源的也极少,用其他语言写的开源的,水平都不敢恭维,尤其是很多作者对传统的剪裁根本就没有理解或者理解是错误的。所以,写了这篇连载,主要是为了让用VB.NET并且有这方面兴趣的童鞋能够有一个参考,而我本身也是研究了”象棋小巫师“这一引擎的源码之后,写的这一系列的连载,其中非常多的东西都是参考其源码甚至照搬来的。巨建议访问http://www.xqbase.com/来学习相关知识。
国际象棋的引擎起源很早,所以它对各种”信息完备“的游戏的引擎开发都具有非常重要的借鉴意义。中国象棋的引擎就是如此,而且现在已经有非常厉害的象棋引擎,象棋巫师本身的棋力也是很高的,当然,和象棋旋风等一些顶尖的象棋引擎相比,还有一些差距。那么,什么是”信息完备“的游戏呢?通俗一点说,就是知道对方有什么子!当然,对方也知道我们都有什么子。说白了,就是明棋。例如,国际象棋,中国象棋,五子棋,黑白棋(奥赛罗),兽棋,井字棋等等,不胜枚举;而像军旗、各种翻棋等等就不属于这个范畴了。
“信息完备”的游戏,在开发引擎时,基本上都是使用剪裁的方式来进行搜索,我们搜索的越深,那么棋力应该越强。就像人类棋手下棋时一样,往往分析的步数越多,那么他下的越好。有些观点认为计算机下棋与人类棋手下棋思考方式有着根本性的差异,我本人不赞同这种观点:无论是计算机,还是人类棋手,都是在搜索,并且是非常相似的。下面来解释一下我的观点:
1、实现界面和位棋盘
2、我的五子棋引擎如何评价局面
3、基石——超出边界的alpha-beta剪裁
4、接近人类的思考方式——迭代加深、棋盘剪裁、空招剪裁、冲棋延伸
5、重点问题重点分析——静态搜索
6、记住曾经的思考——置换表
这是我们的五子棋引擎中使用的各种技术,这些技术都是为了提高搜索速度、准确度而服务的。除了位棋盘和思考方式无关之外,其他的都是与思考方式有关的:
2、我的五子棋引擎如何评价局面
评价局面,无论是计算机还是人类,都必须要做的,这是最根本的东西,它体现了这种棋类游戏的“规则”。在我的五子棋引擎中评价函数是一个比较长的函数:
首先,对棋型进行模板匹配——因为人类棋手也是要识别哪些棋型胜利,哪些棋型失败,哪些棋型发展潜力比较大,哪些棋型要冲,哪些要堵
然后,综合考虑各个棋型——当对方冲4,我们怎么办?当对方活4,我们是不是成5,如果不成,那很遗憾,我们输了,这也意味着对方活4之前我们走的那步棋(甚至前几步)是臭棋。这样,我们就可以给一步棋打分,当然,计算机是用确实的分数来体现的,而人类棋手是以“分数”排序来体现的。可无论如何,我们的程序还是会把走法按分值排序,因为这有利于剪裁,而剪裁越合理(理想状况下剪裁掉全部不合理走法,剩下的合理走法会很少),那么下一步要搜索的走法就越少,可以节省更多的时间来搜索更多的步数。
程序的思考和人类棋手的思考惊人的一致。
3、基石——超出边界的alpha-beta剪裁
人类棋手会首先找到几种可能的走法,然后再继续分析,如果我这样走,对方怎么走呢?如果对方这样走,那么我怎么走呢?当发现一步棋演变若干次之后,对自己不利,那人类棋手就会舍弃这种走法。这就是剪裁。
程序的做法,和人类棋手是完全一样的。
4、接近人类的思考方式——迭代加深、棋盘剪裁、空招剪裁、冲棋延伸
人类棋手首先会考虑当前局面下,自己认为最好的走法(对其进行深入思考),然后考虑其他走法是否好过前面的走法
程序也是这样,搜索1层,进行排序,然后从最好招法进行深入搜索
人类棋手下棋时,不会考虑离棋子很远的位置,例如棋都集中在中间时往角上下一个子明显是不明智的,尤其是五子棋这种“咬得很紧”的棋类,那样做明显是在自杀。
我的程序在生成全部走法时,从位棋盘生成一个“合理棋盘”,它包含了所有棋子周围的3格。
人类棋手经常会考虑,对方下一步会走什么棋更有利?
程序在评价每一步棋时,会在搜索之前,进行“空步剪裁”,以期知道对方的“好棋”,并且评价这个“好棋”是不是会给自己造成致命的结果,从而提出应对策略。
人类棋手下棋时,会首先考虑对方是不是已经要杀死自己了?例如,对方有一个活3,那很明显,人类棋手立刻立马上马意识到去堵或者冲比对方更快达到5的棋,为什么,因为他知道自己如果没有更好的棋再不堵上对方那就输了!
程序也是这样,当被冲的时候,就分析自己是不是比对方冲的更接近5,如何封堵对方的棋?当然,这里可能涉及到自己冲棋是否能同时解决对方的成棋并获得更有利局面。但如论无核这都是更深层搜索所要解决的问题,也就是“冲棋延伸”——针对冲棋的情况,进行更深入的搜索,深入程度甚至有可能达到把棋盘下满!
5、重点问题重点分析——静态搜索
人类棋手在预测若干步之后,确认某一步棋更好,如果是高手还会想一想,这步好棋若干步之后,对方还有没有什么招数呢,自己能不能产生杀招?也就是检查一下自己的思考是否有什么漏洞,对这步棋进行更深入的考虑,这往往是落子之前最后一道工序了。
程序也是这样,当进行alpha-beta剪裁得到一个满意的结果之后,会进入静态搜索,以期验证若干步之后,对方确实不会出现翻盘的情况,而自己尽可能给对方造成更多的麻烦,甚至杀死对方。
6、记住曾经的思考——置换表
人类棋手是有记忆的,这包括刚才他分析过的各种可能,也包括以往积累下类各种经验(例如什么棋型必胜,如何走必胜)。
程序也可以这样做:
短期记忆:把分析过的局面记录下来,那么当”这种局面刚才我已经分析了!“的时候,可以不必再次分析,而直接取出分析结果。
以往经验:使用开局库,残局库等技术来实现。
下集预告:
1、实现界面和位棋盘
全部文章和源码整理完成,以后更新也会在下面地址: