⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 endgame.cpp

📁 c+++ game uploading now
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**
 @file
 A fast endgame searcher.
*/

#include "Endgame.h"
//no need to compile this if we aren't going to build with it anyway.
#ifdef _ENDGAME_TEST_

#include <cassert>
#include <cstdio>

using namespace Othello;

uchar EndGame::board[91];

EndGame::EmList EndGame::EmHead;
EndGame::EmList EndGame::Ems[64];

uint EndGame::HoleId[91];
uint EndGame::RegionParity;
 
const schar EndGame::dirinc[]={1, -1, 8, -8, 9, -9, 10, -10, 0};
    
const uchar EndGame::dirmask[91] = 
{
    0,0,0,0,0,0,0,0,0,
    0,81,81,87,87,87,87,22,22,
    0,81,81,87,87,87,87,22,22,
    0,121,121,255,255,255,255,182,182,
    0,121,121,255,255,255,255,182,182,
    0,121,121,255,255,255,255,182,182,
    0,121,121,255,255,255,255,182,182,
    0,41,41,171,171,171,171,162,162,
    0,41,41,171,171,171,171,162,162,
    0,0,0,0,0,0,0,0,0,0
};

const int EndGame::worst2best[64] =
{
    20 , 25 , 65 , 70 ,
    11 , 16 , 19 , 26 , 64 , 71 , 74 , 79 ,
    21 , 24 , 29 , 34 , 56 , 61 , 66 , 69 ,
    22 , 23 , 38 , 43 , 47 , 52 , 67 , 68 ,
    31 , 32 , 39 , 42 , 48 , 51 , 58 , 59 ,
    13 , 14 , 37 , 44 , 46 , 53 , 76 , 77 ,
    30 , 33 , 57 , 60 ,
    12 , 15 , 28 , 35 , 55 , 62 , 75 , 78 ,
    10 , 17 , 73 , 80 , 
    40 , 41 , 49 , 50
};

uchar* EndGame::GlobalFlipStack[2048];
uchar **EndGame::FlipStack= &(GlobalFlipStack[0]);

inline void EndGame::DrctnlFlips(uchar *sq, int inc, int color, int oppcol)
{
    uchar *pt = sq + inc;
    if(*pt == oppcol)
    {
        pt += inc;
        if(*pt == oppcol)
        {
            pt += inc;
            if(*pt == oppcol)
            {
                pt += inc;
                if(*pt == oppcol)
                {
                    pt += inc;
                    if(*pt == oppcol)
                    {
                        pt += inc;
                        if(*pt == oppcol)
                            pt += inc;
                    }
                }
            }
        }
        if(*pt == color)
        {
            pt -= inc;
            do
            {
                *pt = color;
                *(FlipStack++) = pt;
                pt -= inc;
            }while( pt != sq);
        }
    }
}


int EndGame::DoFlips( uchar *board, int sqnum, int color, int oppcol )
{
    int j=dirmask[sqnum];
    uchar **OldFlipStack = FlipStack;
    uchar *sq;
    sq = sqnum + board;
    if ( j & 128 )
        DrctnlFlips( sq, dirinc[7], color, oppcol );
    if ( j & 64 )
        DrctnlFlips( sq, dirinc[6], color, oppcol );
    if ( j & 32 )
        DrctnlFlips( sq, dirinc[5], color, oppcol );
    if ( j & 16 )
        DrctnlFlips( sq, dirinc[4], color, oppcol );
    if ( j & 8 )
        DrctnlFlips( sq, dirinc[3], color, oppcol );
    if ( j & 4 )
        DrctnlFlips( sq, dirinc[2], color, oppcol );
    if ( j & 2 )
        DrctnlFlips( sq, dirinc[1], color, oppcol );
    if ( j & 1 )
        DrctnlFlips( sq, dirinc[0], color, oppcol );

    return FlipStack - OldFlipStack;
}

inline 
int EndGame::CtDrctnlFlips( uchar *sq, int inc, int color, int oppcol )
{
    uchar *pt = sq + inc;
    if(*pt == oppcol)
    {
        int count = 1;
        pt += inc;
        if(*pt == oppcol)
        {
            count++;                
            pt += inc;
            if(*pt == oppcol)
            {
                count++;            
                pt += inc;
                if(*pt == oppcol)
                {
                    count++;        
                    pt += inc;
                    if(*pt == oppcol)
                    {
                        count++;    
                        pt += inc;
                        if(*pt == oppcol)
                        {
                            count++;  
                            pt += inc;
                        }
                    }
                }
            }
        }
        if(*pt == color) 
            return count;
    }
   return 0;
}

int EndGame::CountFlips( uchar *board, int sqnum, int color, int oppcol )
{
    int ct=0;
    int j=dirmask[sqnum];
    uchar *sq;
    sq = sqnum + board;
    if ( j & 128 )
        ct += CtDrctnlFlips( sq, dirinc[7], color, oppcol );
    if ( j & 64 )
        ct += CtDrctnlFlips( sq, dirinc[6], color, oppcol );
    if ( j & 32 )
        ct += CtDrctnlFlips( sq, dirinc[5], color, oppcol );
    if ( j & 16 )
        ct += CtDrctnlFlips( sq, dirinc[4], color, oppcol );
    if ( j & 8 )
        ct += CtDrctnlFlips( sq, dirinc[3], color, oppcol );
    if ( j & 4 )
        ct += CtDrctnlFlips( sq, dirinc[2], color, oppcol );
    if ( j & 2 )
        ct += CtDrctnlFlips( sq, dirinc[1], color, oppcol );
    if ( j & 1 )
        ct += CtDrctnlFlips( sq, dirinc[0], color, oppcol );
    return(ct);
}


inline int EndGame::AnyDrctnlFlips( uchar *sq, int inc, int color, int oppcol )
{
    uchar *pt = sq + inc;
    if(*pt == oppcol)
    {
        pt += inc;
        if(*pt == oppcol)
        {
            pt += inc;
            if(*pt == oppcol)
            {
                pt += inc;
                if(*pt == oppcol)
                {
                    pt += inc;
                    if(*pt == oppcol)
                    {
                        pt += inc;
                        if(*pt == oppcol)
                            pt += inc;
                    }
                }
            }
        }
        if(*pt == color) 
            return 1;
    }

   return 0;
}

int EndGame::AnyFlips( uchar *board, int sqnum, int color, int oppcol )
{
    int j=dirmask[sqnum];
    uchar *sq;
    sq = sqnum + board;
    if( (( j & 128 ) && AnyDrctnlFlips( sq, dirinc[7], color, oppcol )) ||
        (( j & 64 )  && AnyDrctnlFlips( sq, dirinc[6], color, oppcol )) ||
        (( j & 32 ) && AnyDrctnlFlips( sq, dirinc[5], color, oppcol )) ||
        (( j & 16 ) && AnyDrctnlFlips( sq, dirinc[4], color, oppcol )) ||
        (( j & 8 ) && AnyDrctnlFlips( sq, dirinc[3], color, oppcol )) ||
        (( j & 4 ) && AnyDrctnlFlips( sq, dirinc[2], color, oppcol )) ||
        (( j & 2 ) && AnyDrctnlFlips( sq, dirinc[1], color, oppcol )) ||
        (( j & 1 ) && AnyDrctnlFlips( sq, dirinc[0], color, oppcol )) )
        return 1;
    return 0;
}



void EndGame::UndoFlips( int FlipCount, int oppcol )
{  
    if(FlipCount%2)
    {
        FlipCount--;
        * (*(--FlipStack)) = oppcol;
    }
    while(FlipCount)
    {
        FlipCount -= 2;
        * (*(--FlipStack)) = oppcol;
        * (*(--FlipStack)) = oppcol;
    }
}

inline uint EndGame::minu(uint a, uint b)
{
    if(a<b) 
        return a;
    return b;
}

void EndGame::PrepareToSolve( uchar *board )
{
    int i,sqnum;
    uint k;
    EmList *pt;
    int z;
    // find hole IDs: 
    k = 1;
    for(i=10; i<=80; i++)
    {
        if(board[i]==EMPTY)
        {
            if( board[i-10]==EMPTY ) HoleId[i] = HoleId[i-10];
            else if( board[i-9]==EMPTY ) HoleId[i] = HoleId[i-9];
            else if( board[i-8]==EMPTY ) HoleId[i] = HoleId[i-8];
            else if( board[i-1]==EMPTY ) HoleId[i] = HoleId[i-1];
            else{ HoleId[i] = k; k<<=1; }
        }
        else HoleId[i] = 0;
    }
    const int MAXITERS=1;
   /* In some sense this is wrong, since you
    * ought to keep doing iters until reach fixed point, but in most
    * othello positions with few empties this ought to work, and besides,
    * this is justifiable since the definition of "hole" in othello
    * is somewhat arbitrary anyway. */
    for(z=MAXITERS; z>0; z--)
    {
        for(i=80; i>=10; i--)
        {
            if(board[i]==EMPTY)
            {
                k = HoleId[i];
                if( board[i+10]==EMPTY ) HoleId[i] = minu(k,HoleId[i+10]);
                if( board[i+9]==EMPTY ) HoleId[i] = minu(k,HoleId[i+9]);
                if( board[i+8]==EMPTY ) HoleId[i] = minu(k,HoleId[i+8]);
                if( board[i+1]==EMPTY ) HoleId[i] = minu(k,HoleId[i+1]);
            }
        }
        for(i=10; i<=80; i++)
        {
            if(board[i]==EMPTY)
            {
                k = HoleId[i];
                if( board[i-10]==EMPTY ) HoleId[i] = minu(k,HoleId[i-10]);
                if( board[i-9]==EMPTY ) HoleId[i] = minu(k,HoleId[i-9]);
                if( board[i-8]==EMPTY ) HoleId[i] = minu(k,HoleId[i-8]);
                if( board[i-1]==EMPTY ) HoleId[i] = minu(k,HoleId[i-1]);
            }
        }
    }
    /* find parity of holes: */
    RegionParity = 0;
    for(i=10; i<=80; i++)
        RegionParity ^= HoleId[i];

    /* create list of empty squares: */
    k = 0;
    pt = &EmHead;
    for(i=60-1; i>=0; i--)
    {
        sqnum = worst2best[i];
        if( board[sqnum]==EMPTY )
        {
            pt->succ = &(Ems[k]);
            Ems[k].pred = pt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -