中国象棋机器人

本文深入探讨了游戏开发领域的核心技术,包括游戏引擎、图形渲染、音视频处理等关键环节,为开发者提供全面的技术指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#ifndef ANDROID_USER_ITEM_SINK_HEAD_FILE
#define ANDROID_USER_ITEM_SINK_HEAD_FILE

#pragma once

#include "Stdafx.h"
#include "GameLogic.h"

//

//机器人类
class CAndroidUserItemSink : public IAndroidUserItemSink
{
	/象棋属性/
	//规则变量
protected:
	WORD							m_wRuleRoundID;						//规则标识
	//tagGameRuleInfo					m_GameRuleInfo;						//游戏规则

	//游戏变量
protected:
	WORD							m_wBankerUser;						//庄家玩家
	WORD							m_wCurrentUser;						//当前用户
	BYTE							m_cbChessColor;						//棋子颜色

	//选择信息
protected:
	BYTE							m_cbXSourcePos;						//选择信息
	BYTE							m_cbYSourcePos;						//选择信息

	//辅助变量
protected:
	bool							m_bDrawTimeMode;					//局时模式
	bool							m_bRequestAgree;					//请求同意
	bool							m_bRequestCustomize;				//请求定制
	TCHAR							m_szUserAccounts[2][LEN_ACCOUNTS];	//玩家帐号

	//状态变量
protected:
	WORD							m_wViewStepCount;					//棋谱步数
	//tagStatusInfo					m_UserStatusInfo[2];				//用户状态

	//辅助变量
protected:
	tagChessItem					m_ChessItemView[2][COUNT_CHESS];	//棋子信息
	tagChessItem *					m_ChessBoradView[COUNT_X][COUNT_Y];	//棋盘信息

	//

	//控件变量
protected:
	CGameLogic						m_GameLogic;						//游戏逻辑
	IAndroidUserItem *				m_pIAndroidUserItem;				//用户接口
	//CGlobalUnits *                  m_pGlobalUnits;                     //全局单元

	//函数定义
public:
	//构造函数
	CAndroidUserItemSink();
	//析构函数
	virtual ~CAndroidUserItemSink();

	//基础接口
public:
	//释放对象
	virtual VOID Release() { delete this; }
	//接口查询
	virtual VOID * QueryInterface(REFGUID Guid, DWORD dwQueryVer);

	//控制接口
public:
	//初始接口
	virtual bool Initialization(IUnknownEx * pIUnknownEx);
	//重置接口
	virtual bool RepositionSink();

	//游戏事件
public:
	//时间消息
	virtual bool OnEventTimer(UINT nTimerID);
	//游戏消息
	virtual bool OnEventGameMessage(WORD wSubCmdID, VOID * pData, WORD wDataSize);
	//游戏消息
	virtual bool OnEventFrameMessage(WORD wSubCmdID, VOID * pData, WORD wDataSize);
	//场景消息
	virtual bool OnEventSceneMessage(BYTE cbGameStatus, bool bLookonOther, VOID * pData, WORD wDataSize);

	//用户事件
public:
	//用户进入
	virtual VOID OnEventUserEnter(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser);
	//用户离开
	virtual VOID OnEventUserLeave(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser);
	//用户积分
	virtual VOID OnEventUserScore(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser);
	//用户状态
	virtual VOID OnEventUserStatus(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser);
	//用户段位
	virtual VOID OnEventUserSegment(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser);

	//消息处理
protected:
	//游戏开始
	bool OnSubGameStart(VOID * pData, WORD wDataSize);
	//游戏结束
	bool OnSubGameEnd(VOID * pData, WORD wDataSize);

	/象棋方法/
	//更新按钮
	bool UpdateManualControl(WORD wViewStepCount);
	//执行走棋
	bool PerformMoveChess(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos);

	//移动棋子
	bool OnSubMoveChess(const VOID * pData, WORD wDataSize);
	//悔棋失败
	bool OnSubRegretFaile(const VOID * pData, WORD wDataSize);
	//悔棋结果
	bool OnSubRegretResult(const VOID * pData, WORD wDataSize);
	//悔棋请求
	bool OnSubRegretRequest(const VOID * pData, WORD wDataSize);
	//和棋响应
	bool OnSubPeaceRespond(const VOID * pData, WORD wDataSize);
	//和棋请求
	bool OnSubPeaceRequest(const VOID * pData, WORD wDataSize);
	//请求设置
	bool OnSubRequestRule(const VOID * pData, WORD wDataSize);
	//请求同意
	bool OnSubRequestAgree(const VOID * pData, WORD wDataSize);
	//游戏棋谱
	bool OnSubChessManual(const VOID * pData, WORD wDataSize);

	//消息定义
protected:
	//开始消息
	LRESULT OnMessageStart(WPARAM wParam, LPARAM lParam);
	//求和消息
	LRESULT OnMessagePeace(WPARAM wParam, LPARAM lParam);
	//悔棋消息
	LRESULT OnMessageRegret(WPARAM wParam, LPARAM lParam);
	//认输消息
	LRESULT OnMessageGiveUp(WPARAM wParam, LPARAM lParam);
	//棋谱消息
	LRESULT OnMessageManual(WPARAM wParam, LPARAM lParam);
	//保存消息
	LRESULT OnMessagePreserve(WPARAM wParam, LPARAM lParam);
	//点击棋盘
	LRESULT OnHitChessBorad(WPARAM wParam, LPARAM lParam);
	//同意规则
	LRESULT OnGameRuleAgree(WPARAM wParam, LPARAM lParam);
	//拒绝规则
	LRESULT OnGameRuleReject(WPARAM wParam, LPARAM lParam);
	//棋谱定位
	LRESULT OnOrientationManual(WPARAM wParam, LPARAM lParam);
	//请求回应
	LRESULT OnUserRequestRespond(WPARAM wParam, LPARAM lParam);

	//时间函数
public:
	//时钟标识
	UINT GetClockID();
	//时钟位置
	WORD GetClockChairID();
	//删除时钟
	//VOID KillGameClock(WORD wClockID);
	//设置时钟
	VOID SetGameClock(WORD wChairID, WORD wClockID, UINT nElapse);
protected:


	//
public:
	bool AndoidThink();
};

//

#endif
<pre name="code" class="cpp">#include "Stdafx.h"
#include "AndroidUserItemSink.h"

//
//走棋时间
#define TIME_LESS					5									//走一步棋最少时间


//时间标识
#define IDI_GAME_TIME				100									//游戏定时器
#define IDI_START_GAME				200									//开始定时器

//游戏时间
#define TIME_START_GAME				90									//开始定时器
//

//构造函数
CAndroidUserItemSink::CAndroidUserItemSink()
{
	//游戏变量
	m_wBankerUser=INVALID_CHAIR;
	m_wCurrentUser=INVALID_CHAIR;

	//选择信息
	m_cbXSourcePos=255;
	m_cbYSourcePos=255;

	//辅助变量
	m_bDrawTimeMode=false;
	m_bRequestAgree=false;
	m_bRequestCustomize=false;
	ZeroMemory(m_szUserAccounts,sizeof(m_szUserAccounts));

	//规则变量
	m_wRuleRoundID=0L;
	//ZeroMemory(&m_GameRuleInfo,sizeof(m_GameRuleInfo));

	//状态变量
	//m_wViewStepCount=0;
	//ZeroMemory(&m_UserStatusInfo,sizeof(m_UserStatusInfo));

	//辅助变量
	ZeroMemory(m_ChessItemView,sizeof(m_ChessItemView));
	ZeroMemory(m_ChessBoradView,sizeof(m_ChessBoradView));
	
	//接口变量
	m_pIAndroidUserItem=NULL;;
	m_cbChessColor=CHESS_BLACK;
	m_wBankerUser=INVALID_CHAIR;
	m_wCurrentUser=INVALID_CHAIR;

	return;
}

//析构函数
CAndroidUserItemSink::~CAndroidUserItemSink()
{
}

//接口查询
VOID * CAndroidUserItemSink::QueryInterface(REFGUID Guid, DWORD dwQueryVer)
{
	QUERYINTERFACE(IAndroidUserItemSink,Guid,dwQueryVer);
	QUERYINTERFACE_IUNKNOWNEX(IAndroidUserItemSink,Guid,dwQueryVer);
	return NULL;
}

//初始接口
bool CAndroidUserItemSink::Initialization(IUnknownEx * pIUnknownEx)
{
	//查询接口
	m_pIAndroidUserItem=QUERY_OBJECT_PTR_INTERFACE(pIUnknownEx,IAndroidUserItem);
	if (m_pIAndroidUserItem==NULL) return false;

	return true;
}

//重置接口
bool CAndroidUserItemSink::RepositionSink()
{
	//删除时间
	//KillTimer(IDI_GAME_TIME);
	//KillGameClock(IDI_START_GAME);

	//游戏变量
	m_cbChessColor=CHESS_BLACK;
	m_wBankerUser=INVALID_CHAIR;
	m_wCurrentUser=INVALID_CHAIR;

	//选择信息
	m_cbXSourcePos=255;
	m_cbYSourcePos=255;

	//辅助变量
	m_bDrawTimeMode=false;
	m_bRequestAgree=false;
	m_bRequestCustomize=false;
	ZeroMemory(m_szUserAccounts,sizeof(m_szUserAccounts));

	//游戏逻辑
	m_GameLogic.ResetChessBorad();

	//规则变量
	m_wRuleRoundID=0L;
	//ZeroMemory(&m_GameRuleInfo,sizeof(m_GameRuleInfo));

	//状态变量
	//m_wViewStepCount=0;
	//ZeroMemory(&m_UserStatusInfo,sizeof(m_UserStatusInfo));

	//辅助变量
	ZeroMemory(m_ChessItemView,sizeof(m_ChessItemView));
	ZeroMemory(m_ChessBoradView,sizeof(m_ChessBoradView));

	return true;
}

//时间消息
bool CAndroidUserItemSink::OnEventTimer(UINT nTimerID)
{
	switch (nTimerID)
	{
	case IDI_START_GAME:	//开始游戏
		{
			//开始判断
			m_pIAndroidUserItem->SendUserReady(NULL,0);

			return true;
		}
	case IDI_GAME_TIME:		//对手走了一步棋
		{
			return true;
		}
	}

	return false;
}

//游戏消息
bool CAndroidUserItemSink::OnEventGameMessage(WORD wSubCmdID, VOID * pData, WORD wDataSize)
{
	switch (wSubCmdID)
	{
	case SUB_S_GAME_START:		//游戏开始
		{
			return OnSubGameStart(pData,wDataSize);
		}
	case SUB_S_MOVE_CHESS:		//移动棋子
		{
			return OnSubMoveChess(pData,wDataSize);
		}
	case SUB_S_REGRET_FAILE:	//悔棋失败
		{
			return OnSubRegretFaile(pData,wDataSize);
		}
	case SUB_S_REGRET_RESULT:	//悔棋成功
		{
			return OnSubRegretResult(pData,wDataSize);
		}
	case SUB_S_REGRET_REQUEST:	//悔棋请求
		{
			return OnSubRegretRequest(pData,wDataSize);
		}
	case SUB_S_PEACE_RESPOND:	//和棋响应
		{
			return OnSubPeaceRespond(pData,wDataSize);
		}
	case SUB_S_PEACE_REQUEST:	//和棋请求
		{
			return OnSubPeaceRequest(pData,wDataSize);
		}
	case SUB_S_CHESS_MANUAL:	//棋谱信息
		{
			return OnSubChessManual(pData,wDataSize);
		}
	case SUB_S_REQUEST_RULE:	//请求设置
		{
			return OnSubRequestRule(pData,wDataSize);
		}
	case SUB_S_REQUEST_AGREE:	//请求同意
		{
			return OnSubRequestAgree(pData,wDataSize);
		}
	case SUB_S_GAME_END:		//游戏结束
		{
			return OnSubGameEnd(pData,wDataSize);
		}
	}
	return true;
}

//游戏消息
bool CAndroidUserItemSink::OnEventFrameMessage(WORD wSubCmdID, VOID * pData, WORD wDataSize)
{
	return true;
}

//场景消息
bool CAndroidUserItemSink::OnEventSceneMessage(BYTE cbGameStatus, bool bLookonOther, VOID * pData, WORD wDataSize)
{
	switch (cbGameStatus)
	{
	case GAME_SCENE_FREE:	//空闲状态
		{
			//效验数据
			ASSERT(wDataSize==sizeof(CMD_S_StatusFree));
			if (wDataSize!=sizeof(CMD_S_StatusFree)) return false;

			//变量定义1
			CMD_S_StatusFree * pStatusFree=(CMD_S_StatusFree *)pData;
			IServerUserItem * pIServerUserItem=m_pIAndroidUserItem->GetMeUserItem();

			//变量定义
			WORD wMeChairID=pIServerUserItem->GetChairID();

			//设置变量
			m_wBankerUser=pStatusFree->wBankerUser;
			m_wCurrentUser=pStatusFree->wBankerUser;
			m_cbChessColor=(m_wBankerUser==wMeChairID)?CHESS_BLACK:CHESS_WHITE;

			//玩家设置
			if (pIServerUserItem->GetUserStatus()!=US_READY)
			{
				//UINT nElapse=rand()%TIME_START_GAME+TIME_LESS;
				UINT nElapse=2;
				m_pIAndroidUserItem->SetGameTimer(IDI_START_GAME,nElapse);
			}

			return true;
		}
	case GAME_SCENE_PLAY:	//游戏状态
		{
			//效验数据
			ASSERT(wDataSize==sizeof(CMD_S_StatusPlay));
			if (wDataSize!=sizeof(CMD_S_StatusPlay)) return false;

			//变量定义
			CMD_S_StatusPlay * pStatusPlay=(CMD_S_StatusPlay *)pData;

			//设置变量
			m_wBankerUser=pStatusPlay->wBankerUser;
			m_wCurrentUser=pStatusPlay->wCurrentUser;

			return true;
		}
	}

	//错误断言
	ASSERT(FALSE);

	return false;
}

//用户进入
VOID CAndroidUserItemSink::OnEventUserEnter(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser)
{
	return;
}

//用户离开
VOID CAndroidUserItemSink::OnEventUserLeave(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser)
{
	return;
}

//用户积分
VOID CAndroidUserItemSink::OnEventUserScore(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser)
{
	return;
}

//用户状态
VOID CAndroidUserItemSink::OnEventUserStatus(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser)
{
	return;
}

//用户段位
VOID CAndroidUserItemSink::OnEventUserSegment(IAndroidUserItem * pIAndroidUserItem, bool bLookonUser)
{
	return;
}

//游戏开始
bool CAndroidUserItemSink::OnSubGameStart(VOID * pData, WORD wDataSize)
{
	//效验数据
	ASSERT(wDataSize==sizeof(CMD_S_GameStart));
	if (wDataSize!=sizeof(CMD_S_GameStart)) return false;

	//消息处理
	CMD_S_GameStart * pGameStart=(CMD_S_GameStart *)pData;

	//游戏变量
	m_wBankerUser=pGameStart->wBankerUser;
	m_wCurrentUser=pGameStart->wBankerUser;

	//选择信息
	m_cbXSourcePos=255;
	m_cbYSourcePos=255;

	//游戏变量
	m_bRequestCustomize=false;
	m_wBankerUser=pGameStart->wBankerUser;
	m_wCurrentUser=pGameStart->wBankerUser;
	m_cbChessColor=(m_wBankerUser==m_pIAndroidUserItem->GetChairID())?CHESS_BLACK:CHESS_WHITE;

	//状态变量
	m_wViewStepCount=0;
	//ZeroMemory(&m_UserStatusInfo,sizeof(m_UserStatusInfo));

	//删除时间
	//KillGameClock(IDI_START_GAME);

	//设置棋盘
	m_GameLogic.ResetChessBorad();

	//准备
	OnGameRuleAgree(0,0);

	//机器人先下棋
	if (m_wCurrentUser==m_pIAndroidUserItem->GetChairID())
	{
		m_GameLogic.m_IsBanker=TRUE;
		AndoidThink();
	}
	else
	{
		m_GameLogic.m_IsBanker=FALSE;
	}

	return true;
}
//移动棋子
bool CAndroidUserItemSink::OnSubMoveChess(const VOID * pData, WORD wDataSize)
{
	//效验数据
	ASSERT(wDataSize==sizeof(CMD_S_MoveChess));
	if (wDataSize!=sizeof(CMD_S_MoveChess)) return false;

	//消息处理
	CMD_S_MoveChess * pMoveChess=(CMD_S_MoveChess *)pData;

	//设置用户
	m_wCurrentUser=pMoveChess->wCurrentUser;
	
	/维护logic层成员变量/
	//移动棋子
	TCHAR szManualName[32]=TEXT("");
	tagMoveChessResult MoveChessResult;
	m_GameLogic.MoveChess(pMoveChess->cbXSourcePos,pMoveChess->cbYSourcePos,pMoveChess->cbXTargetPos,pMoveChess->cbYTargetPos,MoveChessResult,szManualName);

	//服务器告诉自己(机器人)走棋成功
	if (pMoveChess->wActionUser==m_pIAndroidUserItem->GetChairID())
	{
		LOG(_T("机器人走棋成功,轮到真人走了"));
		LOG(_T("------------------------------"));
	}
	else	//对手走棋,该自己(机器人)走棋了
	{
		/自己走棋/
		LOG(_T("真人走棋成功,轮到机器人走了"));
		//陪玩
		AndoidThink();
	}

	return true;
}
//悔棋失败
bool CAndroidUserItemSink::OnSubRegretFaile(const VOID * pData, WORD wDataSize)
{
	return true;
}
//悔棋结果
bool CAndroidUserItemSink::OnSubRegretResult(const VOID * pData, WORD wDataSize)
{
	//效验数据
	ASSERT(wDataSize==sizeof(CMD_S_RegretResult));
	if (wDataSize!=sizeof(CMD_S_RegretResult)) return false;

	//变量定义
	CMD_S_RegretResult * pRegretResult=(CMD_S_RegretResult *)pData;

	//设置变量
	m_wCurrentUser=pRegretResult->wCurrentUser;

	//悔棋逻辑
	m_GameLogic.RegretChess(pRegretResult->wTargetStep);

	return true;
}
//悔棋请求
bool CAndroidUserItemSink::OnSubRegretRequest(const VOID * pData, WORD wDataSize)
{
	srand( (unsigned)time( NULL ) );
	int bAcceptRegret=rand()%2;
	//同意悔棋
	{
		//变量定义
		CMD_C_RegretRespond RegretRespond;
		ZeroMemory(&RegretRespond,sizeof(RegretRespond));

		//设置变量
		RegretRespond.cbApprove=(BYTE)bAcceptRegret;

		//发送消息
		m_pIAndroidUserItem->SendSocketData(SUB_C_REGRET_RESPOND,&RegretRespond,sizeof(RegretRespond));
	}
	return true;
}
//和棋响应
bool CAndroidUserItemSink::OnSubPeaceRespond(const VOID * pData, WORD wDataSize)
{
	return true;
}
//和棋请求
bool CAndroidUserItemSink::OnSubPeaceRequest(const VOID * pData, WORD wDataSize)
{
	return true;
}
//游戏棋谱
bool CAndroidUserItemSink::OnSubChessManual(const VOID * pData, WORD wDataSize)
{
	return true;
}
//请求设置
bool CAndroidUserItemSink::OnSubRequestRule(const VOID * pData, WORD wDataSize)
{
	m_bRequestCustomize=true;
	OnGameRuleAgree(0,0);

	return true;
}
//请求同意
bool CAndroidUserItemSink::OnSubRequestAgree(const VOID * pData, WORD wDataSize)
{
	m_bRequestCustomize=false;
	OnGameRuleAgree(0,0);

	return true;
}
//同意规则
LRESULT CAndroidUserItemSink::OnGameRuleAgree(WPARAM wParam, LPARAM lParam)
{
	//发送同意
	if (m_bRequestCustomize==true)
	{
		//发送消息
		CMD_C_CustomizeRult CustomizeRult;
		ZeroMemory(&CustomizeRult,sizeof(CustomizeRult));

		CustomizeRult.GameRuleInfo.cbDirections=1;
		CustomizeRult.GameRuleInfo.cbRegretFlag=1;
		CustomizeRult.GameRuleInfo.cbCurrentMode=2;
		CustomizeRult.GameRuleInfo.wRuleDrawTime=1800;
		CustomizeRult.GameRuleInfo.wRuleStepTime=180;
		CustomizeRult.GameRuleInfo.wRuleSecondTime=0;

		m_pIAndroidUserItem->SendUserReady(&CustomizeRult,sizeof(CustomizeRult));
	}
	else m_pIAndroidUserItem->SendUserReady(NULL,0);

	return 0;
}
//游戏结束
bool CAndroidUserItemSink::OnSubGameEnd(VOID * pData, WORD wDataSize)
{
	//效验数据
	ASSERT(wDataSize==sizeof(CMD_S_GameEnd));
	if (wDataSize!=sizeof(CMD_S_GameEnd)) return false;

	//消息处理
	CMD_S_GameEnd * pGameEnd=(CMD_S_GameEnd *)pData;

	//选择变量
	m_cbXSourcePos=255;
	m_cbYSourcePos=255;

	//设置变量
	m_bRequestAgree=false;
	m_bRequestCustomize=false;
	m_wCurrentUser=INVALID_CHAIR;

	//设置状态
	m_pIAndroidUserItem->SetGameStatus(GAME_SCENE_FREE);

	//删除定时器
	//KillTimer(IDI_GAME_TIME);

	//开始设置
	UINT nElapse=rand()%TIME_START_GAME+TIME_LESS;
	m_pIAndroidUserItem->SetGameTimer(IDI_START_GAME,nElapse);

	return true;
}

//
//调用机器人
bool CAndroidUserItemSink::AndoidThink()
{
	LOG(_T("机器人进行思考了---->AndoidThink"));

	//变量定义
	CMD_C_MoveChess MoveChess;
	ZeroMemory(&MoveChess,sizeof(MoveChess));

	//机器人思考的结果
	BYTE	AIREScbXSourcePos;
	BYTE	AIREScbYSourcePos;
	BYTE	AIREScbXTargetPos;
	BYTE	AIREScbYTargetPos;
	m_GameLogic.AIThinkHowToGo(AIREScbXSourcePos,AIREScbYSourcePos,AIREScbXTargetPos,AIREScbYTargetPos);
	if (m_cbChessColor==CHESS_BLACK)
	{
		//主场
		MoveChess.cbXTargetPos=8-AIREScbXTargetPos;
		MoveChess.cbYTargetPos=9-AIREScbYTargetPos;
		MoveChess.cbXSourcePos=8-AIREScbXSourcePos;
		MoveChess.cbYSourcePos=9-AIREScbYSourcePos;
		MoveChess.wUsedTimeCount=10;
	}
	else
	{
		//客场
		MoveChess.cbXTargetPos=AIREScbXTargetPos;
		MoveChess.cbYTargetPos=AIREScbYTargetPos;
		MoveChess.cbXSourcePos=AIREScbXSourcePos;
		MoveChess.cbYSourcePos=AIREScbYSourcePos;
		MoveChess.wUsedTimeCount=10;
	}
	//机器人思考的结果

	//判断走棋合法性
	tagChessItem * pSourceChessItem=m_GameLogic.GetChessItem(MoveChess.cbXSourcePos,MoveChess.cbYSourcePos);
	bool bWalkLegality=m_GameLogic.IsWalkLegality(pSourceChessItem,MoveChess.cbXTargetPos,MoveChess.cbYTargetPos);
	if (pSourceChessItem==NULL
		||MoveChess.cbXTargetPos<0||MoveChess.cbXTargetPos>=COUNT_X||MoveChess.cbYTargetPos<0||MoveChess.cbYTargetPos>=COUNT_Y
		||!bWalkLegality
		||pSourceChessItem->cbColor!=m_cbChessColor
		)
	{
		LOG(_T("机器人走棋出错"));
		//发送认输消息
		CMD_C_ConcludeRequest ConcludeRequest;
		ZeroMemory(&ConcludeRequest,sizeof(ConcludeRequest));
		ConcludeRequest.cbReason=REASON_GIVE_UP;
		m_pIAndroidUserItem->SendSocketData(SUB_C_CONCLUDE_REQUEST,&ConcludeRequest,sizeof(ConcludeRequest));
	}
	else
	{
		LOG(_T("机器人向服务器发送自己的走棋结果"));
		//发送走棋消息
		m_pIAndroidUserItem->SendSocketData(SUB_C_MOVE_CHESS,&MoveChess,sizeof(MoveChess));
	}

	return true;
}


 

#ifndef GAME_LOGIC_HEAD_FILE
#define GAME_LOGIC_HEAD_FILE

#pragma once

#include "Stdafx.h"

//

//棋盘定义
#define COUNT_X						9									//棋格数目
#define COUNT_Y						10									//棋格数目
#define COUNT_CHESS					16									//棋子数目				

//棋子颜色
#define CHESS_NULL					0									//没有棋子
#define CHESS_BLACK					1									//黑色棋子
#define CHESS_WHITE					2									//白色棋子

//棋子定义
#define CHESS_GENERAL				1									//将
#define CHESS_KAVASS				2									//士
#define CHESS_ELEPHANT				3									//象
#define CHESS_HORSE					4									//马
#define CHESS_ROOK					5									//车
#define CHESS_CANNON				6									//炮
#define CHESS_SOLDIER				7									//兵

//

//棋子定义
struct tagChessItem
{
	BYTE							cbXPos;								//棋子坐标
	BYTE							cbYPos;								//棋子坐标
	BYTE							cbColor;							//棋子颜色
	BYTE							cbChess;							//棋子权位
	BYTE							cbChessID;							//棋子标识
};

//棋谱结构
struct tagChessManual
{
	BYTE							cbXSourceChessPos;					//棋子位置
	BYTE							cbYSourceChessPos;					//棋子位置
	BYTE							cbXTargetChessPos;					//棋子位置
	BYTE							cbYTargetChessPos;					//棋子位置
};

//捉棋结果
struct tagCatchChessInfo
{
	BYTE							cbSourceCount;						//捉子数目
	tagChessItem *					pTargetChessItem;					//捉棋指针
	tagChessItem *					pSourceChessItem[18];				//捉子指针
};

//将军结果
struct tagGeneralChessInfo
{
	BYTE							cbSourceCount;						//将军数目
	tagChessItem *					pSourceChessItem[18];				//将军指针
};

//走棋结果
struct tagMoveChessResult
{
	bool							bCatchChess;						//捉子标志
	bool							bMinatoryKing;						//将军标志
};

//结束信息
struct tagConcludeInfo
{
	bool							bGameConclude;						//结束标志
	BYTE							cbWinnerColor;						//胜利玩家
	BYTE							cbReason;							//结束理由
};

//

//棋谱定义
typedef	CWHArray<tagChessManual,tagChessManual &>	CChessManualArray;

//游戏逻辑类
class CGameLogic
{
	//棋盘变量
public:
	tagChessItem					m_ChessItem[2][COUNT_CHESS];		//棋子信息
	tagChessItem *					m_ChessBorad[COUNT_X][COUNT_Y];		//棋盘信息
	BOOL							m_IsBanker;							//是否庄家

	//状态变量
public:
	WORD							m_wNullStep;						//空走步数
	tagCatchChessInfo				m_CatchChessInfo[2];				//捉子信息
	tagGeneralChessInfo				m_GeneralChessInfo[2];				//将军信息

	//棋谱变量
public:
	CChessManualArray				m_ChessManualArray;					//棋谱信息

	//函数定义
public:
	//构造函数
	CGameLogic();
	//析构函数
	virtual ~CGameLogic();

	//信息函数
public:
	//获取步数
	WORD GetStepCount(BYTE cbColor);
	//获取棋谱
	tagChessManual * GetLastChessManual();
	//获取棋子
	tagChessItem * GetChessItem(BYTE cbXPos, BYTE cbYPos);

	//管理函数
public:
	//重置棋盘
	VOID ResetChessBorad();
	//历史状态
	VOID GetHistoryStatus(tagChessItem ChessItem[2][COUNT_CHESS], tagChessItem * ChessBorad[COUNT_X][COUNT_Y], WORD wStepCount);

	//控制函数
public:
	//悔棋控制
	bool RegretChess(WORD wTargetStep);
	//移动棋子
	bool MoveChess(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos, tagMoveChessResult & MoveChessResult, LPTSTR pszManualName);

	//逻辑函数
public:
	//结束判断
	bool IsGameFinish(BYTE cbMoveColor, tagConcludeInfo & ConcludeInfo);
	//效验步法
	bool IsWalkLegality(const tagChessItem * pSourceChessItem, BYTE cbXTargetPos, BYTE cbYTargetPos);
	//判断将军
	bool IsKillGeneral(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos);
	//判断死棋
	bool IsLoseChess(BYTE cbColor);

	//内部函数
private:
	//获取索引
	inline BYTE GetColorIndex(BYTE cbChessColor);
	//获取偏移
	inline BYTE GetExcursion(BYTE cbSourcePos, BYTE cbTargetPos);

	//内部控制
private:
	//复位棋盘
	bool InitChessBorad(tagChessItem ChessItem[2][COUNT_CHESS], tagChessItem * ChessBorad[COUNT_X][COUNT_Y]);
	//棋谱名字
	bool GetManualItemName(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos, LPTSTR pszManualName);
	//执行走棋
	bool PerformMoveChess(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos, tagMoveChessResult & MoveChessResult);

	//辅助函数
private:
	//威胁棋子
	tagChessItem * GetMinatoryChess(BYTE cbXTargetPos, BYTE cbYTargetPos);
	//有根判断
	tagChessItem * GetProtectedChess(BYTE cbXTargetPos, BYTE cbYTargetPos);
	//阻塞分析
	bool ObstructAnalyse(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos);
public:
	//机器人考虑下一步棋怎么走
	bool AIThinkHowToGo(BYTE &cbXSourcePos, BYTE &cbYSourcePos, BYTE &cbXTargetPos, BYTE &cbYTargetPos);
	//主程序和机器人之间的协议转换
	void TransmitChessBorad();
};

//

#endif

#include "StdAfx.h"
#include "GameLogic.h"

//
//构造函数
CGameLogic::CGameLogic()
{
	//棋盘变量
	ZeroMemory(m_ChessItem,sizeof(m_ChessItem));
	ZeroMemory(m_ChessBorad,sizeof(m_ChessBorad));

	//状态变量
	m_wNullStep=0;
	ZeroMemory(m_CatchChessInfo,sizeof(m_CatchChessInfo));
	ZeroMemory(m_GeneralChessInfo,sizeof(m_GeneralChessInfo));

	m_IsBanker=FALSE;
	return;
}

//析构函数
CGameLogic::~CGameLogic()
{
}

//获取步数
WORD CGameLogic::GetStepCount(BYTE cbColor)
{
	//效验参数
	ASSERT((cbColor==CHESS_BLACK)||(cbColor==CHESS_WHITE));
	if ((cbColor!=CHESS_BLACK)&&(cbColor!=CHESS_WHITE)) return 0;

	//获取步数
	WORD wStepCount=(WORD)m_ChessManualArray.GetCount();
	return (cbColor==CHESS_BLACK)?(wStepCount+1)/2:wStepCount/2;
}

//获取棋谱
tagChessManual * CGameLogic::GetLastChessManual()
{
	INT_PTR nManualCount=m_ChessManualArray.GetCount();
	return (nManualCount>0)?&m_ChessManualArray[nManualCount-1]:NULL;
}

//获取棋子
tagChessItem * CGameLogic::GetChessItem(BYTE cbXPos, BYTE cbYPos)
{
	//效验参数
	ASSERT((cbXPos<COUNT_X)&&(cbYPos<COUNT_Y));
	if ((cbXPos>=COUNT_X)||(cbYPos>=COUNT_Y)) return NULL;

	//获取棋子
	return m_ChessBorad[cbXPos][cbYPos];
}

//重置棋盘
VOID CGameLogic::ResetChessBorad()
{
	//清理棋谱
	m_ChessManualArray.RemoveAll();

	//棋盘变量
	ZeroMemory(m_ChessItem,sizeof(m_ChessItem));
	ZeroMemory(m_ChessBorad,sizeof(m_ChessBorad));

	//状态变量
	m_wNullStep=0;
	ZeroMemory(m_CatchChessInfo,sizeof(m_CatchChessInfo));
	ZeroMemory(m_GeneralChessInfo,sizeof(m_GeneralChessInfo));

	//设置棋盘
	InitChessBorad(m_ChessItem,m_ChessBorad);

	return;
}

//悔棋控制
bool CGameLogic::RegretChess(WORD wTargetStep)
{
	//效验参数
	ASSERT(wTargetStep<=(WORD)m_ChessManualArray.GetCount());
	if (wTargetStep>m_ChessManualArray.GetCount()) return false;

	//棋盘变量
	ZeroMemory(m_ChessItem,sizeof(m_ChessItem));
	ZeroMemory(m_ChessBorad,sizeof(m_ChessBorad));

	//状态变量
	m_wNullStep=0;
	ZeroMemory(m_CatchChessInfo,sizeof(m_CatchChessInfo));
	ZeroMemory(m_GeneralChessInfo,sizeof(m_GeneralChessInfo));

	//设置棋盘
	InitChessBorad(m_ChessItem,m_ChessBorad);

	//设置棋子
	for (INT_PTR i=0;i<wTargetStep;i++)
	{
		//变量定义
		tagChessManual * pChessManual=&m_ChessManualArray[i];
		BYTE cbXSourcePos=pChessManual->cbXSourceChessPos,cbYSourcePos=pChessManual->cbYSourceChessPos;
		BYTE cbXTargetPos=pChessManual->cbXTargetChessPos,cbYTargetPos=pChessManual->cbYTargetChessPos;

		//构造变量
		tagMoveChessResult MoveChessResult;
		ZeroMemory(&MoveChessResult,sizeof(MoveChessResult));

		//移动棋子
		if (PerformMoveChess(cbXSourcePos,cbYSourcePos,cbXTargetPos,cbYTargetPos,MoveChessResult)==false)
		{
			ASSERT(FALSE);
			return false;
		}
	}

	//删除棋谱
	m_ChessManualArray.SetSize(wTargetStep);

	return true;
}

//移动棋子
bool CGameLogic::MoveChess(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos, tagMoveChessResult & MoveChessResult, LPTSTR pszManualName)
{
	//效验坐标
	ASSERT((cbXSourcePos<COUNT_X)&&(cbYSourcePos<COUNT_Y));
	ASSERT((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y));

	//效验坐标
	if (!((cbXSourcePos<COUNT_X)&&(cbYSourcePos<COUNT_Y))) return false;//?
	if (!((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y))) return false;

	//移动棋子
	try
	{
		if (PerformMoveChess(cbXSourcePos,cbYSourcePos,cbXTargetPos,cbYTargetPos,MoveChessResult)==false)
		{
			ASSERT(FALSE);
			return false;
		}
	}
	catch(...)
	{
		//TraceMessage(TEXT("56489_获取移动棋子棋谱"));
		return false;
	}

	//变量定义
	tagChessManual ChessManual;
	ZeroMemory(&ChessManual,sizeof(ChessManual));

	//构造变量
	ChessManual.cbXSourceChessPos=cbXSourcePos;
	ChessManual.cbYSourceChessPos=cbYSourcePos;
	ChessManual.cbXTargetChessPos=cbXTargetPos;
	ChessManual.cbYTargetChessPos=cbYTargetPos;

	try
	{
		//插入棋谱
		m_ChessManualArray.Add(ChessManual);
	}
	catch(...)
	{
		//TraceMessage(TEXT("56489_插入棋谱"));
		return false;
	}

	return true;
}

//获取视图
VOID CGameLogic::GetHistoryStatus(tagChessItem ChessItem[2][COUNT_CHESS], tagChessItem * ChessBorad[COUNT_X][COUNT_Y], WORD wStepCount)
{
	//设置棋盘
	InitChessBorad(ChessItem,ChessBorad);

	//设置结果
	for (WORD i=0;i<wStepCount;i++)
	{
		//效验参数
		ASSERT(i<m_ChessManualArray.GetCount());
		if (i>=m_ChessManualArray.GetCount()) break;

		//获取棋谱
		tagChessManual * pChessManual=&m_ChessManualArray[i];

		//位置定义
		BYTE cbXSourcePos=pChessManual->cbXSourceChessPos;
		BYTE cbYSourcePos=pChessManual->cbYSourceChessPos;
		BYTE cbXTargetPos=pChessManual->cbXTargetChessPos;
		BYTE cbYTargetPos=pChessManual->cbYTargetChessPos;

		//获取棋子
		tagChessItem * pSourceChessItem=ChessBorad[cbXSourcePos][cbYSourcePos];
		tagChessItem * pTargetChessItem=ChessBorad[cbXTargetPos][cbYTargetPos];

		//吃子判断
		if (pTargetChessItem!=NULL)
		{
			pTargetChessItem->cbXPos=0xFF;
			pTargetChessItem->cbYPos=0xFF;
		}

		//移动棋子
		pSourceChessItem->cbXPos=cbXTargetPos;
		pSourceChessItem->cbYPos=cbYTargetPos;
		ChessBorad[cbXSourcePos][cbYSourcePos]=NULL;
		ChessBorad[cbXTargetPos][cbYTargetPos]=pSourceChessItem;
	}

	return;
}

//结束判断
bool CGameLogic::IsGameFinish(BYTE cbMoveColor, tagConcludeInfo & ConcludeInfo)
{
	//索引变量
	BYTE cbEnemyIndex=(cbMoveColor==CHESS_BLACK)?1:0;
	BYTE cbMySelfIndex=(cbMoveColor==CHESS_BLACK)?0:1;

	//捉子信息
	tagCatchChessInfo * pEnemyCatchInfo=&m_CatchChessInfo[cbEnemyIndex];
	tagCatchChessInfo * pMySelfCatchInfo=&m_CatchChessInfo[cbMySelfIndex];

	//将军信息
	tagGeneralChessInfo * pGeneralChessInfo=&m_GeneralChessInfo[cbMySelfIndex];

	长将判断
	//if (pGeneralChessInfo->cbSourceCount>=6)
	//{
	//	//变量定义
	//	BYTE cbGeneralCount=0;
	//	tagChessItem * pSourceChessItem[3];

	//	//棋数计算
	//	for (BYTE i=0;i<pGeneralChessInfo->cbSourceCount;i++)
	//	{
	//		//棋子判断
	//		for (BYTE j=0;j<cbGeneralCount;j++)
	//		{
	//			if (pGeneralChessInfo->pSourceChessItem[i]==pSourceChessItem[j]) break;
	//		}

	//		//设置结果
	//		if (j==cbGeneralCount)
	//		{
	//			//设置结果
	//			pSourceChessItem[cbGeneralCount++]=pGeneralChessInfo->pSourceChessItem[i];

	//			//完成判断
	//			if (cbGeneralCount>=CountArray(pSourceChessItem)) break;
	//		}
	//	}

	//	//长将判断
	//	if (pGeneralChessInfo->cbSourceCount>=cbGeneralCount*6) 
	//	{
	//		//设置变量
	//		ConcludeInfo.cbReason = REASON_CATCH_GENERA;
	//		ConcludeInfo.bGameConclude=true;
	//		ConcludeInfo.cbWinnerColor=(cbMoveColor==CHESS_BLACK)?CHESS_WHITE:CHESS_BLACK;

	//		return true;
	//	}
	//}

	长捉判断
	//if (pMySelfCatchInfo->cbSourceCount>=6)
	//{
	//	//变量定义
	//	BYTE cbCatchCount=0;
	//	tagChessItem * pSourceChessItem[3];

	//	//棋数计算
	//	for (BYTE i=0;i<pMySelfCatchInfo->cbSourceCount;i++)
	//	{
	//		//棋子判断
	//		for (BYTE j=0;j<cbCatchCount;j++)
	//		{
	//			if (pMySelfCatchInfo->pSourceChessItem[i]==pSourceChessItem[j]) break;
	//		}

	//		//设置结果
	//		if (j==cbCatchCount)
	//		{
	//			//设置结果
	//			pSourceChessItem[cbCatchCount++]=pMySelfCatchInfo->pSourceChessItem[i];

	//			//完成判断
	//			if (cbCatchCount>=CountArray(pSourceChessItem)) break;
	//		}
	//	}

	//	//长捉判断
	//	if (pMySelfCatchInfo->cbSourceCount>=cbCatchCount*6) 
	//	{
	//		//设置变量
	//		ConcludeInfo.cbReason = REASON_CATCH_CHESS;
	//		ConcludeInfo.bGameConclude=true;
	//		ConcludeInfo.cbWinnerColor=(cbMoveColor==CHESS_BLACK)?CHESS_WHITE:CHESS_BLACK;

	//		return true;
	//	}
	//}

	try
	{
		//获取将棋
		tagChessItem * pKindChessItem=&m_ChessItem[cbMySelfIndex][4];
		ASSERT((pKindChessItem->cbXPos!=0xFF)&&(pKindChessItem->cbYPos!=0xFF));

		//将死判断
		if (GetMinatoryChess(pKindChessItem->cbXPos,pKindChessItem->cbYPos)!=NULL)
		{
			//设置变量
			ConcludeInfo.bGameConclude=true;
			ConcludeInfo.cbWinnerColor=(cbMoveColor==CHESS_BLACK)?CHESS_WHITE:CHESS_BLACK;

			return true;
		}
	}
	catch(...)
	{
		//TraceMessage(TEXT("56489_(获取将棋,//TraceMessage)"));
		return false;
	}

	空步判和
	//if ((m_wNullStep>=120)||(m_ChessManualArray.GetCount()>=400))
	//{
	//	//设置变量
	//	if(m_wNullStep>=120)ConcludeInfo.cbReason = REASON_LEISURE_STEP;
	//	else ConcludeInfo.cbReason = REASON_OVER_STEP;
	//	ConcludeInfo.bGameConclude = true;
	//	ConcludeInfo.cbWinnerColor = CHESS_NULL;

	//	return true;
	//}

	try
	{
		//困毙判断
		if(IsLoseChess((cbMoveColor==CHESS_BLACK)?CHESS_WHITE:CHESS_BLACK))
		{
			//获取将棋
			tagChessItem * pKindChessItem=&m_ChessItem[cbEnemyIndex][4];
			ASSERT((pKindChessItem->cbXPos!=0xFF)&&(pKindChessItem->cbYPos!=0xFF));

			//困毙判断
			if (GetMinatoryChess(pKindChessItem->cbXPos,pKindChessItem->cbYPos)==NULL)
			{
				ConcludeInfo.cbReason = REASON_CHESS_FEAZE;
			}
			else ConcludeInfo.cbReason = REASON_KILL_GENERA;

			//设置变量
			ConcludeInfo.bGameConclude=true;
			ConcludeInfo.cbWinnerColor=cbMoveColor;

			return true;
		}
	}
	catch(...)
	{
		//TraceMessage(TEXT("56489_(获取将棋,困毙判断)"));
		return false;
	}


	//设置结果
	ZeroMemory(&ConcludeInfo,sizeof(ConcludeInfo));

	return false;
}

//效验步法
bool CGameLogic::IsWalkLegality(const tagChessItem * pSourceChessItem, BYTE cbXTargetPos, BYTE cbYTargetPos)
{
	//效验坐标
	ASSERT(pSourceChessItem!=NULL);
	if(pSourceChessItem==NULL)return false;
	ASSERT((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y));
	if(!((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y)))return false;
	ASSERT((pSourceChessItem->cbXPos<COUNT_X)&&(pSourceChessItem->cbYPos<COUNT_Y));
	if(!((pSourceChessItem->cbXPos<COUNT_X)&&(pSourceChessItem->cbYPos<COUNT_Y)))return false;

	//获取棋子
	BYTE cbXSourcePos=pSourceChessItem->cbXPos;
	BYTE cbYSourcePos=pSourceChessItem->cbYPos;
	tagChessItem * pTargetChessItem=m_ChessBorad[cbXTargetPos][cbYTargetPos];

	//同子判断
	if ((pSourceChessItem->cbXPos==cbXTargetPos)&&(pSourceChessItem->cbYPos==cbYTargetPos)) return false;

	//走棋判断
	switch (pSourceChessItem->cbChess)
	{
	case CHESS_GENERAL:	//将
		{
			try
			{
				//偏移变量
				BYTE cbXExcursion=GetExcursion(cbXSourcePos,cbXTargetPos);
				BYTE cbYExcursion=GetExcursion(cbYSourcePos,cbYTargetPos);

				//飞将判断
				if ((pTargetChessItem!=NULL)&&(pTargetChessItem->cbChess==CHESS_GENERAL))
				{
					if (cbXSourcePos!=cbXTargetPos) return false;
					if (ObstructAnalyse(cbXSourcePos,cbYSourcePos,cbXTargetPos,cbYTargetPos)==true) return false;
					return true;
				}

				//步法判断
				if ((cbXTargetPos<3)||(cbXTargetPos>5)) return false;
				if ((cbXExcursion>1)||(cbYExcursion>1)) return false;
				if ((cbXExcursion==1)&&(cbYExcursion==1)) return false;
				if ((pSourceChessItem->cbColor==CHESS_BLACK)&&(cbYTargetPos<7)) return false;
				if ((pSourceChessItem->cbColor==CHESS_WHITE)&&(cbYTargetPos>2)) return false;

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_CHESS_GENERAL"));
				return false;
			}

			return true;
		}
	case CHESS_KAVASS:	//士
		{
			try
			{
				//偏移变量
				BYTE cbXExcursion=GetExcursion(cbXSourcePos,cbXTargetPos);
				BYTE cbYExcursion=GetExcursion(cbYSourcePos,cbYTargetPos);

				//步法判断
				if ((cbXExcursion!=1)||(cbYExcursion!=1)) return false;
				if ((cbXTargetPos<3)||(cbXTargetPos>5)) return false;
				if ((pSourceChessItem->cbColor==CHESS_BLACK)&&(cbYTargetPos<7)) return false;
				if ((pSourceChessItem->cbColor==CHESS_WHITE)&&(cbYTargetPos>2)) return false;

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ CHESS_KAVASS"));
				return false;
			}

			return true;
		}
	case CHESS_ELEPHANT://象
		{
			try
			{
				//偏移变量
				BYTE cbXExcursion=GetExcursion(cbXSourcePos,cbXTargetPos);
				BYTE cbYExcursion=GetExcursion(cbYSourcePos,cbYTargetPos);

				//步法判断
				if ((cbXExcursion!=2)||(cbYExcursion!=2)) return false;
				if ((pSourceChessItem->cbColor==CHESS_BLACK)&&(cbYTargetPos<5)) return false;
				if ((pSourceChessItem->cbColor==CHESS_WHITE)&&(cbYTargetPos>4)) return false;
				if (m_ChessBorad[(cbXSourcePos+cbXTargetPos)/2][(cbYSourcePos+cbYTargetPos)/2]!=NULL) return false;

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ CHESS_ELEPHANT"));
				return false;
			}
			return true;
		}
	case CHESS_HORSE:	//马
		{
			try
			{
				//偏移变量
				BYTE cbXExcursion=GetExcursion(cbXSourcePos,cbXTargetPos);
				BYTE cbYExcursion=GetExcursion(cbYSourcePos,cbYTargetPos);

				//步法判断
				if (((cbXExcursion!=1)||(cbYExcursion!=2))&&((cbXExcursion!=2)||(cbYExcursion!=1))) return false;

				//撇脚判断
				BYTE cbXVerdict=(cbXExcursion==1)?cbXSourcePos:(cbXSourcePos+cbXTargetPos)/2;
				BYTE cbYVerdict=(cbYExcursion==1)?cbYSourcePos:(cbYSourcePos+cbYTargetPos)/2;
				if (m_ChessBorad[cbXVerdict][cbYVerdict]!=NULL) return false;

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ CHESS_HORSE"));
				return false;
			}
			return true;
		}
	case CHESS_ROOK:	//车
		{
			try
			{
				//步法判断
				if ((cbXSourcePos!=cbXTargetPos)&&(cbYSourcePos!=cbYTargetPos)) return false;

				//阻塞分析
				if (ObstructAnalyse(cbXSourcePos,cbYSourcePos,cbXTargetPos,cbYTargetPos)==true) return false;

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ CHESS_ROOK"));
				return false;
			}
			return true;
		}
	case CHESS_CANNON:	//炮
		{
			try
			{
				//步法判断
				if ((cbXSourcePos!=cbXTargetPos)&&(cbYSourcePos!=cbYTargetPos)) return false;

				//吃子判断
				if (pTargetChessItem!=NULL)
				{
					//变量定义
					INT nXStep=0,nYStep=0;
					if (cbXTargetPos!=cbXSourcePos) nXStep=(cbXTargetPos>cbXSourcePos)?1:-1;
					if (cbYTargetPos!=cbYSourcePos) nYStep=(cbYTargetPos>cbYSourcePos)?1:-1;

					//炮台分析
					bool bEmplacement=false;
					do
					{
						cbXSourcePos+=nXStep;
						cbYSourcePos+=nYStep;
						if ((cbXSourcePos==cbXTargetPos)&&(cbYSourcePos==cbYTargetPos))	return bEmplacement;
						if (m_ChessBorad[cbXSourcePos][cbYSourcePos]!=NULL)
						{
							if (bEmplacement==false) bEmplacement=true;
							else return false;
						}
					} while (true);

					return false;
				}

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ CHESS_CANNON"));
				return false;
			}

			try
			{
				//阻塞分析
				if (ObstructAnalyse(cbXSourcePos,cbYSourcePos,cbXTargetPos,cbYTargetPos)==true) return false;

			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ 阻塞分析"));
				return false;
			}
			return true;
		}
	case CHESS_SOLDIER:	//兵
		{
			try
			{
				//偏移变量
				BYTE cbXExcursion=GetExcursion(cbXSourcePos,cbXTargetPos);
				BYTE cbYExcursion=GetExcursion(cbYSourcePos,cbYTargetPos);

				//步法判断
				if (pSourceChessItem->cbColor==CHESS_BLACK)
				{
					if (cbYSourcePos>=5)
					{
						if (cbXSourcePos!=cbXTargetPos) return false;
						if ((cbYSourcePos-1)!=cbYTargetPos) return false;
					}
					else
					{
						if (cbYTargetPos>cbYSourcePos) return false;
						if ((cbXExcursion>1)||(cbYExcursion>1)) return false;
						if ((cbXExcursion!=0)&&(cbYExcursion!=0)) return false;
					}
				}
				else
				{
					if (cbYSourcePos<=4)
					{
						if (cbXSourcePos!=cbXTargetPos) return false;
						if ((cbYSourcePos+1)!=cbYTargetPos) return false;
					}
					else
					{
						if (cbYTargetPos<cbYSourcePos) return false;
						if ((cbXExcursion>1)||(cbYExcursion>1)) return false;
						if ((cbXExcursion!=0)&&(cbYExcursion!=0)) return false;
					}
				}
			}
			catch(...)
			{
				//TraceMessage(TEXT("56489_ CHESS_SOLDIER"));
				return false;
			}

			return true;
		}
	}

	ASSERT(FALSE);

	return false;
}

//获取索引
BYTE CGameLogic::GetColorIndex(BYTE cbChessColor)
{
	return (cbChessColor==CHESS_BLACK)?0:1;
}

//获取偏移
BYTE CGameLogic::GetExcursion(BYTE cbSourcePos, BYTE cbTargetPos)
{
	return (cbSourcePos>cbTargetPos)?(cbSourcePos-cbTargetPos):(cbTargetPos-cbSourcePos);
}

//执行走棋
bool CGameLogic::PerformMoveChess(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos, tagMoveChessResult & MoveChessResult)
{
	//效验坐标
	ASSERT((cbXSourcePos<COUNT_X)&&(cbYSourcePos<COUNT_Y));
	ASSERT((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y));

	//获取棋子
	tagChessItem * pSourceChessItem=m_ChessBorad[cbXSourcePos][cbYSourcePos];
	tagChessItem * pTargetChessItem=m_ChessBorad[cbXTargetPos][cbYTargetPos];

	//效验棋子
	ASSERT(pSourceChessItem!=NULL);
	if (pSourceChessItem==NULL) return false;

	//吃子处理
	if (pTargetChessItem!=NULL)
	{
		//设置棋子
		pTargetChessItem->cbXPos=0xFF;
		pTargetChessItem->cbYPos=0xFF;
	}

	//设置棋子
	pSourceChessItem->cbXPos=cbXTargetPos;
	pSourceChessItem->cbYPos=cbYTargetPos;
	//设置棋盘
	m_ChessBorad[cbXSourcePos][cbYSourcePos]=NULL;
	m_ChessBorad[cbXTargetPos][cbYTargetPos]=pSourceChessItem;

	return true;
}

//判断将军
bool CGameLogic::IsKillGeneral(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos)
{
	//效验坐标
	ASSERT((cbXSourcePos<COUNT_X)&&(cbYSourcePos<COUNT_Y));
	ASSERT((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y));

	//获取棋子
	tagChessItem * pSourceChessItem = m_ChessBorad[cbXSourcePos][cbYSourcePos];
	tagChessItem * pTargetChessItem = m_ChessBorad[cbXTargetPos][cbYTargetPos];

	//索引变量
	BYTE cbColor = pSourceChessItem->cbColor;
	BYTE cbMySelfIndex=(cbColor==CHESS_BLACK)?0:1;
	//BYTE cbEnemyIndex=(cbColor==CHESS_BLACK)?1:0;

	//吃子处理
	if (pTargetChessItem!=NULL)
	{
		//设置棋子
		pTargetChessItem->cbXPos=0xFF;
		pTargetChessItem->cbYPos=0xFF;
	}

	//设置棋子
	//tagChessItem * pSouTempChessItem = m_ChessBorad[cbXSourcePos][cbYSourcePos];
	pSourceChessItem->cbXPos=cbXTargetPos;
	pSourceChessItem->cbYPos=cbYTargetPos;
	m_ChessBorad[cbXSourcePos][cbYSourcePos]=NULL;
	m_ChessBorad[cbXTargetPos][cbYTargetPos]=pSourceChessItem;

	//我方王棋
	tagChessItem * pKindChessItem=&m_ChessItem[cbMySelfIndex][4];
	ASSERT((pKindChessItem->cbXPos!=0xFF)&&(pKindChessItem->cbYPos!=0xFF));
	ASSERT(pKindChessItem->cbChess==CHESS_GENERAL);

	//判断将军
	bool bKillGeneral = false;
	if (GetMinatoryChess(pKindChessItem->cbXPos,pKindChessItem->cbYPos)!=NULL)
	{
		bKillGeneral =  true;
	}

	//还原数据
	if (pTargetChessItem!=NULL)
	{
		pTargetChessItem->cbXPos = cbXTargetPos;
		pTargetChessItem->cbYPos = cbYTargetPos;
		m_ChessBorad[cbXTargetPos][cbYTargetPos] = pTargetChessItem;
	}
	else m_ChessBorad[cbXTargetPos][cbYTargetPos] = NULL;
	pSourceChessItem->cbXPos=cbXSourcePos;
	pSourceChessItem->cbYPos=cbYSourcePos;
	m_ChessBorad[cbXSourcePos][cbYSourcePos]=pSourceChessItem;

	return bKillGeneral;
}

//判断死棋
bool CGameLogic::IsLoseChess(BYTE cbColor)
{
	//索引变量
	BYTE cbEnemyIndex=(cbColor==CHESS_BLACK)?1:0;
	BYTE cbMySelfIndex=(cbColor==CHESS_BLACK)?0:1;

	//我方王棋
	tagChessItem * pKindChessItem=&m_ChessItem[cbMySelfIndex][4];
	ASSERT((pKindChessItem->cbXPos!=0xFF)&&(pKindChessItem->cbYPos!=0xFF));
	ASSERT(pKindChessItem->cbChess==CHESS_GENERAL);

	//解救搜索
	for (BYTE i=0;i<CountArray(m_ChessItem[cbMySelfIndex]);i++)
	{
		//获取棋子
		tagChessItem * pMySelfChessItem=&m_ChessItem[cbMySelfIndex][i];
		if ((pMySelfChessItem->cbXPos==0xFF)||(pMySelfChessItem->cbYPos==0xFF)) continue;

		//搜索走棋
		for(BYTE x=0;x<COUNT_X;x++)
		{
			for(BYTE y=0;y<COUNT_Y;y++)
			{
				//过滤同棋
				tagChessItem * pChessItem=m_ChessBorad[x][y];
				if ((pChessItem!=NULL)&&(pChessItem->cbColor==cbColor))continue;

				//判断走棋
				if (IsWalkLegality(pMySelfChessItem,x,y))
				{
					//获取棋子
					tagChessItem * pSourceChessItem=pMySelfChessItem;
					tagChessItem * pTargetChessItem=m_ChessBorad[x][y];

					//吃子处理
					if (pTargetChessItem!=NULL)
					{
						//设置棋子
						pTargetChessItem->cbXPos=0xFF;
						pTargetChessItem->cbYPos=0xFF;
					}

					//设置棋子
					BYTE cbXSourcePos = pSourceChessItem->cbXPos;
					BYTE cbYSourcePos = pSourceChessItem->cbYPos;
					//tagChessItem * pTempChessItem = m_ChessBorad[cbXSourcePos][cbYSourcePos];
					pSourceChessItem->cbXPos=x;
					pSourceChessItem->cbYPos=y;
					m_ChessBorad[cbXSourcePos][cbYSourcePos]=NULL;
					m_ChessBorad[x][y]=pSourceChessItem;

					//解救判断
					ASSERT(pKindChessItem->cbChess==CHESS_GENERAL);
					if (GetMinatoryChess(pKindChessItem->cbXPos,pKindChessItem->cbYPos)==NULL)
					{
						//还原数据
						if (pTargetChessItem!=NULL)
						{
							pTargetChessItem->cbXPos = x;
							pTargetChessItem->cbYPos = y;
							m_ChessBorad[x][y] = pTargetChessItem;
						}
						else m_ChessBorad[x][y] = NULL;
						pSourceChessItem->cbXPos=cbXSourcePos;
						pSourceChessItem->cbYPos=cbYSourcePos;
						m_ChessBorad[cbXSourcePos][cbYSourcePos]=pSourceChessItem;

						return false;
					}

					//还原数据
					if (pTargetChessItem!=NULL)
					{
						pTargetChessItem->cbXPos = x;
						pTargetChessItem->cbYPos = y;
						m_ChessBorad[x][y] = pTargetChessItem;
					}
					else m_ChessBorad[x][y] = NULL;
					pSourceChessItem->cbXPos=cbXSourcePos;
					pSourceChessItem->cbYPos=cbYSourcePos;
					m_ChessBorad[cbXSourcePos][cbYSourcePos]=pSourceChessItem;
				}
			}
		}
	}

	return true;
}

//复位棋盘
bool CGameLogic::InitChessBorad(tagChessItem ChessItem[2][COUNT_CHESS], tagChessItem * ChessBorad[COUNT_X][COUNT_Y])
{
	//变量定义
	BYTE cbChessInfo[9]={CHESS_ROOK,CHESS_HORSE,CHESS_ELEPHANT,CHESS_KAVASS,CHESS_GENERAL,
		CHESS_KAVASS,CHESS_ELEPHANT,CHESS_HORSE,CHESS_ROOK};

	//设置数据
	for (BYTE cbUserIndex=0;cbUserIndex<2;cbUserIndex++)
	{
		//主线棋子
		BYTE cbExcursion=0;
		BYTE cbYPos=(cbUserIndex==0)?9:0;
		for (BYTE nIndex=0;nIndex<9;nIndex++,cbExcursion++)
		{
			ChessItem[cbUserIndex][cbExcursion].cbYPos=cbYPos;
			ChessItem[cbUserIndex][cbExcursion].cbXPos=nIndex;
			ChessItem[cbUserIndex][cbExcursion].cbChessID=nIndex;
			ChessItem[cbUserIndex][cbExcursion].cbChess=cbChessInfo[nIndex];
			ChessItem[cbUserIndex][cbExcursion].cbColor=CHESS_BLACK+cbUserIndex;
			ChessBorad[nIndex][cbYPos]=&ChessItem[cbUserIndex][cbExcursion];
		}

		//兵的棋子
		cbYPos=(cbUserIndex==0)?6:3;
		for (BYTE nIndex=0;nIndex<5;nIndex++,cbExcursion++)
		{
			ChessItem[cbUserIndex][cbExcursion].cbYPos=cbYPos;
			ChessItem[cbUserIndex][cbExcursion].cbXPos=nIndex*2;
			ChessItem[cbUserIndex][cbExcursion].cbChess=CHESS_SOLDIER;
			ChessItem[cbUserIndex][cbExcursion].cbChessID=cbExcursion;
			ChessItem[cbUserIndex][cbExcursion].cbColor=CHESS_BLACK+cbUserIndex;
			ChessBorad[nIndex*2][cbYPos]=&ChessItem[cbUserIndex][cbExcursion];
		}

		//炮的棋子
		cbYPos=(cbUserIndex==0)?7:2;
		for (BYTE nIndex=0;nIndex<2;nIndex++,cbExcursion++)
		{
			ChessItem[cbUserIndex][cbExcursion].cbYPos=cbYPos;
			ChessItem[cbUserIndex][cbExcursion].cbXPos=1+nIndex*6;
			ChessItem[cbUserIndex][cbExcursion].cbChess=CHESS_CANNON;
			ChessItem[cbUserIndex][cbExcursion].cbChessID=cbExcursion;
			ChessItem[cbUserIndex][cbExcursion].cbColor=CHESS_BLACK+cbUserIndex;
			ChessBorad[1+nIndex*6][cbYPos]=&ChessItem[cbUserIndex][cbExcursion];
		}
	}

	return true;
}

//棋谱名字
bool CGameLogic::GetManualItemName(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos, LPTSTR pszManualName)
{
	//棋子命名
	LPCTSTR pszChessName[2][7]=
	{
		TEXT("帅"),TEXT("仕"),TEXT("相"),TEXT("马"),TEXT("車"),TEXT("炮"),TEXT("兵"),
		TEXT("将"),TEXT("士"),TEXT("象"),TEXT("马"),TEXT("車"),TEXT("炮"),TEXT("卒"),
	};

	//线条命名
	LPCTSTR pszXLineName[2][COUNT_X]=
	{
		TEXT("九"),TEXT("八"),TEXT("七"),TEXT("六"),TEXT("五"),TEXT("四"),TEXT("三"),TEXT("二"),TEXT("一"),
		TEXT("1"),TEXT("2"),TEXT("3"),TEXT("4"),TEXT("5"),TEXT("6"),TEXT("7"),TEXT("8"),TEXT("9"),
	};

	//线条命名
	LPCTSTR pszYLineName[2][COUNT_Y]=
	{
		TEXT("一"),TEXT("二"),TEXT("三"),TEXT("四"),TEXT("五"),TEXT("六"),TEXT("七"),TEXT("八"),TEXT("九"),TEXT("十"),
		TEXT("1"),TEXT("2"),TEXT("3"),TEXT("4"),TEXT("5"),TEXT("6"),TEXT("7"),TEXT("8"),TEXT("9"),TEXT("10"),
	};

	//变量定义
	bool bLocateDown=true;
	bool bExistSameChess=false;

	//棋子属性
	ASSERT(m_ChessBorad[cbXSourcePos][cbYSourcePos]!=NULL);
	BYTE cbSourceColor=m_ChessBorad[cbXSourcePos][cbYSourcePos]->cbColor;
	BYTE cbSourceChess=m_ChessBorad[cbXSourcePos][cbYSourcePos]->cbChess;

	//存在判断
	for (BYTE nYPos=0;nYPos<COUNT_Y;nYPos++)
	{
		if ((cbYSourcePos!=nYPos)&&(m_ChessBorad[cbXSourcePos][nYPos]!=NULL))
		{
			//获取属性
			BYTE cbTargetColor=m_ChessBorad[cbXSourcePos][nYPos]->cbColor;
			BYTE cbTargetChess=m_ChessBorad[cbXSourcePos][nYPos]->cbChess;

			//相同判断
			if ((cbTargetColor==cbSourceColor)&&(cbTargetChess==cbSourceChess))
			{
				bExistSameChess=true;
				bLocateDown=(nYPos<cbYSourcePos)?true:false;
				break;
			}
		}
	}

	//走棋用户
	lstrcpy(pszManualName,(cbSourceColor==CHESS_BLACK)?TEXT("红方:"):TEXT("黑方:"));

	//构造前叠
	if (bExistSameChess==true)
	{
		//前后字符
		if (cbSourceColor==CHESS_BLACK)
		{
			lstrcat(pszManualName,(bLocateDown==true)?TEXT("后"):TEXT("前"));
		}
		else
		{
			lstrcat(pszManualName,(bLocateDown==true)?TEXT("前"):TEXT("后"));
		}

		//棋子名字
		lstrcat(pszManualName,pszChessName[cbSourceColor-1][cbSourceChess-1]);
	}
	else
	{
		//前叠字符
		lstrcat(pszManualName,pszChessName[cbSourceColor-1][cbSourceChess-1]);
		lstrcat(pszManualName,pszXLineName[cbSourceColor-1][cbXSourcePos]);
	}

	//构造后叠
	if (cbYSourcePos==cbYTargetPos)
	{
		//平移字符
		lstrcat(pszManualName,TEXT("平"));
		lstrcat(pszManualName,pszXLineName[cbSourceColor-1][cbXTargetPos]);
	}
	else if (cbYSourcePos<cbYTargetPos)
	{
		//前进字符
		lstrcat(pszManualName,(cbSourceColor==CHESS_BLACK)?TEXT("退"):TEXT("进"));

		//移动数目
		if (cbXSourcePos==cbXTargetPos)
		{
			lstrcat(pszManualName,pszYLineName[cbSourceColor-1][cbYTargetPos-cbYSourcePos-1]);
		}
		else
		{
			lstrcat(pszManualName,pszXLineName[cbSourceColor-1][cbXTargetPos]);
		}
	}
	else
	{
		//后退字符
		lstrcat(pszManualName,(cbSourceColor==CHESS_BLACK)?TEXT("进"):TEXT("退"));

		//移动数目
		if (cbXSourcePos==cbXTargetPos)
		{
			lstrcat(pszManualName,pszYLineName[cbSourceColor-1][cbYSourcePos-cbYTargetPos-1]);
		}
		else
		{
			lstrcat(pszManualName,pszXLineName[cbSourceColor-1][cbXTargetPos]);
		}
	}

	return true;
}

//危险判断
tagChessItem * CGameLogic::GetMinatoryChess(BYTE cbXTargetPos, BYTE cbYTargetPos)
{
	//效验变量
	ASSERT((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y));
	if(!((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y)))return NULL;

	//获取棋子
	ASSERT(m_ChessBorad[cbXTargetPos][cbYTargetPos]!=NULL);
	tagChessItem * pTargetChessItem=m_ChessBorad[cbXTargetPos][cbYTargetPos];

	//变量定义
	BYTE cbEnemyIndex=(pTargetChessItem->cbColor==CHESS_BLACK)?1:0;

	//棋子搜索
	for (BYTE i=0;i<CountArray(m_ChessItem[cbEnemyIndex]);i++)
	{
		//获取棋子
		tagChessItem * pSourceChessItem=&m_ChessItem[cbEnemyIndex][i];
		if ((pSourceChessItem->cbXPos==0xFF)||(pSourceChessItem->cbYPos==0xFF)) continue;

		//威胁判断
		if (IsWalkLegality(pSourceChessItem,cbXTargetPos,cbYTargetPos)==true) return pSourceChessItem;
	}

	return NULL;
}

//有根判断
tagChessItem * CGameLogic::GetProtectedChess(BYTE cbXTargetPos, BYTE cbYTargetPos)
{
	//效验变量
	ASSERT((cbXTargetPos<COUNT_X)&&(cbYTargetPos<COUNT_Y));

	//获取棋子
	ASSERT(m_ChessBorad[cbXTargetPos][cbYTargetPos]!=NULL);
	tagChessItem * pTargetChessItem=m_ChessBorad[cbXTargetPos][cbYTargetPos];

	//变量定义
	BYTE cbMySelfIndex=(pTargetChessItem->cbColor==CHESS_BLACK)?0:1;

	//棋子搜索
	for (BYTE i=0;i<CountArray(m_ChessItem[cbMySelfIndex]);i++)
	{
		//获取棋子
		tagChessItem * pSourceChessItem=&m_ChessItem[cbMySelfIndex][i];
		if ((pSourceChessItem->cbXPos==0xFF)||(pSourceChessItem->cbYPos==0xFF)) continue;
		if ((pSourceChessItem->cbXPos==cbXTargetPos)&&(pSourceChessItem->cbYPos==cbYTargetPos)) continue;

		//威胁判断
		if (IsWalkLegality(pSourceChessItem,cbXTargetPos,cbYTargetPos)==true) return pSourceChessItem;
	}

	return NULL;
}

//阻塞分析
bool CGameLogic::ObstructAnalyse(BYTE cbXSourcePos, BYTE cbYSourcePos, BYTE cbXTargetPos, BYTE cbYTargetPos)
{
	//效验坐标
	ASSERT((cbXSourcePos!=cbXTargetPos)||(cbYSourcePos!=cbYTargetPos));

	//变量定义
	INT nXStep=0,nYStep=0;
	if (cbXTargetPos!=cbXSourcePos) nXStep=(cbXTargetPos>cbXSourcePos)?1:-1;
	if (cbYTargetPos!=cbYSourcePos) nYStep=(cbYTargetPos>cbYSourcePos)?1:-1;

	//阻塞分析
	do
	{
		cbXSourcePos+=nXStep;
		cbYSourcePos+=nYStep;
		if ((cbXSourcePos==cbXTargetPos)&&(cbYSourcePos==cbYTargetPos))	return false;
	} while (m_ChessBorad[cbXSourcePos][cbYSourcePos]==NULL);

	return true;
}
机器人插件--开始//
/**
 * XiangQi Wizard Light - A Very Simple Chinese Chess Program
 * Designed by Morning Yellow, Version: 0.6, Last Modified: Mar. 2008
 * Copyright (C) 2004-2008 www.elephantbase.net
 *
 * 象棋小巫师 0.6 的目标:
 * 一、实现开局库;
 * 二、实现PVS(主要变例搜索);
 * 三、把根节点的搜索单独处理,增加搜索的随机性;
 * 四、克服由长将引起的置换表的不稳定性。
 */

#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "resource.h"

// 版本号
const LPCSTR cszAbout = "象棋小巫师 0.6\n象棋百科全书 荣誉出品\n\n"
    "(C) 2004-2008 www.elephantbase.net\n本产品符合GNU通用公共许可协议\n\n"
    "欢迎登录 www.elephantbase.net\n免费下载PC版 象棋巫师";

// 窗口和绘图属性
const int WINDOW_STYLES = WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX;
const int MASK_COLOR = RGB(0, 255, 0);
const int SQUARE_SIZE = 56;
const int BOARD_EDGE = 8;
const int BOARD_WIDTH = BOARD_EDGE + SQUARE_SIZE * 9 + BOARD_EDGE;
const int BOARD_HEIGHT = BOARD_EDGE + SQUARE_SIZE * 10 + BOARD_EDGE;

// 棋盘范围
const int RANK_TOP = 3;
const int RANK_BOTTOM = 12;
const int FILE_LEFT = 3;
const int FILE_RIGHT = 11;

// 棋子编号
const int PIECE_KING = 0;
const int PIECE_ADVISOR = 1;
const int PIECE_BISHOP = 2;
const int PIECE_KNIGHT = 3;
const int PIECE_ROOK = 4;
const int PIECE_CANNON = 5;
const int PIECE_PAWN = 6;

// 其他常数
const int MAX_GEN_MOVES = 128; // 最大的生成走法数
const int MAX_MOVES = 256;     // 最大的历史走法数
const int LIMIT_DEPTH = 64;    // 最大的搜索深度
const int MATE_VALUE = 10000;  // 最高分值,即将死的分值
const int BAN_VALUE = MATE_VALUE - 100; // 长将判负的分值,低于该值将不写入置换表
const int WIN_VALUE = MATE_VALUE - 200; // 搜索出胜负的分值界限,超出此值就说明已经搜索出杀棋了
const int DRAW_VALUE = 20;     // 和棋时返回的分数(取负值)
const int ADVANCED_VALUE = 3;  // 先行权分值
const int RANDOM_MASK = 7;     // 随机性分值
const int NULL_MARGIN = 400;   // 空步裁剪的子力边界
const int NULL_DEPTH = 2;      // 空步裁剪的裁剪深度
const int HASH_SIZE = 1 << 20; // 置换表大小
const int HASH_ALPHA = 1;      // ALPHA节点的置换表项
const int HASH_BETA = 2;       // BETA节点的置换表项
const int HASH_PV = 3;         // PV节点的置换表项
const int BOOK_SIZE = 16384;   // 开局库大小

// 判断棋子是否在棋盘中的数组
static const char ccInBoard[256] = {
  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, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

// 判断棋子是否在九宫的数组
static const char ccInFort[256] = {
  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, 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, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 1, 1, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 1, 1, 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, 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
};

// 判断步长是否符合特定走法的数组,1=帅(将),2=仕(士),3=相(象)
static const char ccLegalSpan[512] = {
                       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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 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, 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, 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, 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, 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, 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, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0
};

// 根据步长判断马是否蹩腿的数组
static const char ccKnightPin[512] = {
                              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,  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,  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,  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,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,-16,  0,-16,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0, -1,  0,  0,  0,  1,  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, -1,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0, 16,  0, 16,  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,  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,  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,
  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,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0
};

// 帅(将)的步长
static const char ccKingDelta[4] = {-16, -1, 1, 16};
// 仕(士)的步长
static const char ccAdvisorDelta[4] = {-17, -15, 15, 17};
// 马的步长,以帅(将)的步长作为马腿
static const char ccKnightDelta[4][2] = {{-33, -31}, {-18, 14}, {-14, 18}, {31, 33}};
// 马被将军的步长,以仕(士)的步长作为马腿
static const char ccKnightCheckDelta[4][2] = {{-33, -18}, {-31, -14}, {14, 31}, {18, 33}};

// 棋盘初始设置
static const BYTE cucpcStartup[256] = {
  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,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0, 20, 19, 18, 17, 16, 17, 18, 19, 20,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0, 21,  0,  0,  0,  0,  0, 21,  0,  0,  0,  0,  0,
  0,  0,  0, 22,  0, 22,  0, 22,  0, 22,  0, 22,  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,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0, 14,  0, 14,  0, 14,  0, 14,  0, 14,  0,  0,  0,  0,
  0,  0,  0,  0, 13,  0,  0,  0,  0,  0, 13,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0, 12, 11, 10,  9,  8,  9, 10, 11, 12,  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,  0,  0,  0,  0,  0,  0,  0,
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
};

// 子力位置价值表
static const BYTE cucvlPiecePos[7][256] = {
  { // 帅(将)
    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,  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,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  2,  2,  2,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0, 11, 15, 11,  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,  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,  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,
    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,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0, 20,  0, 20,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0, 23,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0, 20,  0, 20,  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,  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,  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,
    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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0, 20,  0,  0,  0, 20,  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, 18,  0,  0,  0, 23,  0,  0,  0, 18,  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, 20,  0,  0,  0, 20,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0, 90, 90, 90, 96, 90, 96, 90, 90, 90,  0,  0,  0,  0,
    0,  0,  0, 90, 96,103, 97, 94, 97,103, 96, 90,  0,  0,  0,  0,
    0,  0,  0, 92, 98, 99,103, 99,103, 99, 98, 92,  0,  0,  0,  0,
    0,  0,  0, 93,108,100,107,100,107,100,108, 93,  0,  0,  0,  0,
    0,  0,  0, 90,100, 99,103,104,103, 99,100, 90,  0,  0,  0,  0,
    0,  0,  0, 90, 98,101,102,103,102,101, 98, 90,  0,  0,  0,  0,
    0,  0,  0, 92, 94, 98, 95, 98, 95, 98, 94, 92,  0,  0,  0,  0,
    0,  0,  0, 93, 92, 94, 95, 92, 95, 94, 92, 93,  0,  0,  0,  0,
    0,  0,  0, 85, 90, 92, 93, 78, 93, 92, 90, 85,  0,  0,  0,  0,
    0,  0,  0, 88, 85, 90, 88, 90, 88, 90, 85, 88,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,206,208,207,213,214,213,207,208,206,  0,  0,  0,  0,
    0,  0,  0,206,212,209,216,233,216,209,212,206,  0,  0,  0,  0,
    0,  0,  0,206,208,207,214,216,214,207,208,206,  0,  0,  0,  0,
    0,  0,  0,206,213,213,216,216,216,213,213,206,  0,  0,  0,  0,
    0,  0,  0,208,211,211,214,215,214,211,211,208,  0,  0,  0,  0,
    0,  0,  0,208,212,212,214,215,214,212,212,208,  0,  0,  0,  0,
    0,  0,  0,204,209,204,212,214,212,204,209,204,  0,  0,  0,  0,
    0,  0,  0,198,208,204,212,212,212,204,208,198,  0,  0,  0,  0,
    0,  0,  0,200,208,206,212,200,212,206,208,200,  0,  0,  0,  0,
    0,  0,  0,194,206,204,212,200,212,204,206,194,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,100,100, 96, 91, 90, 91, 96,100,100,  0,  0,  0,  0,
    0,  0,  0, 98, 98, 96, 92, 89, 92, 96, 98, 98,  0,  0,  0,  0,
    0,  0,  0, 97, 97, 96, 91, 92, 91, 96, 97, 97,  0,  0,  0,  0,
    0,  0,  0, 96, 99, 99, 98,100, 98, 99, 99, 96,  0,  0,  0,  0,
    0,  0,  0, 96, 96, 96, 96,100, 96, 96, 96, 96,  0,  0,  0,  0,
    0,  0,  0, 95, 96, 99, 96,100, 96, 99, 96, 95,  0,  0,  0,  0,
    0,  0,  0, 96, 96, 96, 96, 96, 96, 96, 96, 96,  0,  0,  0,  0,
    0,  0,  0, 97, 96,100, 99,101, 99,100, 96, 97,  0,  0,  0,  0,
    0,  0,  0, 96, 97, 98, 98, 98, 98, 98, 97, 96,  0,  0,  0,  0,
    0,  0,  0, 96, 96, 97, 99, 99, 99, 97, 96, 96,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  9,  9,  9, 11, 13, 11,  9,  9,  9,  0,  0,  0,  0,
    0,  0,  0, 19, 24, 34, 42, 44, 42, 34, 24, 19,  0,  0,  0,  0,
    0,  0,  0, 19, 24, 32, 37, 37, 37, 32, 24, 19,  0,  0,  0,  0,
    0,  0,  0, 19, 23, 27, 29, 30, 29, 27, 23, 19,  0,  0,  0,  0,
    0,  0,  0, 14, 18, 20, 27, 29, 27, 20, 18, 14,  0,  0,  0,  0,
    0,  0,  0,  7,  0, 13,  0, 16,  0, 13,  0,  7,  0,  0,  0,  0,
    0,  0,  0,  7,  0,  7,  0, 15,  0,  7,  0,  7,  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,  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,  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,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
  }
};

// 判断棋子是否在棋盘中
inline BOOL IN_BOARD(int sq) {
  return ccInBoard[sq] != 0;
}

// 判断棋子是否在九宫中
inline BOOL IN_FORT(int sq) {
  return ccInFort[sq] != 0;
}

// 获得格子的横坐标
inline int RANK_Y(int sq) {
  return sq >> 4;
}

// 获得格子的纵坐标
inline int FILE_X(int sq) {
  return sq & 15;
}

// 根据纵坐标和横坐标获得格子
inline int COORD_XY(int x, int y) {
  return x + (y << 4);
}

// 翻转格子
inline int SQUARE_FLIP(int sq) {
  return 254 - sq;
}

// 纵坐标水平镜像
inline int FILE_FLIP(int x) {
  return 14 - x;
}

// 横坐标垂直镜像
inline int RANK_FLIP(int y) {
  return 15 - y;
}

// 格子水平镜像
inline int MIRROR_SQUARE(int sq) {
  return COORD_XY(FILE_FLIP(FILE_X(sq)), RANK_Y(sq));
}

// 格子水平镜像
inline int SQUARE_FORWARD(int sq, int sd) {
  return sq - 16 + (sd << 5);
}

// 走法是否符合帅(将)的步长
inline BOOL KING_SPAN(int sqSrc, int sqDst) {
  return ccLegalSpan[sqDst - sqSrc + 256] == 1;
}

// 走法是否符合仕(士)的步长
inline BOOL ADVISOR_SPAN(int sqSrc, int sqDst) {
  return ccLegalSpan[sqDst - sqSrc + 256] == 2;
}

// 走法是否符合相(象)的步长
inline BOOL BISHOP_SPAN(int sqSrc, int sqDst) {
  return ccLegalSpan[sqDst - sqSrc + 256] == 3;
}

// 相(象)眼的位置
inline int BISHOP_PIN(int sqSrc, int sqDst) {
  return (sqSrc + sqDst) >> 1;
}

// 马腿的位置
inline int KNIGHT_PIN(int sqSrc, int sqDst) {
  return sqSrc + ccKnightPin[sqDst - sqSrc + 256];
}

// 是否未过河
inline BOOL HOME_HALF(int sq, int sd) {
	return (sq & 0x80) != (sd << 7);
}

// 是否已过河
inline BOOL AWAY_HALF(int sq, int sd) {
  return (sq & 0x80) == (sd << 7);
}

// 是否在河的同一边
inline BOOL SAME_HALF(int sqSrc, int sqDst) {
  return ((sqSrc ^ sqDst) & 0x80) == 0;
}

// 是否在同一行
inline BOOL SAME_RANK(int sqSrc, int sqDst) {
  return ((sqSrc ^ sqDst) & 0xf0) == 0;
}

// 是否在同一列
inline BOOL SAME_FILE(int sqSrc, int sqDst) {
  return ((sqSrc ^ sqDst) & 0x0f) == 0;
}

// 获得红黑标记(红子是8,黑子是16)
inline int SIDE_TAG(int sd) {
  return 8 + (sd << 3);
}

// 获得对方红黑标记
inline int OPP_SIDE_TAG(int sd) {
  return 16 - (sd << 3);
}

// 获得走法的起点
inline int SRC(int mv) {
  return mv & 255;
}

// 获得走法的终点
inline int DST(int mv) {
  return mv >> 8;
}

// 根据起点和终点获得走法
inline int MOVE(int sqSrc, int sqDst) {
  return sqSrc + sqDst * 256;
}

// 走法水平镜像
inline int MIRROR_MOVE(int mv) {
  return MOVE(MIRROR_SQUARE(SRC(mv)), MIRROR_SQUARE(DST(mv)));
}

// RC4密码流生成器
struct RC4Struct {
  BYTE s[256];
  int x, y;

  void InitZero(void);   // 用空密钥初始化密码流生成器
  BYTE NextByte(void) {  // 生成密码流的下一个字节
    BYTE uc;
    x = (x + 1) & 255;
    y = (y + s[x]) & 255;
    uc = s[x];
    s[x] = s[y];
    s[y] = uc;
    return s[(s[x] + s[y]) & 255];
  }
  DWORD NextLong(void) { // 生成密码流的下四个字节
    BYTE uc0, uc1, uc2, uc3;
    uc0 = NextByte();
    uc1 = NextByte();
    uc2 = NextByte();
    uc3 = NextByte();
    return uc0 + (uc1 << 8) + (uc2 << 16) + (uc3 << 24);
  }
};

// 用空密钥初始化密码流生成器
void RC4Struct::InitZero(void) {
  int i, j;
  BYTE uc;

  x = y = j = 0;
  for (i = 0; i < 256; i ++) {
    s[i] = i;
  }
  for (i = 0; i < 256; i ++) {
    j = (j + s[i]) & 255;
    uc = s[i];
    s[i] = s[j];
    s[j] = uc;
  }
}

// Zobrist结构
struct ZobristStruct {
  DWORD dwKey, dwLock0, dwLock1;

  void InitZero(void) {                 // 用零填充Zobrist
    dwKey = dwLock0 = dwLock1 = 0;
  }
  void InitRC4(RC4Struct &rc4) {        // 用密码流填充Zobrist
    dwKey = rc4.NextLong();
    dwLock0 = rc4.NextLong();
    dwLock1 = rc4.NextLong();
  }
  void Xor(const ZobristStruct &zobr) { // 执行XOR操作
    dwKey ^= zobr.dwKey;
    dwLock0 ^= zobr.dwLock0;
    dwLock1 ^= zobr.dwLock1;
  }
  void Xor(const ZobristStruct &zobr1, const ZobristStruct &zobr2) {
    dwKey ^= zobr1.dwKey ^ zobr2.dwKey;
    dwLock0 ^= zobr1.dwLock0 ^ zobr2.dwLock0;
    dwLock1 ^= zobr1.dwLock1 ^ zobr2.dwLock1;
  }
};

// Zobrist表
static struct {
  ZobristStruct Player;
  ZobristStruct Table[14][256];
} Zobrist;

// 初始化Zobrist表
static void InitZobrist(void) {
  int i, j;
  RC4Struct rc4;

  rc4.InitZero();
  Zobrist.Player.InitRC4(rc4);
  for (i = 0; i < 14; i ++) {
    for (j = 0; j < 256; j ++) {
      Zobrist.Table[i][j].InitRC4(rc4);
    }
  }
}

// 历史走法信息(占4字节)
struct MoveStruct {
  WORD wmv;
  BYTE ucpcCaptured, ucbCheck;
  DWORD dwKey;

  void Set(int mv, int pcCaptured, BOOL bCheck, DWORD dwKey_) {
    wmv = mv;
    ucpcCaptured = pcCaptured;
    ucbCheck = bCheck;
    dwKey = dwKey_;
  }
}; // mvs

// 局面结构
struct PositionStruct {
  int sdPlayer;                   // 轮到谁走,0=红方,1=黑方
  BYTE ucpcSquares[256];          // 棋盘上的棋子
  int vlWhite, vlBlack;           // 红、黑双方的子力价值
  int nDistance, nMoveNum;        // 距离根节点的步数,历史走法数
  MoveStruct mvsList[MAX_MOVES];  // 历史走法信息列表
  ZobristStruct zobr;             // Zobrist

  void ClearBoard(void) {         // 清空棋盘
    sdPlayer = vlWhite = vlBlack = nDistance = 0;
    memset(ucpcSquares, 0, 256);
    zobr.InitZero();
  }
  void SetIrrev(void) {           // 清空(初始化)历史走法信息
    mvsList[0].Set(0, 0, Checked(), zobr.dwKey);
    nMoveNum = 1;
  }
  void Startup(void);             // 初始化棋盘
  void ChangeSide(void) {         // 交换走子方
    sdPlayer = 1 - sdPlayer;
    zobr.Xor(Zobrist.Player);
  }
  void AddPiece(int sq, int pc) { // 在棋盘上放一枚棋子
    ucpcSquares[sq] = pc;
    // 红方加分,黑方(注意"cucvlPiecePos"取值要颠倒)减分
    if (pc < 16) {
      vlWhite += cucvlPiecePos[pc - 8][sq];
      zobr.Xor(Zobrist.Table[pc - 8][sq]);
    } else {
      vlBlack += cucvlPiecePos[pc - 16][SQUARE_FLIP(sq)];
      zobr.Xor(Zobrist.Table[pc - 9][sq]);
    }
  }
  void DelPiece(int sq, int pc) { // 从棋盘上拿走一枚棋子
    ucpcSquares[sq] = 0;
    // 红方减分,黑方(注意"cucvlPiecePos"取值要颠倒)加分
    if (pc < 16) {
      vlWhite -= cucvlPiecePos[pc - 8][sq];
      zobr.Xor(Zobrist.Table[pc - 8][sq]);
    } else {
      vlBlack -= cucvlPiecePos[pc - 16][SQUARE_FLIP(sq)];
      zobr.Xor(Zobrist.Table[pc - 9][sq]);
    }
  }
  int Evaluate(void) const {      // 局面评价函数
    return (sdPlayer == 0 ? vlWhite - vlBlack : vlBlack - vlWhite) + ADVANCED_VALUE;
  }
  BOOL InCheck(void) const {      // 是否被将军
    return mvsList[nMoveNum - 1].ucbCheck;
  }
  BOOL Captured(void) const {     // 上一步是否吃子
    return mvsList[nMoveNum - 1].ucpcCaptured != 0;
  }
  int MovePiece(int mv);                      // 搬一步棋的棋子
  void UndoMovePiece(int mv, int pcCaptured); // 撤消搬一步棋的棋子
  BOOL MakeMove(int mv);                      // 走一步棋
  void UndoMakeMove(void) {                   // 撤消走一步棋
    nDistance --;
    nMoveNum --;
    ChangeSide();
    UndoMovePiece(mvsList[nMoveNum].wmv, mvsList[nMoveNum].ucpcCaptured);
  }
  void NullMove(void) {                       // 走一步空步
    DWORD dwKey;
    dwKey = zobr.dwKey;
    ChangeSide();
    mvsList[nMoveNum].Set(0, 0, FALSE, dwKey);
    nMoveNum ++;
    nDistance ++;
  }
  void UndoNullMove(void) {                   // 撤消走一步空步
    nDistance --;
    nMoveNum --;
    ChangeSide();
  }
  // 生成所有走法,如果"bCapture"为"TRUE"则只生成吃子走法
  int GenerateMoves(int *mvs, BOOL bCapture = FALSE) const;
  BOOL LegalMove(int mv) const;               // 判断走法是否合理
  BOOL Checked(void) const;                   // 判断是否被将军
  BOOL IsMate(void);                          // 判断是否被杀
  int DrawValue(void) const {                 // 和棋分值
    return (nDistance & 1) == 0 ? -DRAW_VALUE : DRAW_VALUE;
  }
  int RepStatus(int nRecur = 1) const;        // 检测重复局面
  int RepValue(int nRepStatus) const {        // 重复局面分值
    int vlReturn;
    vlReturn = ((nRepStatus & 2) == 0 ? 0 : nDistance - BAN_VALUE) +
        ((nRepStatus & 4) == 0 ? 0 : BAN_VALUE - nDistance);
    return vlReturn == 0 ? DrawValue() : vlReturn;
  }
  BOOL NullOkay(void) const {                 // 判断是否允许空步裁剪
    return (sdPlayer == 0 ? vlWhite : vlBlack) > NULL_MARGIN;
  }
  void Mirror(PositionStruct &posMirror) const; // 对局面镜像
};

// 初始化棋盘
void PositionStruct::Startup(void) {
  int sq, pc;
  ClearBoard();
  for (sq = 0; sq < 256; sq ++) {
    pc = cucpcStartup[sq];
    if (pc != 0) {
      AddPiece(sq, pc);
    }
  }
  SetIrrev();
}

// 搬一步棋的棋子
int PositionStruct::MovePiece(int mv) {
  int sqSrc, sqDst, pc, pcCaptured;
  sqSrc = SRC(mv);
  sqDst = DST(mv);
  pcCaptured = ucpcSquares[sqDst];
  if (pcCaptured != 0) {
    DelPiece(sqDst, pcCaptured);
  }
  pc = ucpcSquares[sqSrc];
  DelPiece(sqSrc, pc);
  AddPiece(sqDst, pc);
  return pcCaptured;
}

// 撤消搬一步棋的棋子
void PositionStruct::UndoMovePiece(int mv, int pcCaptured) 
{
	int sqSrc, sqDst, pc;
	sqSrc = SRC(mv);
	sqDst = DST(mv);
	pc = ucpcSquares[sqDst];
	DelPiece(sqDst, pc);
	AddPiece(sqSrc, pc);
	if (pcCaptured != 0)
	{
		AddPiece(sqDst, pcCaptured);
	}
}

// 走一步棋
BOOL PositionStruct::MakeMove(int mv) {
  int pcCaptured;
  DWORD dwKey;

  dwKey = zobr.dwKey;
  pcCaptured = MovePiece(mv);
  if (Checked()) {
    UndoMovePiece(mv, pcCaptured);
    return FALSE;
  }
  ChangeSide();
  mvsList[nMoveNum].Set(mv, pcCaptured, Checked(), dwKey);
  nMoveNum ++;
  nDistance ++;
  return TRUE;
}

// "GenerateMoves"参数
const BOOL GEN_CAPTURE = TRUE;

// 生成所有走法,如果"bCapture"为"TRUE"则只生成吃子走法
int PositionStruct::GenerateMoves(int *mvs, BOOL bCapture) const {
  int i, j, nGenMoves, nDelta, sqSrc, sqDst;
  int pcSelfSide, pcOppSide, pcSrc, pcDst;
  // 生成所有走法,需要经过以下几个步骤:

	nGenMoves  = 0;
	pcSelfSide = SIDE_TAG(sdPlayer);
	pcOppSide  = OPP_SIDE_TAG(sdPlayer);
	for (sqSrc = 0; sqSrc < 256; sqSrc ++)
	{

    // 1. 找到一个本方棋子,再做以下判断:
    pcSrc = ucpcSquares[sqSrc];
    if ((pcSrc & pcSelfSide) == 0) {
      continue;
    }

    // 2. 根据棋子确定走法
    switch (pcSrc - pcSelfSide) {
    case PIECE_KING:
      for (i = 0; i < 4; i ++) {
        sqDst = sqSrc + ccKingDelta[i];
        if (!IN_FORT(sqDst)) {
          continue;
        }
        pcDst = ucpcSquares[sqDst];
        if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
          mvs[nGenMoves] = MOVE(sqSrc, sqDst);
          nGenMoves ++;
        }
      }
      break;
    case PIECE_ADVISOR:
      for (i = 0; i < 4; i ++) {
        sqDst = sqSrc + ccAdvisorDelta[i];
        if (!IN_FORT(sqDst)) {
          continue;
        }
        pcDst = ucpcSquares[sqDst];
        if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
          mvs[nGenMoves] = MOVE(sqSrc, sqDst);
          nGenMoves ++;
        }
      }
      break;
    case PIECE_BISHOP:
      for (i = 0; i < 4; i ++) {
        sqDst = sqSrc + ccAdvisorDelta[i];
        if (!(IN_BOARD(sqDst) && HOME_HALF(sqDst, sdPlayer) && ucpcSquares[sqDst] == 0)) {
          continue;
        }
        sqDst += ccAdvisorDelta[i];
        pcDst = ucpcSquares[sqDst];
        if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
          mvs[nGenMoves] = MOVE(sqSrc, sqDst);
          nGenMoves ++;
        }
      }
      break;
    case PIECE_KNIGHT:
      for (i = 0; i < 4; i ++) {
        sqDst = sqSrc + ccKingDelta[i];
        if (ucpcSquares[sqDst] != 0) {
          continue;
        }
        for (j = 0; j < 2; j ++) {
          sqDst = sqSrc + ccKnightDelta[i][j];
          if (!IN_BOARD(sqDst)) {
            continue;
          }
          pcDst = ucpcSquares[sqDst];
          if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
            mvs[nGenMoves] = MOVE(sqSrc, sqDst);
            nGenMoves ++;
          }
        }
      }
      break;
    case PIECE_ROOK:
      for (i = 0; i < 4; i ++) {
        nDelta = ccKingDelta[i];
        sqDst = sqSrc + nDelta;
        while (IN_BOARD(sqDst)) {
          pcDst = ucpcSquares[sqDst];
          if (pcDst == 0) {
            if (!bCapture) {
              mvs[nGenMoves] = MOVE(sqSrc, sqDst);
              nGenMoves ++;
            }
          } else {
            if ((pcDst & pcOppSide) != 0) {
              mvs[nGenMoves] = MOVE(sqSrc, sqDst);
              nGenMoves ++;
            }
            break;
          }
          sqDst += nDelta;
        }
      }
      break;
    case PIECE_CANNON:
      for (i = 0; i < 4; i ++) {
        nDelta = ccKingDelta[i];
        sqDst = sqSrc + nDelta;
        while (IN_BOARD(sqDst)) {
          pcDst = ucpcSquares[sqDst];
          if (pcDst == 0) {
            if (!bCapture) {
              mvs[nGenMoves] = MOVE(sqSrc, sqDst);
              nGenMoves ++;
            }
          } else {
            break;
          }
          sqDst += nDelta;
        }
        sqDst += nDelta;
        while (IN_BOARD(sqDst)) {
          pcDst = ucpcSquares[sqDst];
          if (pcDst != 0) {
            if ((pcDst & pcOppSide) != 0) {
              mvs[nGenMoves] = MOVE(sqSrc, sqDst);
              nGenMoves ++;
            }
            break;
          }
          sqDst += nDelta;
        }
      }
      break;
    case PIECE_PAWN:
      sqDst = SQUARE_FORWARD(sqSrc, sdPlayer);
      if (IN_BOARD(sqDst)) {
        pcDst = ucpcSquares[sqDst];
        if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
          mvs[nGenMoves] = MOVE(sqSrc, sqDst);
          nGenMoves ++;
        }
      }
      if (AWAY_HALF(sqSrc, sdPlayer)) {
        for (nDelta = -1; nDelta <= 1; nDelta += 2) {
          sqDst = sqSrc + nDelta;
          if (IN_BOARD(sqDst)) {
            pcDst = ucpcSquares[sqDst];
            if (bCapture ? (pcDst & pcOppSide) != 0 : (pcDst & pcSelfSide) == 0) {
              mvs[nGenMoves] = MOVE(sqSrc, sqDst);
              nGenMoves ++;
            }
          }
        }
      }
      break;
    }
  }
  return nGenMoves;
}

// 判断走法是否合理
BOOL PositionStruct::LegalMove(int mv) const {
  int sqSrc, sqDst, sqPin;
  int pcSelfSide, pcSrc, pcDst, nDelta;
  // 判断走法是否合法,需要经过以下的判断过程:

  // 1. 判断起始格是否有自己的棋子
  sqSrc = SRC(mv);
  pcSrc = ucpcSquares[sqSrc];
  pcSelfSide = SIDE_TAG(sdPlayer);
  if ((pcSrc & pcSelfSide) == 0) {
    return FALSE;
  }

  // 2. 判断目标格是否有自己的棋子
  sqDst = DST(mv);
  pcDst = ucpcSquares[sqDst];
  if ((pcDst & pcSelfSide) != 0) {
    return FALSE;
  }

  // 3. 根据棋子的类型检查走法是否合理
  switch (pcSrc - pcSelfSide) {
  case PIECE_KING:
    return IN_FORT(sqDst) && KING_SPAN(sqSrc, sqDst);
  case PIECE_ADVISOR:
    return IN_FORT(sqDst) && ADVISOR_SPAN(sqSrc, sqDst);
  case PIECE_BISHOP:
    return SAME_HALF(sqSrc, sqDst) && BISHOP_SPAN(sqSrc, sqDst) &&
        ucpcSquares[BISHOP_PIN(sqSrc, sqDst)] == 0;
  case PIECE_KNIGHT:
    sqPin = KNIGHT_PIN(sqSrc, sqDst);
    return sqPin != sqSrc && ucpcSquares[sqPin] == 0;
  case PIECE_ROOK:
  case PIECE_CANNON:
    if (SAME_RANK(sqSrc, sqDst)) {
      nDelta = (sqDst < sqSrc ? -1 : 1);
    } else if (SAME_FILE(sqSrc, sqDst)) {
      nDelta = (sqDst < sqSrc ? -16 : 16);
    } else {
      return FALSE;
    }
    sqPin = sqSrc + nDelta;
    while (sqPin != sqDst && ucpcSquares[sqPin] == 0) {
      sqPin += nDelta;
    }
    if (sqPin == sqDst) {
      return pcDst == 0 || pcSrc - pcSelfSide == PIECE_ROOK;
    } else if (pcDst != 0 && pcSrc - pcSelfSide == PIECE_CANNON) {
      sqPin += nDelta;
      while (sqPin != sqDst && ucpcSquares[sqPin] == 0) {
        sqPin += nDelta;
      }
      return sqPin == sqDst;
    } else {
      return FALSE;
    }
  case PIECE_PAWN:
    if (AWAY_HALF(sqDst, sdPlayer) && (sqDst == sqSrc - 1 || sqDst == sqSrc + 1)) {
      return TRUE;
    }
    return sqDst == SQUARE_FORWARD(sqSrc, sdPlayer);
  default:
    return FALSE;
  }
}

// 判断是否被将军
BOOL PositionStruct::Checked() const {
  int i, j, sqSrc, sqDst;
  int pcSelfSide, pcOppSide, pcDst, nDelta;
  pcSelfSide = SIDE_TAG(sdPlayer);
  pcOppSide = OPP_SIDE_TAG(sdPlayer);
  // 找到棋盘上的帅(将),再做以下判断:

  for (sqSrc = 0; sqSrc < 256; sqSrc ++) {
    if (ucpcSquares[sqSrc] != pcSelfSide + PIECE_KING) {
      continue;
    }

    // 1. 判断是否被对方的兵(卒)将军
    if (ucpcSquares[SQUARE_FORWARD(sqSrc, sdPlayer)] == pcOppSide + PIECE_PAWN) {
      return TRUE;
    }
    for (nDelta = -1; nDelta <= 1; nDelta += 2) {
      if (ucpcSquares[sqSrc + nDelta] == pcOppSide + PIECE_PAWN) {
        return TRUE;
      }
    }

    // 2. 判断是否被对方的马将军(以仕(士)的步长当作马腿)
    for (i = 0; i < 4; i ++) {
      if (ucpcSquares[sqSrc + ccAdvisorDelta[i]] != 0) {
        continue;
      }
      for (j = 0; j < 2; j ++) {
        pcDst = ucpcSquares[sqSrc + ccKnightCheckDelta[i][j]];
        if (pcDst == pcOppSide + PIECE_KNIGHT) {
          return TRUE;
        }
      }
    }

    // 3. 判断是否被对方的车或炮将军(包括将帅对脸)
    for (i = 0; i < 4; i ++) {
      nDelta = ccKingDelta[i];
      sqDst = sqSrc + nDelta;
      while (IN_BOARD(sqDst)) {
        pcDst = ucpcSquares[sqDst];
        if (pcDst != 0) {
          if (pcDst == pcOppSide + PIECE_ROOK || pcDst == pcOppSide + PIECE_KING) {
            return TRUE;
          }
          break;
        }
        sqDst += nDelta;
      }
      sqDst += nDelta;
      while (IN_BOARD(sqDst)) {
        int pcDst = ucpcSquares[sqDst];
        if (pcDst != 0) {
          if (pcDst == pcOppSide + PIECE_CANNON) {
            return TRUE;
          }
          break;
        }
        sqDst += nDelta;
      }
    }
    return FALSE;
  }
  return FALSE;
}

// 判断是否被杀
BOOL PositionStruct::IsMate(void) {
  int i, nGenMoveNum, pcCaptured;
  int mvs[MAX_GEN_MOVES];

  nGenMoveNum = GenerateMoves(mvs);
  for (i = 0; i < nGenMoveNum; i ++) {
    pcCaptured = MovePiece(mvs[i]);
    if (!Checked()) {
      UndoMovePiece(mvs[i], pcCaptured);
      return FALSE;
    } else {
      UndoMovePiece(mvs[i], pcCaptured);
    }
  }
  return TRUE;
}

// 检测重复局面
int PositionStruct::RepStatus(int nRecur) const {
  BOOL bSelfSide, bPerpCheck, bOppPerpCheck;
  const MoveStruct *lpmvs;

  bSelfSide = FALSE;
  bPerpCheck = bOppPerpCheck = TRUE;
  lpmvs = mvsList + nMoveNum - 1;
  while (lpmvs->wmv != 0 && lpmvs->ucpcCaptured == 0) {
    if (bSelfSide) {
      bPerpCheck = bPerpCheck && lpmvs->ucbCheck;
      if (lpmvs->dwKey == zobr.dwKey) {
        nRecur --;
        if (nRecur == 0) {
          return 1 + (bPerpCheck ? 2 : 0) + (bOppPerpCheck ? 4 : 0);
        }
      }
    } else {
      bOppPerpCheck = bOppPerpCheck && lpmvs->ucbCheck;
    }
    bSelfSide = !bSelfSide;
    lpmvs --;
  }
  return 0;
}

// 对局面镜像
void PositionStruct::Mirror(PositionStruct &posMirror) const {
  int sq, pc;
  posMirror.ClearBoard();
  for (sq = 0; sq < 256; sq ++) {
    pc = ucpcSquares[sq];
    if (pc != 0) {
      posMirror.AddPiece(MIRROR_SQUARE(sq), pc);
    }
  }
  if (sdPlayer == 1) {
    posMirror.ChangeSide();
  }
  posMirror.SetIrrev();
}

static PositionStruct pos; // 局面实例

// 与图形界面有关的全局变量
static struct {
  HINSTANCE hInst;                              // 应用程序句柄实例
  HWND hWnd;                                    // 主窗口句柄
  HDC hdc, hdcTmp;                              // 设备句柄,只在"ClickSquare"过程中有效
  HBITMAP bmpBoard, bmpSelected, bmpPieces[24]; // 资源图片句柄
  int sqSelected, mvLast;                       // 选中的格子,上一步棋
  BOOL bFlipped, bGameOver;                     // 是否翻转棋盘,是否游戏结束(不让继续玩下去)
} Xqwl;

// 置换表项结构
struct HashItem {
  BYTE ucDepth, ucFlag;
  short svl;
  WORD wmv, wReserved;
  DWORD dwLock0, dwLock1;
};

// 开局库项结构
struct BookItem {
  DWORD dwLock;
  WORD wmv, wvl;
};

// 与搜索有关的全局变量
static struct {
  int mvResult;                  // 电脑走的棋
  int nHistoryTable[65536];      // 历史表
  int mvKillers[LIMIT_DEPTH][2]; // 杀手走法表
  HashItem HashTable[HASH_SIZE]; // 置换表
  int nBookSize;                 // 开局库大小
  BookItem BookTable[BOOK_SIZE]; // 开局库
} Search;

// 装入开局库
static void LoadBook(void) {
  HRSRC hrsrc;
  hrsrc = FindResource(Xqwl.hInst, "BOOK_DATA", RT_RCDATA);
  Search.nBookSize = SizeofResource(Xqwl.hInst, hrsrc) / sizeof(BookItem);
  if (Search.nBookSize > BOOK_SIZE) {
    Search.nBookSize = BOOK_SIZE;
  }
  memcpy(Search.BookTable, LockResource(LoadResource(Xqwl.hInst, hrsrc)),
      Search.nBookSize * sizeof(BookItem));
}

static int CompareBook(const void *lpbk1, const void *lpbk2) {
  DWORD dw1, dw2;
  dw1 = ((BookItem *) lpbk1)->dwLock;
  dw2 = ((BookItem *) lpbk2)->dwLock;
  return dw1 > dw2 ? 1 : dw1 < dw2 ? -1 : 0;
}

// 搜索开局库
static int SearchBook(void) {
  int i, vl, nBookMoves, mv;
  int mvs[MAX_GEN_MOVES], vls[MAX_GEN_MOVES];
  BOOL bMirror;
  BookItem bkToSearch, *lpbk;
  PositionStruct posMirror;
  // 搜索开局库的过程有以下几个步骤

  // 1. 如果没有开局库,则立即返回
  if (Search.nBookSize == 0) {
    return 0;
  }
  // 2. 搜索当前局面
  bMirror = FALSE;
  bkToSearch.dwLock = pos.zobr.dwLock1;
  lpbk = (BookItem *) bsearch(&bkToSearch, Search.BookTable, Search.nBookSize, sizeof(BookItem), CompareBook);
  // 3. 如果没有找到,那么搜索当前局面的镜像局面
  if (lpbk == NULL) {
    bMirror = TRUE;
    pos.Mirror(posMirror);
    bkToSearch.dwLock = posMirror.zobr.dwLock1;
    lpbk = (BookItem *) bsearch(&bkToSearch, Search.BookTable, Search.nBookSize, sizeof(BookItem), CompareBook);
  }
  // 4. 如果镜像局面也没找到,则立即返回
  if (lpbk == NULL) {
    return 0;
  }
  // 5. 如果找到,则向前查第一个开局库项
  while (lpbk >= Search.BookTable && lpbk->dwLock == bkToSearch.dwLock) {
    lpbk --;
  }
  lpbk ++;
  // 6. 把走法和分值写入到"mvs"和"vls"数组中
  vl = nBookMoves = 0;
  while (lpbk < Search.BookTable + Search.nBookSize && lpbk->dwLock == bkToSearch.dwLock) {
    mv = (bMirror ? MIRROR_MOVE(lpbk->wmv) : lpbk->wmv);
    if (pos.LegalMove(mv)) {
      mvs[nBookMoves] = mv;
      vls[nBookMoves] = lpbk->wvl;
      vl += vls[nBookMoves];
      nBookMoves ++;
      if (nBookMoves == MAX_GEN_MOVES) {
        break; // 防止"BOOK.DAT"中含有异常数据
      }
    }
    lpbk ++;
  }
  if (vl == 0) {
    return 0; // 防止"BOOK.DAT"中含有异常数据
  }
  // 7. 根据权重随机选择一个走法
  vl = rand() % vl;
  for (i = 0; i < nBookMoves; i ++) {
    vl -= vls[i];
    if (vl < 0) {
      break;
    }
  }
  return mvs[i];
}

// 提取置换表项
static int ProbeHash(int vlAlpha, int vlBeta, int nDepth, int &mv) {
  BOOL bMate; // 杀棋标志:如果是杀棋,那么不需要满足深度条件
  HashItem hsh;

  hsh = Search.HashTable[pos.zobr.dwKey & (HASH_SIZE - 1)];
  if (hsh.dwLock0 != pos.zobr.dwLock0 || hsh.dwLock1 != pos.zobr.dwLock1) {
    mv = 0;
    return -MATE_VALUE;
  }
  mv = hsh.wmv;
  bMate = FALSE;
  if (hsh.svl > WIN_VALUE) {
    if (hsh.svl < BAN_VALUE) {
      return -MATE_VALUE; // 可能导致搜索的不稳定性,立刻退出,但最佳着法可能拿到
    }
    hsh.svl -= pos.nDistance;
    bMate = TRUE;
  } else if (hsh.svl < -WIN_VALUE) {
    if (hsh.svl > -BAN_VALUE) {
      return -MATE_VALUE; // 同上
    }
    hsh.svl += pos.nDistance;
    bMate = TRUE;
  }
  if (hsh.ucDepth >= nDepth || bMate) {
    if (hsh.ucFlag == HASH_BETA) {
      return (hsh.svl >= vlBeta ? hsh.svl : -MATE_VALUE);
    } else if (hsh.ucFlag == HASH_ALPHA) {
      return (hsh.svl <= vlAlpha ? hsh.svl : -MATE_VALUE);
    }
    return hsh.svl;
  }
  return -MATE_VALUE;
};

// 保存置换表项
static void RecordHash(int nFlag, int vl, int nDepth, int mv) {
  HashItem hsh;
  hsh = Search.HashTable[pos.zobr.dwKey & (HASH_SIZE - 1)];
  if (hsh.ucDepth > nDepth) {
    return;
  }
  hsh.ucFlag = nFlag;
  hsh.ucDepth = nDepth;
  if (vl > WIN_VALUE) {
    if (mv == 0 && vl <= BAN_VALUE) {
      return; // 可能导致搜索的不稳定性,并且没有最佳着法,立刻退出
    }
    hsh.svl = vl + pos.nDistance;
  } else if (vl < -WIN_VALUE) {
    if (mv == 0 && vl >= -BAN_VALUE) {
      return; // 同上
    }
    hsh.svl = vl - pos.nDistance;
  } else {
    hsh.svl = vl;
  }
  hsh.wmv = mv;
  hsh.dwLock0 = pos.zobr.dwLock0;
  hsh.dwLock1 = pos.zobr.dwLock1;
  Search.HashTable[pos.zobr.dwKey & (HASH_SIZE - 1)] = hsh;
};

// MVV/LVA每种子力的价值
static BYTE cucMvvLva[24] = {
  0, 0, 0, 0, 0, 0, 0, 0,
  5, 1, 1, 3, 4, 3, 2, 0,
  5, 1, 1, 3, 4, 3, 2, 0
};

// 求MVV/LVA值
inline int MvvLva(int mv) {
  return (cucMvvLva[pos.ucpcSquares[DST(mv)]] << 3) - cucMvvLva[pos.ucpcSquares[SRC(mv)]];
}

// "qsort"按MVV/LVA值排序的比较函数
static int CompareMvvLva(const void *lpmv1, const void *lpmv2) {
  return MvvLva(*(int *) lpmv2) - MvvLva(*(int *) lpmv1);
}

// "qsort"按历史表排序的比较函数
static int CompareHistory(const void *lpmv1, const void *lpmv2) {
  return Search.nHistoryTable[*(int *) lpmv2] - Search.nHistoryTable[*(int *) lpmv1];
}


// 走法排序阶段
const int PHASE_HASH = 0;
const int PHASE_KILLER_1 = 1;
const int PHASE_KILLER_2 = 2;
const int PHASE_GEN_MOVES = 3;
const int PHASE_REST = 4;

// 走法排序结构
struct SortStruct {
  int mvHash, mvKiller1, mvKiller2; // 置换表走法和两个杀手走法
  int nPhase, nIndex, nGenMoves;    // 当前阶段,当前采用第几个走法,总共有几个走法
  int mvs[MAX_GEN_MOVES];           // 所有的走法

  void Init(int mvHash_) { // 初始化,设定置换表走法和两个杀手走法
    mvHash = mvHash_;
    mvKiller1 = Search.mvKillers[pos.nDistance][0];
    mvKiller2 = Search.mvKillers[pos.nDistance][1];
    nPhase = PHASE_HASH;
  }
  int Next(void); // 得到下一个走法
};

// 得到下一个走法
int SortStruct::Next(void) {
  int mv;
  switch (nPhase) {
  // "nPhase"表示着法启发的若干阶段,依次为:

  // 0. 置换表着法启发,完成后立即进入下一阶段;
  case PHASE_HASH:
    nPhase = PHASE_KILLER_1;
    if (mvHash != 0) {
      return mvHash;
    }
    // 技巧:这里没有"break",表示"switch"的上一个"case"执行完后紧接着做下一个"case",下同

  // 1. 杀手着法启发(第一个杀手着法),完成后立即进入下一阶段;
  case PHASE_KILLER_1:
    nPhase = PHASE_KILLER_2;
    if (mvKiller1 != mvHash && mvKiller1 != 0 && pos.LegalMove(mvKiller1)) {
      return mvKiller1;
    }

  // 2. 杀手着法启发(第二个杀手着法),完成后立即进入下一阶段;
  case PHASE_KILLER_2:
    nPhase = PHASE_GEN_MOVES;
    if (mvKiller2 != mvHash && mvKiller2 != 0 && pos.LegalMove(mvKiller2)) {
      return mvKiller2;
    }

  // 3. 生成所有着法,完成后立即进入下一阶段;
  case PHASE_GEN_MOVES:
    nPhase = PHASE_REST;
    nGenMoves = pos.GenerateMoves(mvs);
    qsort(mvs, nGenMoves, sizeof(int), CompareHistory);
    nIndex = 0;

  // 4. 对剩余着法做历史表启发;
  case PHASE_REST:
    while (nIndex < nGenMoves) {
      mv = mvs[nIndex];
      nIndex ++;
      if (mv != mvHash && mv != mvKiller1 && mv != mvKiller2) {
        return mv;
      }
    }

  // 5. 没有着法了,返回零。
  default:
    return 0;
  }
}

// 对最佳走法的处理
inline void SetBestMove(int mv, int nDepth) {
  int *lpmvKillers;
  Search.nHistoryTable[mv] += nDepth * nDepth;
  lpmvKillers = Search.mvKillers[pos.nDistance];
  if (lpmvKillers[0] != mv) {
    lpmvKillers[1] = lpmvKillers[0];
    lpmvKillers[0] = mv;
  }
}

// 静态(Quiescence)搜索过程
static int SearchQuiesc(int vlAlpha, int vlBeta) {
  int i, nGenMoves;
  int vl, vlBest;
  int mvs[MAX_GEN_MOVES];
  // 一个静态搜索分为以下几个阶段

  // 1. 检查重复局面
  vl = pos.RepStatus();
  if (vl != 0) {
    return pos.RepValue(vl);
  }

  // 2. 到达极限深度就返回局面评价
  if (pos.nDistance == LIMIT_DEPTH) {
    return pos.Evaluate();
  }

  // 3. 初始化最佳值
  vlBest = -MATE_VALUE; // 这样可以知道,是否一个走法都没走过(杀棋)

  if (pos.InCheck()) {
    // 4. 如果被将军,则生成全部走法
    nGenMoves = pos.GenerateMoves(mvs);
    qsort(mvs, nGenMoves, sizeof(int), CompareHistory);
  } else {

    // 5. 如果不被将军,先做局面评价
    vl = pos.Evaluate();
    if (vl > vlBest) {
      vlBest = vl;
      if (vl >= vlBeta) {
        return vl;
      }
      if (vl > vlAlpha) {
        vlAlpha = vl;
      }
    }

    // 6. 如果局面评价没有截断,再生成吃子走法
    nGenMoves = pos.GenerateMoves(mvs, GEN_CAPTURE);
    qsort(mvs, nGenMoves, sizeof(int), CompareMvvLva);
  }

  // 7. 逐一走这些走法,并进行递归
  for (i = 0; i < nGenMoves; i ++) {
    if (pos.MakeMove(mvs[i])) {
      vl = -SearchQuiesc(-vlBeta, -vlAlpha);
      pos.UndoMakeMove();

      // 8. 进行Alpha-Beta大小判断和截断
      if (vl > vlBest) {    // 找到最佳值(但不能确定是Alpha、PV还是Beta走法)
        vlBest = vl;        // "vlBest"就是目前要返回的最佳值,可能超出Alpha-Beta边界
        if (vl >= vlBeta) { // 找到一个Beta走法
          return vl;        // Beta截断
        }
        if (vl > vlAlpha) { // 找到一个PV走法
          vlAlpha = vl;     // 缩小Alpha-Beta边界
        }
      }
    }
  }

  // 9. 所有走法都搜索完了,返回最佳值
  return vlBest == -MATE_VALUE ? pos.nDistance - MATE_VALUE : vlBest;
}

// "SearchFull"的参数
const BOOL NO_NULL = TRUE;

// 超出边界(Fail-Soft)的Alpha-Beta搜索过程
static int SearchFull(int vlAlpha, int vlBeta, int nDepth, BOOL bNoNull = FALSE) {
  int nHashFlag, vl, vlBest;
  int mv, mvBest, mvHash, nNewDepth;
  SortStruct Sort;
  // 一个Alpha-Beta完全搜索分为以下几个阶段

  // 1. 到达水平线,则调用静态搜索(注意:由于空步裁剪,深度可能小于零)
  if (nDepth <= 0) {
    return SearchQuiesc(vlAlpha, vlBeta);
  }

  // 1-1. 检查重复局面(注意:不要在根节点检查,否则就没有走法了)
  vl = pos.RepStatus();
  if (vl != 0) {
    return pos.RepValue(vl);
  }

  // 1-2. 到达极限深度就返回局面评价
  if (pos.nDistance == LIMIT_DEPTH) {
    return pos.Evaluate();
  }

  // 1-3. 尝试置换表裁剪,并得到置换表走法
  vl = ProbeHash(vlAlpha, vlBeta, nDepth, mvHash);
  if (vl > -MATE_VALUE) {
    return vl;
  }

  // 1-4. 尝试空步裁剪(根节点的Beta值是"MATE_VALUE",所以不可能发生空步裁剪)
  if (!bNoNull && !pos.InCheck() && pos.NullOkay()) {
    pos.NullMove();
    vl = -SearchFull(-vlBeta, 1 - vlBeta, nDepth - NULL_DEPTH - 1, NO_NULL);
    pos.UndoNullMove();
    if (vl >= vlBeta) {
      return vl;
    }
  }

  // 2. 初始化最佳值和最佳走法
  nHashFlag = HASH_ALPHA;
  vlBest = -MATE_VALUE; // 这样可以知道,是否一个走法都没走过(杀棋)
  mvBest = 0;           // 这样可以知道,是否搜索到了Beta走法或PV走法,以便保存到历史表

  // 3. 初始化走法排序结构
  Sort.Init(mvHash);

  // 4. 逐一走这些走法,并进行递归
  while ((mv = Sort.Next()) != 0) {
    if (pos.MakeMove(mv)) {
      // 将军延伸
      nNewDepth = pos.InCheck() ? nDepth : nDepth - 1;
      // PVS
      if (vlBest == -MATE_VALUE) {
        vl = -SearchFull(-vlBeta, -vlAlpha, nNewDepth);
      } else {
        vl = -SearchFull(-vlAlpha - 1, -vlAlpha, nNewDepth);
        if (vl > vlAlpha && vl < vlBeta) {
          vl = -SearchFull(-vlBeta, -vlAlpha, nNewDepth);
        }
      }
      pos.UndoMakeMove();

      // 5. 进行Alpha-Beta大小判断和截断
      if (vl > vlBest) {    // 找到最佳值(但不能确定是Alpha、PV还是Beta走法)
        vlBest = vl;        // "vlBest"就是目前要返回的最佳值,可能超出Alpha-Beta边界
        if (vl >= vlBeta) { // 找到一个Beta走法
          nHashFlag = HASH_BETA;
          mvBest = mv;      // Beta走法要保存到历史表
          break;            // Beta截断
        }
        if (vl > vlAlpha) { // 找到一个PV走法
          nHashFlag = HASH_PV;
          mvBest = mv;      // PV走法要保存到历史表
          vlAlpha = vl;     // 缩小Alpha-Beta边界
        }
      }
    }
  }

  // 5. 所有走法都搜索完了,把最佳走法(不能是Alpha走法)保存到历史表,返回最佳值
  if (vlBest == -MATE_VALUE) {
    // 如果是杀棋,就根据杀棋步数给出评价
    return pos.nDistance - MATE_VALUE;
  }
  // 记录到置换表
  RecordHash(nHashFlag, vlBest, nDepth, mvBest);
  if (mvBest != 0) {
    // 如果不是Alpha走法,就将最佳走法保存到历史表
    SetBestMove(mvBest, nDepth);
  }
  return vlBest;
}

// 根节点的Alpha-Beta搜索过程
static int SearchRoot(int nDepth) {
  int vl, vlBest, mv, nNewDepth;
  SortStruct Sort;

  vlBest = -MATE_VALUE;
  Sort.Init(Search.mvResult);
  while ((mv = Sort.Next()) != 0) {
    if (pos.MakeMove(mv)) {
      nNewDepth = pos.InCheck() ? nDepth : nDepth - 1;
      if (vlBest == -MATE_VALUE) {
        vl = -SearchFull(-MATE_VALUE, MATE_VALUE, nNewDepth, NO_NULL);
      } else {
        vl = -SearchFull(-vlBest - 1, -vlBest, nNewDepth);
        if (vl > vlBest) {
          vl = -SearchFull(-MATE_VALUE, -vlBest, nNewDepth, NO_NULL);
        }
      }
      pos.UndoMakeMove();
      if (vl > vlBest) {
        vlBest = vl;
        Search.mvResult = mv;
        if (vlBest > -WIN_VALUE && vlBest < WIN_VALUE) {
          vlBest += (rand() & RANDOM_MASK) - (rand() & RANDOM_MASK);
        }
      }
    }
  }
  RecordHash(HASH_PV, vlBest, nDepth, Search.mvResult);
  SetBestMove(Search.mvResult, nDepth);
  return vlBest;
}

// 迭代加深搜索过程
static void SearchMain(void) {
  LOG(_T("机器人进入---SearchMain函数"));

  int i, t, vl, nGenMoves;
  int mvs[MAX_GEN_MOVES];

  // 初始化
  memset(Search.nHistoryTable, 0, 65536 * sizeof(int));       // 清空历史表
  memset(Search.mvKillers, 0, LIMIT_DEPTH * 2 * sizeof(int)); // 清空杀手走法表
  memset(Search.HashTable, 0, HASH_SIZE * sizeof(HashItem));  // 清空置换表
  t = clock();       // 初始化定时器
  pos.nDistance = 0; // 初始步数

  // 搜索开局库
  Search.mvResult = SearchBook();
  if (Search.mvResult != 0) {
    pos.MakeMove(Search.mvResult);
    if (pos.RepStatus(3) == 0) {
      pos.UndoMakeMove();
      return;
    }
    pos.UndoMakeMove();
  }

  // 检查是否只有唯一走法
  vl = 0;
  nGenMoves = pos.GenerateMoves(mvs);
  for (i = 0; i < nGenMoves; i ++) {
    if (pos.MakeMove(mvs[i])) {
      pos.UndoMakeMove();
      Search.mvResult = mvs[i];
      vl ++;
    }
  }
  if (vl == 1) {
    return;
  }

  // 迭代加深过程
  for (i = 1; i <= LIMIT_DEPTH; i ++) {
    vl = SearchRoot(i);
    // 搜索到杀棋,就终止搜索
    if (vl > WIN_VALUE || vl < -WIN_VALUE) {
      break;
    }
    // 超过一秒,就终止搜索
    if (clock() - t > CLOCKS_PER_SEC) {
      break;
    }
  }
}
机器人插件--结束//
机器人---游戏协议转换//
// 主程序和机器人之间的协议转换
void CGameLogic::TransmitChessBorad()
{
	LOG(_T("机器人翻译棋盘"));
	int sq, pc;
	pos.vlWhite = pos.vlBlack = 0;
	memset(pos.ucpcSquares, 0, 256);

	int xPos,yPos;
	tagChessItem *pOneChess=NULL;
	for (sq = 0; sq < 256; sq ++)
	{
		if (IN_BOARD(sq))
		{
			if (!m_IsBanker)
			{
				xPos=FILE_X(sq)-3;
				yPos=RANK_Y(sq)-3;
			}
			else
			{
				xPos=8-(FILE_X(sq)-3);
				yPos=9-(RANK_Y(sq)-3);
			}
			pOneChess=m_ChessBorad[xPos][yPos];
			if (pOneChess!=NULL)
			{
				pc=pOneChess->cbChess;
				if (!m_IsBanker)
				{
					pc+=(pOneChess->cbColor==(CHESS_BLACK)?7:15);
				}
				else
				{
					pc+=(pOneChess->cbColor==(CHESS_WHITE)?7:15);
				}
				pos.AddPiece(sq, pc);
			}

		}
	}
}
机器人---游戏协议转换//

//
//机器人考虑下一步棋怎么走
bool CGameLogic::AIThinkHowToGo(BYTE &cbXSourcePos, BYTE &cbYSourcePos, BYTE &cbXTargetPos, BYTE &cbYTargetPos)
{
	//机器人大脑初始化
	static bool bInitAI=false;
	if (!bInitAI)
	{
		bInitAI=true;
		srand((DWORD) time(NULL));
		InitZobrist();
		LoadBook();
	}

	LOG(_T("机器人进行思考了---->AIThinkHowToGo"));
	static bool bHaveInit=false;
	if (!bHaveInit)
	{
		bHaveInit=true;
		pos.nDistance=0;
	}
	pos.sdPlayer=1;

	//先让机器人知道棋盘布局
	TransmitChessBorad();

	//机器人搜索如何走棋
	SearchMain();

	cbXSourcePos=FILE_X(SRC(Search.mvResult))-3;
	cbYSourcePos=RANK_Y(SRC(Search.mvResult))-3;
	cbXTargetPos=FILE_X(DST(Search.mvResult))-3;
	cbYTargetPos=RANK_Y(DST(Search.mvResult))-3;

	return true;
}
//











































































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值