致力于电脑围棋程序的开发
发新话题
打印

杨云的新版判定表

杨云的新版判定表

马上要出远门,暂时用附件贴出来,回来再整理。
附件: 您所在的用户组无法下载或查看附件
MAY THE SOURCE BE WITH YOU

TOP

出现了严重的搜索和估值错误

大家看我的函数哪儿错误了
int CsearchEngine::IsGameStatic(STONENODE position[][GRID_NUM], int UserColor,int type)
{
int score=0;
//计算要下的棋子的颜色

if(m_pMG->ModeFlag==2)
{//吃子棋
//如果提子,返回最大,否则返回0

score=m_pMG->iTakeStone;
if(score)
{//有提子发生
if(UserColor==WHITE)
{//电脑执白
if(type==WHITE)
{//白来评估
if(score==1)
{//提黑子
score=19900;
}
else
{//提白子
score=-19900;
}
//如果轮到WHITE棋走返回估值
}
else
{

if(score==1)
{
score=-19900;
}
else
{
score=19900;
}//如果轮到黑棋走返回负估值
}
}
else
{
if(type==WHITE)
{
if(score==1)
{
score=-19900;
}
else
{
score=19900;
}
//如果轮到WHITE棋走返回负估值
}
else
{
if(score==1)
{
score=19900;
}
else
{
score=-19900;
}//如果轮到黑棋走返回估值
}

}
}
else
{
score= 0;
}
}
return score;

}

int CEveluation::Eveluate(STONENODE position[][GRID_NUM],STONEPOS posList[],int iCount, BOOL bIsWhiteTurn,int UserColor)
{
if(UserColor==BLACK)
{//电脑执黑
if(bIsWhiteTurn)
{//白棋评估
return BValue-WValue;
}
else
{
return WValue-BValue;
}
}
else
{
if(bIsWhiteTurn)
{
return WValue-BValue;
}
else
{
return BValue-WValue;
}
}
}

TOP

我觉得Eveluate函数的黑白返回值反了。

为了详细让大家了解我的设计,现在介绍我的棋盘结构。

BYTE CurPosition[GRID_NUM][GRID_NUM];
这个是显示结构,没特殊的地方,0表示有黑棋,1表示有白棋,0xff表示空
typedef struct _StoneNode
{
int Score; //棋子分数
int iLife; //气
STONEPOS up; //前一个棋子
STONEPOS down; //后一个棋子
STONEPOS left; //左一个棋子
STONEPOS right; //右一个棋子
BYTE iColor; //颜色
BYTE iState;//状态,0位自由未定,1已活;2活型;3,单关;4位将死,5垂死
int iStep;//已经计算过那一步的影响了
int iSum;// 棋块中棋子总数
}STONENODE;
这个是棋盘的逻辑结构,显然这一个更重要。
同一颜色的棋子构成棋块
int Score; //棋子分数,每走一步都可能有变化
int iLife; //气,是这个棋块的总气,不是单个棋子的
STONEPOS up; //前一个棋子
STONEPOS down; //后一个棋子
STONEPOS left; //左一个棋子
STONEPOS right; //右一个棋子
这些指向棋块的其他伙伴,0xff是空
BYTE iColor; //颜色,这个棋子的颜色。
BYTE iState;//状态,0位自由未定,1已活;2活型;3,单关;4位将死,5垂死
目前状态判断不对,这个是Eveluate最大的问题
int iStep;//已经计算过那一步的影响了,当前走了多少步
int iSum;// 棋块中棋子总数

状态问题大家有建议吗?我这儿的情况是已知一个连通图,判断状态
0位自由未定,落子时都是这个状态,后来会转化成1,2,3,4,5;电脑会考虑弃自由子

1已活;在图的范围里,有两个分离的空;如果被切断,后来会转化成2,3,4,5;

2活型;在图的范围里,只有1个分离的空而且有活动范围;或者在图的范围里,包含的空点大于6个;后来会转化成1,3,4,5;电脑会考虑活型的兑换

3,单关;在图的范围里,没有分离的空单有活动范围;后来会转化成1,2,4,5;电脑会考虑单关的兑换

4位将死,在图的范围里,包含的空点小于等于6个而且没有活动范围;后来会转化成1,2,3,5;电脑会考虑放弃

5垂死;只有1个分离的空而且没有活动范围;后来会转化成1,2,3,4;电脑会考虑放弃

TOP

活动范围就是就是STONEPOS up; //前一个棋子
STONEPOS down; //后一个棋子
STONEPOS left; //左一个棋子
STONEPOS right; //右一个棋子
这些方向如果没有联接友方,就扩散层次遍历,遇到第一个有效的敌方,(气大于2),小于3层就没有活动余地,因为连跳都走不出来

TOP

现在考虑增加表示四个活动余地的变量

TOP

新增加如下判断

4位将死,在图的范围里,包含的空点小于等于6个而且没有活动范围;气不紧(棋块含棋子个数为1,气大于1;含多个棋子,气大于等于棋子数目);后来会转化成1,2,3,5;电脑会考虑放弃
5垂死;只有1个分离的空而且没有活动范围;气紧(棋块含棋子个数为1,气小于2;含多个棋子,气小于棋子数目);后来会转化成1,2,3,4;电脑会考虑放弃

TOP

电脑对一个实战死活产生的走法,电脑对想出黑47这一步,算一个进步

[ Last edited by 杨云 on 2006-3-1 at 14:10 ]
附件: 您所在的用户组无法下载或查看附件

TOP

围棋有静态这个概念,常见的是定势
何时静态,我认为是棋块状态没有变化,就达到静态

下面的程序分别判定吃子棋和正常对局时达到静态的估值
int score=0;
//计算要下的棋子的颜色
int ModeFlag=m_pMG->ModeFlag;
if(Depth<m_nMaxDepth)
{
if(m_pMG->iTakeBlack+m_pMG->iTakeWhite+m_pMG->Step>((GRID_COUNT*4)/5) && m_pMG->gWhiteCount<(GRID_COUNT/5) && m_pMG->gBlackCount<(GRID_NUM/5))
{
score=m_pEval->Eveluate(position,m_pMG->PosLog,m_pMG->Step,type,iMaxDepth-Depth,m_pMG->iTakeBlack,m_pMG->iTakeWhite);
return score;
}
}

if(ModeFlag==2 && Depth<m_nMaxDepth)
{//吃子棋
//如果提子,返回最大,否则返回0

if(type==WHITE)
{
if(m_pMG->iTakeBlack>iTakeBlack)
{
if(iTakeBlack<10)
{
score=m_pEval->Eveluate(position,m_pMG->PosLog,m_pMG->Step,type,iMaxDepth-Depth,m_pMG->iTakeBlack,m_pMG->iTakeWhite);
}
else
{
score=19900;
}
}
else if(m_pMG->iTakeWhite>iTakeWhite)
{
if(iTakeWhite<10)
{
score=m_pEval->Eveluate(position,m_pMG->PosLog,m_pMG->Step,type,iMaxDepth-Depth,m_pMG->iTakeBlack,m_pMG->iTakeWhite);
}
else
{
score=-19900;
}
}
else
{
score=0;
}
//如果轮到WHITE棋走返回估值
}
else
{

if(m_pMG->iTakeBlack>iTakeBlack)
{
if(iTakeBlack<10)
{
score=m_pEval->Eveluate(position,m_pMG->PosLog,m_pMG->Step,type,iMaxDepth-Depth,m_pMG->iTakeBlack,m_pMG->iTakeWhite);
}
else
{
score=-19900;
}
}
else if(m_pMG->iTakeWhite>iTakeWhite)
{
if(iTakeWhite<10)
{
score=m_pEval->Eveluate(position,m_pMG->PosLog,m_pMG->Step,type,iMaxDepth-Depth,m_pMG->iTakeBlack,m_pMG->iTakeWhite);
}
else
{
score=19900;
}
}
else
{
score=0;
}
//如果轮到黑棋走返回负估值
}
}
else if(Depth<m_nMaxDepth)
{
/*//如果本地急所不存在,
//调用估值函数
*/

if(m_pMG->LocalExact & (FIGHT1|FIGHT2))
{

score=0;
}
else
{
score=m_pEval->Eveluate(position,m_pMG->PosLog,m_pMG->Step,type,iMaxDepth-Depth,m_pMG->iTakeBlack,m_pMG->iTakeWhite);
}
}
return score;

[ Last edited by 杨云 on 2006-3-8 at 10:45 ]

TOP

所有博弈程序的构架都是类似的,我使用了如下的对象
1、操作界面--有朋友建议用烂柯围棋组件,没问题的,有时间就可以转换过去
2、走法产生器
3、搜索引擎
4、价值计算
5、历史纪录
6、HashTable表
7、搜索算法

TOP

基本估值函数

//估值函数
//position是要估值得棋盘
//bIsWhiteTurn是谁走,TRUE是白,FALSE是黑
//iCount计算的数量
//Flag 0表示只计算值,1表示计算值+计算吃子;2表示计算值+计算地域;3表示都计算
int CEveluation::Eveluate(STONENODE position[][GRID_NUM],STONEPOS posList[],int iCount, BOOL bIsWhiteTurn,int iDepth,int iTakeBlack,int iTakeWhite,int Flag)
{
int i,TmpX,TmpY;
count++;
BYTE nStoneType;
int iLife=0;
int iScore;
int iSum;
int iState;
int BValue=0,WValue=0;
double BArea=0,WArea=0;
for(i=0;i<iCount;i++)
{
TmpX=posList.x;
TmpY=posList.y;

nStoneType=position[TmpY][TmpX].iColor;
iLife=position[TmpY][TmpX].iLife;
iScore=position[TmpY][TmpX].Score;
iSum=position[TmpY][TmpX].iSum;
iState=position[TmpY][TmpX].iState;
if(iLife<=1)
{
iScore=1;
}
else if(iLife==2 && iSum>1)
{//5垂死
iScore=1;
}
else if(iLife==3 && iSum>1)
{//4位将死
iScore>>=1;
}
if(iState==4)
{//4位将死
iScore>>=1;
}
else if(iState==5)
{//5垂死
iScore=1;
}
if(nStoneType!=NOSTONE)
{
if(nStoneType==BLACK)
{

BValue+=iScore;
BArea+=position[TmpY][TmpX].Area;

}
else
{

WValue+=iScore;
WArea+=position[TmpY][TmpX].Area;
}
}
}
if(Flag&1)
{
BValue+=(iTakeWhite-iTakeBlack)*INITVALUE;
WValue+=(iTakeBlack-iTakeWhite)*INITVALUE;
}
if(Flag&2)
{
BValue+=(int)((int)BArea-(int)WArea)*INITVALUE;
WValue+=(int)((int)WArea-(int)BArea)*INITVALUE;
}

if(bIsWhiteTurn)
{//白评估,正
return WValue-BValue;
}
else
{//返回负
return BValue-WValue;
}

}

[ Last edited by 杨云 on 2006-3-8 at 10:46 ]

TOP

发新话题
最近访问的版块