static IList <TableEntry> MakeOpeningTable(uint from, uint to, uint state, Player player, TSearchType searchType, uint incr) { var size = to + 1; IList <uint> rngStateArr; IList <int> offsetArr; if (searchType == TSearchType.First) { var rng = new CardRng(state); rngStateArr = new uint[size].Select(_ => { var stateCopy = rng.State; rng.Next(); return(stateCopy); }).ToList(); var offsetArrSize = (int)(60f / _options.AutofireSpeed); offsetArr = new int[offsetArrSize].Select((_, i) => { return((int)_options.ForcedIncr + i); }).ToList(); } else if (searchType == TSearchType.Counting) { var(firstState, _, count, _) = ReadArgs(_args, silent: true); var rng = new CardRng(firstState); var maxIdx = count + _options.CountingWidth; rngStateArr = new uint[maxIdx].Select(_ => { var stateCopy = rng.State; rng.Next(); return(stateCopy + incr); }).ToList(); offsetArr = new int[_options.CountingFrameWidth].Select((_, i) => { return(i - (int)_options.CountingFrameWidth / 2); }).ToList(); } else { rngStateArr = new uint[size].Select((_, i) => { return((state + (uint)i) & 0xffff_ffff); }).ToList(); offsetArr = new[] { 0 }; } var table = new List <TableEntry>(); for (var idx = 0; idx <= to; idx++) { if (!(idx >= from && idx <= to)) { continue; } foreach (var offset in offsetArr) { var rngState = (rngStateArr[idx] + offset) & 0xffff_ffff; table.Add(new TableEntry() { Index = idx, Offset = offset, Opening = OpeningSituation((uint)rngState, player), }); } } return(table); }
static Func <Pattern, bool, IEnumerable <ScanEntry> > OpeningScanner(uint state, Player player, TSearchType searchType, uint incr = 0) { var startIndex = 0U; var width = 0U; switch (searchType) { case TSearchType.First: startIndex = _options.Base; width = _options.Width; break; case TSearchType.Counting: startIndex = ReadArgs(_args, silent: true).count; width = _options.CountingWidth; break; case TSearchType.Recovery: startIndex = _options.RecoveryWidth / 2; state = (state + incr - startIndex) & 0xffff_ffff; width = _options.RecoveryWidth; break; } var order = Enumerable.Range(1, (int)(width / 2)) .Select(offset => new[] { startIndex + offset, startIndex - offset }) .SelectMany(x => x) .ToList(); order.Insert(0, startIndex); order = order.Where(x => x >= 0).ToList(); if (width % 2 == 0) { order.Remove(order.Max()); } switch (_options.Order) { case Options.TOrder.Reverse: order.Reverse(); break; case Options.TOrder.Ascending: order.Sort(); break; case Options.TOrder.Descending: order.Sort(); order.Reverse(); break; } var table = MakeOpeningTable((uint)order.Min(), (uint)order.Max(), state, player, searchType, incr); return((pattern, fuzzyOrder) => { return order .Select(idx => { var dataArr = table.Where(x => x.Index == idx); return dataArr.Select(data => { if (OpeningMatch(pattern, data, fuzzyOrder)) { return new ScanEntry() { Diff = (int)idx - (int)startIndex, Index = (uint)idx, Data = data, }; } return null; }); }) .SelectMany(x => x) .Where(x => x != null); }); }