银行 社区服务 每日签到 会员排行 网站地图
  • 8559阅读
  • 39回复

兵河开局库与鹏飞开局库的异同比较

楼层直达
级别: 上尉
[棋中红钻3级]发帖数量≥500篇 [棋中黄钻1级]金币数量≥100枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
800
金币
959
威望
4
贡献值
5
乐币
12
主题
43

— 本帖被 棋中天豪 执行加亮操作(2012-07-10) —
今天读了一下鹏飞破解部的部分代码,主要是看了一下开局库有关的操作,现将部分结论公布如下,如有说明不正确的地方,欢迎您的指出,也让我能更准确的了解相关细节。

一、兵河开局库是什么?

      这个问题看上去实在是有点傻,因为论坛里的人几乎每天都在与开局库打交道,更是有大量做库的高手,相关的教程在教我们制作兵河开局库的方法,就是收集利用已有的棋谱文件,在兵河软件中按相关步骤进行操作,然后生成一个文件,该文件是一个以.obk为结尾的文件。

      到这里我们的结论是兵河开局库是一个以.obk为后缀名的文件,这种说法肯定是没有错误的,但是这个文件具体是怎么组成的呢,我今天在google上搜索了一些资料,未看到究竟。

二、兵河里的文档说明

     下载现在的兵河五四后,会有一个技术文档的文件夹,其中里面有一个bhobk的文件夹,里面有一个bhobk.c的程序,该程序的代码如下
      typedef struct book_entry_t book_entry_t ;
struct book_entry_t
{
    unsigned __int64 key ;
    unsigned __int16 move ;
    __int32 score ;
    __int32 win_count ;
    __int32 draw_count ;
    __int32 lost_count ;
    unsigned __int16 valid ;
    char comments[64];
};

int GetBookEntry(book_entry_t *entry,unsigned __int64 key)
{    
    int result ;
    char *errmsg=NULL ;
    char **dbResult ;
    int nRow,nColumn ;
    int i,j ;
    int index ;
    char szSql[1024]={0};
    _snprintf(szSql,1024,"select * from bhobk where vkey=%I64u;",key);
    result=sqlite3_get_table(db,szSql,&dbResult,&nRow,&nColumn,&errmsg);
    if(SQLITE_OK==result)
    {
        index=nColumn ;
        for(i=0;i<nRow;i++)
        {
            if(i>127) break ;
            for(j=0;j<nColumn;j++)
            {
                if(j==2)entry.move=atoi(dbResult[index]);
                else if(j==3)entry.score=atoi(dbResult[index]);
                else if(j==4)entry.win_count=atoi(dbResult[index]);
                else if(j==5)entry.draw_count=atoi(dbResult[index]);
                else if(j==6)entry.lost_count=atoi(dbResult[index]);
                else if(j==7)entry.valid=atoi(dbResult[index]);
                else if(j==8)strncpy(entry.comments,dbResult[index],64);
                index++;
            }
        }
    }
    sqlite3_free_table(dbResult);
    
    return nRow>128?128:nRow ;
}

int main(int argc,char **argv)
{
    //某个局面开局库棋步总数
    int nCount;
    //记录某个局面开局库数据
    book_entry_t entry[128]={0};
    //这里的key是某个局面的ZobrisKey,采用无符号64位整数,具体计算方法见说明文件,这里给定常数作为实例
    unsigned __int64 key=15265892774299731920;

    int result=sqlite3_open("c:\\test.obk",&db);
    if(result!=SQLITE_OK)
    {
        return 1;
    }

    nCount=GetBookEntry(entry,key);

    sqlite3_close(db);
    return 0 ;
}

    这里面声明了一个数据结构,并且有一段读取SQLite数据库的代码,这里就先到此为止。

三、验证

    再次验证鹏飞中的相关代码,已可以确认兵河开局库,实际上就是一个SQLite的数据库文件,而SQLite又是什么呢,他是一个文件形式的内存数据库,如果您需要更多这方面的知识,可以去了解该数据库,简言之,就是该数据库虽然是一个文件,但他也可以包含常用数据库的很多概念,如表、存储过程、视图及索引等。

    因此,兵河开局库文件实际上就是一个SQLite的数据库文件,于是我使用SQLiteDev连接兵河文件,完全能够正常连接,现将分析的数据公布如下:

  
兵河库数据库格式
1、采用了SQLite数据库
2、表名为bhobk
3、表中列的定义
     3.1 id:主键
     3.2  vk:当前局面的数字化,是当前的局面经过Zobrist 方法得到的哈希值,该值的具体Hash方法,我目前还没有准确测试出,希望有人能给出具体的算法或者准确的说明,不然还得仔细看程序实现了。关于Zobrist是什么的问题,它其实是一个基于无符号64位整形的(建议)的局面hash方法,子在走动时可以通过异或的方法快速的调整对应值,是整个象棋软件局面判断的一个重要数据结构。

           目前库中:7101337512282506414表示初始局面
     3.3 vmove:当前招法的数字法表示  
     3.4 vscore:分数,是指当前局面
     3.5 vwin:当前局面的胜局数
     3.6 vdraw:当前局面的和局数
     3.7 vlost:当前局面的负局数
     3.8 vvalid:当前招法是否为有效步数,1为有效,0为无效
     3.9 vmemo:当前招法的备注
     3.10 vindex:当前招法达到的步数(如多少步脱谱)

开局的着法,如果在数据库中直接检索,可以利用类似下面的语句
Select * FromMAIN.[bhobk]  
where vindex=1 order by vwin desc ;  


实际搜索时使用的算法是

Select * from bhobk where vkey=某个数值 and  vvalid=1 这种方式

其中vkey的值,要根据当前局面子的位置计算而得到

四、鹏飞库

     这也是这两天论坛里有人一直在问的问题,现在可以这样说,本质上讲鹏飞开局库与兵河库无任何差异,因为鹏飞库也是SQLite的数据库,只是对应的表名不一样而已,鹏飞开局库的相关规定如下:


1、采用了SQLite数据库
2、库着的表名为pfbook,注意这里与兵河是本质的不同,便搞过数据库开发的人都知道,这种差异只是表名的差异而已。
3、库的版本信息:bookVersion表,记录当前库的版本,如1.0.0.0
4、库的配置信息:config,用于记录当前库是否为加密处理地的开局库
5、表中列的定义,与兵河库的定义没有差别,便vkey值从兵河库中到鹏飞中时,做了一次到64位无符号整形的转换
6、具体的列定义基本如下:
     6.1 id:主键
     6.2  vk:当前局面的数字化,是当前的局面经过Zobrist 得到的哈希值,该值在兵河的基础上做了一次64位无符号整形的转换
     6.3 vmove:当前招法的数字法表示 ,加密库中该值有变化
     6.4 vscore:分数,是指当前局面,加密时使用的种子
     6.5 vwin:当前局面的胜局数
     6.6 vdraw:当前局面的和局数
     6.7 vlost:当前局面的负局数
     6.8 vvalid:当前招法是否为有效步数,1为有效,0为无效
     6.9 vmemo:当前招法的备注
     6.10 vindex:当前招法达到的步数(如多少步脱谱)

7、加密的处理,只对vmove的数据进行了加密,采用了一个自定义的加密方法EncryptMove,该方法继承自SQLite的Function,其种子是vscore。

加密的原理也非常简单,但是这里我就不再详细说明了。


五、结论

  1.     兵河库可以自由转换为鹏飞库
  2.      鹏飞库也可以转换为兵河库
  3.      鹏飞的加密库,只要你愿意,你可以很轻松的将其还原


      我这里只是总结性的给出了这些结论,并没有具体描述相关实现的具体过程,有兴趣的朋友,可以在此基础上进行更深入的了解。






本帖最近评分记录: 14 条评分 乐币 +1 金币 +58 威望 +1
jyh
级别: 四级士官
[棋中红钻2级]发帖数量≥100篇 [棋中黄钻1级]金币数量≥100枚 [未点亮棋中蓝钻]乐币数量<10枚 [未点亮棋中粉钻]贡献值数量<1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
130
金币
260
威望
0
贡献值
0
乐币
0
主题
4
只看该作者 一楼  发表于: 2012-06-20
哈哈,对于软件开发者而言,有点参考意义。
级别: 论坛检查
[棋中红钻6级]发帖数量≥5000篇 [棋中黄钻4级]金币数量≥5000枚 [棋中蓝钻2级]乐币数量≥50枚 [棋中粉钻6级]贡献值数量≥100点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
6414
金币
7124
威望
6
贡献值
147
乐币
79
主题
304

只看该作者 二楼  发表于: 2012-06-20
优秀技术性文章,感谢您的分享。
级别: 少校
[棋中红钻4级]发帖数量≥1000篇 [棋中黄钻2级]金币数量≥1000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻5级]贡献值数量≥50点 [棋中彩钻1级]精华帖数量≥1篇
发帖
1576
金币
1790
威望
6
贡献值
57
乐币
42
主题
17

只看该作者 三楼  发表于: 2012-06-20
优秀文章,助人为乐谢谢您
级别: 上尉
[棋中红钻4级]发帖数量≥1000篇 [棋中黄钻5级]金币数量≥10000枚 [棋中蓝钻3级]乐币数量≥100枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
1557
金币
12245
威望
5
贡献值
5
乐币
253
主题
5

只看该作者 4楼 发表于: 2012-06-20
楼主最好开发一款能把鹏飞开局库转换成兵河开局库的小软件,那我们就会方便很多了。
yne
级别: 子爵
[棋中红钻5级]发帖数量≥2000篇 [棋中黄钻2级]金币数量≥1000枚 [棋中蓝钻3级]乐币数量≥100枚 [棋中粉钻1级]贡献值数量≥1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
2257
金币
1825
威望
2
贡献值
1
乐币
297
主题
0

只看该作者 5楼 发表于: 2012-06-20
感谢您的分享,棋中有你更精彩
级别: 中校
[棋中红钻6级]发帖数量≥5000篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻2级]乐币数量≥50枚 [棋中粉钻5级]贡献值数量≥50点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
6131
金币
4069
威望
15
贡献值
51
乐币
62
主题
1

只看该作者 6楼 发表于: 2012-06-20
感谢您的付出,棋中有你更精彩!
级别: 少尉
[棋中红钻2级]发帖数量≥100篇 [未点亮棋中黄钻]金币数量<100枚 [未点亮棋中蓝钻]乐币数量<10枚 [未点亮棋中粉钻]贡献值数量<1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
294
金币
8
威望
0
贡献值
0
乐币
0
主题
2
只看该作者 7楼 发表于: 2012-06-20
感谢您的分享,棋中有你更精彩
级别: 四级士官
[棋中红钻2级]发帖数量≥100篇 [棋中黄钻1级]金币数量≥100枚 [未点亮棋中蓝钻]乐币数量<10枚 [未点亮棋中粉钻]贡献值数量<1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
178
金币
478
威望
0
贡献值
0
乐币
2
主题
2
只看该作者 8楼 发表于: 2012-06-20
看不懂,但表示感谢,作者用心了。。。
级别: 中尉
[棋中红钻3级]发帖数量≥500篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
803
金币
4451
威望
0
贡献值
5
乐币
28
主题
4
只看该作者 9楼 发表于: 2012-06-20
具体算法大概如下:

此算法的思想是创建一个hash [ chessman ] [ location ] 的数组,数组中每一个元素都是一个64 位随机数. 对中国象棋来说,就是hash[14 ] [ 90 ] . 求当前局面的哈希值,就是将棋盘上所有棋子在数组中对应的64 位数做异或运算,生成这一局面的唯一标识数. 哈希技术有2 个明显的优点:1) 64 位数使得局面冲突的可能性非常小,基本可以唯一标识当前局面,可以用作哈希表的索引;2)不用每一次展开节点时都计算局面的哈希值.只要在搜索开始时做初始化运算,在着法执行过程中通过异或运算求出变动的棋子及其位置即可.
开局库数据结构定义如下:
typedef st ruct {
  Hash position ;    / / 64 位哈希值
  int stat u played ; / / 32 位局面权值
  }BOO K KEY;
此结构包含了一个着法的信息. 开局库即为若干该种数据组成. Hash position 为局面的哈希值,
共64 位,将局面按“簇”存储,根据哈希值的高15 位值将局面分为若干簇,簇数量为215 个,所以哈希值的高15 位可作为哈希表的簇索引,即一级索引,索引数量共为32 768 个. 然后在相应簇中通过哈希值即可搜索到相应局面,哈希值可视为二级索引,这种方式大大提高了搜索开局库的效率。
本帖最近评分记录: 1 条评分 金币 +6
_仯帥軟件象棋群
级别: 司令员
[棋中红钻6级]发帖数量≥5000篇 [未点亮棋中黄钻]金币数量<100枚 [棋中蓝钻3级]乐币数量≥100枚 [棋中粉钻2级]贡献值数量≥5点 [棋中彩钻1级]精华帖数量≥1篇
发帖
5629
金币
75
威望
6
贡献值
5
乐币
178
主题
188

只看该作者 10楼 发表于: 2012-06-20
谢谢您的支持,棋中有你更精彩
级别: 中尉
[棋中红钻3级]发帖数量≥500篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
803
金币
4451
威望
0
贡献值
5
乐币
28
主题
4
只看该作者 11楼 发表于: 2012-06-20
将当前棋局转换为哈希数,用作棋局的存储与查询. 哈希数的最大优点就在它求的是64 位数的异或和,当在着法(涉及所走棋子、棋子起始位置、棋子目标位置、所吃棋子等变量) 的作用下,棋局发生了变化,只要将相应变化棋子的哈希数再异或一次,便可以转变成新局面对应的哈希数. 具体实现如式
(2) .
Hn+1 = Hn ·qn+1 , H0 = H(0) ,                                                                     (2)
Hn = ©32 j =1(打不出来,注意!呵呵)Random64 ( kj , ( PMn) j ) .       (3)
式中:qn + 1表示着法算子(即当前着法) , H (0) 表示初始局面, Hn 表示n 步后的局面, ©为异或算子, kj表示相应的棋子, ( PMn) j 表示第j 个棋子n 步后在棋盘上的位置.通过式(2) 可以从当前局面( Hn ) 计算出若干个后续局面( Hn + 1 ) ,然后就能够以Hn + 1 的高15 位为一级索引搜索到局面所在簇中,再以Hn + 1 作为二级索引在相应簇中对局面进行搜索, 大大提高了搜索效率.
本帖最近评分记录: 1 条评分 金币 +2
级别: 上尉
[棋中红钻4级]发帖数量≥1000篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻1级]乐币数量≥10枚 [未点亮棋中粉钻]贡献值数量<1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
1871
金币
4262
威望
0
贡献值
0
乐币
34
主题
0
只看该作者 12楼 发表于: 2012-06-20
是真是假你把鹏飞开局库转换成兵河开局库给大家看看嘛 文章优秀咱也看不懂
级别: 中尉
[棋中红钻3级]发帖数量≥500篇 [棋中黄钻1级]金币数量≥100枚 [未点亮棋中蓝钻]乐币数量<10枚 [棋中粉钻1级]贡献值数量≥1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
717
金币
943
威望
0
贡献值
3
乐币
0
主题
0
只看该作者 13楼 发表于: 2012-06-20
感谢你的付出,棋中有你更精彩
兵之胜在于篡卒,其勇在于制。
级别: 上尉
[棋中红钻2级]发帖数量≥100篇 [未点亮棋中黄钻]金币数量<100枚 [未点亮棋中蓝钻]乐币数量<10枚 [棋中粉钻2级]贡献值数量≥5点 [棋中彩钻1级]精华帖数量≥1篇
发帖
398
金币
40
威望
11
贡献值
9
乐币
0
主题
22

只看该作者 14楼 发表于: 2012-06-21
自已的见解很到位,支持你再次研究出可以怎样转换鹏飞库!
您好,回帖是美德,看帖请回帖,谢谢
级别: 侯爵
[棋中红钻4级]发帖数量≥1000篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
1566
金币
2945
威望
4
贡献值
8
乐币
13
主题
158

只看该作者 15楼 发表于: 2012-06-21
感谢您的分享,棋中有你更精彩
级别: 少尉
[棋中红钻2级]发帖数量≥100篇 [棋中黄钻1级]金币数量≥100枚 [未点亮棋中蓝钻]乐币数量<10枚 [未点亮棋中粉钻]贡献值数量<1点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
359
金币
753
威望
0
贡献值
0
乐币
6
主题
0
只看该作者 16楼 发表于: 2012-06-21
对于只用软而不深究的我来说,这个就如云里雾里。
级别: 少校
[棋中红钻5级]发帖数量≥2000篇 [棋中黄钻4级]金币数量≥5000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
3464
金币
7217
威望
0
贡献值
5
乐币
47
主题
51

只看该作者 17楼 发表于: 2012-06-21
感谢您的分享   棋中有你更精彩
开开心心过好每一天
级别: 少校
[棋中红钻4级]发帖数量≥1000篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻4级]贡献值数量≥20点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
1627
金币
4289
威望
6
贡献值
25
乐币
30
主题
0
只看该作者 18楼 发表于: 2012-06-21
感谢您的付出,棋中有你更精彩
级别: 版主
[棋中红钻4级]发帖数量≥1000篇 [棋中黄钻3级]金币数量≥2000枚 [棋中蓝钻1级]乐币数量≥10枚 [棋中粉钻2级]贡献值数量≥5点 [未点亮棋中彩钻]精华帖数量<1篇
发帖
1478
金币
2574
威望
1
贡献值
9
乐币
24
主题
12

只看该作者 19楼 发表于: 2012-06-21
学习了。谢谢您的支持,棋中有你更精彩
快速回复

限56 字节
请不要在回贴只采用字母:“ PP、asdfhjkl、HAO、OK、ddddddd ......”。  请不要在回贴过于简单的内容:“不错、顶、支持、厉害、呵呵、靠、晕........”
 
验证问题: 我们的论坛名字是?
上一个 下一个