FreeKill/docs/dev/ai.rst

45 lines
2.6 KiB
ReStructuredText
Raw Normal View History

.. SPDX-License-Identifier: GFDL-1.3-or-later
FreeKill 的 AI 系统
===================
概述
----
备选算法:
- MCTS
- 神杀算法
--------------
MCTS实现
--------
实现该算法的最大难点在于如何模拟。
首先是树中各个节点的保存我们自然无法给某个节点都分配一个Room对象。由于节点是通过根节点进行相应的决策拓展而来的所以其实节点内部的数据可以保存为各个决策的数组。
然后节点首先要能知道自己的双亲节点和孩子节点,这个分别用一个值和一个数组表示就行了。
想要实现模拟的话重点是如何创造一个一模一样的Room出来。指望lua提供完全clone一个coroutine所有内容或许不是很现实。以下是一种备选方案
1. 首先Room初始化的时候也初始化一个AI用的Room
2. Room内要能够录像记录所有的request结果和random生成的值。为此可能要自定义一个random函数对自带的math.random进行封装。
3. 在录像的时候AI Room也跟着录像的内容进行更新。AI
Room本质上也就是一个Room而已或者可以是Room的子类反正他的内容就是用这个方式和真Room即时同步的。
4. 在AI即将处理问题的时候首先获得所有可行选项。根据算法需要对某个节点进行randomplay。
5. randomplay的话如果直接用AI Room那么回溯的时候如何回到先前的状态呢
1. 考虑新建一个新的AI
Room然后重放录像以达到开始状态。这样每次randomplay之前都要先回复一下状态而随着录像的加长这个过程也可能变长导致AI越来越慢
2. 考虑真Room的所有字段全部复制给AI
Room一份。但有个问题在于如何把程序控制流和栈也跳转到一样的地方。所以这个是很难实现的。
3. 所以考虑用方案1。为了缓解太慢的情况可以把1和2结合起来。约定好在某个时间点比如GameLogic:action中的那个死循环执行就与Room交换数据然后这时候复盘录像的起始时间点修改。这样的话为了从randomplay恢复状态就有必要将此时交换的数据额外保存一份。为了能让Logic平安跑到那个时间点从人凑齐直到那个时间点的录像也要保存一份。
6. 解决了模拟和回溯的问题的话,就可以考虑实现该算法了。
那么为了模拟首先得实现一个RandomAI才行。
然后还有一项前置工作是服务器端的录像功能。得先做好这个才能进行AI编写啊。所以AI暂且推迟一下好了。