public void CalculatesTurnsForZeroAugmentColumnPriorToGaussianElimination() { const int nodeCount = 25; const int mineCount = 1; Span <Node> nodes = stackalloc Node[] { new(0, false, 0, NodeState.Revealed), new(1, false, 1, NodeState.Revealed), new(2, true, 0, NodeState.Flagged), new(3, false, 0, NodeState.Hidden), new(4, false, 0, NodeState.Hidden), new(5, false, 0, NodeState.Revealed), new(6, false, 1, NodeState.Revealed), new(7, false, 1, NodeState.Revealed), new(8, false, 0, NodeState.Hidden), new(9, false, 0, NodeState.Hidden), new(10, false, 1, NodeState.Revealed), new(11, false, 1, NodeState.Revealed), new(12, false, 1, NodeState.Revealed), new(13, false, 0, NodeState.Hidden), new(14, false, 0, NodeState.Hidden), new(15, false, 0, NodeState.Hidden), new(16, false, 0, NodeState.Hidden), new(17, false, 3, NodeState.Revealed), new(18, false, 0, NodeState.Hidden), new(19, false, 0, NodeState.Hidden), new(20, false, 0, NodeState.Hidden), new(21, false, 0, NodeState.Hidden), new(22, false, 0, NodeState.Hidden), new(23, false, 0, NodeState.Hidden), new(24, false, 0, NodeState.Hidden) }; var buffs = new BufferKeeper { Turns = stackalloc Turn[nodeCount], EdgeIndexes = stackalloc int[Engine.MaxNodeEdges], Mines = stackalloc int[mineCount], VisitedIndexes = stackalloc int[nodeCount - mineCount], RevealedMineCountNodeIndexes = stackalloc int[nodeCount - mineCount], AdjacentHiddenNodeIndexes = stackalloc int[nodeCount], Grid = stackalloc float[nodeCount * nodeCount] }; var matrix = new Matrix <Node>(nodes, 5); var turnCount = MatrixSolver.CalculateTurns(matrix, buffs, false); Assert.Equal(3, turnCount); Assert.Equal(new Turn(3, NodeOperation.Reveal), buffs.Turns[0]); Assert.Equal(new Turn(8, NodeOperation.Reveal), buffs.Turns[1]); Assert.Equal(new Turn(13, NodeOperation.Reveal), buffs.Turns[2]); }
public static void Simulation(Matrix <Node> matrix, Span <Turn> turns, int firstTurnNodeIndex, int mineCount) { var nodeCount = matrix.Nodes.Length; var buffs = new BufferKeeper { Turns = stackalloc Turn[nodeCount], EdgeIndexes = stackalloc int[Engine.MaxNodeEdges], Mines = stackalloc int[mineCount], VisitedIndexes = stackalloc int[nodeCount - mineCount], RevealedMineCountNodeIndexes = stackalloc int[nodeCount - mineCount], AdjacentHiddenNodeIndexes = stackalloc int[nodeCount], Grid = stackalloc float[nodeCount * nodeCount] }; Engine.FillCustomBoard(matrix, buffs.Mines, firstTurnNodeIndex); var firstTurn = new Turn(firstTurnNodeIndex, NodeOperation.Reveal); Engine.ComputeBoard(matrix, firstTurn, buffs.VisitedIndexes); while (true) { var turnCount = MatrixSolver.CalculateTurns(matrix, buffs, false); if (turnCount == 0) { turnCount = MatrixSolver.CalculateTurns(matrix, buffs, true); if (turnCount == 0) { break; } } foreach (var turn in turns.Slice(0, turnCount)) { Engine.ComputeBoard(matrix, turn, buffs.VisitedIndexes); } } } }
public void CalculatesTurnsForVectorSumEqualsAugmentColumnPriorToGaussianElimination() { const int nodeCount = 64; const int mineCount = 4; Span <Node> nodes = stackalloc Node[] { new(0, false, 0, NodeState.Revealed), new(1, false, 0, NodeState.Revealed), new(2, false, 0, NodeState.Revealed), new(3, false, 0, NodeState.Revealed), new(4, false, 1, NodeState.Revealed), new(5, false, 0, NodeState.Hidden), new(6, false, 1, NodeState.Revealed), new(7, false, 0, NodeState.Revealed), new(8, false, 1, NodeState.Revealed), new(9, false, 1, NodeState.Revealed), new(10, false, 2, NodeState.Revealed), new(11, false, 1, NodeState.Revealed), new(12, false, 2, NodeState.Revealed), new(13, false, 0, NodeState.Hidden), new(14, false, 1, NodeState.Revealed), new(15, false, 0, NodeState.Revealed), new(16, false, 1, NodeState.Revealed), new(17, true, 0, NodeState.Flagged), new(18, false, 2, NodeState.Revealed), new(19, true, 0, NodeState.Flagged), new(20, false, 2, NodeState.Revealed), new(21, false, 1, NodeState.Revealed), new(22, false, 1, NodeState.Revealed), new(23, false, 0, NodeState.Revealed), new(24, false, 2, NodeState.Revealed), new(25, false, 2, NodeState.Revealed), new(26, false, 3, NodeState.Revealed), new(27, false, 1, NodeState.Revealed), new(28, false, 2, NodeState.Revealed), new(29, false, 0, NodeState.Hidden), new(30, false, 1, NodeState.Revealed), new(31, false, 0, NodeState.Revealed), new(32, false, 2, NodeState.Revealed), new(33, true, 0, NodeState.Flagged), new(34, false, 2, NodeState.Revealed), new(35, false, 0, NodeState.Revealed), new(36, false, 1, NodeState.Revealed), new(37, false, 0, NodeState.Hidden), new(38, false, 3, NodeState.Revealed), new(39, false, 2, NodeState.Revealed), new(40, false, 3, NodeState.Revealed), new(41, true, 0, NodeState.Flagged), new(42, false, 3, NodeState.Revealed), new(43, false, 1, NodeState.Revealed), new(44, false, 1, NodeState.Revealed), new(45, false, 2, NodeState.Revealed), new(46, false, 0, NodeState.Hidden), new(47, false, 0, NodeState.Hidden), new(48, false, 0, NodeState.Hidden), new(49, false, 0, NodeState.Hidden), new(50, false, 0, NodeState.Hidden), new(51, false, 0, NodeState.Hidden), new(52, false, 0, NodeState.Hidden), new(53, false, 0, NodeState.Hidden), new(54, false, 0, NodeState.Hidden), new(55, false, 0, NodeState.Hidden), new(56, false, 0, NodeState.Hidden), new(57, false, 0, NodeState.Hidden), new(58, false, 0, NodeState.Hidden), new(59, false, 0, NodeState.Hidden), new(60, false, 0, NodeState.Hidden), new(61, false, 0, NodeState.Hidden), new(62, false, 0, NodeState.Hidden), new(63, false, 0, NodeState.Hidden) }; var buffs = new BufferKeeper { Turns = stackalloc Turn[nodeCount], EdgeIndexes = stackalloc int[Engine.MaxNodeEdges], Mines = stackalloc int[mineCount], VisitedIndexes = stackalloc int[nodeCount - mineCount], RevealedMineCountNodeIndexes = stackalloc int[nodeCount - mineCount], AdjacentHiddenNodeIndexes = stackalloc int[nodeCount], Grid = stackalloc float[nodeCount * nodeCount] }; var matrix = new Matrix <Node>(nodes, 8); var turnCount = MatrixSolver.CalculateTurns(matrix, buffs, false); Assert.Equal(2, turnCount); Assert.Equal(new Turn(46, NodeOperation.Flag), buffs.Turns[0]); Assert.Equal(new Turn(47, NodeOperation.Flag), buffs.Turns[1]); }
public void CalculatesTurnsWhenGaussianEliminationProducesNonIntegers() { const int nodeCount = 64; const int mineCount = 10; Span <Node> nodes = stackalloc Node[] { new(0, false, 1, NodeState.Revealed), new(1, false, 1, NodeState.Revealed), new(2, false, 1, NodeState.Revealed), new(3, true, 1, NodeState.Flagged), new(4, false, 2, NodeState.Revealed), new(5, false, 1, NodeState.Revealed), new(6, false, 1, NodeState.Revealed), new(7, false, 1, NodeState.Hidden), new(8, true, 1, NodeState.Flagged), new(9, false, 2, NodeState.Revealed), new(10, false, 3, NodeState.Revealed), new(11, false, 3, NodeState.Revealed), new(12, true, 2, NodeState.Hidden), new(13, false, 1, NodeState.Hidden), new(14, false, 1, NodeState.Revealed), new(15, true, 0, NodeState.Hidden), new(16, false, 2, NodeState.Revealed), new(17, true, 1, NodeState.Flagged), new(18, false, 2, NodeState.Revealed), new(19, true, 2, NodeState.Flagged), new(20, false, 3, NodeState.Hidden), new(21, false, 2, NodeState.Revealed), new(22, false, 1, NodeState.Revealed), new(23, false, 1, NodeState.Revealed), new(24, false, 1, NodeState.Revealed), new(25, false, 1, NodeState.Revealed), new(26, false, 3, NodeState.Revealed), new(27, false, 3, NodeState.Revealed), new(28, true, 2, NodeState.Hidden), new(29, false, 1, NodeState.Hidden), new(30, false, 0, NodeState.Hidden), new(31, false, 0, NodeState.Hidden), new(32, false, 0, NodeState.Revealed), new(33, false, 0, NodeState.Revealed), new(34, false, 1, NodeState.Revealed), new(35, true, 1, NodeState.Flagged), new(36, false, 2, NodeState.Revealed), new(37, false, 1, NodeState.Hidden), new(38, false, 0, NodeState.Hidden), new(39, false, 0, NodeState.Hidden), new(40, false, 0, NodeState.Revealed), new(41, false, 0, NodeState.Revealed), new(42, false, 1, NodeState.Revealed), new(43, false, 1, NodeState.Revealed), new(44, false, 2, NodeState.Revealed), new(45, false, 2, NodeState.Revealed), new(46, false, 2, NodeState.Hidden), new(47, false, 1, NodeState.Hidden), new(48, false, 0, NodeState.Revealed), new(49, false, 0, NodeState.Revealed), new(50, false, 0, NodeState.Revealed), new(51, false, 0, NodeState.Revealed), new(52, false, 1, NodeState.Revealed), new(53, true, 1, NodeState.Hidden), new(54, true, 1, NodeState.Hidden), new(55, false, 1, NodeState.Hidden), new(56, false, 0, NodeState.Revealed), new(57, false, 0, NodeState.Revealed), new(58, false, 0, NodeState.Revealed), new(59, false, 0, NodeState.Revealed), new(60, false, 1, NodeState.Revealed), new(61, false, 2, NodeState.Hidden), new(62, false, 2, NodeState.Hidden), new(63, false, 1, NodeState.Hidden) }; var buffs = new BufferKeeper { Turns = stackalloc Turn[nodeCount], EdgeIndexes = stackalloc int[Engine.MaxNodeEdges], Mines = stackalloc int[mineCount], VisitedIndexes = stackalloc int[nodeCount - mineCount], RevealedMineCountNodeIndexes = stackalloc int[nodeCount - mineCount], AdjacentHiddenNodeIndexes = stackalloc int[nodeCount], Grid = stackalloc float[nodeCount * nodeCount] }; var matrix = new Matrix <Node>(nodes, 8); var turnCount = MatrixSolver.CalculateTurns(matrix, buffs, false); Assert.Equal(2, turnCount); // changing float to sbyte will cause our solver to generate incorrect turns Assert.NotEqual(6, turnCount); Assert.Equal(new Turn(29, NodeOperation.Reveal), buffs.Turns[0]); Assert.Equal(new Turn(61, NodeOperation.Reveal), buffs.Turns[1]); }
static void Main(string[] args) { var options = new ChromeOptions(); //options.AddArgument("-headless"); using var driver = new ChromeDriver(options); // some key aspects have been omitted from this bot // also, performance is purposefully degraded driver.Navigate().GoToUrl(""); var squares = driver .FindElementById("game") .FindElements(By.ClassName("square")) .Where(x => x.Displayed) .ToList(); Debug.Assert(squares.Count == nodeCount); LeftClickNode(squares, 93); var buffs = new BufferKeeper { Turns = stackalloc Turn[nodeCount], EdgeIndexes = stackalloc int[Engine.MaxNodeEdges], Mines = stackalloc int[mineCount], VisitedIndexes = stackalloc int[nodeCount - mineCount], RevealedMineCountNodeIndexes = stackalloc int[nodeCount - mineCount], AdjacentHiddenNodeIndexes = stackalloc int[nodeCount], Grid = stackalloc float[nodeCount * nodeCount] }; while (IsGamePending(driver)) { var nodes = squares .Select(x => x.GetAttribute("class")) .Select((x, i) => new Node(i, false, GetMineCount(x), GetNodeState(x))) .ToArray() .AsSpan(); var matrix = new Matrix <Node>(nodes, columns); var turnCount = MatrixSolver.CalculateTurns(matrix, buffs, true); if (turnCount == 0) { break; } // ignore the other turns for now var turn = buffs.Turns[0]; if (turn.Operation == NodeOperation.Reveal) { LeftClickNode(squares, turn.NodeIndex); } else { RightClickNode(squares, turn.NodeIndex, driver); } Console.WriteLine(turn); } Console.WriteLine("finished"); Console.ReadLine(); }