#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;
}
//