/// <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()