此页面所有软件内容、截图、价格、介绍等均来源于互联网,地址均为第三方提供,请谨慎下载。



Honinbo

Honinbo是一款开源的围棋ai程序,名称来源于日本古棋圣【本因坊秀策】。

技术架构

前端: Electron Vue Node.js

引擎: Python torch sqlite

开发流程

您如果想要加入本项目,请添加QQ群790148267。

可能需要的软件:Visual Studio Code,Pycharm,fork(一种免费的git管理工具)

开发新功能时从product分支签出新分支,在staging分支进行开发,最后测试完毕由管理员合并至product分支。

分支名字考虑用中文名,可以用xxx/xxxx的方式创建在文件夹内的分支,比如feature/xxx,则该分支会出现在feature文件夹下。

数据集地址: git@gitee.com:Jifashi_619/go-data-set.git

神经网络权重文件地址:https://gitee.com/Jifashi_619/saved_model

多写注释。

🥂安装

前端:

cd /honinbo;
# 安装
npm i;
# 如果网路卡顿 尝试以下命令进行安装
npm i cnpm -g;
cnpm i
#运行
npm run dev;

引擎:

cd /honinbo/engine
pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
git clone https://gitee.com/Jifashi_619/saved_model.git  
python3 main.py

前端部分

围棋规则浅谈

  1. 吃子

一个棋子的上下左右四个格子若为空,则称为棋子的气,当四个气都被其他棋子占据之后,这个子就被称为死棋。

多个相邻(指相邻的上下左右格子)的同色棋子组成一个棋串,棋串会按整体去计算气,若气为0,则应该从棋盘上提去。

  1. 打劫

围棋不允许出现重复(指完全一样)的棋形,所以当一方被吃一子的时候,不能马上吃回,必须先去其他地方落子,这就是打劫。打劫只会发生在被吃单个棋子的情况,吃多个马上吃回并不会导致棋盘重复。

  1. 胜负

去除棋盘上所有的死棋后,黑白计算棋子的个数 棋盘围空的数量,黑需要贴6目半(目即棋子围起来的空,1空为1目),多者获胜。

围棋逻辑实现

棋盘数据结构

棋盘是一个19*19的二维数组,0代表空,-1为白子,1为黑子,每次落子后程序对数组进行处理

程序中棋盘边界为0-18,用户层为1-19

落子

  1. Honinbo会先判断落子是否合法,即x,y坐标是否在(1,19)的范围内。再判断该点是否处于打劫状态

  2. combine(x,y)会尝试将当前落子点与上下左右四个方向匹配,若找到同色棋子,则会合并到棋串当中。

//棋串数据结构:
    {
        black:{
            1:{
                2: {
                    num:19
                    }
                },
            19:[{x:1,y:2}]
        }
    }

即棋串按黑白二色区分,次级键是x,y坐标,最后则是这个棋串的编号。19开始则为棋串数组(因为棋盘只会是0-18的点),管理了该棋串共有哪些元素。

  1. getStringInfo(x,y)会根据传入的坐标获取棋串,或者返回该点不存在棋串

  2. getSrcString(su,sd,sl,sr)会对四个方向的棋串进行选举,决定基准棋串。

  3. combineCurrentString(x,y,su,sd,sl,sr,src)对这些棋串进行合并操作。

if (sd > 0 && sd !== src) {
        console.log("合并sd :>> ", sd);

        subString[src] = subString[src].concat(subString[sd]);
        for (let key in subString) {
          if (key < 19) {
            for (let subKey in subString[key]) {
              if (subString[key][subKey] === sd) {
                subString[key][subKey] = src;
              }
            }
          }
        }
        delete subString[sd];
      }

吃子、杀棋

每次落子的时候,若出现杀棋也只会是上下左右四个方向的相邻格,因此:

  1. kill(x,y) 会获取上下左右四个点的坐标,若是异色棋子则进行处理,交给checkKill判断

  2. checkKill(x,y,flag) 从棋串中按编号查询到该棋串数组,进行遍历:

  • 若四个方向没有为空的点,则判断为死棋,继续递归。

  • 若有空格则直接判断为活棋,return

  • 棋盘边界与同色棋子也是死棋,因为它们都算是占了一个气眼

  1. 若出现杀棋则交给cleanString(num),从棋串中将棋子信息清除

自身死棋

围棋不允许落子导致自身死棋,因此未杀棋就需要交给kill(x,y)判断,只是这里的flag颜色标识是判断的自身

若自身死棋则交给suicide(x,y)将刚才的落子从棋串中清除。

总结整体流程

  1. 落子基本判断

  2. combine()

  3. kill()

  4. suicide()

⏳ 引擎部分

通信

前后端通信有两种方式:Tcp和命令行(暂不支持),Tcp传输Json数据。

引擎分析

{
    "operator":"run",
    "board": [],
    "color": "black"
}

run命令代表前端要求引擎进行分析。

保存前端的棋谱

{
"operator":"saveGoban",
"goban": "sgf..."
}

引擎会将这些数据入库保存。

神经网络部分

架构

提取器(feature.py)->评价器(value.py)、策略器(policy.py)->结果

损失计算:

  1. 评价器:均方差损失

  2. 策略器:交叉熵损失

def forward(winner, self_play_winner, probas, self_play_probas):
    value_error = (self_play_winner - winner) ** 2
    policy_error = torch.sum((-self_play_probas * (1e-6   probas).log()), 1)
    total_error = (value_error.view(-1)   policy_error).mean()
    return total_error

神经网络设计

输入

由于棋盘状态是:0->空,1->落黑子,-1->落白子,与图像识别类似,所以考虑用卷积神经网络。

输入给提取器的共23通道,如下:

1.全部是自己的棋 2-8. 最近7步 棋盘上是否有自己的棋 9,10,11自己的棋子分别还剩1 2 3 口气的棋盘

12全部是对手的棋 13-19.最近7步 棋盘上是否有对手的棋 20,21,22对手的棋子分别还剩1 2 3 口气的棋盘 23. 全1或全-1 表示目前是谁在落子

输出

提取器输出10通道

评价器输出单通道的胜率值

策略器输出[1,361]的矩阵,对应每个点的落子概率

分析

引擎从策略器的输出中取出5个概率最大的点,并且是合法的落子点,返回给前端

后续会接入蒙特卡洛树,未完待续。

网友提问

构建多叉树模块 考虑开发蒙特卡洛树模块 蒙特卡洛树模块接入引擎 考虑去除winner网络 开发前端判断胜负功能 前端实现棋盘转sgf 绘制前端棋盘数字与字母坐标 前端导入棋谱增加loading

温馨提示! 即将跳转到 第三方 网站下载具体内容

点赞(64) 打赏

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部