/// <summary>
        /// Build all the internal analysis data for the given PieceGrid
        /// </summary>
        /// <param name="pieceGrid">PieceGrid to analyze</param>
        /// <param name="playerToMove">Player whos turn it is</param>
        public void BuildAnalysis(PieceGrid pieceGrid, Owner playerToMove)
        {
            if (pieceGrid.Id == LastAnalyzedPieceGridId)
            {
                return;
            }
            LastAnalyzedPieceGridId = pieceGrid.Id;

            LocalAdvantages        = new PointSquareArray <LocalAdvantage>(pieceGrid.Size);
            AmazonMobilityScores   = new PointSquareArray <double>(pieceGrid.Size);
            SpecificQueenDistances = new PointSquareArray <PointSquareArray <double> >(pieceGrid.Size);
            SpecificKingDistances  = new PointSquareArray <PointSquareArray <double> >(pieceGrid.Size);

            SpecificQueenDistances.Clear();
            SpecificKingDistances.Clear();

            Player1QueenMinDistances = BuildDistancesDictionary(pieceGrid, Owner.Player1, true);
            Player1KingMinDistances  = BuildDistancesDictionary(pieceGrid, Owner.Player1, false);
            Player2QueenMinDistances = BuildDistancesDictionary(pieceGrid, Owner.Player2, true);
            Player2KingMinDistances  = BuildDistancesDictionary(pieceGrid, Owner.Player2, false);

            CalculateLocalAdvantages(pieceGrid, playerToMove);
            CalculateAllAmazonMobility(pieceGrid);

            W = LocalAdvantages.Where(a => a.Value != null && a.Value.Player1Reachable && a.Value.Player2Reachable)
                .Sum(a => Math.Pow(2, -(Math.Abs(a.Value.Player1QueenDistance - a.Value.Player2QueenDistance))));
            C1 = 2 * LocalAdvantages.Where(a => a.Value != null).Sum(a => Math.Pow(2, -(a.Value.Player1QueenDistance)) - Math.Pow(2, -(a.Value.Player2QueenDistance)));
            C2 = LocalAdvantages.Where(a => a.Value != null).Sum(a => Math.Min(1, Math.Max(-1, (a.Value.Player2KingDistance - a.Value.Player1KingDistance) / 6d)));
            T1 = LocalAdvantages.Where(a => a.Value != null).Sum(a => a.Value.DeltaQueen);
            T2 = LocalAdvantages.Where(a => a.Value != null).Sum(a => a.Value.DeltaKing);

            T = (F1(W) * T1) + (F2(W) * C1) + (F3(W) * C2) + (F4(W) * T2);

            double player1MobilitySum = AmazonMobilityScores.Where(s => pieceGrid.Amazon1Points.Contains(s.Key))
                                        .Sum(s => IndividualWeightForM(W, s.Value));
            double player2MobilitySum = AmazonMobilityScores.Where(s => pieceGrid.Amazon2Points.Contains(s.Key))
                                        .Sum(s => IndividualWeightForM(W, s.Value));

            M = player2MobilitySum - player1MobilitySum;
        }
        /// <summary>
        /// Build all the internal analysis data for the given PieceGrid
        /// </summary>
        /// <param name="pieceGrid">PieceGrid to analyze</param>
        /// <param name="playerToMove">Player whos turn it is</param>
        public void BuildAnalysis(PieceGrid pieceGrid, Owner playerToMove)
        {
            if (pieceGrid.Id == LastAnalyzedPieceGridId)
            {
                return;
            }
            LastAnalyzedPieceGridId = pieceGrid.Id;

            LocalAdvantages = new PointSquareArray <LocalAdvantage>(pieceGrid.Size);

            Player1QueenMinDistances = BuildDistancesDictionary(pieceGrid, Owner.Player1);
            Player2QueenMinDistances = BuildDistancesDictionary(pieceGrid, Owner.Player2);

            CalculateLocalAdvantages(pieceGrid, playerToMove);

            T1 = LocalAdvantages.Where(a => a.Value != null).Sum(a => a.Value.DeltaQueen);
        }