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

📄 moveexecuter.cpp

📁 c+++ game uploading now
💻 CPP
字号:
/**
 @file
 The code that updates the board representation during search.
*/

#include <cassert>
#include <cstddef>
#include "MoveExecuter.h"
#include "TTable.h"

using namespace Othello;

const int MoveExecuter::directions[]=
{
    1, -1, 9, -9, 10, -10, 11, -11, 0
};

const unsigned int MoveExecuter::dir_mask[10*10]=
{
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0, 81, 81, 87, 87, 87, 87, 22, 22,  0,
    0, 81, 81, 87, 87, 87, 87, 22, 22,  0,
    0,121,121,255,255,255,255,182,182,  0,
    0,121,121,255,255,255,255,182,182,  0,
    0,121,121,255,255,255,255,182,182,  0,
    0,121,121,255,255,255,255,182,182,  0,
    0, 41, 41,171,171,171,171,162,162,  0,
    0, 41, 41,171,171,171,171,162,162,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

FullMoveExecuter::FullMoveExecuter(const int pos, UndoData &udata, int dir)
    :MoveExecuter(actualb.isblacksturn, pos),
     _backupTTBoard(actualbtt),
     _hash32(actualb.hash32),
     _backup_blaks(actualb.blacks),
     _udata(udata)
{   
    assert(actualb.table[_move]==empty);
    assert(actualb.AssertIsInSync());

    const unsigned int mask=dir_mask[_move];
    unsigned int idir=dir;
    
    switch(player)
    {
    case black:
        //scan in every direction
        for(; directions[idir]; idir++)
        {
            //if this is not a possible direction from square x then skipp
            if(! (mask & (1<<idir)) )
                continue;

            //now go trough opponents down
            int x=_move+directions[idir];
            for(; actualb.table[x]==white; x+=directions[idir])
                ;

            //if found an actual players's disc then go backwards and do flips
            if(actualb.table[x]==black)
            {
                x -= directions[idir];
                for(; x!=_move; x-=directions[idir])
                {
                    _ttable.FlipInKey32(x, black);
                    BlackUpdateIndexFlip(x);
                    actualb.table[x]=black;
                    UpdateUndoInfo(actualb.table[x]); 
                }
            }
        }

        //place the new disc
        _ttable.PlaceInKey32(pos, black);
        BlackUpdateIndexPlace(pos);
        actualb.table[pos]=black;
        actualb.blacks += _udata.count+1;
        actualb.isblacksturn=false;
        actualbtt.isblacksturn=false;
        break;
    default:
        assert(player==white);
        for(; directions[idir]; idir++)
        {
            if(! (mask & (1<<idir)))
                continue;
            
            int x=_move+directions[idir];
            for(; actualb.table[x]==black; x+=directions[idir])
                ;
            if(actualb.table[x]==white)
            {
                x -= directions[idir];
                for(; x!=_move; x-=directions[idir])
                {
                    _ttable.FlipInKey32(x, white);
                    WhiteUpdateIndexFlip(x);
                    actualb.table[x]=white;
                    UpdateUndoInfo(actualb.table[x]); 
                }
            }
        }

        //place the new disc
        _ttable.PlaceInKey32(pos, white);
        WhiteUpdateIndexPlace(pos);
        actualb.table[pos]=white;
        actualb.blacks -= _udata.count;
        actualb.isblacksturn=true;
        actualbtt.isblacksturn=true;
        break;
    }
    actualb.empties--;
    assert(actualb.AssertIsInSync());
}

GuiMoveExecuter::GuiMoveExecuter(Board &board, int pos)
    :MoveExecuter(board.isblacksturn, pos)
{   
    assert(board.table[_move]==empty || 
           board.table[_move]==_gui__possible || 
           board.table[_move]==_gui__hint);
 
    int flips=0;
    //do flips
    unsigned int idir=0;
    for(; directions[idir]; idir++)
    {
        int x;
        for(x=_move+directions[idir]; 
            board.table[x]==opponent;
            x += directions[idir])
            ;
        if(board.table[x]==player)
            for(x -= directions[idir]; x!=_move; x -= directions[idir])
            {
                board.table[x]=player;
                flips++;
            }

    }
    assert(flips);

    //place the new disc
    board.table[pos]=player;
    board.isblacksturn=!board.isblacksturn;
    board.empties--;
    if(player==black)
        board.blacks += flips+1;
    else
        board.blacks -= flips;
}

FullMoveExecuter::~FullMoveExecuter()
{
    //restore from backup    
    Undo();
    actualbtt=_backupTTBoard;
    actualb.empties++;
    actualb.blacks=_backup_blaks;
    assert(actualb.AssertIsInSync());
}


void FullMoveExecuter::Undo()
{
    //undo disc place
    actualb.table[_move]=empty;
    unsigned int i=0;
    if(_backupTTBoard.isblacksturn)
    {
        //'place a white over the black'
        //indeces (place) 
        WhiteUpdateIndexPlace(_move);
        //undo flip (disc, and indices)
        for(; i<_udata.count; i++)
        {
            //disc
            *(_udata.Prev[i])=white;
            //indices
            const int x=_udata.Prev[i]-actualb.table;
            WhiteUpdateIndexFlip(x);
        }
    }
    else
    {
        // 'place a balck over the white'
        //indeces (place)
        BlackUpdateIndexPlace(_move);
        //undo flip (disc, and indices)
        for(; i<_udata.count; i++)
        {
            //disc
            *(_udata.Prev[i])=black;
            //indices
            int const x=_udata.Prev[i]-actualb.table;
            BlackUpdateIndexFlip(x);
        }
    }
    actualb.isblacksturn= _backupTTBoard.isblacksturn;
    _udata.count=0; 
    actualb.hash32=_hash32;
}

inline void FullMoveExecuter::BlackUpdateIndexPlace(int x)
{
    for(int i=0; i<5; i++)
        *actualb.updatetable[x][i].Index += 
                 actualb.updatetable[x][i].PlaceOffset;
}

inline void FullMoveExecuter::WhiteUpdateIndexPlace(int x)
{
    for(int i=0; i<5; i++)
        *actualb.updatetable[x][i].Index -=
            actualb.updatetable[x][i].PlaceOffset;
}

inline void FullMoveExecuter::BlackUpdateIndexFlip(int x)
{
    for(int i=0; i<5; i++)
        *actualb.updatetable[x][i].Index +=
            actualb.updatetable[x][i].FlipOffset;
}

inline void FullMoveExecuter::WhiteUpdateIndexFlip(int x)
{
    for(int i=0; i<5; i++)
        *actualb.updatetable[x][i].Index -=
            actualb.updatetable[x][i].FlipOffset;
}

inline void FullMoveExecuter::UpdateUndoInfo(squarevalue &p)
{
    _udata.Prev[_udata.count] = &p;
    _udata.count++;
}

TranspositionTable& FullMoveExecuter::_ttable=TranspositionTable::Instance();

⌨️ 快捷键说明

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