public override bool MatchAction(Reflex reflex, out object param)
        {
            param = null;
            // Previously the default here was false.  But when I removed the hiddendefault comparison
            // this started causing timers with random times to fail.  HiddenDefault is evil and
            // should never exist.
            // At a deeper level there's something not quite right with the architecture if it doesn't
            // allow scores to be used as timer inputs without adding hidden tiles.  Need to understand
            // this better.
            bool match = true;

            if (reflex.targetSet != null && reflex.targetSet.Param != null)
            {
                GameScoredSensorResult sensorResult = (GameScoredSensorResult)reflex.targetSet.Param;

                Debug.Assert(sensorResult != null, "Why would this ever be null?");

                // Just looking to see if that bucket has changed.
                if (sensorResult.TestingForChange)
                {
                    match = sensorResult.ScoreChanged;
                }
                else
                {
                    // Actually doing a comparison.
                    switch (op)
                    {
                    case ScoreCompare.Is:
                        match = sensorResult.LeftValue == sensorResult.RightValue;
                        break;

                    case ScoreCompare.Above:
                        match = sensorResult.LeftValue > sensorResult.RightValue;
                        break;

                    case ScoreCompare.Below:
                        match = sensorResult.LeftValue < sensorResult.RightValue;
                        break;

                    case ScoreCompare.GTEQ:
                        match = sensorResult.LeftValue >= sensorResult.RightValue;
                        break;

                    case ScoreCompare.LTEQ:
                        match = sensorResult.LeftValue <= sensorResult.RightValue;
                        break;

                    case ScoreCompare.NotIs:
                        match = sensorResult.LeftValue != sensorResult.RightValue;
                        break;
                    }
                }
            }   // if not null target set

            return(match);
        }   // end of MatchAction()
        /// <summary>
        /// Gets the current score values based of the set of filters.
        /// This used to return the ScoreBucket but by calculating the scores here
        /// we can allow richer comparisons.
        /// The Health Filter can also be used as a value as can SettingsFilters.
        ///
        /// The result values depend on how the sensor is used.
        ///
        /// --Testing for Health
        /// WHEN Health Comparison Points
        ///
        /// --Testing for change.
        /// WHEN Red DO
        ///     Bucket will contain the bucket to test for changed value from the previous frame.
        ///
        /// --Testing against a value.
        /// WHEN Red 5Points 2Points Green
        ///     Left will contain the value for red.
        ///     Right will contain value to compare against.
        ///     CompareOp will contain the op to apply, in this case equals.
        ///
        /// --Comparisons
        /// WHEN Red White 2Points > Blue Blue Random Green 5Points
        ///     Left will contain the sum of the values to the left of the comparison.
        ///     Right will contain the sum of the values to the right of the comparison.
        ///     CompareOp will contain the op to apply.
        ///
        /// </summary>
        /// <param name="actor"></param>
        /// <param name="reflex"></param>
        /// <returns></returns>
        public static GameScoredSensorResult ScoresFromFilterSet(GameActor actor, Reflex reflex)
        {
            List <Filter> filters = reflex.Filters;

            GameScoredSensorResult result = new GameScoredSensorResult();

            bool testingHealth = reflex.sensorUpid == "sensor.health";

            if (!testingHealth && TestScoreChange(filters))
            {
                // Find ScoreBucketFilter and grab it's bucket.
                foreach (Filter filter in filters)
                {
                    ScoreBucketFilter sbf = filter as ScoreBucketFilter;
                    if (sbf != null)
                    {
                        int curScore  = Scoreboard.GetScore(actor, sbf);
                        int prevScore = Scoreboard.GetPrevScore(actor, sbf);

                        result.TestingForChange = true;
                        result.ScoreChanged     = curScore != prevScore;
                    }
                }
            }
            else if (!testingHealth && TestScoreValue(filters))
            {
                bool hasScoreBucket   = false; // Do we have a scorebucket in our list of filters?
                int  scoreBucketIndex = -1;
                for (int i = 0; i < filters.Count; i++)
                {
                    if (filters[i] is ScoreBucketFilter)
                    {
                        hasScoreBucket   = true;
                        scoreBucketIndex = i;
                    }
                }

                Filter specialFilter     = null; // Will be either RandomFilter or PercentFiter if found.
                int    pointsPostSpecial = 0;

                if (hasScoreBucket)
                {
                    // Compare first scorebucket value to sum of all other values.

                    // Use first found scorebucket as left value.
                    result.LeftValue = Scoreboard.GetScore(actor, filters[scoreBucketIndex] as ScoreBucketFilter);

                    // Sum remaining tiles for right value.
                    for (int i = 0; i < filters.Count; i++)
                    {
                        if (i == scoreBucketIndex)
                        {
                            // Skip over the first scorebucket filter.
                            continue;
                        }

                        if (filters[i] is RandomFilter || filters[i] is PercentFilter)
                        {
                            Debug.Assert(specialFilter == null, "Two special tiles should not be valid here.");
                            specialFilter = filters[i];
                        }

                        ScoreFilter sf = filters[i] as ScoreFilter;
                        if (sf != null)
                        {
                            if (specialFilter != null)
                            {
                                pointsPostSpecial += sf.points;
                            }
                            else
                            {
                                result.RightValue += sf.points;
                            }
                        }

                        if (filters[i] is HealthFilter)
                        {
                            if (specialFilter != null)
                            {
                                pointsPostSpecial += actor.HitPoints;
                            }
                            else
                            {
                                result.RightValue += actor.HitPoints;
                            }
                        }

                        SettingsFilter settings = filters[i] as SettingsFilter;
                        if (settings != null)
                        {
                            if (specialFilter != null)
                            {
                                pointsPostSpecial += actor.GetSettingsValue(actor, settings.name);
                            }
                            else
                            {
                                result.RightValue += actor.GetSettingsValue(actor, settings.name);
                            }
                        }
                    }   // end of loop over filters.
                }
                else
                {
                    // No scorebucket exists therefore compare the total to the Red score.

                    // Use red bucket as left value.
                    result.LeftValue = Scoreboard.GetGlobalScore((ScoreBucket)Classification.Colors.Red);

                    // Sum point tiles for right value.
                    for (int i = 0; i < filters.Count; i++)
                    {
                        if (filters[i] is RandomFilter || filters[i] is PercentFilter)
                        {
                            Debug.Assert(specialFilter == null, "Two special tiles should not be valid here.");
                            specialFilter = filters[i];
                        }

                        ScoreFilter sf = filters[i] as ScoreFilter;
                        if (sf != null)
                        {
                            if (specialFilter != null)
                            {
                                pointsPostSpecial += sf.points;
                            }
                            else
                            {
                                result.RightValue += sf.points;
                            }
                        }

                        if (filters[i] is HealthFilter)
                        {
                            if (specialFilter != null)
                            {
                                pointsPostSpecial += actor.HitPoints;
                            }
                            else
                            {
                                result.RightValue += actor.HitPoints;
                            }
                        }

                        SettingsFilter settings = filters[i] as SettingsFilter;
                        if (settings != null)
                        {
                            if (specialFilter != null)
                            {
                                pointsPostSpecial += actor.GetSettingsValue(actor, settings.name);
                            }
                            else
                            {
                                result.RightValue += actor.GetSettingsValue(actor, settings.name);
                            }
                        }
                    }   // end of loop over filters.
                }

                // Calc effect of special tiles.
                if (specialFilter != null)
                {
                    if (specialFilter is RandomFilter)
                    {
                        if (pointsPostSpecial > 0)
                        {
                            result.RightValue += BokuGame.bokuGame.rnd.Next(pointsPostSpecial);
                        }
                        else if (pointsPostSpecial < 0)
                        {
                            result.RightValue -= BokuGame.bokuGame.rnd.Next(-pointsPostSpecial);
                        }
                    }
                    if (specialFilter is PercentFilter)
                    {
                        result.RightValue = (int)Math.Round((float)result.RightValue / 100.0f * (float)pointsPostSpecial);
                    }
                }

                // Set op to equals.
                result.CompareOp = ScoreCompareFilter.ScoreCompare.Is;
            }
            else if (TestComparison(filters))
            {
                // If testing health, the lhs is just the # hitkpoints.
                if (testingHealth)
                {
                    result.LeftValue = actor.HitPoints;
                }

                // Sum left side.
                Filter specialFilter     = null; // Will be either RandomFilter or PercentFiter if found.
                int    pointsPostSpecial = 0;

                int filterIndex = 0;
                for (; filterIndex < filters.Count; filterIndex++)
                {
                    // Did we find a comparison filter, if so we're done with the left side.
                    if (filters[filterIndex] is ScoreCompareFilter)
                    {
                        break;
                    }

                    // Did we find a special filter?
                    if (filters[filterIndex] is RandomFilter || filters[filterIndex] is PercentFilter)
                    {
                        Debug.Assert(specialFilter == null, "Two special tiles should not be valid here.");
                        specialFilter = filters[filterIndex];
                    }

                    ScoreFilter sf = filters[filterIndex] as ScoreFilter;
                    if (sf != null)
                    {
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += sf.points;
                        }
                        else
                        {
                            result.LeftValue += sf.points;
                        }
                    }

                    ScoreBucketFilter sbf = filters[filterIndex] as ScoreBucketFilter;
                    if (sbf != null)
                    {
                        int sbValue = Scoreboard.GetScore(actor, sbf);
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += sbValue;
                        }
                        else
                        {
                            result.LeftValue += sbValue;
                        }
                    }

                    if (filters[filterIndex] is HealthFilter)
                    {
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += actor.HitPoints;
                        }
                        else
                        {
                            result.LeftValue += actor.HitPoints;
                        }
                    }

                    SettingsFilter settings = filters[filterIndex] as SettingsFilter;
                    if (settings != null)
                    {
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += actor.GetSettingsValue(actor, settings.name);
                        }
                        else
                        {
                            result.LeftValue += actor.GetSettingsValue(actor, settings.name);
                        }
                    }
                }   // end of loop over left hand side

                // Apply effect of specials.
                if (specialFilter != null)
                {
                    if (specialFilter is RandomFilter)
                    {
                        if (pointsPostSpecial > 0)
                        {
                            result.LeftValue += BokuGame.bokuGame.rnd.Next(pointsPostSpecial);
                        }
                        else if (pointsPostSpecial < 0)
                        {
                            result.LeftValue -= BokuGame.bokuGame.rnd.Next(-pointsPostSpecial);
                        }
                    }
                    if (specialFilter is PercentFilter)
                    {
                        result.LeftValue = (int)Math.Round((float)result.LeftValue / 100.0f * (float)pointsPostSpecial);
                    }
                }

                // Grab op from ComparisonFilter which we should be looking at.
                result.CompareOp = (filters[filterIndex] as ScoreCompareFilter).op;
                ++filterIndex;

                // Now sum right hand side.
                specialFilter     = null;
                pointsPostSpecial = 0;

                for (; filterIndex < filters.Count; filterIndex++)
                {
                    // Did we find a comparison filter, if so we're broken.  There should be only one.
                    if (filters[filterIndex] is ScoreCompareFilter)
                    {
                        Debug.Assert(false, "Invalid to have two compare filters.");
                    }

                    // Did we find a random filter?
                    if (filters[filterIndex] is RandomFilter)
                    {
                        Debug.Assert(specialFilter == null, "Two special tiles should not be valid here.");
                        specialFilter = filters[filterIndex];
                    }

                    ScoreFilter sf = filters[filterIndex] as ScoreFilter;
                    if (sf != null)
                    {
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += sf.points;
                        }
                        else
                        {
                            result.RightValue += sf.points;
                        }
                    }

                    ScoreBucketFilter sbf = filters[filterIndex] as ScoreBucketFilter;
                    if (sbf != null)
                    {
                        int sbValue = Scoreboard.GetScore(actor, sbf);
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += sbValue;
                        }
                        else
                        {
                            result.RightValue += sbValue;
                        }
                    }

                    if (filters[filterIndex] is HealthFilter)
                    {
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += actor.HitPoints;
                        }
                        else
                        {
                            result.RightValue += actor.HitPoints;
                        }
                    }

                    SettingsFilter settings = filters[filterIndex] as SettingsFilter;
                    if (settings != null)
                    {
                        if (specialFilter != null)
                        {
                            pointsPostSpecial += actor.GetSettingsValue(actor, settings.name);
                        }
                        else
                        {
                            result.RightValue += actor.GetSettingsValue(actor, settings.name);
                        }
                    }
                }   // end of loop over right hand side

                // Apply effec of special tiles.
                if (specialFilter != null)
                {
                    if (specialFilter is RandomFilter)
                    {
                        if (pointsPostSpecial > 0)
                        {
                            result.RightValue += BokuGame.bokuGame.rnd.Next(pointsPostSpecial);
                        }
                        else if (pointsPostSpecial < 0)
                        {
                            result.RightValue -= BokuGame.bokuGame.rnd.Next(-pointsPostSpecial);
                        }
                    }
                    if (specialFilter is PercentFilter)
                    {
                        result.RightValue = (int)Math.Round((float)result.RightValue / 100.0f * (float)pointsPostSpecial);
                    }
                }
            }
            else
            {
                Debug.Assert(false, "Not sure what we're testing for.  Not good.");
            }

            return(result);
        }   // end of ScoresFromFilterSet()