private void SetStage(int stage) { _stage = stage; _subprogress = 0; for (int i = 0; i < 16; i++) { if (_colors[i] != SquareColor.White) { Scaffold.SetButtonBlack(i); } } if (stage == 5) { ModulePassed(); return; } Log("On to stage {0}.", _stage); // Put 2–3 of the active color in that many random squares var availableSquares = Enumerable.Range(0, 16).Where(ix => stage == 1 || _colors[ix] != SquareColor.White).ToList().Shuffle(); var take = Math.Min(stage == 1 ? 3 : Rnd.Range(2, 4), availableSquares.Count); for (int i = 0; i < take; i++) { _colors[availableSquares[i]] = _rememberedColors[stage - 1]; } // Fill the rest of the grid with the other colors for (int i = take; i < availableSquares.Count; i++) { var cl = Rnd.Range(1, 5); _colors[availableSquares[i]] = (SquareColor)(cl >= (int)_rememberedColors[stage - 1] ? cl + 1 : cl); } var relevantSquares = availableSquares.Take(take).OrderBy(sq => _ordersByStage[stage - 1][sq]).ToArray(); Log("Stage {0}: {1} squares in the correct order are {2}.", stage, _rememberedColors[stage - 1], relevantSquares.Select(sq => coord(sq)).Join(", ")); // Process the active squares in the correct order for this stage to compute the intended solution _expectedPresses = new List <int>(); foreach (var activeSquare in relevantSquares) { if (_expectedPresses.Contains(activeSquare)) // square already became white in this stage { Log("— {0} has already become white. Skip it.", coord(activeSquare)); continue; } var solutionSquare = activeSquare; do { solutionSquare = process(solutionSquare, _instructions[_rememberedPositions[stage - 1]]); }while (_colors[solutionSquare] == SquareColor.White || _expectedPresses.Contains(solutionSquare)); Log("— {0} / {1} translates to {2}", coord(activeSquare), _instructions[_rememberedPositions[stage - 1]], coord(solutionSquare)); _expectedPresses.Add(solutionSquare); } Scaffold.StartSquareColorsCoroutine(_colors, delay: true); }
protected override void ButtonPressed(int index) { if (index != _modulePosition) { Log("{0} was pressed when {1} was expected. Strike and reset.", convertCoord(index, 4), convertCoord(_modulePosition, 4)); Strike(); SetInitialState(); } else if (NextSquare(_modulePosition) == null) { ModulePassed(); } else { Log("{0} pressed correctly.", convertCoord(index, 4)); // We know this isn’t null because of the above if _modulePosition = NextSquare(_modulePosition).Value; // Make everything white _including_ the square that was pressed var indexes = _updateColors.Select(i => (int?)i).ToList(); indexes.Add(index); foreach (var ix in indexes) { _colors[ix.Value] = SquareColor.White; } indexes.Add(null); var indexes2 = new List <int?>(); for (int?i = _modulePosition; i != null; i = NextSquare(i.Value)) { Scaffold.SetButtonBlack(i.Value); _colors[i.Value] = _usefulColors[Rnd.Range(0, _usefulColors.Length)]; indexes2.Add(i.Value); } _updateColors.Clear(); ProcessCurrentSquare(); if (!_isSolved) { indexes2.Shuffle(); indexes.AddRange(indexes2); Scaffold.StartSquareColorsCoroutine(_colors, indexes.ToArray()); } } }
protected override void ButtonPressed(int index) { if (_activeCoroutine != null) { StopCoroutine(_activeCoroutine); } if (_lastPress != -1) { Scaffold.SetButtonColor(_lastPress, _colors[_lastPress]); } if (_lastPress == -1 && _allowedPresses.Contains(index)) { PlaySound(index); _lastPress = index; _startingPosition = index; _allowedPresses = CalculateNewAllowedPresses(index); Log("Button #{0} pressed successfully. Current color is now {1}. Next color is {2}.", index, _currentColor, _nextColor); _activeCoroutine = StartCoroutine(BlinkLastSquare()); } else if (!_allowedPresses.Contains(index)) { Log("Button #{0} ({1}) was incorrect at this time.", index, _colors[index]); Strike(); SetInitialState(); } else { PlaySound(index); _lastPress = index; _updateIndices = new HashSet <int>(); LogDebug("Calling SpreadColor({0}, {1}, {2})", _currentColor, _colors[index], _startingPosition); SpreadColor(_currentColor, _colors[index], _startingPosition); if (_updateIndices.SetEquals(_lastArea)) { _pressesWithoutChange++; } else { _lastArea = _updateIndices; _pressesWithoutChange = 0; } _currentColor = _colors[index]; if (_pressesWithoutChange >= 3) { var currentColor = _colors[index]; while (currentColor == _colors[index]) { _colors[index] = _colorCandidates[Rnd.Range(0, _colorCandidates.Length)]; } _pressesWithoutChange = 0; Scaffold.SetButtonBlack(index); Scaffold.Audio.PlaySoundAtTransform("colorreset", Scaffold.Buttons[index].transform); } if (_colors.All(c => c == _colors[0])) { Log("Module passed."); _allowedPresses = null; _activeCoroutine = StartCoroutine(SetSquareColors(delay: false, solve: true)); } else { _allowedPresses = CalculateNewAllowedPresses(index); Log("Button #{0} pressed successfully. Current color is now {1}. Next color is {2}.", index, _currentColor, _nextColor); _activeCoroutine = StartCoroutine(SetSquareColors(delay: false)); } } }
private void SetStage(bool isStart) { if (isStart) { for (int i = 0; i < 16; i++) { _colors[i] = SquareColor.White; Scaffold.SetButtonBlack(i); } } else { var sq = 0; for (int i = 0; i < 16; i++) { switch (_colors[i]) { case SquareColor.Black: break; case SquareColor.Red: case SquareColor.Green: case SquareColor.Blue: case SquareColor.Yellow: case SquareColor.Magenta: Scaffold.SetButtonBlack(i); sq++; break; case SquareColor.White: _colors[i] = SquareColor.Black; break; } } if (sq <= 3) { ModulePassed(); return; } } // Check all color combinations and find all valid pattern placements var order = new[] { SquareColor.Red, SquareColor.Green, SquareColor.Blue, SquareColor.Yellow, SquareColor.Magenta }; var validCombinations = Enumerable.Range(0, 5).SelectMany(first => Enumerable.Range(0, 5).Select(second => { if (first == second) { return(null); } var pattern = _table[second][first]; var w = pattern.GetLength(0); var h = pattern.GetLength(1); var placements = new List <List <int> >(); for (int i = 0; i < 16; i++) { if (i % 4 + w > 4 || i / 4 + h > 4) { continue; } var placement = new List <int>(); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if (pattern[x, y]) { var ix = i % 4 + x + 4 * (i / 4 + y); if (_colors[ix] == SquareColor.Black) { goto nope; } placement.Add(ix); } } } placements.Add(placement); nope:; } return(placements.Count == 0 ? null : new { First = order[first], Second = order[second], Placements = placements }); })).Where(inf => inf != null).ToArray(); if (validCombinations.Length == 0) { ModulePassed(); return; } // Fill the still-lit squares with “codes” (numbers 0–5 that we will later map to actual colors) // in such a way that there’s a two-way tie for fewest number of occurrences int[] colorCodes = new int[16]; tryAgain: var counts = new int[5]; for (int i = 0; i < 16; i++) { if (_colors[i] != SquareColor.Black) { var col = Rnd.Range(0, 5); colorCodes[i] = col; counts[col]++; } else { colorCodes[i] = -1; } } var minCount = counts.Where(c => c > 0).Min(); var minCountCodes = Enumerable.Range(0, 5).Where(code => counts[code] == minCount).OrderBy(c => Array.IndexOf(colorCodes, c)).ToArray(); if (minCountCodes.Length != 2) { goto tryAgain; } // Pick a color combination at random var combination = validCombinations[Rnd.Range(0, validCombinations.Length)]; // Create the map from color code to actual color in such a way that the chosen colors are in the correct place var allColors = new List <SquareColor> { SquareColor.Blue, SquareColor.Green, SquareColor.Magenta, SquareColor.Red, SquareColor.Yellow }; allColors.Remove(combination.First); allColors.Remove(combination.Second); if (minCountCodes[0] > minCountCodes[1]) { allColors.Insert(minCountCodes[1], combination.Second); allColors.Insert(minCountCodes[0], combination.First); } else { allColors.Insert(minCountCodes[0], combination.First); allColors.Insert(minCountCodes[1], combination.Second); } // Assign the colors for (int i = 0; i < 16; i++) { if (_colors[i] != SquareColor.Black) { _colors[i] = allColors[colorCodes[i]]; } } if (isStart) { _firstStageColor1 = combination.First; _firstStageColor2 = combination.Second; } Log("{0} stage color pair is {1}/{2}", isStart ? "First" : "Next", combination.First, combination.Second); _permissiblePatterns = combination.Placements; _squaresPressedThisStage.Clear(); Scaffold.StartSquareColorsCoroutine(_colors, delay: true); }
protected override void ButtonPressed(int index) { if (_expectedPresses == null) { return; } if (!_allowedPresses.Contains(index)) { Log(@"Button #{0} ({1}) was incorrect at this time.", index, _colors[index]); Strike(); SetInitialState(); } else { PlaySound(index); _expectedPresses.Remove(index); _colors[index] = SquareColor.White; Scaffold.SetButtonColor(index, SquareColor.White); if (_expectedPresses.Count == 0) { var whiteCount = _colors.Count(c => c == SquareColor.White); if (whiteCount == 16) { _expectedPresses = null; _allowedPresses = null; ModulePassed(); } else { _allowedPresses.Clear(); var nonWhite = Enumerable.Range(0, 16).Where(i => _colors[i] != SquareColor.White).ToArray(); foreach (var i in nonWhite) { Scaffold.SetButtonBlack(i); _colors[i] = (SquareColor)Rnd.Range(1, 6); } // Move to next stage. var nextStage = _table[whiteCount - 1][_lastStage is SquareColor ? (int)(SquareColor)_lastStage - 1 : _lastStage.Equals(true) ? 5 : 6]; Log("{0} lit: next stage is {1}.", whiteCount, nextStage.Equals(true) ? "Row" : nextStage.Equals(false) ? "Column" : ((SquareColor)nextStage).ToString()); if (nextStage.Equals(true)) { // Row var firstRow = Enumerable.Range(0, 4).First(row => Enumerable.Range(0, 4).Any(col => _colors[4 * row + col] != SquareColor.White)); for (int col = 0; col < 4; col++) { if (_colors[4 * firstRow + col] != SquareColor.White) { _allowedPresses.Add(4 * firstRow + col); _expectedPresses.Add(4 * firstRow + col); } } } else if (nextStage.Equals(false)) { // Column var firstCol = Enumerable.Range(0, 4).First(col => Enumerable.Range(0, 4).Any(row => _colors[4 * row + col] != SquareColor.White)); for (int row = 0; row < 4; row++) { if (_colors[4 * row + firstCol] != SquareColor.White) { _allowedPresses.Add(4 * row + firstCol); _expectedPresses.Add(4 * row + firstCol); } } } else { // A specific color // Make sure at least one square has that color var color = (SquareColor)nextStage; _colors[nonWhite[Rnd.Range(0, nonWhite.Length)]] = color; for (int i = 0; i < 16; i++) { if (_colors[i] == color) { _allowedPresses.Add(i); _expectedPresses.Add(i); } } } _lastStage = nextStage; Scaffold.StartSquareColorsCoroutine(_colors, SquaresToRecolor.NonwhiteOnly, delay: true); } } } }