Пример #1
0
        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);
        }
Пример #2
0
        public MaxMinBitField(MaxMinBitField other)
        {
            mMyGoodGhostBit = other.mMyGoodGhostBit;
            mMyEvilGhostBit = other.mMyEvilGhostBit;
            mEnemyGhostBit  = other.mEnemyGhostBit;
            mEnemyEvilNum   = other.mEnemyEvilNum;
            mEnemyGoodNum   = other.mEnemyGoodNum;
            mMyPlayerId     = other.mMyPlayerId;

            mTurn         = other.mTurn;
            mNextPlayerId = other.mNextPlayerId;
        }
Пример #3
0
        static public double Score(MaxMinBitField f)
        {
            double myGhostTypeScore    = f.countMyGood() * 0.8 + f.getEnemyEvil() * 0.2;
            double enemyGhostTypeScore = f.getEnemyGood() * 0.8 + f.getEnemyEvil() * 0.2;
            double myManhattanScore    = f.myGoodManhattanScore() * 0.6 + f.myEvilManhattanScore() * 0.4;
            double enemyManhattanScore = f.enemyManhattanScoreAllColor();

            double myScore    = myGhostTypeScore * 1000 - myManhattanScore;
            double enemyScore = enemyGhostTypeScore * 1000 - enemyManhattanScore;

            double s = myScore / (myScore + enemyScore);

            //            Debug.WriteLine(f + "Score:" + s);
            return(s);
        }
Пример #4
0
        private static List <Move> sMovesBuff = new List <Move>(6 * 4);    // 高速化のための魔改造的バッファ
        public static List <Move> CreateMoves(MaxMinBitField field, int teamId)
        {
            sMovesBuff.Clear();
            ulong myEvilGhostBit = field.mMyEvilGhostBit;
            ulong myGoodGhostBit = field.mMyGoodGhostBit;
            ulong myGhostBit     = myEvilGhostBit | myGoodGhostBit;

            ulong targetGhostBit = (teamId == field.mMyPlayerId) ? myGhostBit : field.mEnemyGhostBit;
            ulong unpassable     = targetGhostBit | cWall;

            //
            ulong left  = (targetGhostBit >> 1) & ~unpassable;
            ulong right = (targetGhostBit << 1) & ~unpassable;
            ulong up    = (targetGhostBit >> 7) & ~unpassable;
            ulong down  = (targetGhostBit << 7) & ~unpassable;
            //いずれかに遷移できたものを残す
            ulong movable = (left << 1) | (right >> 1) | (up << 7) | (down >> 7);

            while (targetGhostBit != 0)
            {
                var target = Bit.rightOneBits(targetGhostBit);
                int index  = Bit.GetNumberOfTrailingZeros(target);
                int x      = index % 7 - 1;
                int y      = index / 7 - 1;

                foreach (Way w in WayUtil.way4)
                {
                    var toBit =
                        w == Way.Left ? (target >> 1) :
                        w == Way.Right ? (target << 1) :
                        w == Way.Up ? (target >> 7) :
                        target << 7;

                    if ((toBit & unpassable) != 0)
                    {
                        continue;
                    }

                    sMovesBuff.Add(new Move(new TPoint(x, y), w));
                }
                targetGhostBit &= ~target;
            }
            return(sMovesBuff);
        }
Пример #5
0
        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.updateByMyMove(mLastMove);
                mValue = result[0];
                mProb  = result[1];
            }

            if (depth >= 4)
            {
                ulong   hash = mField.TransPositionHash();
                MinNode node = null;
                if (minNodesCache.TryGetValue(hash, out node))
                {
                    mScore = node.getScore();
                    return(mScore);
                }
                else
                {
                    minNodesCache.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 <MaxNode>(moveList.Count);
                foreach (Move m in moveList)
                {
                    mChildList.Add(new MaxNode(m, this));
                }
            }
            else
            {
                // 昇順
                mChildList.Sort((MaxNode n0, MaxNode n1) =>
                {
                    return(n0.getScore() > n1.getScore() ? 1 :
                           n0.getScore() < n1.getScore() ? -1 : 0);
                });
            }
            mScore = Double.PositiveInfinity;
            foreach (MaxNode node in mChildList)
            {
                double s = mProb * mValue;
                if (s >= 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;
                    if (s < beta)
                    {
                        beta = s;
                        if (s <= alpha)
                        {
                            break;
                        }
                    }
                }
            }
            return(mScore);
        }
Пример #6
0
 public MaxNode(MaxMinBitField field)
 {
     mField    = field;
     mLastMove = null;
     mParent   = null;
 }