protected override void DoStart() { var rnd = RuleSeedable.GetRNG(); Log("Using rule seed: {0}", rnd.Seed); var skip = rnd.Next(0, 6); for (var i = 0; i < skip; i++) { rnd.NextDouble(); } _instructions = rnd.ShuffleFisherYates((Instruction[])Enum.GetValues(typeof(Instruction))); var numbers = Enumerable.Range(0, 16).ToArray(); _ordersByStage = new int[5][]; for (var stage = 0; stage < 4; stage++) { rnd.ShuffleFisherYates(numbers); _ordersByStage[stage] = numbers.ToArray(); } SetInitialState(); }
private void GenerateRules() { var rnd = RuleSeedable.GetRNG(); // Add more random spread for (int i = 0; i < 13; i++) { rnd.Next(); } // Generate color pentagons _table = new Dictionary <SquareColor, SquareColor[]>(); var origColors = new[] { SquareColor.Red, SquareColor.Blue, SquareColor.Green, SquareColor.Yellow, SquareColor.Magenta }; for (int i = 0; i < 5; i++) { rnd.ShuffleFisherYates(_colorCandidates); _table[origColors[i]] = _colorCandidates.ToArray(); LogDebug("Rule Generator: {0} pentagon is: {1}", origColors[i], _table[origColors[i]].Select(c => c.ToString()[0]).JoinString("-")); } // Random spread rnd.Next(); rnd.Next(); rnd.Next(); // Generate directions _ruleOneDirection = (rnd.Next(2) * 2) - 1; _backupDirection = (rnd.Next(2) * 2) - 1; LogDebug("Rule Generator: rule one direction is: {0}", _ruleOneDirection == -1 ? "counter-clockwise" : "clockwise"); LogDebug("Rule Generator: backup rule direction is: {0}", _backupDirection == -1 ? "counter-clockwise" : "clockwise"); }
protected override void StartModule() { _moduleId = _moduleIdCounter++; var rnd = RuleSeedable.GetRNG(); Debug.LogFormat("[X-Ray #{0}] Using rule seed: {1}", _moduleId, rnd.Seed); if (_ruleSeededRules.ContainsKey(rnd.Seed)) { _rules = _ruleSeededRules[rnd.Seed]; } else { if (rnd.Seed == 1) { _rules = new XRayRules( columns: Enumerable.Range(0, 12).Select(convertForSeed1).ToArray(), rows: Enumerable.Range(0, 12).Select(i => convertForSeed1(i + 12)).ToArray(), t3x3: Enumerable.Range(0, 9).Select(i => convertForSeed1(i + 24)).ToArray(), numbersInTable: GenerateTableOfNumbers(rnd)); } else { // Decide on the icons for the 3×3 table up top var _3x3 = rnd.ShuffleFisherYates(Enumerable.Range(0, 22).ToArray()).Take(9).Select(x => new SymbolInfo(x + 88, false)).ToArray(); // For the rows, we can use any non-symmetric icon var _rows = rnd.ShuffleFisherYates(Enumerable.Range(0, 88).ToArray()).Take(12).Select(x => new SymbolInfo(x, x < 55 ? rnd.Next(0, 2) != 0 : false)).ToArray(); // For the columns, we can only use flippable icons that we haven’t already used for rows var columnsRaw = rnd.ShuffleFisherYates(Enumerable.Range(0, 55).Where(x => !_rows.Any(r => r.Index == x)).ToArray()); var _columns = new SymbolInfo[12]; for (var i = 0; i < 6; i++) { var f = rnd.Next(0, 2); _columns[2 * i] = new SymbolInfo(columnsRaw[i], f == 0); _columns[2 * i + 1] = new SymbolInfo(columnsRaw[i], f != 0); } _rules = new XRayRules(_columns, _rows, _3x3, GenerateTableOfNumbers(rnd)); } _ruleSeededRules[rnd.Seed] = _rules; } Initialize(); }
protected override void DoStart() { // Start of rule-seed code var rnd = RuleSeedable.GetRNG(); Log("Using rule seed: {0}", rnd.Seed); var colors = _allColors.ToArray(); _table = new AdjacentColors[16]; for (var row = 0; row < 16; row++) { rnd.ShuffleFisherYates(colors); var theseColors = colors.Where(c => c != _allColors[row]).ToArray(); _table[row].LeftRight = theseColors.Take(3).ToArray(); _table[row].UpDown = theseColors.Skip(3).Take(3).ToArray(); LogDebug("Row {0}: LR {1} // UD {2}", _allColors[row], _table[row].LeftRight.JoinString(", "), _table[row].UpDown.JoinString(", ")); } // End of rule-seed code SetInitialState(); }
protected override void DoStart() { var rnd = RuleSeedable.GetRNG(); Log("Using rule seed: {0}", rnd.Seed); if (rnd.Seed == 1) { _table = newArray( // false = Column; true = Row new object[] { SquareColor.Blue, false, SquareColor.Red, SquareColor.Yellow, true, SquareColor.Green, SquareColor.Magenta }, new object[] { true, SquareColor.Green, SquareColor.Blue, SquareColor.Magenta, SquareColor.Red, false, SquareColor.Yellow }, new object[] { SquareColor.Yellow, SquareColor.Magenta, SquareColor.Green, true, SquareColor.Blue, SquareColor.Red, false }, new object[] { SquareColor.Blue, SquareColor.Green, SquareColor.Yellow, false, SquareColor.Red, true, SquareColor.Magenta }, new object[] { SquareColor.Yellow, true, SquareColor.Blue, SquareColor.Magenta, false, SquareColor.Red, SquareColor.Green }, new object[] { SquareColor.Magenta, SquareColor.Red, SquareColor.Yellow, SquareColor.Green, false, SquareColor.Blue, true }, new object[] { SquareColor.Green, true, false, SquareColor.Blue, SquareColor.Magenta, SquareColor.Yellow, SquareColor.Red }, new object[] { SquareColor.Magenta, SquareColor.Red, SquareColor.Green, SquareColor.Blue, SquareColor.Yellow, false, true }, new object[] { false, SquareColor.Yellow, SquareColor.Red, SquareColor.Green, true, SquareColor.Magenta, SquareColor.Blue }, new object[] { SquareColor.Green, false, true, SquareColor.Red, SquareColor.Magenta, SquareColor.Blue, SquareColor.Yellow }, new object[] { SquareColor.Red, SquareColor.Yellow, true, false, SquareColor.Green, SquareColor.Magenta, SquareColor.Blue }, new object[] { false, SquareColor.Blue, SquareColor.Magenta, SquareColor.Red, SquareColor.Yellow, true, SquareColor.Green }, new object[] { true, SquareColor.Magenta, false, SquareColor.Yellow, SquareColor.Blue, SquareColor.Green, SquareColor.Red }, new object[] { SquareColor.Red, SquareColor.Blue, SquareColor.Magenta, true, SquareColor.Green, SquareColor.Yellow, false }, new object[] { false, true, false, true, false, true, false } ); } else { var candidates = new object[] { SquareColor.Blue, false, SquareColor.Red, SquareColor.Yellow, true, SquareColor.Green, SquareColor.Magenta }; _table = new object[15][]; for (int i = 0; i < 14; i++) { _table[i] = rnd.ShuffleFisherYates(candidates).ToArray(); } _table[14] = new object[] { false, true, false, true, false, true, false }; } SetInitialState(); }
protected override void DoStart() { var rnd = RuleSeedable.GetRNG(); Log("Using rule seed: {0}", rnd.Seed); var shapes = new List <bool[, ]>(); var extraShapes = rnd.ShuffleFisherYates(_sometimesShapes.ToArray()); for (var i = 0; i < 18; i++) { shapes.Add(extraShapes[i]); } // Sneaky! Put the two “alwaysShapes” in the right place to recreate original rules under Seed #1 shapes.Insert(8, _alwaysShapes[0]); shapes.Insert(8, _alwaysShapes[1]); rnd.ShuffleFisherYates(shapes); _table = newArray( new bool[][, ] { null, shapes[0], shapes[1], shapes[2], shapes[3] }, new bool[][, ] { shapes[4], null, shapes[5], shapes[6], shapes[7] }, new bool[][, ] { shapes[8], shapes[9], null, shapes[10], shapes[11] }, new bool[][, ] { shapes[12], shapes[13], shapes[14], null, shapes[15] }, new bool[][, ] { shapes[16], shapes[17], shapes[18], shapes[19], null }); SetStage(isStart: true); }
protected override void DoStart() { var rnd = RuleSeedable.GetRNG(); Log("Using rule seed: {0}", rnd.Seed); var skip = rnd.Next(0, 50); for (var i = 0; i < skip; i++) { rnd.NextDouble(); } _direction = rnd.Next(0, 8); _squareForFlowchartStartColumn = rnd.Next(0, 16); _squareForFlowchartStartRow = rnd.Next(0, 15); if (_squareForFlowchartStartRow >= _squareForFlowchartStartColumn) { _squareForFlowchartStartRow++; } var subsets = new List <HashSet <SquareColor> >(); var colorList = new List <SquareColor>(); for (var i = 0; i < 32; i++) { colorList.Clear(); for (var j = 0; j < 5; j++) { if ((i & (1 << j)) != 0) { colorList.Add(_usefulColors[j]); } } rnd.ShuffleFisherYates(colorList); // this has no impact on the module, but the manual does this subsets.Add(new HashSet <SquareColor>(colorList)); } rnd.ShuffleFisherYates(subsets); var pointedAt = new bool[36]; _pointsAtY = new int[36]; _pointsAtN = new int[36]; var missingCells = new List <int>(); do { missingCells.Clear(); _flowchartStartColumnFromColor = rnd.ShuffleFisherYates(Enumerable.Range(0, 6).ToArray()); for (var i = 0; i < 6; i++) { missingCells.Add(_flowchartStartColumnFromColor[5] + 6 * i); } _flowchartStartRowFromColor = rnd.ShuffleFisherYates(_flowchartStartColumnFromColor.ToArray()); for (var i = 0; i < 6; i++) { if (!missingCells.Contains(i + 6 * _flowchartStartRowFromColor[5])) { missingCells.Add(i + 6 * _flowchartStartRowFromColor[5]); } } for (var ix = 0; ix < 36; ix++) { pointedAt[ix] = false; } rnd.ShuffleFisherYates(missingCells); missingCells.RemoveRange(4, missingCells.Count - 4); var pointsAtSquare = new Func <int, int, int?>((px, dir) => { var x = px % 6; var y = (px / 6) | 0; do { x += _flowChartDeltaX[dir]; y += _flowChartDeltaY[dir]; if (x < 0 || x >= 6 || y < 0 || y >= 6) { return(null); } }while (missingCells.Contains(x + 6 * y)); return(x + 6 * y); }); _flowchart = new HashSet <SquareColor> [36]; for (var ix = 0; ix < 36; ix++) { if (missingCells.Contains(ix)) { continue; } var dirs = new List <int?>(); for (var dir = 0; dir < 4; dir++) { if (pointsAtSquare(ix, dir) != null) { dirs.Add(dir); } } rnd.ShuffleFisherYates(dirs); dirs.RemoveRange(2, dirs.Count - 2); // 0 = no, 1 = yes var sbstIx = ix - missingCells.Count(cel => cel < ix); _flowchart[ix] = subsets[sbstIx]; if (subsets[sbstIx].Count == 0) { dirs[1] = null; } else if (subsets[sbstIx].Count == 5) { dirs[0] = null; } for (var yn = 0; yn < 2; yn++) { if (dirs[yn] == null) { continue; } var target = pointsAtSquare(ix, dirs[yn].Value); (yn == 0 ? _pointsAtN : _pointsAtY)[ix] = target.Value; pointedAt[target.Value] = true; } } }while (pointedAt.Where((p, pIx) => !p && (!missingCells.Contains(pIx))).Any()); SetInitialState(); }
protected override void StartModule() { _moduleId = _moduleIdCounter++; _isSolved = false; var rnd = RuleSeedable.GetRNG(); Debug.LogFormat("[Not X-Ray #{0}] Using rule seed: {1}", _moduleId, rnd.Seed); // RULE SEED if (_ruleSeededRules.ContainsKey(rnd.Seed)) { _rules = _ruleSeededRules[rnd.Seed]; } else { var _tables = new SymbolInfo[8][]; var _notWallses = new int[8][]; var sqs = Enumerable.Range(0, 49).Where(c => c != 0 && c != 6 && c != 42 && c != 48 && c != 24).ToArray(); // First 55 symbols can be flipped, next 55 cannot const int numFlippable = 55; const int numUnflippable = 55; var unflippableSymbols = rnd.ShuffleFisherYates(Enumerable.Range(0, numUnflippable).Select(c => numFlippable + c).ToArray()); var flippableSymbols = rnd.ShuffleFisherYates(Enumerable.Range(0, numFlippable).ToArray()); var combinations = new List <int[]>(); for (var ai = 0; ai < sqs.Length; ai++) { for (var bi = ai + 1; bi < sqs.Length; bi++) { if (sqs[bi] / 7 > sqs[ai] / 7 && sqs[bi] % 7 < sqs[ai] % 7) { for (var ci = ai + 1; ci < sqs.Length; ci++) { if (ci != bi && sqs[ci] / 7 > sqs[ai] / 7 && sqs[ci] % 7 > sqs[ai] % 7 && sqs[ci] % 7 > sqs[bi] % 7) { for (var di = Math.Max(bi, ci) + 1; di < sqs.Length; di++) { if (sqs[di] / 7 > sqs[bi] / 7 && sqs[di] / 7 > sqs[ci] / 7 && sqs[di] % 7 > sqs[bi] % 7 && sqs[di] % 7 < sqs[ci] % 7) { combinations.Add(new int[] { sqs[ai], sqs[bi], sqs[ci], sqs[di] }); } } } } } } } for (var tableIx = 0; tableIx < 8; tableIx++) { var symbols = new List <SymbolInfo>(); for (var i = 0; i < 4; i++) { symbols.Add(new SymbolInfo(flippableSymbols[tableIx * 4 + i], false)); } for (var i = 0; i < 4; i++) { symbols.Add(new SymbolInfo(flippableSymbols[tableIx * 4 + i], true)); } for (var i = 0; i < 3; i++) { symbols.Add(new SymbolInfo(unflippableSymbols[tableIx * 3 + i], false)); } // generate maze const int w = 7, h = 7; var notWalls = new List <int>(); // (cell << 1) + (right ? 1 : 0) var todo = Enumerable.Range(0, 49).Where(c => c != 0 && c != 6 && c != 42 && c != 48).ToList(); var active = new List <int>(); var start = rnd.Next(0, todo.Count); active.Add(todo[start]); todo.RemoveAt(start); while (todo.Count > 0) { var activeIx = rnd.Next(0, active.Count); var sq = active[activeIx]; var adjs = new List <int>(); if ((sq % w) > 0 && todo.Contains(sq - 1)) { adjs.Add(sq - 1); } if ((sq % w) < w - 1 && todo.Contains(sq + 1)) { adjs.Add(sq + 1); } if (((sq / w) | 0) > 0 && todo.Contains(sq - w)) { adjs.Add(sq - w); } if (((sq / w) | 0) < h - 1 && todo.Contains(sq + w)) { adjs.Add(sq + w); } if (adjs.Count == 0) { active.RemoveAt(activeIx); continue; } var adj = adjs[rnd.Next(0, adjs.Count)]; todo.RemoveAt(todo.IndexOf(adj)); active.Add(adj); if (adj == sq - 1) { notWalls.Add((adj << 1) | 1); } else if (adj == sq + 1) { notWalls.Add((sq << 1) | 1); } else if (adj == sq - w) { notWalls.Add(adj << 1); } else if (adj == sq + w) { notWalls.Add(sq << 1); } } // generate symbol arrangements var backtracks = 0; Func <int, int[][], List <int[]> > findArrangement = null; findArrangement = (numSofar, combinationsLeft) => { if (numSofar == 11) { return(new List <int[]>()); } if (combinationsLeft.Length == 0) { return(null); } var offset = rnd.Next(0, combinationsLeft.Length); for (var ir = 0; ir < combinationsLeft.Length; ir++) { var i = (ir + offset) % combinationsLeft.Length; var combination = combinationsLeft[i]; var combLeft = combinationsLeft.Where(cmb => cmb.All(c => !combination.Contains(c))).ToArray(); var result = findArrangement(numSofar + 1, combLeft); if (result != null) { result.Add(combination); return(result); } if (backtracks > 500) { return(null); } } backtracks++; return(null); }; List <int[]> arrangement; do { backtracks = 0; arrangement = findArrangement(0, combinations.ToArray()); }while (arrangement == null); // generate symbol table var table = new SymbolInfo[49]; for (var cell = 0; cell < 49; cell++) { if (cell == 0 || cell == 6 || cell == 42 || cell == 48 || cell == 24) { continue; } var arrIx = arrangement.IndexOf(comb => comb.Contains(cell)); table[cell] = symbols[arrIx]; } _tables[tableIx] = table; _notWallses[tableIx] = notWalls.ToArray(); } _rules = new NotXRayRules(_tables, _notWallses); _ruleSeededRules[rnd.Seed] = _rules; } // END RULE SEED Initialize(); }