黑白棋开局库研究

来源:互联网 发布:郑州app软件开发 编辑:程序博客网 时间:2024/04/29 08:36

    众所周知,开局库在黑白棋中是非常重要的。以下是我设想的开局库数据结构。为了简单,设计成一个链表,而没有采用树形结构。align这些都是为了字节对齐而加的,没有实际意义。

typedef struct  BOOK_MOVE_Tag
{
    char    x;      //走法
    char    y;
    char    _align0;
    char    _align1;
    long    score;  //得分,根据数据库数据生成(直接累加由此走法导致的结果比分),如果某走法在数据库中没有,赋值为负最大(-INF)
    long    count;  //这个走法在数据库中出现的次数
} BOOK_MOVE;

typedef struct  BOOKEX_Tag
{
    unsigned char       board[BOARD_SIZE * BOARD_SIZE / 4]; //当前局面,每个点用2bits表示,00-White, 01-Black, 10-Blank, 11-NA
    char                side;       //当前局面该谁走棋
    char                _align0;
    char                _align1;
    char                _align2;
    long                move_count; //当前局面下side一方的可行走法数
    BOOK_MOVE           *ml;        //走法列表,动态分配内存。
    struct BOOKEX_Tag   *next;
} BOOKEX;

    有了这两个基本的结构后,就可以对大量的棋局分析,来生成一个开局库。分析方法大致是这样。我得到的棋局格式是一系列的走法。首先我要根据这些走法得到这次比赛的每一个局面(通常是60个局面,也有的不到60,实际上开局库没必要把60个局面都记录下来,只要前40个就足够了,再多的意义也不大,实际上几乎不会用到)和最终比分。然后把这些局面加入开局库里。对于库里没有的局面就new一个节点出来,填写好各个字段的值,注意ml这个字段又是一个数组,当前局面有多少个走法就有多少项,然后将本次的走法(得分就是最终比分,次数等于1)写入其中的第一项,其余项设置为无效(走法(-1,-1),得分负无穷,次数0)。对于库里已经有的局面,首先定位到库里的这个节点,然后在ml中查找和本次相同的有效走法,如果找到,将库中相应走法的得分和本次走法的得分相加,并将count加1,如果没有找到,则将走法数组中第一个无效走法改写为本次走法。如此反复直到分析完所有的棋局。

    然后遍历整个链表,对其中的ml数组进行排序,得分最高的排在第一位,比较得分时应该用score/count。这样使用时就很简单了,只要取出相应局面的ml[0]即可。

    分析棋局是一项非常费时间的事,我分析了3590个棋局,用了30分钟左右,最终生成的开局库文件有14M,包含了约10万个局面。但我现在还不知道这种方法是否可行、有效。

    这个开局库还有一项很有用的功能,就是可以对刚刚结束的比赛进行分析,从而达到自学习的目的,当然这还是设想,我还没有试验过效果。但我想开局库自学习的前提是估值函数很强,否则学习到的知识也不会好到哪儿去。

    本文所述的还只是我的一些设想,效果如何还不知道。还请高手指点。