0% found this document useful (0 votes)
13 views7 pages

Message

llac eht rotcod

Uploaded by

spinning1777
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views7 pages

Message

llac eht rotcod

Uploaded by

spinning1777
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

_G.

Enabled = true
_G.Debugging = true

local Workspace = game:GetService("Workspace")


local START_POS = Vector3.new(41.5, 56.5, 72.5)

local function Log(...)


if _G.Debugging then
print("[SafeMineSweeperSolver]", ...)
end
end

local function SafeAccess(obj, ...)


local current = obj
for _, key in ipairs({...}) do
if not current then return nil end
current = current:FindFirstChild(key)
end
return current
end

local function CalculateCoordinates(tile, origin)


local x = math.round((tile.Position.X - origin.X) / 5)
local z = math.round((tile.Position.Z - origin.Z) / 5)
return x, z
end

local function CreateDot(tile, kind)


if tile:FindFirstChild("SolverDot") then return end
local dot = Instance.new("Part")
dot.Name = "SolverDot"
dot.Shape = Enum.PartType.Ball
dot.Size = Vector3.new(0.8,0.8,0.8)
dot.Material = Enum.Material.Neon
dot.Anchored = true
dot.CanCollide = false
dot.TopSurface = Enum.SurfaceType.Smooth
dot.BottomSurface= Enum.SurfaceType.Smooth
dot.BrickColor = (kind=="safe") and BrickColor.new("Bright green")
or BrickColor.new("Bright red")
dot.Position = tile.Position
+ Vector3.new(0, tile.Size.Y/2 + dot.Size.Y/2, 0)
dot.Parent = tile
end

local function GetTileState(tile)


if not tile or not tile:IsA("BasePart") then
return { state = "invalid" }
end
local st = {
tile = tile,
name = tile.Name,
position = {0,0},
state = "unknown",
number = nil,
}
local dot = tile:FindFirstChild("SolverDot")
if dot then
st.state = (dot.BrickColor.Name=="Bright green")
and "safe_marked"
or "bomb_marked"
return st
end
local label = SafeAccess(tile, "NumberGui", "TextLabel")
if label then
st.state = "revealed"
st.number = tonumber(label.Text) or 0
return st
end
if tile.BrickColor.Name == "Really red" or tile.BrickColor.Name == "Bright red"
or tile.BrickColor.Name == "Red" then
st.state = "bomb"
return st
end
local mine = tile:FindFirstChild("Mine") or tile:FindFirstChild("Bomb")
if mine then
st.state = "bomb"
return st
end
if tile.Name:lower():find("mine") or tile.Name:lower():find("bomb") then
st.state = "bomb"
return st
end
return st
end

local function AnalyzeGrid()


local parts = SafeAccess(Workspace, "Flag", "Parts")
if not parts then return nil end

local grid = {}
local constraints = {}

for _, tile in ipairs(parts:GetChildren()) do


if tile:IsA("BasePart") then
local x, z = CalculateCoordinates(tile, START_POS)
local ts = GetTileState(tile)
ts.position = { x, z }
grid[x.."|"..z] = ts
end
end

for key, ts in pairs(grid) do


if ts.state == "revealed" and ts.number and ts.number > 0 then
local c = {
tile = ts,
number = ts.number,
neighbors = {},
unknowns = {},
bombs = 0,
}
for dx = -1,1 do
for dz = -1,1 do
if not (dx == 0 and dz == 0) then
local nk = (ts.position[1]+dx).."|"..(ts.position[2]+dz)
local nt = grid[nk]
if nt then
table.insert(c.neighbors, nt)
if nt.state=="bomb" or nt.state=="bomb_marked" then
c.bombs = c.bombs + 1
elseif nt.state=="unknown" then
table.insert(c.unknowns, nt)
end
end
end
end
end
c.remaining = c.number - c.bombs
constraints[key] = c
end
end

return { grid = grid, constraints = constraints }


end

local function ValidateMove(kind, tiles, A)


if #tiles == 0 then return false end

local moveSet = {}
for _, ts in ipairs(tiles) do
moveSet[ts.position[1].."|"..ts.position[2]] = true
end

for _, c in pairs(A.constraints) do
local unknownCount = 0
local neighMap = {}
for _, n in ipairs(c.neighbors) do
local k = n.position[1].."|"..n.position[2]
neighMap[k] = n
if n.state=="unknown" then unknownCount = unknownCount + 1 end
end

local db, du = 0, 0
for k in pairs(moveSet) do
if neighMap[k] then
if kind=="bomb" then
db = db + 1
du = du - 1
else
du = du - 1
end
end
end

local sb = c.bombs + db
local su = unknownCount + du
if sb > c.number or su < (c.number - sb) then
return false
end
end

return true
end

local function MarkTiles(kind, tiles, reason, A)


if #tiles==0 or not ValidateMove(kind, tiles, A) then
return 0
end

local count = 0
for _, ts in ipairs(tiles) do
if ts.state=="unknown" then
CreateDot(ts.tile, kind)
gameState.solvedTiles[ts.tile.Name] = (kind=="safe" and "safe" or
"bomb")
count = count + 1
end
end
if count>0 then
Log((kind=="safe" and "✠SAFE:" or "ðŸ'£ BOMB:"), count, reason)
end
return count
end

local function ApplyBasic(C, A)


local moves = 0
for _, c in pairs(C) do
local hidden = {}
for _, n in ipairs(c.neighbors) do
if n.state=="unknown" then
table.insert(hidden, n)
end
end
local hcount = #hidden
if c.remaining <= 0 and hcount > 0 then
moves = moves + MarkTiles("safe", hidden, c.tile.name.." all safe", A)
elseif c.remaining == hcount and hcount > 0 then
moves = moves + MarkTiles("bomb", hidden, c.tile.name.." all bombs", A)
end
end
return moves
end

local function SolveSingleton(C, A)


local moves = 0
local map = {}
for _, c in pairs(C) do
for _, u in ipairs(c.unknowns) do
local k = u.position[1].."|"..u.position[2]
map[k] = map[k] or { u, {} }
table.insert(map[k][2], c)
end
end
for _, entry in pairs(map) do
local u, cs = entry[1], entry[2]
local mustBomb, mustSafe = false, false
for _, c in ipairs(cs) do
local total = #c.unknowns
local bs = c.bombs
if bs + 1 > c.number then mustSafe = true end
if total - 1 < (c.number - bs) then mustBomb = true end
end
if mustBomb and not mustSafe then
moves = moves + MarkTiles("bomb", {u}, "singleton bomb", A)
elseif mustSafe and not mustBomb then
moves = moves + MarkTiles("safe", {u}, "singleton safe", A)
end
if moves > 0 then return moves end
end
return moves
end

local function SolveOverlap(C, A)


local moves = 0
local list = {}
for _, c in pairs(C) do
table.insert(list, c)
end
local function keyOf(u) return u.position[1].."|"..u.position[2] end

for i = 1, #list do
for j = i+1, #list do
local c1, c2 = list[i], list[j]
local map2 = {}
for _, u in ipairs(c2.unknowns) do
map2[keyOf(u)] = u
end
local S,U1,U2 = {},{},{}
for _, u in ipairs(c1.unknowns) do
if map2[keyOf(u)] then table.insert(S, u)
else table.insert(U1,u) end
end
local sharedMap = {}
for _, u in ipairs(S) do sharedMap[keyOf(u)] = true end
for _, u in ipairs(c2.unknowns) do
if not sharedMap[keyOf(u)] then table.insert(U2,u) end
end
local s = #S
local r1 = c1.remaining
local r2 = c2.remaining
local u1 = #U1
local u2 = #U2
if s > 0 then
local low = math.max(0, r1 - u1, r2 - u2)
local high = math.min(r1, r2, s)
if high == 0 then
moves = moves + MarkTiles("safe", S, "overlap safe", A)
elseif low == s then
moves = moves + MarkTiles("bomb", S, "overlap bombs", A)
else
local minA,maxA = r1 - high, r1 - low
if u1 > 0 then
if maxA == 0 then
moves = moves + MarkTiles("safe", U1,"unique1 safe",A)
elseif minA==u1 and maxA==u1 then
moves = moves + MarkTiles("bomb", U1,"unique1 bombs",A)
end
end
local minB,maxB = r2 - high, r2 - low
if u2 > 0 then
if maxB == 0 then
moves = moves + MarkTiles("safe", U2,"unique2 safe",A)
elseif minB==u2 and maxB==u2 then
moves = moves + MarkTiles("bomb", U2,"unique2 bombs",A)
end
end
end
if moves>0 then return moves end
end
end
end
return moves
end

local function SolveStep()


local total = 0
while _G.Enabled do
local A = AnalyzeGrid()
if not A then return total end

local made = 0
made = made + ApplyBasic(A.constraints, A)
if made==0 then made = made + SolveSingleton(A.constraints, A) end
if made==0 then made = made + SolveOverlap(A.constraints, A) end

total = total + made


if made == 0 then break end
end
return total
end

task.spawn(function()
local fails = 0
while _G.Enabled do
local ok, err = pcall(function()
local parts = SafeAccess(Workspace, "Flag", "Parts")
if parts and #parts:GetChildren() > 30 then
local moves = SolveStep()
if moves > 0 then
fails = 0
Log("✠Made", moves, "moves")
task.wait(0.05)
else
fails = fails + 1
if fails > 20 then
Log("Manual intervention needed")
task.wait(0.5)
fails = 0
end
end
else
Log("Waiting for grid")
end
end)
if not ok then
Log("Solver error:", err)
fails = fails + 1
end
task.wait(0.05)
end
end)

_G.StopSolver = function()
_G.Enabled = false
Log("Solver stopped")
end

_G.StartSolver = function()
_G.Enabled = true
gameState = { solvedTiles = {}, constraints = {}, lastGridHash = "",
moveHistory = {} }
Log("Solver started")
end

_G.GetStats = function()
local s,b = 0,0
for _, v in pairs(gameState.solvedTiles) do
if v=="safe" then s=s+1 elseif v=="bomb" then b=b+1 end
end
Log("Stats - Safe:", s, "Bombs:", b)
end

_G.ToggleDebug = function()
_G.Debugging = not _G.Debugging
Log("Debug:", _G.Debugging)
end

Log("SAFE Minesweeper Solver loaded")

You might also like