Choose Language
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
language choose
Abak Logo
ABK-GOFAI:Good Old-Fashion Artificial Intelligence

ABK-GOFAI:一个老派人工智能,用来玩 Abak Evolution Backgammon。

在没有神经网络帮助的情况下,为 Abak 开发人工智能(AI)被证明是一项极具挑战的任务,并且随着时间推移似乎达到了一个上限。不过,开发它的过程非常有趣,而且它至今仍在“easy”、“normal”和“advanced”级别上服役。这篇文章讲的是它如何工作,以及它是如何被做出来的。

阶段 1,GOFAI PHP

Abak 的第一个 AI 版本是用 PHP 编写的,最终因为“out of memory”错误而被认为会拖垮系统,但它为 C++ 版本铺平了道路。对我来说,它是一个原型试验场,用来摸索到底该怎么做一个 AI。第一次我把它挂到 web 服务器上运行时(也就是我真的在和它对战),它用了漫长的 15 秒才选出一步棋。当我看到服务器自己开始走棋时,我兴奋坏了,可能还跳了一小段舞。不太确定。

阶段 2,GOFAI C

于是,这个 AI 的 C/C++ 版本——第一个进入生产环境的版本、我心爱的 GOFAI 引擎——从 PHP 的灰烬中诞生了。它会在纳秒间对成千上万个局面运行 29 个分析算法,过程如下:

  • 给定一个棋盘局面和一组骰子。
  • 计算状态
  • 获取所有可能走法。
  • 分析每一种走法并给出分数。
  • 选择“最佳”分数。

下面是该过程的示意图。

Diagrama Abak-GOFAI Artificial Intelligence

它由四个主要函数组成:

  • Get Actions(计算合法走法):

    给定一个棋盘局面和一次掷骰结果,它会计算出所有合法走法。

    合法走法的数量可能从 0 到数万不等。

    无论我用哪种语言来写这部分,我都采用了一种不必要的递归方式,这让代码极难调试,但它又实在太美了。它有几百行代码,却花了我几周时间写完,之后又花了几周把它翻译成 C。

  • Get state(计算棋盘状态):

    给定一个棋盘局面,它会计算出一个语义状态,这些状态基本都很好理解:

    • Starting
    • MiddleGame
    • Running without Hope
    • Running with Hope
    • EndGame
    • Entering Home
  • Analyse Movement(为棋盘局面计算分数):

    这是迄今为止最庞大的算法。它会分析棋盘的各种特征,每一种都返回一个分数,然后根据之前算出的状态对它们应用权重因子,从而根据不同的游戏阶段,赋予分析中不同方面不同的重要性。

    这个 AI 一开始只有 8 个算法,最后增加到了 29 个,随便举几个:

    • 列高
    • 被击中的风险
    • 被困住的风险
    • 内盘强度
    • 逃脱枢纽
    • 中栏棋子数
    • 安全棋子

    这些算法中很多一开始都非常基础,甚至压根不存在。

    随着时间推移,我不断为它们增加功能并微调因子。

  • Select Action(选择“最佳”走法):

    如果你只是想选出最高分,这个算法相对简单(Advanced 等级就是这么做的)。

    对于 Normal 和 Easy 等级,它会在一组最佳走法中随机选择一步;这个列表的大小(或者说它对较差走法的容忍度)由难度等级决定。

由于使用 C,这个引擎快得惊人,所以我会始终把它作为主要的 get-actions 函数。

阶段 3,GOFAI C 调优

为了调试、排查问题和微调这个引擎,我不得不构建许多工具来监控它的决策过程。与神经网络不同,这里的每个决定都是可审计的,所以至少你还有这一点可依赖。

这个过程很有趣,但也慢得痛苦。我和 CPU 对战了很多次,每当我看到一个糟糕的走法,就会回到这些工具里查看哪里出了问题。有时这会把我带向修复某个算法、调优某个因子,或者干脆构建一个新的分析模型。有时——而这真的很美——它还会让我重新思考自己的 Abak Evolution 策略。

Abak-GOFAI Debug Tool Screenshot 1 Abak-GOFAI Debug Tool Screenshot 2

随着时间推移,我得到了一套相当扎实的 AI,但要继续把它打磨得更完美却变得越来越困难。代码行数太多,场景太多,运算规模太大,以至于在代码层面调试成了一项沉重的工作,而手工微调因子也开始不再有效。

阶段 4,绝望

但我还想要更多,因为我自己也玩 Abak,而我需要一个足够强的对手来获得乐趣。那时玩这款游戏的人类并不多(甚至在我写下这些文字的时候也是如此)。

而这种方法有很多缺点:

  • 它会根据当前棋盘位置计算一个棋盘状态,并用这个状态来调整所有合法走法的分析算法因子。但某个走法本身其实可能已经改变了状态,而引擎并没有把这一点考虑进去。
  • 手动微调因子需要耗费巨量时间。过程当然也挺有趣,但真的太多了。
  • 鉴于可能场景的数量如此庞大,状态的计算极其困难。这个算法一直都有缺陷。
  • Game Equity 不可能被精确计算,因为这个引擎对每个分析算法都有一套任意的评分系统,最终分数并不反映胜率概率,它只是作为不同棋盘局面之间的相对比较分值。你可以说它只有相对值,而不是绝对值。

阶段 5,觉醒

然后,在 2018 年的某一天,Google 用 AlphaGo 神经网络击败了 GO 冠军,整个世界都沸腾了。同时,各种出色的开源机器学习库也陆续可用,并开始使用家用 GPU 来加速训练过程。

当然,我之前对神经网络已经有一点了解,但我从未真正搭建过,而且老实说,我一直觉得那是超出我能力范围的事情。

所以我根本抵挡不住诱惑,Expert 等级后来就不再运行在 GOFAI 引擎上了,除了 get-actions 这部分。

不过,这个故事就在这里结束。

如果你一直读到了这里,我真的很惊讶。

这段文字由诚实的 Abak Evolution Team 为了 SEO 目的撰写,
也就是 Samy Garib。

Abak Evolution Backgammon 是一款出色的职业制 Backgammon 变体,它确实为这款经典棋盘游戏加入了一个全新的维度。