local function solve(clues) local known = {} local changed = true while changed do changed = false local residuals, byTile = {}, {} for _, clue in ipairs(clues) do local need, remaining = clue.count, {} for _, id in ipairs(clue.ids) do if known[id] == nil then remaining[id] = true else need -= known[id] end end local count = 0 for _ in pairs(remaining) do count += 1 end if need < 0 or need > count then return {}, false end if count > 0 and (need == 0 or need == count) then local value = if need == 0 then 0 else 1 for id in pairs(remaining) do known[id] = value end changed = true elseif count > 0 then local residual = {ids = remaining, count = count, need = need} table.insert(residuals, residual) for id in pairs(remaining) do byTile[id] = byTile[id] or {} table.insert(byTile[id], residual) end end end if not changed then for _, small in ipairs(residuals) do local first = next(small.ids) for _, large in ipairs(byTile[first]) do if small == large or small.count > large.count then continue end local subset = true for id in pairs(small.ids) do if not large.ids[id] then subset = false break end end if not subset then continue end local need = large.need - small.need local extra = large.count - small.count if need < 0 or need > extra then return {}, false end if extra > 0 and (need == 0 or need == extra) then for id in pairs(large.ids) do if not small.ids[id] then known[id] = if need == 0 then 0 else 1 end end changed = true break end end if changed then break end end end end local frontier = {} for _, clue in ipairs(clues) do local edge = {ids = {}, need = clue.count, used = 0, left = 0} for _, id in ipairs(clue.ids) do if known[id] == nil then table.insert(edge.ids, id) frontier[id] = frontier[id] or {} table.insert(frontier[id], edge) else edge.need -= known[id] end end edge.left = #edge.ids end local visited, budget = {}, 180000 local stopAt = os.clock() + 0.035 for first in pairs(frontier) do if visited[first] then continue end local ids, seenEdges = {first}, {} visited[first] = true local cursor = 1 while cursor <= #ids do for _, edge in ipairs(frontier[ids[cursor]]) do if seenEdges[edge] then continue end seenEdges[edge] = true for _, id in ipairs(edge.ids) do if not visited[id] then visited[id] = true table.insert(ids, id) end end end cursor += 1 end if #ids > 64 or budget <= 0 or os.clock() >= stopAt then continue end local linked, used = {}, {} local ordered = {} for _ = 1, #ids do local best, bestScore for _, id in ipairs(ids) do if used[id] then continue end local score = (linked[id] or 0) * 100 + #frontier[id] if not bestScore or score > bestScore then best, bestScore = id, score end end used[best] = true table.insert(ordered, best) for _, edge in ipairs(frontier[best]) do for _, id in ipairs(edge.ids) do if not used[id] then linked[id] = (linked[id] or 0) + 1 end end end end ids = ordered local assignments, mineCounts, solutions = {}, {}, 0 local componentBudget = math.min(70000, budget) local function enumerate(index) if componentBudget <= 0 or (componentBudget % 256 == 0 and os.clock() >= stopAt) then return false end budget -= 1 componentBudget -= 1 if index > #ids then solutions += 1 for i, value in ipairs(assignments) do mineCounts[i] = (mineCounts[i] or 0) + value end return true end local adjacent = frontier[ids[index]] for value = 0, 1 do local valid = true for _, edge in ipairs(adjacent) do edge.left -= 1 edge.used += value if edge.used > edge.need or edge.used + edge.left < edge.need then valid = false end end local complete = true if valid then assignments[index] = value complete = enumerate(index + 1) end for _, edge in ipairs(adjacent) do edge.left += 1 edge.used -= value end if not complete then return false end end return true end if not enumerate(1) then continue end if solutions == 0 then return {}, false end for i, id in ipairs(ids) do known[id] = (mineCounts[i] or 0) / solutions end end return known, true end local Players = game:GetService("Players") local Teams = game:GetService("Teams") local ReplicatedStorage = game:GetService("ReplicatedStorage") local player = Players.LocalPlayer assert(game.GameId == 3047037061, "This script is for bLockerman's Minesweeper.") local environment = getgenv() local resumedSettings = environment.MinesweeperESPReloadSettings environment.MinesweeperESPReloadSettings = nil local previous = environment.MinesweeperESP if previous then previous.cleanup() end local state = {alive = true, scans = 0, flagsPlaced = 0} environment.MinesweeperESP = state local overlay = Instance.new("Folder") overlay.Name = "MinesweeperMarkers" overlay.Parent = workspace local window function state.cleanup() if not state.alive then return end state.alive = false overlay:Destroy() if window and not window.unloaded then window:Unload() end if environment.MinesweeperESP == state then environment.MinesweeperESP = nil end end if STATE then STATE.onCleanup(state.cleanup) end local ok, rayfield = pcall(function() local compile = assert(loadstring(game:HttpGet("https://sirius.menu/gen2"))) return compile() end) if not ok then state.cleanup() error(tostring(rayfield)) end window = rayfield:CreateWindow({name = "Minesweeper", subtitle = "Rayfield Gen2", sidebarLayout = true}) local tab = window:CreateTab({name = "Board"}) local settings = {safe = true, bomb = true, half = true, auto = false, radius = 20, delayMs = 100, suggest = true} if resumedSettings then for _, key in ipairs({"safe", "bomb", "half", "auto", "radius", "delayMs", "suggest"}) do if resumedSettings[key] ~= nil then settings[key] = resumedSettings[key] end end end state.settings = settings local colors = { safe = Color3.fromRGB(64, 236, 117), bomb = Color3.fromRGB(255, 70, 85), half = Color3.fromRGB(255, 208, 66), suggest = Color3.fromRGB(79, 180, 255), } for _, option in ipairs({{"safe", "Safe ESP"}, {"bomb", "Bomb ESP"}, {"half", "50/50 ESP"}, {"suggest", "Show a guess when stuck"}}) do local key = option[1] tab:CreateToggle({name = option[2], value = settings[key], callback = function(value) settings[key] = value end}) end tab:CreateSlider({ name = "Auto-flag range", range = {1, 31}, increment = 1, value = settings.radius, suffix = " studs", callback = function(value) settings.radius = value end, }) tab:CreateSlider({ name = "Auto-flag delay", range = {50, 1000}, increment = 10, value = settings.delayMs, suffix = " ms", callback = function(value) settings.delayMs = value end, }) tab:CreateToggle({name = "Auto-flag", value = settings.auto, forgetState = true, callback = function(value) settings.auto = value end}) local status = tab:CreateText({name = "Board status", text = "Reading the board."}) tab:CreateButton({name = "Unload", callback = state.cleanup}) local function readTile(part) local gui = part:FindFirstChild("NumberGui") if not gui then return nil, part:FindFirstChildWhichIsA("Model") ~= nil end local label = gui:FindFirstChild("TextLabel") if not label or not label:IsA("TextLabel") then return nil, true end local value = label.Text if value == "X" then return nil, true end if value == "" then return 0, false end local clue = tonumber(value) if clue and clue >= 0 and clue <= 8 and clue % 1 == 0 then return clue, false end return nil, true end local function tileId(x, z) return tostring(x) .. "," .. tostring(z) end local function readBoard(parts) local tiles, occupied = {}, 0 for _, part in ipairs(parts:GetChildren()) do if not part:IsA("BasePart") then continue end local x = math.round(part.Position.X / part.Size.X) local z = math.round(part.Position.Z / part.Size.Z) local number, flagged = readTile(part) tiles[tileId(x, z)] = {part = part, x = x, z = z, number = number, flagged = flagged} occupied += 1 end return tiles, occupied end local cachedTiles, cachedCount, cachedParts, cachedMarks, cachedValid, cachedClueCount local function solveBoard(parts, tiles, occupied) local unchanged = cachedParts == parts and cachedCount == occupied if unchanged then for id, tile in pairs(tiles) do local old = cachedTiles[id] if not old or old.part ~= tile.part or old.number ~= tile.number then unchanged = false break end end end if unchanged then return cachedMarks, cachedValid, cachedClueCount end local clues = {} for _, tile in pairs(tiles) do if tile.number == nil then continue end local ids = {} for dx = -1, 1 do for dz = -1, 1 do local id = tileId(tile.x + dx, tile.z + dz) local neighbor = tiles[id] if neighbor and neighbor.number == nil then table.insert(ids, id) end end end table.insert(clues, {ids = ids, count = tile.number}) end local marks, valid = solve(clues) cachedParts, cachedTiles, cachedCount = parts, tiles, occupied cachedMarks, cachedValid, cachedClueCount = marks, valid, #clues return marks, valid, #clues end local events = ReplicatedStorage:FindFirstChild("Events") local flagEvents = events and events:FindFirstChild("FlagEvents") local placeFlag = flagEvents and flagEvents:FindFirstChild("PlaceFlag") local info = ReplicatedStorage:FindFirstChild("Info") local flagless = info and info:FindFirstChild("Flagless") local requestArgument local nextLookup = 0 local function getFlagArgument() if requestArgument then return requestArgument end if os.clock() < nextLookup then return nil end nextLookup = os.clock() + 5 local closures = filtergc("function", {Constants = {"PlaceFlag"}, IgnoreExecutor = true}, false) for _, closure in ipairs(closures) do if not string.find(debug.info(closure, "s"), "ReplicatedFirst.MouseControl", 1, true) then continue end for _, value in pairs(debug.getupvalues(closure)) do if type(value) == "string" and value:match("^%d+$") then requestArgument = value return value end end end return nil end local markers = {} local route = Instance.new("BillboardGui") route.Name = "NextTile" route.Size = UDim2.fromOffset(100, 28) route.StudsOffsetWorldSpace = Vector3.new(0, 3.6, 0) route.AlwaysOnTop = true route.Enabled = false route.Parent = overlay local routeLabel = Instance.new("TextLabel") routeLabel.Size = UDim2.fromScale(1, 1) routeLabel.BackgroundColor3 = Color3.fromRGB(16, 24, 29) routeLabel.BackgroundTransparency = 0.15 routeLabel.Font = Enum.Font.GothamBold routeLabel.TextSize = 13 routeLabel.Parent = route local attempts = setmetatable({}, {__mode = "k"}) local pending local function showMarker(tile, key, active) local part = tile.part local marker = markers[part] if not marker then marker = Instance.new("BoxHandleAdornment") marker.Adornee = part marker.Size = Vector3.new(part.Size.X * 0.92, 0.08, part.Size.Z * 0.92) marker.CFrame = CFrame.new(0, part.Size.Y / 2 + 0.08, 0) marker.ZIndex = 3 marker.AlwaysOnTop = true marker.Parent = overlay markers[part] = marker end marker.Color3 = colors[key] marker.Transparency = if key == "safe" and tile.flagged then 0.18 else 0.38 active[part] = true end local lastFlagAt = -math.huge local function update() local board = workspace:FindFirstChild("Flag") local parts = board and board:FindFirstChild("Parts") if not parts then for _, marker in pairs(markers) do marker:Destroy() end table.clear(markers) route.Enabled = false status:Set("Waiting for the board.") return end local tiles, count = readBoard(parts) local marks, valid, clueCount = solveBoard(parts, tiles, count) local root = player.Character and player.Character:FindFirstChild("HumanoidRootPart") local playing = player.Team ~= nil and player.Team == Teams:FindFirstChild("Playing") local eligible = playing and root and not (flagless and flagless:IsA("BoolValue") and flagless.Value) local now = os.clock() local counts = {safe = 0, bomb = 0, half = 0} local active = {} local candidate, bestDistance if pending then local _, flagged = readTile(pending.part) if pending.part.Parent == parts and flagged then state.flagsPlaced += 1 pending = nil elseif pending.part.Parent ~= parts or now >= pending.deadline then pending = nil end end local openableSafe, flaggedSafe = 0, 0 local guess, guessRisk, guessDistance local nearestSafe, safeDistance, nearestFlaggedSafe, flaggedSafeDistance local position = root and root.Position or (workspace.CurrentCamera and workspace.CurrentCamera.CFrame.Position) for id, tile in pairs(tiles) do if tile.number ~= nil then continue end local risk = marks[id] local key = if risk == 0 then "safe" elseif risk == 1 then "bomb" elseif risk == 0.5 then "half" else nil if key then counts[key] += 1 end if key == "safe" then local distance = position and (position - tile.part.Position).Magnitude if tile.flagged then flaggedSafe += 1 if distance and (not flaggedSafeDistance or distance < flaggedSafeDistance) then nearestFlaggedSafe, flaggedSafeDistance = tile, distance end else openableSafe += 1 if distance and (not safeDistance or distance < safeDistance) then nearestSafe, safeDistance = tile, distance end end end if key and settings[key] and (not tile.flagged or key == "safe") then showMarker(tile, key, active) end if tile.flagged or not position then continue end local distance = (position - tile.part.Position).Magnitude if key == "bomb" and eligible and not attempts[tile.part] then if distance <= settings.radius and (not bestDistance or distance < bestDistance) then candidate, bestDistance = tile.part, distance end elseif risk ~= 0 and risk ~= 1 and settings.suggest and valid and clueCount > 0 then local score = risk or math.huge local bestScore = guessRisk or math.huge if not guess or score < bestScore or (score == bestScore and distance < guessDistance) then guess, guessRisk, guessDistance = tile, risk, distance end end end local nextMove = "" local routeTile, routeText, routeColor if valid and count == 0 then nextMove = "\nWaiting for tiles." elseif valid and clueCount == 0 then nextMove = "\nOpen a tile to start solving." elseif valid and nearestSafe and settings.safe then routeTile, routeText, routeColor = nearestSafe, "SAFE", colors.safe nextMove = ("\nNearest safe tile: %.0f studs."):format(safeDistance) elseif valid and openableSafe == 0 then if flaggedSafe > 0 then if nearestFlaggedSafe and settings.safe then routeTile, routeText, routeColor = nearestFlaggedSafe, "UNFLAG", colors.safe end nextMove = ("\nUnflag a green tile (%d flagged)."):format(flaggedSafe) elseif guess then showMarker(guess, "suggest", active) routeTile, routeText, routeColor = guess, "GUESS", colors.suggest nextMove = if guessRisk then ("\nBlue guess: %.0f%% mine risk from connected clues."):format(guessRisk * 100) else "\nBlue guess: risk unknown." else nextMove = "\nNo proven safe move." end end route.Enabled = routeTile ~= nil route.Adornee = routeTile and routeTile.part or nil if routeTile then routeLabel.Text = routeText routeLabel.TextColor3 = routeColor end for part, marker in pairs(markers) do if not active[part] then marker:Destroy() markers[part] = nil end end local flagStatus = "Off" if settings.auto then if not eligible then flagStatus = "Waiting until you are playing" elseif not placeFlag or not placeFlag:IsA("RemoteEvent") or not getFlagArgument() then flagStatus = "Flag control unavailable" else flagStatus = ("%d placed | %d studs | %d ms"):format(state.flagsPlaced, settings.radius, settings.delayMs) if candidate and not pending and now - lastFlagAt >= settings.delayMs / 1000 then local number, flagged = readTile(candidate) if candidate.Parent == parts and number == nil and not flagged then attempts[candidate] = true lastFlagAt = now pending = {part = candidate, deadline = now + 1.5} placeFlag:FireServer(candidate, requestArgument, true) end end end end state.scans += 1 state.last = {tiles = count, clues = clueCount, safe = counts.safe, bomb = counts.bomb, half = counts.half, flagControl = requestArgument ~= nil, eligible = not not eligible, nearest = bestDistance, valid = valid, flagsPlaced = state.flagsPlaced, flaggedSafe = flaggedSafe, openableSafe = openableSafe, suggested = guess ~= nil and openableSafe == 0 and flaggedSafe == 0} local message = ("%d safe | %d mines | %d at 50/50\nAuto-flag: %s%s"):format( counts.safe, counts.bomb, counts.half, flagStatus, if valid then nextMove else "\nWaiting for consistent clues") if status.text ~= message then status:Set(message) end end task.spawn(function() while state.alive and not window.unloaded do update() task.wait(if settings.auto then 0.05 else 0.4) end state.cleanup() end) return "bebebebe"