Beispiel #1
0
        public static MetricWeights ReadMetricWeightsXml(XmlReader xmlReader)
        {
            if (null == xmlReader)
            {
                throw new ArgumentNullException("xmlReader");
            }

            MetricWeights mw = new MetricWeights();

            while (xmlReader.Read())
            {
                if (xmlReader.IsStartElement() && !xmlReader.Name.EndsWith("MetricWeights"))
                {
                    string key   = xmlReader.Name;
                    double value = xmlReader.ReadElementContentAsDouble();

                    BugType       bugType;
                    BugTypeWeight bugTypeWeight;

                    if (TryParseKeyName(key, out bugType, out bugTypeWeight))
                    {
                        mw.Set(bugType, bugTypeWeight, value + mw.Get(bugType, bugTypeWeight));
                    }
                }
            }

            return(mw);
        }
Beispiel #2
0
        public GameAI()
        {
            StartMetricWeights = new MetricWeights();
            EndMetricWeights   = new MetricWeights();

            TranspositionTable = new TranspositionTable();
        }
Beispiel #3
0
        public GameAI(GameAIConfig config)
        {
            if (null == config)
            {
                throw new ArgumentNullException("config");
            }

            StartMetricWeights = config.StartMetricWeights?.Clone() ?? new MetricWeights();
            EndMetricWeights   = config.EndMetricWeights?.Clone() ?? new MetricWeights();

            if (config.TranspositionTableSizeMB.HasValue)
            {
                if (config.TranspositionTableSizeMB.Value <= 0)
                {
                    throw new ArgumentOutOfRangeException("config.TranspositionTableSizeMB");
                }

                _transpositionTable = new TranspositionTable(config.TranspositionTableSizeMB.Value * 1024 * 1024);
            }
            else
            {
                _transpositionTable = new TranspositionTable();
            }

            if (config.MaxBranchingFactor.HasValue)
            {
                if (config.MaxBranchingFactor.Value <= 0)
                {
                    throw new ArgumentOutOfRangeException("config.MaxBranchingFactor");
                }

                _maxBranchingFactor = config.MaxBranchingFactor.Value;
            }
        }
Beispiel #4
0
        private void DeltaFromTransTable(GameBoard gameBoard, HashSet <ulong> visitedKeys, CancellationToken token, out MetricWeights deltaStart, out MetricWeights deltaEnd)
        {
            MetricWeights ds = new MetricWeights();
            MetricWeights de = new MetricWeights();

            ulong key    = gameBoard.ZobristKey;
            bool  newKey = visitedKeys.Add(key);

            if (newKey && TranspositionTable.TryLookup(key, out TranspositionTableEntry tEntry) && tEntry.Depth > 1 && !token.IsCancellationRequested)
            {
                double colorValue = gameBoard.CurrentTurnColor == PlayerColor.White ? 1.0 : -1.0;

                double boardScore = colorValue * TruncateBounds(CalculateBoardScore(gameBoard));

                double storedValue = TruncateBounds(tEntry.Value);

                BoardMetrics boardMetrics = gameBoard.GetBoardMetrics();

                MetricWeights startGradient = GetGradient(boardMetrics);
                MetricWeights endGradient   = startGradient.Clone();

                double scaleFactor = TreeStrapStepConstant * (storedValue - boardScore);

                double startRatio = boardMetrics.PiecesInHand / (double)(boardMetrics.PiecesInHand + boardMetrics.PiecesInPlay);
                double endRatio   = 1 - startRatio;

                startGradient.Scale(scaleFactor * startRatio * colorValue);
                endGradient.Scale(scaleFactor * endRatio * colorValue);

                if ((tEntry.Type == TranspositionTableEntryType.LowerBound || tEntry.Type == TranspositionTableEntryType.Exact) && storedValue > boardScore)
                {
                    ds.Add(startGradient);
                    de.Add(endGradient);
                }

                if ((tEntry.Type == TranspositionTableEntryType.UpperBound || tEntry.Type == TranspositionTableEntryType.Exact) && storedValue < boardScore)
                {
                    ds.Add(startGradient);
                    de.Add(endGradient);
                }

                foreach (Move move in GetValidMoves(gameBoard))
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    gameBoard.TrustedPlay(move);
                    DeltaFromTransTable(gameBoard, visitedKeys, token, out MetricWeights ds1, out MetricWeights de1);
                    ds.Add(ds1);
                    de.Add(de1);
                    gameBoard.UndoLastMove();
                }
            }

            deltaStart = ds;
            deltaEnd   = de;
        }
Beispiel #5
0
        public MetricWeights Clone()
        {
            MetricWeights clone = new MetricWeights();

            clone.CopyFrom(this);

            return(clone);
        }
Beispiel #6
0
        public void CopyFrom(MetricWeights source)
        {
            if (null == source)
            {
                throw new ArgumentNullException("source");
            }

            Array.Copy(source._bugTypeWeights, _bugTypeWeights, source._bugTypeWeights.Length);
        }
Beispiel #7
0
        public void Add(MetricWeights a)
        {
            if (null == a)
            {
                throw new ArgumentNullException("a");
            }

            for (int i = 0; i < _bugTypeWeights.Length; i++)
            {
                _bugTypeWeights[i] += a._bugTypeWeights[i];
            }
        }
Beispiel #8
0
        private static double CalculateBoardScore(BoardMetrics boardMetrics, MetricWeights startMetricWeights, MetricWeights endMetricWeights)
        {
            double endScore = CalculateBoardScore(boardMetrics, endMetricWeights);

            if (boardMetrics.PiecesInHand == 0)
            {
                // In "end-game", no need to blend
                return(endScore);
            }
            else
            {
                // Pieces still in hand, blend start and end scores
                double startScore = CalculateBoardScore(boardMetrics, startMetricWeights);

                double startRatio = boardMetrics.PiecesInHand / (double)(boardMetrics.PiecesInHand + boardMetrics.PiecesInPlay);
                double endRatio   = 1 - startRatio;

                return((startRatio * startScore) + (endRatio * endScore));
            }
        }
Beispiel #9
0
        private MetricWeights GetGradient(BoardMetrics boardMetrics)
        {
            MetricWeights gradient = new MetricWeights();

            foreach (PieceName pieceName in EnumUtils.PieceNames)
            {
                BugType bugType = EnumUtils.GetBugType(pieceName);

                double colorValue = EnumUtils.GetColor(pieceName) == PlayerColor.White ? 1.0 : -1.0;

                gradient.Set(bugType, BugTypeWeight.InPlayWeight, gradient.Get(bugType, BugTypeWeight.InPlayWeight) + colorValue * boardMetrics[pieceName].InPlay);
                gradient.Set(bugType, BugTypeWeight.IsPinnedWeight, gradient.Get(bugType, BugTypeWeight.IsPinnedWeight) + colorValue * boardMetrics[pieceName].IsPinned);
                gradient.Set(bugType, BugTypeWeight.IsCoveredWeight, gradient.Get(bugType, BugTypeWeight.IsCoveredWeight) + colorValue * boardMetrics[pieceName].IsCovered);
                gradient.Set(bugType, BugTypeWeight.NoisyMoveWeight, gradient.Get(bugType, BugTypeWeight.NoisyMoveWeight) + colorValue * boardMetrics[pieceName].NoisyMoveCount);
                gradient.Set(bugType, BugTypeWeight.QuietMoveWeight, gradient.Get(bugType, BugTypeWeight.QuietMoveWeight) + colorValue * boardMetrics[pieceName].QuietMoveCount);
                gradient.Set(bugType, BugTypeWeight.FriendlyNeighborWeight, gradient.Get(bugType, BugTypeWeight.FriendlyNeighborWeight) + colorValue * boardMetrics[pieceName].FriendlyNeighborCount);
                gradient.Set(bugType, BugTypeWeight.EnemyNeighborWeight, gradient.Get(bugType, BugTypeWeight.EnemyNeighborWeight) + colorValue * boardMetrics[pieceName].EnemyNeighborCount);
            }

            return(gradient);
        }
Beispiel #10
0
        private static double CalculateBoardScore(BoardMetrics boardMetrics, MetricWeights metricWeights)
        {
            double score = 0;

            foreach (PieceName pieceName in EnumUtils.PieceNames)
            {
                BugType bugType = EnumUtils.GetBugType(pieceName);

                double colorValue = EnumUtils.GetColor(pieceName) == PlayerColor.White ? 1.0 : -1.0;

                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.InPlayWeight) * boardMetrics[pieceName].InPlay;
                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.IsPinnedWeight) * boardMetrics[pieceName].IsPinned;
                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.IsCoveredWeight) * boardMetrics[pieceName].IsCovered;
                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.NoisyMoveWeight) * boardMetrics[pieceName].NoisyMoveCount;
                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.QuietMoveWeight) * boardMetrics[pieceName].QuietMoveCount;
                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.FriendlyNeighborWeight) * boardMetrics[pieceName].FriendlyNeighborCount;
                score += colorValue * metricWeights.Get(bugType, BugTypeWeight.EnemyNeighborWeight) * boardMetrics[pieceName].EnemyNeighborCount;
            }

            return(score);
        }
Beispiel #11
0
        public MetricWeights GetNormalized(double targetMaxValue = 100.0, bool round = true, int decimals = 6)
        {
            if (targetMaxValue <= 0.0)
            {
                throw new ArgumentOutOfRangeException("targetMaxValue");
            }

            MetricWeights clone = Clone();

            // Copy bug weights into local array
            double[] dblWeights = new double[clone._bugTypeWeights.Length];
            Array.Copy(clone._bugTypeWeights, dblWeights, clone._bugTypeWeights.Length);

            double max = double.MinValue;

            foreach (double weight in dblWeights)
            {
                max = Math.Max(max, Math.Abs(weight));
            }

            // Normalize to new range
            for (int i = 0; i < dblWeights.Length; i++)
            {
                double value    = dblWeights[i];
                int    sign     = Math.Sign(value);
                double absValue = Math.Abs(value);

                dblWeights[i] = sign * (absValue / max) * targetMaxValue;
            }

            // Populate clone with normalized weights
            for (int i = 0; i < clone._bugTypeWeights.Length; i++)
            {
                clone._bugTypeWeights[i] = round ? Math.Round(dblWeights[i], decimals) : dblWeights[i];
            }

            return(clone);
        }