前言:
  对弈类游戏的智能算法, 网上资料颇多, 大同小异. 然而书上得来终觉浅, 绝知此事要躬行. 结合了自己的工程实践, 简单汇总整理下. 一方面是对当年的经典<<PC游戏编程(人机博弈)>>表达敬意, 另一方面, 也想对自己当年的游戏编程人生做下回顾.
  承接上两篇博文:
  (1). 评估函数+博弈树算法
  (2). 学习算法
  这篇博文回归到博弈树这边, 具体阐述下博弈树的优化手段, 为了游戏性添加的合理技巧.

启发搜索:
  博弈树本质是极大极小的求解过程, 而alpha+beta剪枝则加速该求解过程.
  让我们来构建一个简单的alpha+beta剪枝用例:

  注: 紫色代表极大值求解, 绿色代表极小值求解.
  通过人工演算和模拟, 整个博弈过程, 成功地减少了3个节点的计算量的, 效果一般.
  这个过程, 我们是否有优化的余地呢? 让我们调整下, 节点S1和S2的搜索顺序.

  与调整顺序之前相比, 其alpha+beta剪枝的效果提升, 砍去了一个大分支, 减少了4个节点的计算量.
  从这个例子中, 我们可以清晰的看到, 对于博弈树而言, 其alpha+beta的剪枝效果, 和搜索顺序是有一定关系的. 简单的总结: alpha+beta效果, 对搜素的顺序敏感.
  于是我们找到了一个优化方向: 调整可行步的顺序, 并优先搜索预期高的分支. 该技巧命名为: 启发搜索. 常有人借助历史值, killer步来构造启发函数.

// 负极大值算法
int negamax(GameState S, int depth, int alpha, int beta) {// 游戏是否结束 || 探索的递归深度是否到边界if ( gameover(S) || depth == 0 ) {return evaluation(S);}// 依据预估(历史, 经验)对可行步, 进行排序sort (candidate list);// 遍历每一个候选步foreach ( move in candidate list ) {S' = makemove(S);value = -negamax(S', depth - 1, -beta, -alpha);unmakemove(S') if ( value > alpha ) {// alpha + beta剪枝点if ( value >= beta ) {return beta;}alpha = value;}}return alpha;
}

  此时的核心算法结构中: 添加了可行步排序过程(sort (candidate list)).
  当然该过程是有一定代价的, 在alpha+beta剪枝效果提升和排序损耗需要均衡和折中. 一般采用计算简单预估函数即可.
  让我们回到黑白棋AI, 我们可以简单选定, 预估函数等同于位置表, 即P(x, y) = Map(x, y). (Map 为 黑白棋棋面的位置重要度矩阵), 效果斐然.

置换表:
  搞过ACM的人, 都知道DP求解的一种方式: 记忆化搜索. 本质就是把中间状态保存, 减少重复搜索的一种技巧.
  置换表的核心思想基本一致: 状态保存, 减少重复搜索.
  但置换表的难点不在于思想, 而在于状态保存.
  具体可以分析如下:
  1). 游戏局面S本身占用空间大, 而且需要保存的状态S集合多, 因此需要一个转换函数F(S) => key, (key为不长二进制串, 或一个很大的整数)
  2). 转换后的key, 一一对应了某个具体局面S (冲突率很低可忽略, 或不存在)
  让我们以黑白棋来做个例子, 局面转换为矩阵(0: 空白, 1: 黑棋, 2:白棋), 扁平化为字符串, 在借助强有力的Hash函数来转化.

  这边展示了具体的流程, 其效果的好坏, 取决于Hash函数的选择.
  简单采用MD5算法, 其实是可行的, 不过比较消耗CPU. Zobrist hashing算法也是备受推荐.
  和记忆化搜索相比, 置换表对应的局面是, 只是中间的预测节点, 因此该状态除了本身和游戏局面相关, 还和当前的搜索深度有关.
  因此具体代码可修正如下:

// 负极大值算法
int negamax(GameState S, int depth, int alpha, int beta) {// 判断状态已存在于置换表中, 且搜索深度小于等于已知的, 则直接返回if ( exists(TranspositionTable[S]) && TranspositionTable[S].depth >= depth ) {return TranspositionTable[S].value} // 游戏是否结束 || 探索的递归深度是否到边界if ( gameover(S) || depth == 0 ) {return evaluation(S);}// 遍历每一个候选步foreach ( move in candidate list ) {S' = makemove(S);value = -negamax(S', depth - 1, -beta, -alpha);// 保存S'到置换表中, 当depth更深时.TranspositionTable[S'] <= (depth, value) If TranspositionTable[S'].depth < depthunmakemove(S') if ( value > alpha ) {// alpha + beta剪枝点if ( value >= beta ) {return beta;}alpha = value;}}return alpha;
}

总结:
  启发搜索和置换表, 两者都是很好的思路, 前者通过调整搜索顺序来加速剪枝效果. 后者通过空间换时间. 总而言之, 这些都是博弈树上很常见的优化手段. 当然在具体游戏中, 需要权衡和评估. 下一篇讲讲出于游戏性的考虑, 如何进行优化和策略选择.

写在最后:
  
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

  

对弈类游戏的人工智能(3)--博弈树优化相关推荐

  1. 谈一款MOBA类游戏《码神联盟》的服务端架构设计与实现(更新优化思路)

    一.前言 <码神联盟>是一款为技术人做的开源情怀游戏,每一种编程语言都是一位英雄.客户端和服务端均使用C#开发,客户端使用Unity3D引擎,数据库使用MySQL.这个MOBA类游戏是笔者 ...

  2. 在3D生存类游戏中加入人工智能

    2016年AlphaGo的横空出世,吹响了人工智能在游戏领域攻城掠地的号角.短短三年间,星际.Dota2.德州扑克.麻将相继被AI攻克.随着OpenAI Five和AlphaStar血洗天梯竞技场,游 ...

  3. 设计一款博弈类游戏的人机对战算法、策略_卡牌游戏八合一,华人团队开源强化学习研究平台RLCard...

    雷锋网 AI 科技评论按:在过去的两三年中,我们经常听说人工智能在棋牌类游戏(博弈)中取得新的成果,比如基于深度强化学习的 AlphaGo 击败了人类世界冠军,由 AlphaGo 进化而来的 Alph ...

  4. 打游戏学习人工智能!不写代码|湾区人工智能

    栗子 乾明 发自 凹非寺  量子位 报道 | 公众号 QbitAI 撸猫.咖啡,玩游戏. 但我其实是在入门机器学习. 2019年最简单有趣的入门方式,就在这里: Steam高赞游戏,极度易上手. 现在 ...

  5. 游戏ai人工智能_为什么游戏AI无法帮助AI在现实世界中发挥作用,但可以

    游戏ai人工智能 多人游戏被视为一个硕果累累的竞技场,在其中可以模拟许多现实世界中的AI应用程序场景(例如自动驾驶汽车,无人驾驶无人机和协作商务),这些场景可能过于昂贵,投机性或冒险性,无法在现实世界 ...

  6. 用遗传算法加强足球游戏的人工智能

    终于等够了三个月,杂志的约定已经到期,可以把这篇文章发表到网络跟大家分享.本文原发表于<游戏创造>杂志www.chinagcn.com,如蒙转载,请保留原文和本声明完整,并注明转载自恋花蝶 ...

  7. 厉害了,24分钟让AI跑起飞车类游戏

    来源|腾讯WeTest 编辑|布袋熊 导Lead语 谷歌用人工智能技术训练了AlphaGo机器人在围棋盘上打败了柯洁和李在石,阿里训练了千牛店小蜜为商家提供智能客服服务,百度用人工智能技术做出了Apo ...

  8. 游戏美术干货:各大MOBA类游戏视觉包装设计解析

    MOBA英文全称为Multiplayer Online Battle Arena Games,意为多人联机在线竞技游戏.但是与CS等游戏又明显不同,Moba广泛使用于Dota类游戏,是作为类Dota的 ...

  9. 利用遗传算法演化一个棋类游戏的人工智能

    人工智能设计是大多数计算机游戏设计的一个重要组成部分,其最为主要的作用是塑造一个虚拟的玩家形象与游戏之中的真实玩家竞技或交流.目前在技术上说,大部分游戏之中的人工智能设计工作可以归结为有限状态机的设计 ...

最新文章

  1. html获取text值_Python小程序2获取href的值
  2. java 知乎面试题_面试题|Java基础17道常见面试题
  3. hosts文件与resolv.conf文件
  4. Linux 多线程可重入函数
  5. 我看《Linux0.11内核完全注释2.01》的方法
  6. 关于C的函数指针总结
  7. 谨慎设计方法签名(40)
  8. Python实战—CSDN自动登录及评论
  9. 使用Word批量删除换行和空白行
  10. 【微机】ALU的核心就是带标志加法器
  11. 美团实习面(45min + 35min)
  12. [转]oracle性能调优之--Oracle 10g AWR 配置
  13. Document.getElement方法
  14. js/javaScript通过setTimeout做动画和需要注意的点
  15. 微信最新数据:每天有 10.9 亿人打开微信,7.8 亿人进入朋友圈
  16. 中国汽车使用保险行业市场供需与战略研究报告
  17. 渐进式量产进阶!卡车自动驾驶进入商业化新周期
  18. SSO: Basic-Auth OAuth2 SAML OpeanID
  19. App推广如何快速实现,这些方法能帮你
  20. GTOT和RGBT234测评工具箱使用

热门文章

  1. MYSQL进程权限过大_mysql查询较长的执行进程及创建权限账号
  2. linux ipc 漏洞,1月19日Linux发现内核0Day漏洞,编号”CVE-2016-0728“
  3. Typecho webstack开源导航主题
  4. Java23种设计模式之工厂模式
  5. SpringCloud Hoxton版微服务- Gateway网关
  6. 用.Net开发Windows服务初探
  7. c#中abstract与virtual的区别
  8. asp.net 3.5 知识点
  9. HTML5: 两个viewport的故事(第一部分)
  10. BuddyPress安装指南