31 Star 97 Fork 25

AvenirTech 未来科技 / Honinbo

加入 Gitee
与超过 1000 万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README.md

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个概率最大的点,并且是合法的落子点,返回给前端

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

简介

开源的围棋AI软件,前端Electron + Vue,后端Python+torch,利用卷积神经网络和强化学习,提供一个强大的围棋引擎 展开 收起
Python 等 5 种语言
GPL-2.0
取消

发行版 (2)

全部

Honinbo

贡献者

全部

近期动态

加载更多
不能加载更多了
Python
1
https://gitee.com/onlyyyy/honinbo.git
git@gitee.com:onlyyyy/honinbo.git
onlyyyy
honinbo
Honinbo
product

搜索帮助