// 点击格子事件处理 static void ClickSquare(int sq) { int pc; Xqwl.hdc = GetDC(Xqwl.hWnd); Xqwl.hdcTmp = CreateCompatibleDC(Xqwl.hdc); sq = Xqwl.bFlipped ? SQUARE_FLIP(sq) : sq; pc = pos.ucpcSquares[sq]; if ((pc & SIDE_TAG(pos.sdPlayer)) != 0) { // 如果点击自己的子,那么直接选中该子 if (Xqwl.sqSelected != 0) { DrawSquare(Xqwl.sqSelected); } Xqwl.sqSelected = sq; DrawSquare(sq, DRAW_SELECTED); if (Xqwl.mvLast != 0) { DrawSquare(SRC(Xqwl.mvLast)); DrawSquare(DST(Xqwl.mvLast)); } PlayResWav(IDR_CLICK); // 播放点击的声音 } else if (Xqwl.sqSelected != 0) { // 如果点击的不是自己的子,但有子选中了(一定是自己的子),那么走这个子 Xqwl.mvLast = MOVE(Xqwl.sqSelected, sq); pos.MakeMove(Xqwl.mvLast); DrawSquare(Xqwl.sqSelected, DRAW_SELECTED); DrawSquare(sq, DRAW_SELECTED); Xqwl.sqSelected = 0; PlayResWav(pc == 0 ? IDR_MOVE : IDR_CAPTURE); // 播放走子或吃子的声音 } DeleteDC(Xqwl.hdcTmp); ReleaseDC(Xqwl.hWnd, Xqwl.hdc); }
void BuildPos(PositionStruct &pos, const UcciCommStruct &UcciComm) { int i, mv; pos.FromFen(UcciComm.szFenStr); for (i = 0; i < UcciComm.nMoveNum; i ++) { mv = COORD_MOVE(UcciComm.lpdwMovesCoord[i]); if (mv == 0) { break; } if (pos.LegalMove(mv) && pos.MakeMove(mv) && pos.LastMove().CptDrw > 0) { // 始终让pos.nMoveNum反映没吃子的步数 pos.SetIrrev(); } } }
void BuildPos(PositionStruct &pos, const UcciCommStruct &UcciComm) { int i, mv; pos.FromFen(UcciComm.szFenStr); for (i = 0; i < UcciComm.nMoveNum; i ++) { mv = COORD_MOVE(UcciComm.lpdwMovesCoord[i]); if (mv == 0) { break; } if (pos.ucpcSquares[SRC(mv)] == 0) { break; } pos.MakeMove(mv); } }
// 检测下一个着法是否稳定,有助于减少置换表的不稳定性 inline bool MoveStable(PositionStruct &pos, int mv) { // 判断下一个着法是否稳定的依据是: // 1. 没有后续着法,则假定是稳定的; if (mv == 0) { return true; } // 2. 吃子着法是稳定的; __ASSERT(pos.LegalMove(mv)); if (pos.ucpcSquares[DST(mv)] != 0) { return true; } // 3. 可能因置换表引起路线迁移,使得路线超过"MAX_MOVE_NUM",此时应立刻终止路线,并假定是稳定的。 if (!pos.MakeMove(mv)) { return true; } return false; }
// 尝试某个着法,并返回着法状态,参阅"cchess.h" bool TryMove(PositionStruct &pos, int &nStatus, int mv) { if (!pos.LegalMove(mv)) { nStatus = MOVE_ILLEGAL; return false; } if (!pos.MakeMove(mv)) { nStatus = MOVE_INCHECK; return false; } nStatus = 0; nStatus += (pos.LastMove().CptDrw > 0 ? MOVE_CAPTURE : 0); nStatus += (pos.LastMove().ChkChs > 0 ? MOVE_CHECK : 0); nStatus += (pos.IsMate() ? MOVE_MATE : 0); nStatus += pos.RepStatus(3) * MOVE_PERPETUAL; // 提示:参阅"position.cpp"中的"IsRep()"函数 nStatus += (pos.IsDraw() ? MOVE_DRAW : 0); pos.UndoMakeMove(); return true; }
int Node::playRollout(){ PositionStruct p = pos; int player = p.sdPlayer; int k = K; int mv[128]; int i; for (i = 0; i < k; i++){ mv[k] = move[k]; } while (1){ p.MakeMove(mv[ppi(pos2fen(&p), k, mv)]); genMove(&p, k, mv); if (k == 0){ //无子可走被将死 if (p.sdPlayer == player){ //自己被将死 return 0; } else{ return 1; } } } }
// 静态搜索例程 static int SearchQuiesc(PositionStruct &pos, int vlAlpha, int vlBeta) { int vlBest, vl, mv; bool bInCheck; MoveSortStruct MoveSort; // 静态搜索例程包括以下几个步骤: Search2.nAllNodes ++; // 1. 无害裁剪; vl = HarmlessPruning(pos, vlBeta); if (vl > -MATE_VALUE) { return vl; } #ifdef HASH_QUIESC // 3. 置换裁剪; vl = ProbeHashQ(pos, vlAlpha, vlBeta); if (Search.bUseHash && vl > -MATE_VALUE) { return vl; } #endif // 4. 达到极限深度,直接返回评价值; if (pos.nDistance == LIMIT_DEPTH) { return Evaluate(pos, vlAlpha, vlBeta); } __ASSERT(Search.pos.nDistance < LIMIT_DEPTH); // 5. 初始化; vlBest = -MATE_VALUE; bInCheck = (pos.LastMove().ChkChs > 0); // 6. 对于被将军的局面,生成全部着法; if (bInCheck) { MoveSort.InitAll(pos); } else { // 7. 对于未被将军的局面,在生成着法前首先尝试空着(空着启发),即对局面作评价; vl = Evaluate(pos, vlAlpha, vlBeta); __ASSERT_BOUND(1 - WIN_VALUE, vl, WIN_VALUE - 1); __ASSERT(vl > vlBest); if (vl >= vlBeta) { #ifdef HASH_QUIESC RecordHashQ(pos, vl, MATE_VALUE); #endif return vl; } vlBest = vl; vlAlpha = MAX(vl, vlAlpha); // 8. 对于未被将军的局面,生成并排序所有吃子着法(MVV(LVA)启发); MoveSort.InitQuiesc(pos); } // 9. 用Alpha-Beta算法搜索这些着法; while ((mv = MoveSort.NextQuiesc(bInCheck)) != 0) { __ASSERT(bInCheck || pos.ucpcSquares[DST(mv)] > 0); if (pos.MakeMove(mv)) { vl = -SearchQuiesc(pos, -vlBeta, -vlAlpha); pos.UndoMakeMove(); if (vl > vlBest) { if (vl >= vlBeta) { #ifdef HASH_QUIESC if (vl > -WIN_VALUE && vl < WIN_VALUE) { RecordHashQ(pos, vl, MATE_VALUE); } #endif return vl; } vlBest = vl; vlAlpha = MAX(vl, vlAlpha); } } } // 10. 返回分值。 if (vlBest == -MATE_VALUE) { __ASSERT(pos.IsMate()); return pos.nDistance - MATE_VALUE; } else { #ifdef HASH_QUIESC if (vlBest > -WIN_VALUE && vlBest < WIN_VALUE) { RecordHashQ(pos, vlBest > vlAlpha ? vlBest : -MATE_VALUE, vlBest); } #endif return vlBest; } }
// 静态搜索 int SearchQuiesc ( int alpha, int beta ) { int mv, vl; int bvl = - MATE_VALUE; MoveSortStruct mvsort; if ( TimeOut() ) { // 超时 return bvl; } // 无害裁剪 vl = HarmlessPruning (); if ( vl > - MATE_VALUE ) { return vl; } // 置换裁剪 vl = QueryValueInHashTableQC ( alpha, beta ); if ( vl > - MATE_VALUE ) { return vl; } // 生成着法 if ( pos.checked ) { mvsort.InitMove (); } else { bvl = pos.Evaluate (); if ( bvl >= beta ) { InsertInfoToHashTableQC ( bvl, MATE_VALUE ); return bvl; } if ( bvl > alpha ) { alpha = bvl; } mvsort.InitGoodCapMove (); } // 大搜索 while ( (mv = mvsort.NextMove()) != 0 ) { pos.MakeMove (mv); vl = - SearchQuiesc ( -beta, -alpha ); pos.UndoMakeMove (); if ( TimeOut() ) { // 超时 return bvl; } if ( vl > bvl ) { bvl = vl; if ( bvl >= beta ) { if ( bvl > - BAN_VALUE && bvl < BAN_VALUE ) { InsertInfoToHashTableQC ( bvl, MATE_VALUE ); } return vl; } if ( bvl > alpha ) { alpha = bvl; } } } // 最后 if ( bvl > - BAN_VALUE && bvl < BAN_VALUE ) { InsertInfoToHashTableQC ( bvl, bvl ); } return bvl; }
// Alpha-Beta 搜索 int SearchAlphaBeta ( int depth, int alpha, int beta ) { int mv, vl; int bmv[nBest], bvl[nBest]; ClearBmvBvl ( bmv, bvl ); int hash_type = HASH_TYPE_ALPHA; MoveSortStruct mvsort; if ( TimeOut() ) { // 超时 return bvl[0]; } // 无害裁剪 vl = HarmlessPruning (); if ( vl > - MATE_VALUE ) { return vl; } // 置换裁剪 vl = QueryValueInHashTable ( depth, alpha, beta ); if ( vl > - MATE_VALUE ) { Search.bmv[0] = QueryMoveInHashTable ( depth, alpha, beta ); Search.bvl[0] = vl; return vl; } // 达到极限深度 if ( depth <= 0 ) { return SearchQuiesc ( alpha, beta ); } // 内部迭代加深启发 if ( depth > 2 ) { mv = QueryMoveInHashTableWithoutLimit (); if ( mv == 0 ) { SearchAlphaBeta ( depth / 2, alpha, beta ); if ( TimeOut() ) { // 超时 return bvl[0]; } } } // 生成着法 int nMoveNum = mvsort.InitMove (); Search.nNode ++; // 大搜索 while ( (mv = mvsort.NextMove()) != 0 ) { pos.MakeMove ( mv ); int newDepth = ( pos.checked || nMoveNum == 1 ) ? depth : depth - 1; vl = - SearchCut ( newDepth, - alpha ); if ( vl > alpha && vl < beta ) { vl = - SearchAlphaBeta ( newDepth, -beta, -alpha ); } pos.UndoMakeMove (); if ( TimeOut() ) { return bvl[0]; } UpdateBmvBvl ( bmv, bvl, mv, vl ); if ( bvl[0] >= beta ) { Search.nBeta ++; hash_type = HASH_TYPE_BETA; break; } if ( bvl[0] > alpha ) { alpha = bvl[0]; hash_type = HASH_TYPE_PV; } } // 最后 InsertInfoToHashTable ( depth, bmv[0], bvl[0], hash_type ); InsertHistoryTable ( bmv[0], depth ); CopyBmvBvl ( Search.bmv, Search.bvl, bmv, bvl ); return bvl[0]; }
// 零窗口搜索 int SearchCut ( int depth, int beta, bool bNoNull = false ) { int mv, vl; int bmv = 0; int bvl = - MATE_VALUE; MoveSortStruct mvsort; if ( TimeOut() ) { // 超时 return bvl; } // 无害裁剪 vl = HarmlessPruning (); if ( vl > - MATE_VALUE ) { return vl; } // 置换裁剪 vl = QueryValueInHashTable ( depth, beta - 1, beta ); if ( vl > - MATE_VALUE ) { return vl; } // 达到极限深度 if ( depth <= 0 ) { return SearchQuiesc ( beta - 1, beta ); } // 空着裁剪 : 大切に if ( !bNoNull && pos.checked == false && pos.NullOkay() ) { pos.NullMove (); vl = - SearchCut ( depth - NULL_DEPTH - 1, beta, true ); pos.UndoNullMove (); if ( TimeOut() ) { // 超时 return bvl; } if ( vl >= beta ) { if ( pos.NullSafe() ) { InsertInfoToHashTable ( MAX(depth, NULL_DEPTH + 1), 0, vl, HASH_TYPE_BETA ); return vl; } else if ( SearchCut(depth - NULL_DEPTH, beta, true) >= beta ) { InsertInfoToHashTable ( MAX(depth, NULL_DEPTH), 0, vl, HASH_TYPE_BETA ); return vl; } } } // 生成着法 int nMoveNum = mvsort.InitMove (); Search.nNode ++; // 大搜索 while ( (mv = mvsort.NextMove()) != 0 ) { pos.MakeMove ( mv ); int newDepth = ( pos.checked || nMoveNum == 1 ) ? depth : depth - 1; vl = - SearchCut ( newDepth, 1 - beta ); pos.UndoMakeMove (); if ( TimeOut() ) { // 超时 return bvl; } // 边界 if ( vl > bvl ) { bvl = vl; bmv = mv; if ( bvl >= beta ) { Search.nBeta ++; InsertInfoToHashTable ( depth, bmv, bvl, HASH_TYPE_BETA ); InsertHistoryTable ( bmv, depth ); return bvl; } } } // 最后 InsertInfoToHashTable ( depth, bmv, bvl, HASH_TYPE_ALPHA ); return bvl; }