static private void PrintPuzzleAppearances(PuzzleAppearance[] appear, string puzzle, StreamWriter sw, ulong total, ulong flipped) { PuzzleAppearance totalInfo = appear[appear.Length - 1]; Array.Resize(ref appear, appear.Length - 1); sw.WriteLine("Stats for {0} ({1} puzzles)", puzzle, appear.Length); Array.Sort(appear, new Comparison <PuzzleAppearance>((x, y) => { return(y.times.CompareTo(x.times)); })); sw.WriteLine( "Puzzle {0} = {1} ({2}%) - Flipped {3} ({4}%)", appear[0].puzzle, appear[0].times, (appear[0].times / (float)totalInfo.times) * 100, appear[0].timesFlipped, (appear[0].timesFlipped / (float)appear[0].times) * 100 ); PuzzleAppearance last = appear[appear.Length - 1]; sw.WriteLine( "Puzzle {0} = {1} ({2}%) - Flipped {3} ({4}%)", last.puzzle, last.times, (last.times / (float)totalInfo.times) * 100, last.timesFlipped, (last.timesFlipped / (float)last.times) * 100 ); //for (int i = 0; i < appear.Length; ++i) //{ // sw.WriteLine( // "Puzzle {0} = {1} ({2}%) - Flipped {3} ({4}%)", // appear[i].puzzle, // appear[i].times, // (appear[i].times / (float)totalInfo.times) * 100, // appear[i].timesFlipped, // (appear[i].timesFlipped / (float)appear[i].times) * 100 // ); //} sw.WriteLine("Total puzzles seen = {0}", totalInfo.times); sw.WriteLine("Total flipped puzzles = {0}", totalInfo.timesFlipped); Array.Sort(appear, new Comparison <PuzzleAppearance>((x, y) => { return(y.timesFlipped.CompareTo(x.timesFlipped)); })); sw.WriteLine("Most flipped puzzle: {0} ({1}%)", appear[0].puzzle, (appear[0].timesFlipped / (float)appear[0].times) * 100); last = appear[appear.Length - 1]; sw.WriteLine("Least flipped puzzle: {0} ({1}%)", last.puzzle, (last.timesFlipped / (float)last.times) * 100); sw.WriteLine(); }
static public void SeqMain() { Dictionary <string, PuzzleAppearance[]> puzzleAppearances = new Dictionary <string, PuzzleAppearance[]>(); StringBuilder sb = new StringBuilder(); using (StreamWriter sw = new StreamWriter("t:\\FinalPuzzleSequences.txt")) { int startPoint = 30000; KurushRNG.Program.seed = 0; for (int j = 0; j < startPoint - 1; ++j) { KurushRNG.Program.Rand(); } int lastSeed = KurushRNG.Program.seed; sw.WriteLine("Each | represents the next wave"); sw.WriteLine("IF USING NUMBERS FROM THE HTML, SUBTRACT 1. THIS IS 0 BASED, THAT IS 1-BASED"); uint totalPuzzles = 0; uint totalflipped = 0; for (int i = startPoint; i < 50000 + startPoint; ++i) { // so we don't have to do all the loops to set the correct seed each time around KurushRNG.Program.seed = lastSeed; KurushRNG.Program.Rand(); lastSeed = KurushRNG.Program.seed; uint seed = (uint)KurushRNG.Program.Rand(); uint flippedSeed = seed; sw.WriteLine("Starting after {0} calls to rand", i); sw.WriteLine("Puzzles:"); foreach (WaveInformation wi in waves) { // tektonics is fixed, so doesn't take part in this if (wi.puzWidth == 9 && wi.puzHeight == 10) { continue; } string size = String.Format("{0}x{1}", wi.puzWidth, wi.puzHeight); sw.Write("{0}: ", size); PuzzleAppearance[] puzzles = null; if (!puzzleAppearances.TryGetValue(size, out puzzles)) { //last puzzle contains total information for this puzzle size puzzles = new PuzzleAppearance[wi.numPuzzles + 1]; for (uint y = 0; y < wi.numPuzzles + 1; ++y) { puzzles[y] = new PuzzleAppearance(); puzzles[y].puzzle = y; puzzles[y].times = 0; puzzles[y].timesFlipped = 0; } puzzleAppearances.Add(size, puzzles); } PuzzleAppearance totalPuzzleInfo = puzzles[puzzles.Length - 1]; sb.Length = 0; for (int k = 0; k < wi.puzzlesPerWave; ++k) { uint seedSoFar = seed; // seed = 0x2e75cf10 seedSoFar <<= 2; seedSoFar += seed; seedSoFar += 1; seed = seedSoFar; // it does it separately in the game code, so that's how I'm doing it too (800434C0) uint flippedSeedSoFar = flippedSeed; flippedSeedSoFar <<= 2; flippedSeedSoFar += flippedSeed; flippedSeedSoFar += 1; flippedSeed = flippedSeedSoFar; // all this determines if the puzzle should be flipped - this code at 80043500 to the jump ulong flippedRes = UBigMul(flippedSeedSoFar, 0xCCCCCCCD); uint highRes = (uint)(flippedRes >> 32); uint eighth = highRes >> 3; uint runningTotal = eighth << 2; runningTotal += eighth; runningTotal <<= 1; uint subRes = flippedSeedSoFar - runningTotal; uint canFlipNum = Convert.ToUInt32(subRes < 3); // stored at 0xDF5($a1) (a1 = 800bc664) uint puzArg = seedSoFar & 0xFFFF; ushort puzzle = DetermineWhichPuzzle(puzArg, wi); bool didFlip = false; // second part of flip decision - this part is at 80064428 uint flipInt = canFlipNum << 16; if ((flipInt != 0) && (wi.puzHeight > 0)) { ++puzzles[puzzle].timesFlipped; ++totalflipped; ++totalPuzzleInfo.timesFlipped; didFlip = true; } sb.AppendFormat("{0}{1} ", puzzle, didFlip ? "(f)" : String.Empty); Debug.Assert(puzzle < puzzles.Length); ++puzzles[puzzle].times; ++totalPuzzleInfo.times; ++totalPuzzles; } sb.Length -= 1; sb.Append(" | "); sw.Write(sb.ToString()); } sw.WriteLine(Environment.NewLine); } using (StreamWriter sw2 = new StreamWriter("T:\\finalpuzzleappearances.txt")) { foreach (KeyValuePair <string, PuzzleAppearance[]> kvp in puzzleAppearances) { PrintPuzzleAppearances( kvp.Value, kvp.Key, sw2, totalPuzzles, totalflipped ); } } } }