public static void InitTranslationTable() { ChessBoard InitCB = new ChessBoard(); InitChessBoardHashCode = NodeTranslationTable.ZobristList[0, 0, 3]; InitChessBoardHashCode = InitChessBoardHashCode ^ NodeTranslationTable.ZobristList[1, 6, 3]; TranslationTable.GameTreeNodeForHash NodeBuff = new TranslationTable.GameTreeNodeForHash(); //NodeTranslationTable.ChessBoardTT.Add(InitChessBoardHashCode, NodeBuff); }
/// <summary> /// 以Alpha-Beta剪枝框架并使用TranslationTable生成博弈树 /// </summary> /// <param name="ThisChessBoard">当前棋盘状态</param> /// <param name="ThisNode">当前博弈树节点</param> public void ExpandNode_ABPruning(ChessBoard ThisChessBoard, GameTreeNode ThisNode, bool IfUseTT = true) { if (IfUseTT) { bool IfInTT = false; TranslationTable.GameTreeNodeForHash HashNode1 = new TranslationTable.GameTreeNodeForHash(); HashNode1 = NodeTranslationTable.Search(ThisNode.NodeHashCode, ref IfInTT); if (ThisNode.depth != 0 && IfInTT && ThisNode.depth + RootDepth <= HashNode1.depth) { ThisNode.alpha = HashNode1.alpha; ThisNode.beta = HashNode1.beta; return; } } ///暂存一些量以便恢复 EnumNowPlayer PlayerSave = NowQuoridor.ReversePlayer(ThisNode.NodePlayer); NowQuoridor.Player_Now = PlayerSave; List <QuoridorAction> QABuff = NowQuoridor.ActionList; //QABuff = NowQuoridor.CreateActionList_ALL(ThisChessBoard, ThisNode.P1Distance, ThisNode.P2Distance); QABuff = NowQuoridor.CreateActionList(ThisChessBoard, GameTreePlayer , ThisNode.NodeAction.ActionCheckResult.P1Distance , ThisNode.NodeAction.ActionCheckResult.P2Distance); foreach (QuoridorAction QA in QABuff) { #region 保存棋盘状态 ChessBoard ChessBoardBuff = new ChessBoard(); ChessBoard.SaveChessBoard(ref ChessBoardBuff, ThisChessBoard); #endregion #region 模拟落子 string Hint = NowQuoridor.QuoridorRule.Action(ref ThisChessBoard, QA.ActionPoint.X, QA.ActionPoint.Y, QA.PlayerAction); try { if (Hint != "OK") { Exception e = new Exception(); } } catch (Exception) { throw; } if (QA.PlayerAction == NowAction.Action_PlaceHorizontalBoard || QA.PlayerAction == NowAction.Action_PlaceVerticalBoard) { if (PlayerSave == EnumNowPlayer.Player1) { ThisChessBoard.NumPlayer1Board -= 2; } else { ThisChessBoard.NumPlayer2Board -= 2; } } #endregion if (ThisNode.depth <= DepthMax) { CreateNewSon(ThisNode, new GameTreeNode(QA , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, ThisNode.beta, ThisNode.score)); if (IfUseTT) { long HashCodeBuff = NodeTranslationTable.NodeGetHashCode(ThisNode.NodeHashCode, QA, ChessBoardBuff);//ThisChessBoard已变,不能作为原棋盘传入,只能上一步的棋盘ChessBoardBuff ThisNode.SonNode.Last().NodeHashCode = HashCodeBuff; } ExpandNode_ABPruning(ThisChessBoard, ThisNode.SonNode.Last(), IfUseTT); } else { CreateNewSon(ThisNode, new GameTreeNode(QA , PlayerSave, ThisNode.depth + 1, ThisNode.alpha, QA.WholeScore, QA.WholeScore)); } ChessBoard.ResumeChessBoard(ref ThisChessBoard, ChessBoardBuff); #region Min层 if (ThisNode.NodePlayer == PolicyPlayer) { if (ThisNode.SonNode.Last().alpha < ThisNode.beta) { ThisNode.beta = ThisNode.SonNode.Last().alpha; ThisNode.score = ThisNode.SonNode.Last().alpha; } } #endregion #region Max层 else { if (ThisNode.SonNode.Last().beta > ThisNode.alpha) { ThisNode.alpha = ThisNode.SonNode.Last().beta; ThisNode.score = ThisNode.SonNode.Last().beta; } } #endregion if (ThisNode.depth <= DepthMax && ThisNode.beta <= ThisNode.alpha)//剪枝 { #region 存入置换表 if (IfUseTT) { /*剪枝break前这个时刻该节点已经遍历完毕,可以加入置换表*/ TranslationTable.GameTreeNodeForHash HashNodeBuff = new TranslationTable.GameTreeNodeForHash(); HashNodeBuff.alpha = ThisNode.alpha; HashNodeBuff.beta = ThisNode.beta; HashNodeBuff.depth = ThisNode.depth + RootDepth; NodeTranslationTable.Add(ThisNode.NodeHashCode, HashNodeBuff); } #endregion break; } } #region 存入置换表 if (IfUseTT) { /*遍历完整个动作列表后可以加入置换表*/ TranslationTable.GameTreeNodeForHash HashNodeBuff2 = new TranslationTable.GameTreeNodeForHash(); HashNodeBuff2.alpha = ThisNode.alpha; HashNodeBuff2.beta = ThisNode.beta; HashNodeBuff2.depth = ThisNode.depth + RootDepth; NodeTranslationTable.Add(ThisNode.NodeHashCode, HashNodeBuff2); } #endregion }