public override Move move(IField field, int teamId, int turn) { Stopwatch sw = new Stopwatch(); sw.Start(); mMyTeamId = teamId; MaxMinBitField f = new MaxMinBitField(field, teamId, turn); MaxNode root = new MaxNode(f); Move bestMove = null; double bestScore = -1; int d = 1; Dictionary <ulong, MaxNode> maxNodesCache = new Dictionary <ulong, MaxNode>(100000); Dictionary <ulong, MinNode> minNodesCache = new Dictionary <ulong, MinNode>(100000); for (;; d++) { maxNodesCache.Clear(); minNodesCache.Clear(); double s = root.search(d, Double.NegativeInfinity, Double.PositiveInfinity, sw, maxNodesCache, minNodesCache); if (s < 0) { break; } bestMove = root.getBestChild().getLastMove(); bestScore = root.getScore(); if (s < 0.0001 || s >= 0.9999) { break; } } Debug.WriteLine("s:" + bestScore + "(d=" + d); mTotalDepth += d; return(bestMove); }
public double search(int depth, double alpha, double beta, Stopwatch sw, Dictionary <ulong, MaxNode> maxNodsCache, Dictionary <ulong, MinNode> minNodesCache) { if (mField == null) { if (sw.ElapsedMilliseconds > 200) { return(-1.0); } mField = new MaxMinBitField(mParent.getField()); var result = mField.updateByEnemyMove(mLastMove); mValue = result[0]; mProb = result[1]; } if (depth >= 4) { ulong hash = mField.TransPositionHash(); MaxNode node = null; if (maxNodsCache.TryGetValue(hash, out node)) { mScore = node.getScore(); return(mScore); } else { maxNodsCache.Add(hash, this); } } if (mProb == 1.0) { mScore = mValue; return(mValue); } if (depth <= 0) { mScore = mProb * mValue + (1.0 - mProb) * MaxMinVotingPlayer.Score(mField); return(mScore); } if (mChildList == null) { var moveList = MaxMinBitField.CreateMoves(mField, mField.getNextPlayerId()); mChildList = new List <MinNode>(moveList.Count); foreach (Move m in moveList) { mChildList.Add(new MinNode(m, this)); } } else { // 降順 mChildList.Sort((MinNode n0, MinNode n1) => { return(n0.getScore() > n1.getScore() ? -1 : n0.getScore() < n1.getScore() ? 1 : 0); }); } mScore = Double.NegativeInfinity; foreach (MinNode node in mChildList) { double s = mProb * mValue; if (s + (1.0 - mProb) <= mScore) { continue; } double childValue = node.search(depth - 1, alpha, beta, sw, maxNodsCache, minNodesCache); if (childValue < 0) { //打ち切り return(childValue); } s += (1.0 - mProb) * childValue; if (s > mScore) { mScore = s; mBestChild = node; if (s > alpha) { alpha = s; if (s >= beta) { break; } } } } return(mScore); }