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

📄 evaluate.cpp

📁 《C++Builder程序设计范例--中国象棋》配书盘自述文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include "Cdefines.h"
#include "Global.h"

#undef max
#undef min
#define max(a, b)  (((a) > (b)) ? (a) : (b))
#define min(a, b)  (((a) < (b)) ? (a) : (b))

#define     TOLERANCE           9   /*容忍值*/
#define     EXCHANGEVALUE      32

MAXTYPE RootValue;
BOARDTYPE ChessBoard[0x99];
extern int DirectionTab[];

extern MAXTYPE MainEvaluat;

bool  OnlyKnOrPa;
int RookActive, KnightActive, GunnerActive, KingActive;  //车马炮王的活动性

typedef unsigned char FILETYPE;  /*  列数  */
typedef unsigned char RANKTYPE;  /*  行数  */
typedef unsigned char SETOFFILE;

/*
 *  本模块的全局变量
 */

int PieceValue[8] = {0, 0x1000, 0x900, 0x450, 0x400, 0x200, 0x200, 0x100};

const char distanR[10] = { 0, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
const char distanL[9] = { 3, 3, 3, 1, 0, 1, 3, 3, 3 };
const char distanCR[10] = { 3, 2, 1, 0, 0, 0, 0, 1, 2, 3 };
const char distanCL[9] = { 3, 2, 1, 0, 0, 0, 1, 2, 3 };

const char pawnrank[10] = {0, 0, 0, 0, 2, 4, 8, 20, 15, 2};
const char pawnfilefactor[9] = {0, 0, 2, 4, 5, 4, 2, 0, 0};


int totalmaterial, pawntotalmaterial, material;
  /*  子力级别。开局、中局子力比较重要,残局时子力作用减小  */
int materiallevel;
const unsigned char squarerankvalue[10] = { 0, 0, 0, 0, 0, 1, 1, 2, 4, 4};
COLORTYPE tempcolor;
int temp, temp2;  /*  临时变量  */

/*车位置值表*/
const int rookposvalu[10][9] = { {-26,128,76, 180,154,180,76, 128,-26},
				 {102,52, 102,204,102,204,102,52, 102},
				 {52, 102,76, 180,154,180,76, 102,52},
				 {76, 128,102,180,180,180,102,128,76},
				 {154,204,180,256,256,256,180,204,154},
				 {154,180,154,230,230,230,154,180,154},
				 {154,230,204,282,282,282,204,230,154},
				 {154,154,154,230,230,230,154,154,154},
				 {204,256,230,308,332,308,230,256,204},
                                 {180,180,154,230,204,230,154,180,180}};

 /*马位置值表*/
const int knightposvalu[10][9] = { {0,  -52,0,  0,  0,  0,  0,  -52,0},
				   {0,  26, 52, 52, -26,52, 52, 26, 0},
				   {52, 26, 102,102,52, 102,102,26, 52},
				   {26, 76, 102,76, 128,76, 102,76, 26},
				   {52, 154,204,180,154,180,204,154,52},
				   {76, 204,180,230,204,230,180,204,76},
				   {102,308,230,308,256,308,230,308,102},
				   {154,180,204,256,230,256,204,180,154},
				   {52, 128,358,204,102,204,358,128,52},
                                   {52, 102,204,154,52, 154,204,102,52}};

 /*炮位置值表*/
const int gunposvalu[10][9] = { {0,  0,  26, 76,  76,  76,  26, 0,  0},
				{0,  26, 52, 76,  76,  76,  52, 26, 0},
				{52, 0,  102,76,  128, 76,  102,0,  52},
				{0,  0,  0,  26,  52,  26,  0,  0,  0},
				{-26,0,  52, 26,  76,  26,  52, 0,  -26},
				{0,  0,  0,  26,  102, 26,  0,  0,  0},
				{0,  0,  -26,52,  128, 52,  -26,0,  0},
				{26, 26, 0,  -128,-102,-128,0,  26, 26},
				{26, 26, 0,  -52, -180,-52, 0,  26, 26},
                                {76, 52, 0,  -128,-154,-128,0,  52, 76} };

/*兵位置值表*/
const int pawnposvalu[10][9] = {  {0,  0,  0,  0,   0,   0,   0,  0,  0},
				  {0,  0,  0,  0,   0,   0,   0,  0,  0},
				  {0,  0,  0,  0,   0,   0,   0,  0,  0},
				  {0,  0,  -26,0,   52,  0,   -26,0,  0},
				  {26, 0,  102,0,   102, 0,   102,0,  26},
				  {76, 154,230,230, 256, 230, 230,154,76},
				  {128,256,384,435, 512, 435, 384,256,128},
				  {180,332,538,768, 1024,768, 538,332,180},
				  {230,460,716,1024,1536,1024,716,460,230},
				  {0,  38, 76, 115, 154, 115, 76, 38, 0} };

int i,j;


/*
 *  计算兵结构值,此处实际上没有定义
 */

static int pawnstrval(DEPTHTYPE depth, COLORTYPE color)
{
    return 0;    
}


/*
 *  计算棋子位置值
 */

inline int PiecePosVal(PIECETYPE piece, COLORTYPE color, SQUARETYPE square)
{
    return (PieceValue[piece] + PVTable[color][piece][square]);
}


short mating;  /*  进行子力交换时要用到  */

/*
 *  计算棋子值表,后面的静态估价函数需要
 */

void CalcPVTable(void)
{
    typedef SETOFFILE PAWNTABTYPE[9];


    /*  存储棋子的攻击性  */
    char attackvalue[2][0x99];
    /*  棋子的控位功能值  */
    int pvcontrol[2][6][0x99];

    COLORTYPE losingcolor;     /*  子力交换时吃亏的一方  */
    int posval;                /*  棋子位置值  */
    int attval;                /*  棋格的攻击值  */
    FILETYPE line;             /*  棋子的列数  */
    RANKTYPE rank;             /*  棋子的行数  */
    char dist, kingdist;       /*  到棋盘中心的距离,离王的距离 */
    short direct;              /*  指示直接攻击  */
    int cnt;                   /*  攻击值变量  */
    COLORTYPE color, oppcolor; /*  己方和对方  */
    PIECETYPE piececount;
    SQUARETYPE square;

    SQUARETYPE asquare;
    COLORTYPE acolor;
    PIECETYPE apiece;

    DIRTYPE dir;               /*  棋子可移动的方向(左、右、前、后) */
    EDGESQUARETYPE sq;
    int colortemp, piecetemp;           /*  临时变量  */

    material = pawntotalmaterial = totalmaterial = mating = 0;

    for (square = 0; square < 0x99; square++)
	if (((square>>4)<10) && ((square % 16)<9) && ((square | 0xff)>=0))
            if (ChessBoard[square].piece != empty)
                if (ChessBoard[square].piece != king)
                {
                    temp = PieceValue[ChessBoard[square].piece];
                    totalmaterial += temp;
                    if (ChessBoard[square].piece == pawn)
                        pawntotalmaterial += PieceValue[pawn];
                    if (ChessBoard[square].color == red) temp = -temp;
                    material -= temp;
                }
    materiallevel = max(0, totalmaterial - 0x2000) / 0x100;

    /*  根据物质力量来确定是否进行子力交换  */
    if (material < 0)
        losingcolor = red;
    else
        losingcolor = black;
    mating = ((totalmaterial - abs(material)) / 2 <= PieceValue[gunner] * 2)
	&& (abs(material) >= PieceValue[rook] - PieceValue[gunner]);
    /*  计算攻击值 */
    for (rank = 0; rank < 10; rank++)
	for (line = 0; line < 9; line++)
        {
            square = (rank << 4) + line;
	    attval = max(0, 9 - 3 * (distanCR[rank] + distanCL[line]));
		    /*  占据中心的重要性 */
                    /*  棋子所在行数的重要性  */
    /*
    在C++ Builder中枚举常量加一个常数,不能成为后一个常量。
     只得采用整数间接来达到目的。
    */
             for (colortemp = 0; colortemp <= 1; colortemp++)
            {
                { if (colortemp==0)
                  color = red;
                  if (colortemp==1)
                    color = black;
                }
	        attackvalue[color][square] = char(((squarerankvalue[rank] * 3 *
			(materiallevel + 8)) >> 5) + attval);
		 square = (((0xa0 - square) / 16) << 4 )+ line;
		 if ((square ==0xa0)||(square == 0x90)||(square == 0x80)||
		(square == 0x70)||(square == 0x60)||(square == 0x50)||
		 (square == 0x40) || (square == 0x30)||(square == 0x20) ||
		  (square == 0x10)||(square == 0x0))
	           {
	            square -= 0x10;
	           }
	          else
		   {
	            square = square;
	           }
	    }
        }
     /*
    在C++ Builder中枚举常量加一个常数,不能成为后一个常量。
     只得采用整数间接来达到目的。
    */
  for (colortemp = 0; colortemp <= 1; colortemp++)
    {
      {
      if (colortemp==0)
       color=red;
        if (colortemp ==1)
          color = black;
      }
       	oppcolor = (COLORTYPE)(1 - color);
	  if ( materiallevel > 0)
	    /*  计算围绕对方王的四个位置的重要性  */
     	for (dir = 0; dir < 4; dir++)
        {
            sq = PieceTable[oppcolor][0].isquare + DirectionTab[dir];
	      if (((square>>4)<10) && ((square % 16)<9) && ((square | 0xff)>=0))
		attackvalue[color][sq] += char(((12 * (materiallevel + 8)) >> 5));
        }
    }

    /*  计算棋子的局面控制值  */
    /*
    在C++ Builder中枚举常量加一个常数,不能成为后一个常量。
     只得采用整数间接来达到目的。
    */
    for (square = 0; square <= 0x98; square++)
       if (((square>>4)<10) && ((square % 16)<9) && ((square | 0xff)>=0))
         for (colortemp = 0; colortemp <= 1; colortemp++)
          {
             {
              if (colortemp==0)
                  color = red;
                  if (colortemp==1)
                    color = black;
              }
		 piececount = rook;
		 pvcontrol[color][piececount][square] = 0;
	  }
    /*
    在C++ Builder中枚举常量加一个常数,不能成为后一个常量。
     只得采用整数间接来达到目的。
    */
       for (square = 0; square <= 0x98; square++)
       if (((square>>4)<10) && ((square % 16)<9) && ((square | 0xff)>=0))
           for (colortemp = 0; colortemp <= 1; colortemp++)
            {
             {
              if (colortemp==0)
                  color = red;
                  if (colortemp==1)
                    color = black;
              }
             	for (dir = 3; dir > 0; dir--)
                {
                        piececount = rook;
                /* 计算棋子每个方位的攻击性。己方对对方同样棋子的攻击,算是正常攻击;
                对不是同样棋子的攻击,算是半个攻击。
                 */
                   cnt = 0;
                    sq = square;
                    direct = 1;
                    do
                    {
                        sq += DirectionTab[dir];
	      		if (((sq >>4)>10) || ((sq % 16)>9)
			   || ((sq | 0xff)<0)) goto TEN;
                        temp = attackvalue[color][sq];
                        if (direct)
                            cnt += temp;
                        else
                            cnt += (temp >> 1);
                        if (ChessBoard[sq].piece != empty)
                            if ((ChessBoard[sq].piece != piececount))
                            direct = 0;
                   } while (ChessBoard[sq].piece != pawn);
  TEN:           pvcontrol[color][piececount][square] += (cnt >> 2);
                }
            }

    /*  逐个计算棋子表 */
    /*
    在C++ Builder中枚举常量加一个常数,不能成为后一个常量。
     只得采用整数间接来达到目的。
    */
    for (square = 0; square <= 0x98; square++)
       if (((square>>4)<10) && ((square % 16)<9) && ((square | 0xff)>=0))
      {
       	for (colortemp = 0; colortemp <= 1; colortemp++)
           {
              {
               if (colortemp==0)
                  color = red;
                  if (colortemp==1)
                    color = black;
              }
         
	    line = FILETYPE(square % 16);
	    rank = RANKTYPE(square >> 4);
	    if (color == black) rank = RANKTYPE(9 - rank);
	    dist = char(distanR[rank] + distanL[line]);
            if ((rank<=9) && (line<=8))
	     kingdist = char(abs((square >> 4) - (PieceTable[oppcolor][0].isquare
	    	   >> 4)) + ((square - PieceTable[oppcolor][0].isquare) % 16));
      /*
    在C++ Builder中枚举常量加一个常数,不能成为后一个常量。
     只得采用整数间接来达到目的。
    */
            for (piecetemp = 0; piecetemp <= 6; piecetemp++)
     {
       {
       if (piecetemp==0)
        piececount=king;
          if (piecetemp==1)
            piececount=rook;
             if (piecetemp==2)
              piececount=gunner;
               if (piecetemp==3)
                piececount=knight;
                 if (piecetemp==4)
                  piececount=assist;
                    if(piecetemp==5)
                     piececount=bishop;
                      if (piecetemp==6)
                        piececount=pawn;

        }

                posval = 0;        /*  根据棋格的位置计算棋子位置值  */
	    	if (mating)
                {
                    if (piececount == king)
			if (color == losingcolor)  /*  子力交换估算  */
			{
                            posval = 128 - 16 * distanR[rank]
                                - 12 * distanL[line];
                            if (distanR[rank] == 3)
                                posval -= 16;
                        }
                       else
			{
                            posval = 128 - 4 * kingdist;
                            if ((distanR[rank] >= 2) || (distanL[line] == 3))
                                posval -= 16;
                        }
                }
                else
                {
	       	    temp = pvcontrol[color][rook][square];
                    /*  正常估价函数  */
                    switch (piececount)
                    {
                        case king :
			    if (materiallevel <= 0) posval = -2 * dist;
                            break;
	    		case assist :
                        case bishop:
			    posval = temp >> 2;
                            break;
                        case rook :
                            posval = temp;
                            break;
                        case gunner :
                            posval = temp>>1;
                            break;
                        case knight :
                            cnt = 0;
                            for (dir = 0; dir < 8; dir++)
                            {
                                sq = square + KnightDir[dir];
			 if (((square>>4)<10) && ((square % 16)<9) && ((square | 0xff)>=0))
                                    cnt += attackvalue[color][sq];
                            }
                            posval = (cnt >> 1) - dist * 3;
                            break;
                        case pawn :
			    posval = pawnrank[rank] +
			    pawnfilefactor[line] * (rank + 2) - 12;

	     	    }
                }

⌨️ 快捷键说明

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