static private IEnumerable <int[]> GeneratePossibleCombinations(ExpressionMinigameSettings inLevel) { // Bitwise subset mask algorithm from: // https://www.topcoder.com/community/data-science/data-science-tutorials/a-bit-of-fun-fun-with-bits/ int[] combination = new int[inLevel.NumValueSlots]; int mask = (1 << combination.Length) - 1; while ((mask & (1 << inLevel.Chickens.Length)) == 0) { int chickenIndex = 0; for (int i = 0; i < inLevel.Chickens.Length; ++i) { int chickenBit = 1 << i; if ((chickenBit & mask) > 0) { combination[chickenIndex++] = inLevel.Chickens[i]; } } yield return(combination); int lowBit = mask & ~(mask - 1); int lowZero = (mask + lowBit) & ~mask; mask |= lowZero; mask &= ~(lowZero - 1); mask |= (lowZero / lowBit / 2) - 1; } }
static private bool ValidateLevel(JSONNode inLevelJSON) { ExpressionMinigameSettings level = ExpressionMinigameSettings.FromJSON(inLevelJSON, ExpressionMinigameCategories.Single); bool bCanSolve = false; // Horrible, brute force solving foreach (int[] combination in GeneratePossibleCombinations(level)) { if (CanReachTarget(level, combination)) { bCanSolve = true; break; } } if (!bCanSolve) { UnityEngine.Debug.LogWarningFormat("Unsolvable: {0}", inLevelJSON.ToFormattedString()); EditorUtility.DisplayDialog("Unsolvable!", "Unable to solve level generated with:\n" + inLevelJSON.ToFormattedString(), "OK"); } return(bCanSolve); }
static private bool CanReachTarget(ExpressionMinigameSettings inLevel, int[] inValues) { if (inLevel.FixedOperator) { if (inLevel.Operator == OperatorType.Add) { int current = 0; foreach (int chicken in inValues) { current += chicken; } return(current == inLevel.Value); } else { for (int i = 0; i < inValues.Length; ++i) { int current = 0; for (int chickenIndex = 0; chickenIndex < inValues.Length; ++chickenIndex) { if (chickenIndex == i) { current += inValues[chickenIndex]; } else { current -= inValues[chickenIndex]; } } if (current == inLevel.Value) { return(true); } } } } else { for (int i = 0; i < (int)Math.Max(inValues.Length, 2); ++i) { int current = 0; for (int chickenIndex = 0; chickenIndex < inValues.Length; ++chickenIndex) { if (chickenIndex == i) { current -= inValues[chickenIndex]; } else { current += inValues[chickenIndex]; } } if (current == inLevel.Value) { return(true); } } } return(false); }