static bool CheckDeadlock(TopLeftTodo topLeftTodo, SokowahnField view, ushort playerTopLeft) { HashSet<ulong> bHash; int boxesCount = topLeftTodo.state.Length - 1; if (boxesHash.TryGetValue(boxesCount, out bHash)) { ulong crc = Crc64.Start.Crc64Update(playerTopLeft).Crc64Update(topLeftTodo.state, 1, boxesCount); if (!bHash.Contains(crc)) { return true; } } else { // --- schnelle Vorprüfung --- for (int b = 1; b < topLeftTodo.state.Length; b++) { if (invalidBoxes.Contains(topLeftTodo.state[b])) return true; } // --- bestmögliche Hashprüfung --- int boxesCountMin = boxesHash.Count; bHash = boxesHash[boxesCountMin]; var checkBoxes = topLeftTodo.state.Skip(1).Where(b => b != topLeftTodo.lastBox).ToArray(); var checkState = new ushort[1 + boxesCountMin]; checkState[0] = playerTopLeft; foreach (var variant in SokoTools.FieldBoxesVariantsStatic(checkBoxes.Length, boxesCountMin - 1)) { for (int v = 0; v < variant.Length; v++) checkState[v + 1] = checkBoxes[variant[v]]; AppendBoxes(checkState, topLeftTodo.lastBox); view.SetGameState(checkState); view.SetPlayerTopLeft(); ulong crc = view.GetGameStateCrc(); if (!bHash.Contains(crc)) { return true; } } } return false; }
static ushort[] TestScan(int width, TopLeftTodo topLeftTodo, HashSet<ushort> ways, SokowahnField view, bool debug = true) { var state = topLeftTodo.state; view.SetGameState(state); var result = ScanBestTopLeftWay(state[0], width, ways, new HashSet<ushort>(state.Skip(1))); if (state.Length > 1 && CheckDeadlock(topLeftTodo, view, result[result.Count - 1])) return null; if (debug) { Console.SetCursorPosition(0, Math.Max(0, Console.CursorTop - 2)); Console.WriteLine(new string(' ', Console.WindowWidth - 1)); Console.SetCursorPosition(0, 1); Console.WriteLine(view.ToString()); Console.WriteLine(); string line = state[0] + " - " + string.Join(", ", result.Skip(1)); Console.WriteLine(line); Console.WriteLine(); } var known = new HashSet<ushort>(topLeftTodo.known); if (known.Contains(result[result.Count - 1])) return new[] { result[result.Count - 1] }; var resultFiltered = result.Where(f => !known.Contains(f)).ToArray(); return resultFiltered; }