public Rule(Condition condition, EdgeworkValue ev) { Condition = condition; Solution = new Solution(ev); }
public static Condition QuadrantMajorityCount(Comparison comparison, bool white, EdgeworkValue ev) { return(new Condition( string.Format("If there are {0} mostly-{1} quadrants {2} {3}", comparison == Comparison.Same ? "exactly as many" : comparison == Comparison.Fewer ? "fewer" : "more", white ? "white" : "black", comparison == Comparison.Same ? "as" : "than", ev.Name), Extra.None, (grid, bomb) => { var quadrants = getQuadrantCounts(grid); var numMajQuadrants = quadrants.Count(q => white ? (q > 8) : (q < 8)); return comparison == Comparison.Same ? (numMajQuadrants == ev.GetValue(bomb)) : comparison == Comparison.More ? (numMajQuadrants > ev.GetValue(bomb)) : (numMajQuadrants < ev.GetValue(bomb)); })); }
public Solution(EdgeworkValue ev) { Name = ev.Name; Answer = (grid, bomb, extra) => ev.GetValue(bomb); }
void Start() { _colorIx = Rnd.Range(0, _lightColors.Length); _moduleId = _moduleIdCounter++; Buttons[0].OnInteract += delegate { PushButton(1); return(false); }; Buttons[1].OnInteract += delegate { PushButton(2); return(false); }; Buttons[2].OnInteract += delegate { PushButton(3); return(false); }; Buttons[3].OnInteract += delegate { PushButton(4); return(false); }; _bitmap = new bool[8][]; for (int j = 0; j < 8; j++) { _bitmap[j] = new bool[8]; for (int i = 0; i < 8; i++) { _bitmap[j][i] = Rnd.Range(0, 2) == 0; } } _isSolved = false; Bitmap.material.mainTexture = generateTexture(); Bitmap.material.shader = Shader.Find("Unlit/Transparent"); Debug.LogFormat("[Bitmaps #{0}] Bitmap ({1}):", _moduleId, _colorNames[_colorIx]); for (int y = 0; y < 8; y++) { Debug.LogFormat("[Bitmaps #{0}] {1}", _moduleId, string.Join("", Enumerable.Range(0, 8).Select(x => (_bitmap[x][y] ? "░░" : "██") + (x == 3 ? "│" : null)).ToArray())); if (y == 3) { Debug.LogFormat("[Bitmaps #{0}] ────────┼────────", _moduleId); } } Debug.LogFormat("[Bitmaps #{0}] Quadrant counts: {1}", _moduleId, string.Join(", ", getQuadrantCounts(_bitmap).Select(w => string.Format("{0}w/{1}b", w, 16 - w)).ToArray())); var rnd = RuleSeedable.GetRNG(); Debug.LogFormat("[Bitmaps #{0}] Using rule seed: {1}", _moduleId, rnd.Seed); if (rnd.Seed == 1) { _defaultRuleset = true; _rules = Ut.NewArray( // If exactly one quadrant has 5 or fewer white pixels, the answer is the number of white pixels in the other 3 quadrants. new Rule(Condition.QuadrantPixelCount(NumberComparison.ExactlyOne, 5, orFewer: true, white: true), Solution.WhiteInOtherThreeQuadrants), // If there are exactly as many mostly-white quadrants as there are lit indicators, the answer is the number of batteries. new Rule(Condition.QuadrantMajorityCount(Comparison.Same, white: true, ev: EdgeworkValue.LitIndicators), EdgeworkValue.NumberOfBatteries), // If exactly one row or column is completely white or completely black, the answer is its x-/y-coordinate (starting from 1 in the top/left). new Rule(Condition.RowOrColumn, Solution.RowColumnCoordinate), // If there are fewer mostly-white quadrants than mostly-black quadrants, the answer is the number of mostly-black quadrants. new Rule(Condition.QuadrantMajorityComparison(Comparison.Fewer), Solution.NumMostlyBlackQuadrants), // If the entire bitmap has 36 or more white pixels, the answer is the total number of white pixels. new Rule(Condition.BitmapPixelCount(36, 64, white: true), Solution.NumWhitePixels), // If there are more mostly-white quadrants than mostly-black quadrants, the answer is the smallest number of black pixels in any quadrant. new Rule(Condition.QuadrantMajorityComparison(Comparison.More), Solution.MinBlackInQuadrant), // If exactly one quadrant has 5 or fewer black pixels, the answer is the number of black pixels in the other 3 quadrants. new Rule(Condition.QuadrantPixelCount(NumberComparison.ExactlyOne, 5, orFewer: true, white: false), Solution.BlackInOtherThreeQuadrants), // If there are exactly as many mostly-black quadrants as there are unlit indicators, the answer is the number of ports. new Rule(Condition.QuadrantMajorityCount(Comparison.Same, white: false, ev: EdgeworkValue.UnlitIndicators), EdgeworkValue.Ports), // If there is a 3×3 square that is completely white or completely black, the answer is the x-coordinate (starting from 1) of the center of the first such square in reading order. new Rule(Condition.Square3, Solution.SquareCoordinate(SquarePoint.Center, 3, y: false, last: false)), // If there are exactly as many mostly-white quadrants as mostly-black quadrants, the answer is the first numeric digit of the serial number. new Rule(Condition.QuadrantMajorityComparison(Comparison.Same), EdgeworkValue.SnFirstDigit)); _startRule = EdgeworkValue.SnLastDigit; } else { _defaultRuleset = false; // Add extra randomness var skip = rnd.Next(0, 100); for (var i = 0; i < skip; i++) { rnd.NextDouble(); } // Take a copy of the (static) array var edgeworkVariables = rnd.ShuffleFisherYates(EdgeworkValue.Default.ToArray()); var edgeworkVariableIx = 0; // Optional conditions var conditions = new List <Condition> { Condition.RowOrColumn, Condition.Row, Condition.Column, Condition.Square3, new[] { Condition.Square2BW, Condition.Square2W, Condition.Square2B }[rnd.Next(0, 3)], Condition.QuadrantMajorityCount(Comparison.Same, white: true, ev: edgeworkVariables[edgeworkVariableIx++]), Condition.QuadrantMajorityCount(Comparison.More, white: true, ev: edgeworkVariables[edgeworkVariableIx++]), Condition.QuadrantMajorityCount(Comparison.Fewer, white: true, ev: edgeworkVariables[edgeworkVariableIx++]), Condition.QuadrantMajorityCount(Comparison.Same, white: false, ev: edgeworkVariables[edgeworkVariableIx++]), Condition.QuadrantMajorityCount(Comparison.More, white: false, ev: edgeworkVariables[edgeworkVariableIx++]), Condition.QuadrantMajorityCount(Comparison.Fewer, white: false, ev: edgeworkVariables[edgeworkVariableIx++]) }; // We will make sure that all three conditions from one of these triplets are present so that there is always one rule that matches. var pixelCount1 = rnd.Next(3, 8); var orFewer = rnd.Next(0, 2) == 0; var whiteNotBlack = rnd.Next(0, 2) == 0; var pixelCount2 = rnd.Next(26, 30); var whiteNotBlack2 = rnd.Next(0, 2) == 0; var tripletConditions = Ut.NewArray( Ut.NewArray( Condition.QuadrantPixelCount(NumberComparison.None, orFewer ? pixelCount1 : 16 - pixelCount1, orFewer, whiteNotBlack), Condition.QuadrantPixelCount(NumberComparison.ExactlyOne, orFewer ? pixelCount1 : 16 - pixelCount1, orFewer, whiteNotBlack), Condition.QuadrantPixelCount(NumberComparison.MoreThanOne, orFewer ? pixelCount1 : 16 - pixelCount1, orFewer, whiteNotBlack)), Ut.NewArray( Condition.QuadrantMajorityComparison(Comparison.Fewer), Condition.QuadrantMajorityComparison(Comparison.More), Condition.QuadrantMajorityComparison(Comparison.Same)), Ut.NewArray( Condition.BitmapPixelCount(64 - pixelCount2, 64, whiteNotBlack2), Condition.BitmapPixelCount(0, pixelCount2, whiteNotBlack2), Condition.BitmapPixelCount(pixelCount2 + 1, 63 - pixelCount2, whiteNotBlack2)), Ut.NewArray( Condition.QuadrantBalancedNone, Condition.QuadrantBalancedOne, Condition.QuadrantBalancedMoreThanOne)); var tripletIx = rnd.Next(0, tripletConditions.Length); var triplet = tripletConditions[tripletIx]; for (var i = 0; i < tripletConditions.Length; i++) { if (i != tripletIx) { for (var j = 0; j < tripletConditions[i].Length; j++) { conditions.Add(tripletConditions[i][j]); } } } rnd.ShuffleFisherYates(conditions); conditions.RemoveRange(7, conditions.Count - 7); conditions.AddRange(triplet); rnd.ShuffleFisherYates(conditions); _startRule = edgeworkVariables[edgeworkVariableIx++]; var solutions = new List <Solution> { Solution.NumMostlyBlackQuadrants, Solution.NumMostlyWhiteQuadrants, Solution.NumBalancedQuadrants, Solution.NumWhitePixels, Solution.NumBlackPixels, Solution.MinBlackInQuadrant, Solution.MaxBlackInQuadrant, Solution.MinWhiteInQuadrant, Solution.MaxWhiteInQuadrant }; for (var i = edgeworkVariableIx; i < edgeworkVariables.Length; i++) { solutions.Add(new Solution(edgeworkVariables[i])); } var extraSolutions = new Dictionary <Extra, List <Solution> >(); extraSolutions[Extra.Quadrant] = new List <Solution> { Solution.WhiteInOtherThreeQuadrants, Solution.BlackInOtherThreeQuadrants, new Solution("the number of white pixels in the diagonally opposite quadrant", (grid, bomb, extra) => getQuadrantCounts(grid)[3 - extra]), new Solution("the number of black pixels in the diagonally opposite quadrant", (grid, bomb, extra) => 16 - getQuadrantCounts(grid)[3 - extra]), new Solution("the number of white pixels in the horizontally adjacent quadrant", (grid, bomb, extra) => getQuadrantCounts(grid)[extra ^ 1]), new Solution("the number of black pixels in the horizontally adjacent quadrant", (grid, bomb, extra) => 16 - getQuadrantCounts(grid)[extra ^ 1]), new Solution("the number of white pixels in the vertically adjacent quadrant", (grid, bomb, extra) => getQuadrantCounts(grid)[extra ^ 2]), new Solution("the number of black pixels in the vertically adjacent quadrant", (grid, bomb, extra) => 16 - getQuadrantCounts(grid)[extra ^ 2]) }; extraSolutions[Extra.Row] = new List <Solution> { new Solution("its y-coordinate, counting from 1 from top to bottom", (grid, bomb, extra) => extra + 1), new Solution("its y-coordinate, counting from 1 from bottom to top", (grid, bomb, extra) => 8 - extra) }; extraSolutions[Extra.Column] = new List <Solution> { new Solution("its x-coordinate, counting from 1 from left to right", (grid, bomb, extra) => extra + 1), new Solution("its x-coordinate, counting from 1 from right to left", (grid, bomb, extra) => 8 - extra) }; extraSolutions[Extra.Line] = new List <Solution> { Solution.RowColumnCoordinate, new Solution("its x-/y-coordinate, counting from 1 from bottom/right to top/left", (grid, bomb, extra) => 8 - extra) }; extraSolutions[Extra.Square3] = new List <Solution> { Solution.SquareCoordinate(SquarePoint.Center, 3, y: false, last: false), Solution.SquareCoordinate(SquarePoint.Center, 3, y: true, last: false), Solution.SquareCoordinate(SquarePoint.Center, 3, y: false, last: true), Solution.SquareCoordinate(SquarePoint.Center, 3, y: true, last: true), Solution.SquareCoordinate(SquarePoint.TopLeft, 3, y: false, last: false), Solution.SquareCoordinate(SquarePoint.TopLeft, 3, y: true, last: false), Solution.SquareCoordinate(SquarePoint.TopLeft, 3, y: false, last: true), Solution.SquareCoordinate(SquarePoint.TopLeft, 3, y: true, last: true), Solution.SquareCoordinate(SquarePoint.TopRight, 3, y: false, last: false), Solution.SquareCoordinate(SquarePoint.TopRight, 3, y: true, last: false), Solution.SquareCoordinate(SquarePoint.TopRight, 3, y: false, last: true), Solution.SquareCoordinate(SquarePoint.TopRight, 3, y: true, last: true), Solution.SquareCoordinate(SquarePoint.BottomLeft, 3, y: false, last: false), Solution.SquareCoordinate(SquarePoint.BottomLeft, 3, y: true, last: false), Solution.SquareCoordinate(SquarePoint.BottomLeft, 3, y: false, last: true), Solution.SquareCoordinate(SquarePoint.BottomLeft, 3, y: true, last: true), Solution.SquareCoordinate(SquarePoint.BottomRight, 3, y: false, last: false), Solution.SquareCoordinate(SquarePoint.BottomRight, 3, y: true, last: false), Solution.SquareCoordinate(SquarePoint.BottomRight, 3, y: false, last: true), Solution.SquareCoordinate(SquarePoint.BottomRight, 3, y: true, last: true) }; extraSolutions[Extra.Square2] = new List <Solution> { Solution.SquareCoordinate(SquarePoint.TopLeft, 2, y: false, last: false), Solution.SquareCoordinate(SquarePoint.TopLeft, 2, y: true, last: false), Solution.SquareCoordinate(SquarePoint.TopLeft, 2, y: false, last: true), Solution.SquareCoordinate(SquarePoint.TopLeft, 2, y: true, last: true), Solution.SquareCoordinate(SquarePoint.TopRight, 2, y: false, last: false), Solution.SquareCoordinate(SquarePoint.TopRight, 2, y: true, last: false), Solution.SquareCoordinate(SquarePoint.TopRight, 2, y: false, last: true), Solution.SquareCoordinate(SquarePoint.TopRight, 2, y: true, last: true), Solution.SquareCoordinate(SquarePoint.BottomLeft, 2, y: false, last: false), Solution.SquareCoordinate(SquarePoint.BottomLeft, 2, y: true, last: false), Solution.SquareCoordinate(SquarePoint.BottomLeft, 2, y: false, last: true), Solution.SquareCoordinate(SquarePoint.BottomLeft, 2, y: true, last: true), Solution.SquareCoordinate(SquarePoint.BottomRight, 2, y: false, last: false), Solution.SquareCoordinate(SquarePoint.BottomRight, 2, y: true, last: false), Solution.SquareCoordinate(SquarePoint.BottomRight, 2, y: false, last: true), Solution.SquareCoordinate(SquarePoint.BottomRight, 2, y: true, last: true) }; _rules = new Rule[10]; for (int i = 0; i < 10; i++) { var numSol = solutions.Count; if (extraSolutions.ContainsKey(conditions[i].Extra)) { numSol += extraSolutions[conditions[i].Extra].Count; } var ix = rnd.Next(0, numSol); if (ix < solutions.Count) { _rules[i] = new Rule(conditions[i], solutions[ix]); solutions.RemoveAt(ix); } else { ix -= solutions.Count; _rules[i] = new Rule(conditions[i], extraSolutions[conditions[i].Extra][ix]); extraSolutions[conditions[i].Extra].RemoveAt(ix); } } Debug.LogFormat("<Bitmaps #{0}> RULES:", _moduleId); for (int i = 0; i < 10; i++) { Debug.LogFormat("<Bitmaps #{0}> {1}, the answer is {2}.", _moduleId, _rules[i].Condition.Name, _rules[i].Solution.Name); } Debug.LogFormat("[Bitmaps #{0}] SOLUTION AT START (may change if solution depends on number of solved modules):", _moduleId); } // Evaluate the answer just to log it. findAnswer(log: true); }