public bool Next(int index, Tristate selected) { switch (state) { case State.Initial: if (selected.IsYes()) { state = State.InRun; runCount = 1; runStartIndex = index; } return(false); case State.JustAfterRun: if (selected.IsYes()) { state = State.InRun; runCount = 1; runStartIndex = index; goto checkCases; } else { state = State.Initial; prevRunCount = 0; runCount = 0; } return(false); case State.InRun: if (selected.IsYes()) { state = State.InRun; runCount += 1; if (runCount > max) { // Immediate contradiction return(true); } goto checkCases; } else { // Also case 1. if (runCount == max) { if (selected.Possible()) { banAt(index); } } state = State.JustAfterRun; prevRunCount = runCount; runCount = 0; } return(false); } // Unreachable throw new Exception("Unreachable"); checkCases: // Have we entered case 1 or 2? if (prevRunCount + runCount == max) { // Ban on the previous end of the run if (runStartIndex == 0) { if (periodic) { banAt(indexCount - 1); } } else { banAt(runStartIndex - 1); } } return(false); }