private void FloodFillMinDistancesQueen(Point point, PieceGrid pieceGrid, PointSquareArray <double?> result)
        {
            ISet <Point>            visited = new HashSet <Point>();
            Queue <(Point, double)> toVisit = new Queue <(Point, double)>();

            foreach (Point p in pieceGrid.GetOpenPointsOutFrom(point))
            {
                toVisit.Enqueue((p, 1));
            }

            while (toVisit.Any())
            {
                (Point, double)p = toVisit.Dequeue();
                if (visited.Contains(p.Item1))
                {
                    continue;
                }
                if (result[p.Item1].HasValue)
                {
                    result[p.Item1] = Math.Min(p.Item2, result[p.Item1].Value);
                }
                else
                {
                    result.Add(p.Item1, p.Item2);
                }
                visited.Add(p.Item1);
                foreach (Point pNext in pieceGrid.GetOpenPointsOutFrom(p.Item1)
                         .Where(adj => !visited.Contains(adj)))
                {
                    toVisit.Enqueue((pNext, p.Item2 + 1));
                }
            }
        }
Example #2
0
        /// <summary>
        /// Calculate the mobility score for a specific amazon point on the PieceGrid.
        /// </summary>
        /// <remarks>
        /// Mobility is based on the breathing space of each space that can be moved to by an
        /// amazon at the given point. Closer (king distance) spaces are more valuable than
        /// distant ones.
        /// </remarks>
        /// <param name="p">Point containing an amazon</param>
        /// <param name="pieceGrid">PieceGrid to analyze</param>
        /// <returns>Numeric mobility score, higher numbers = more mobile</returns>
        private double CalculateAmazonMobility(Point p, Owner owner, PieceGrid pieceGrid)
        {
            IDictionary <Point, double?> minDistancesOppositePlayer;

            if (owner == Owner.Player1)
            {
                minDistancesOppositePlayer = Player2QueenMinDistances;
            }
            else if (owner == Owner.Player2)
            {
                minDistancesOppositePlayer = Player1QueenMinDistances;
            }
            else
            {
                throw new ArgumentException($"Point {p} doesn't have an amazon for either player!");
            }

            double mobility = 0d;

            foreach (Point target in pieceGrid.GetOpenPointsOutFrom(p))
            {
                int degree = target.GetAdjacentPoints()
                             .Where(adj => pieceGrid.PointPieces.ContainsKey(adj) && !pieceGrid.PointPieces[adj].Impassible)
                             .Count();
                if (!minDistancesOppositePlayer.ContainsKey(target))
                {
                    continue;
                }
                if (owner == Owner.Player1 && !LocalAdvantages[target].Player2Reachable)
                {
                    continue;
                }
                if (owner == Owner.Player2 && !LocalAdvantages[target].Player1Reachable)
                {
                    continue;
                }
                double localMobility = Math.Pow(2, -(SpecificKingDistances[p][target])) * degree;
                mobility += localMobility;
            }
            return(mobility);
        }