-- ╔══════════════════════════════════════════════════════════════════╗ -- ║ RoChess! Best-Move Bot · WindUI · by AGY ║ -- ║ • Uses the game's built-in engine at high depth ║ -- ║ • PERSISTENT CONFIG: Auto-saves & auto-loads all settings ║ -- ║ • STARTS ON: Auto-Play, Auto-Queue (3+2), Auto-Claim, Anti-AFK ║ -- ║ • UI Toggles start VISUALLY ON (Value = saved/true) ║ -- ║ • Immediately queues upon script launch if not in game ║ -- ║ • Configurable Keybind to toggle GUI & Auto-Play ║ -- ╚══════════════════════════════════════════════════════════════════╝ -- Ensure CoreGui compatibility for WindUI local CoreGui = game:GetService("CoreGui") if not CoreGui:FindFirstChild("RobloxGui") then local dummy = Instance.new("Folder") dummy.Name = "RobloxGui" dummy.Parent = CoreGui end -- ── Load WindUI ─────────────────────────────────────────────────────── local WindUI = loadstring(game:HttpGet( "https://raw.githubusercontent.com/Footagesus/WindUI/main/dist/main.lua" ))() -- ── Game references ─────────────────────────────────────────────────── local RS = game:GetService("ReplicatedStorage") local HttpService = game:GetService("HttpService") local Players = game:GetService("Players") local VirtualUser = game:GetService("VirtualUser") local LocalPlayer = Players.LocalPlayer local Chess = RS:WaitForChild("Chess", 15) local ChessClient = RS:WaitForChild("ChessClient", 15) assert(Chess and ChessClient, "[RoChessBot] Not in RoChess!") local Engine = require(Chess:WaitForChild("Engine")) local Bot = require(Chess:WaitForChild("Bot")) local Config = require(Chess:WaitForChild("Config")) local App = require(ChessClient:WaitForChild("App")) local Remotes = Chess:WaitForChild("Remotes") local Action = Remotes:WaitForChild("Action") local Request = Remotes:WaitForChild("Request") local function send(t) Action:FireServer(t) end local function request(t) local ok, res = pcall(function() return Request:InvokeServer(t) end) return ok and res or nil end -- ── Persistent Config System (writefile / readfile) ─────────────────── local CONFIG_FILE = "RoChess_Bot_Config.json" local defaultCfg = { enabled = true, autoQueue = true, autoClaim = true, antiAfk = true, depth = 20, delayMin = 0.30, delayMax = 0.80, keybind = "V", } local cfg = table.clone(defaultCfg) local function saveConfig() pcall(function() if writefile then local data = HttpService:JSONEncode(cfg) writefile(CONFIG_FILE, data) end end) end local function loadConfig() pcall(function() if isfile and isfile(CONFIG_FILE) and readfile then local raw = readfile(CONFIG_FILE) local parsed = HttpService:JSONDecode(raw) if type(parsed) == "table" then for k, v in pairs(parsed) do if defaultCfg[k] ~= nil then cfg[k] = v end end print("[RoChessBot] 💾 Loaded saved configuration") end end end) end loadConfig() local botRunning = false -- ── Anti-AFK System ─────────────────────────────────────────────────── LocalPlayer.Idled:Connect(function() if cfg.antiAfk then VirtualUser:CaptureController() VirtualUser:ClickButton2(Vector2.new(0, 0)) print("[RoChessBot] 🛡 Anti-AFK: Kept connection alive") end end) task.spawn(function() while true do task.wait(300) if cfg.antiAfk then pcall(function() VirtualUser:CaptureController() VirtualUser:ClickButton2(Vector2.new(0, 0)) end) end end end) -- ── Helpers ─────────────────────────────────────────────────────────── local function session() return App.session end local function isMyTurn() local s = session() return s and not s.over and s.myColor ~= nil and s.engine.side == s.myColor and s.viewPly == #s.ucis end local function getBestMove() local s = session() if not s then return nil end return Bot.think(s.startFen, table.clone(s.ucis), { rating = 3000, depth = cfg.depth, noise = 0, blunder = 0 }) end local function queueGame() send({ type = "queue", tc = "3+2" }) print("[RoChessBot] ⚔ Fired queue 3+2") end local function claimAllTasks() if not cfg.autoClaim then return end local td = App.Tasks and App.Tasks.tasks local defs = Config.TASKS or {} if not td then return end for _, def in ipairs(defs) do local id = def.id local prog = tonumber(td.p and td.p[id]) or 0 local ok = prog >= (def.goal or 1) and not (td.c and td.c[id]) if ok then task.spawn(function() local res = request({ type = "claimTask", id = id }) if type(res) == "table" and res.ok then print(("[RoChessBot] ✓ Claimed task: %s"):format(def.label or id)) end end) end end end -- ── Play Best Move ──────────────────────────────────────────────────── local function playBestMove() if not cfg.enabled or botRunning then return end local s = session() if not s or s.over then return end if not (s.kind == "online" or s.kind == "bot") then return end if not isMyTurn() then return end botRunning = true task.spawn(function() task.wait(cfg.delayMin + math.random() * (cfg.delayMax - cfg.delayMin)) if not isMyTurn() then botRunning = false; return end local uci = getBestMove() if not uci or uci == "" then botRunning = false; return end local from64 = Engine.algToIndex64(uci:sub(1,2)) local to64 = Engine.algToIndex64(uci:sub(3,4)) local promo = ({ q=5, r=4, b=3, n=2 })[uci:sub(5,5):lower()] or 0 if not from64 or not to64 then botRunning = false; return end local ok = pcall(App.onBoardMove, from64, to64, promo, false) if ok then print(("[RoChessBot] ♟ Played: %s"):format(uci)) else local sv = session() if sv and sv.kind == "online" and not sv.over then send({ type = "move", id = sv.id, uci = uci, ply = #sv.ucis }) print(("[RoChessBot] ♟ Remote move: %s"):format(uci)) end end task.wait(0.5) claimAllTasks() botRunning = false end) end -- ── Auto Queue / Rematch loop ───────────────────────────────────────── local queueCooldown = false task.spawn(function() while true do task.wait(1.5) if cfg.enabled and cfg.autoQueue and not queueCooldown then local s = session() if not s or s.over then queueCooldown = true task.wait(2.5) claimAllTasks() print("[RoChessBot] ↺ Auto-queuing into 3+2 game...") queueGame() task.wait(5.0) queueCooldown = false end end end end) -- ── Main turn-polling loop ──────────────────────────────────────────── task.spawn(function() while true do task.wait(0.25) local ok, err = pcall(playBestMove) if not ok then warn("[RoChessBot] " .. tostring(err)) botRunning = false end end end) -- ── Startup Actions ─────────────────────────────────────────────────── task.spawn(function() task.wait(1.0) claimAllTasks() local s = session() if not s or s.over then print("[RoChessBot] 🚀 Initial startup: Auto-queuing 3+2 match...") queueGame() end end) -- ── WindUI Interface ────────────────────────────────────────────────── local Window = WindUI:CreateWindow({ Title = "RoChess Bot", Icon = "swords", Author = "AGY", Folder = "RoChessBot", Size = UDim2.fromOffset(460, 520), }) -- Default toggle key for the UI window (RightShift) Window:SetToggleKey(Enum.KeyCode.RightShift) -- ── Tab: Auto Play ── local TabMain = Window:Tab({ Title = "Auto Play", Icon = "swords" }) local autoPlayToggle = TabMain:Toggle({ Title = "Auto Best Move", Desc = "Automatically calculates and plays strongest move", Value = cfg.enabled, Callback = function(v) cfg.enabled = v botRunning = false saveConfig() print("[RoChessBot] Auto-play: " .. (v and "ON" or "OFF")) end, }) TabMain:Keybind({ Title = "Toggle Auto-Play Keybind", Desc = "Press this key anytime to toggle Auto Best Move", Value = cfg.keybind, Callback = function(key) if type(key) == "string" and #key > 0 then cfg.keybind = key saveConfig() end cfg.enabled = not cfg.enabled botRunning = false saveConfig() if autoPlayToggle and autoPlayToggle.Set then autoPlayToggle:Set(cfg.enabled) end WindUI:Notify({ Title = "Auto-Play " .. (cfg.enabled and "Enabled" or "Disabled"), Duration = 2, Icon = cfg.enabled and "check" or "x", }) end, }) TabMain:Toggle({ Title = "Auto Queue (3+2)", Desc = "Automatically queues 3+2 match on launch & after each game", Value = cfg.autoQueue, Callback = function(v) cfg.autoQueue = v saveConfig() print("[RoChessBot] Auto-queue 3+2: " .. (v and "ON" or "OFF")) end, }) TabMain:Toggle({ Title = "Auto Claim Daily Tasks", Desc = "Automatically claims task rewards on launch & after moves", Value = cfg.autoClaim, Callback = function(v) cfg.autoClaim = v saveConfig() print("[RoChessBot] Auto-claim: " .. (v and "ON" or "OFF")) end, }) TabMain:Toggle({ Title = "Anti-AFK", Desc = "Prevents idle disconnect (20 min Roblox AFK kick)", Value = cfg.antiAfk, Callback = function(v) cfg.antiAfk = v saveConfig() print("[RoChessBot] Anti-AFK: " .. (v and "ON" or "OFF")) end, }) TabMain:Slider({ Title = "Search Depth", Desc = "Engine depth (1–25, default: 20)", Value = { Min = 1, Max = 25, Default = cfg.depth }, Callback = function(v) cfg.depth = math.floor(v) saveConfig() end, }) TabMain:Slider({ Title = "Min Delay (s)", Desc = "Minimum seconds before making a move", Value = { Min = 0, Max = 3, Default = cfg.delayMin }, Callback = function(v) cfg.delayMin = v saveConfig() end, }) TabMain:Slider({ Title = "Max Delay (s)", Desc = "Maximum seconds before making a move", Value = { Min = 0, Max = 5, Default = cfg.delayMax }, Callback = function(v) cfg.delayMax = math.max(v, cfg.delayMin) saveConfig() end, }) TabMain:Button({ Title = "⚔ Queue 3+2 Match NOW", Desc = "Fires action remote to enter 3+2 matchmaking", Callback = function() queueGame() end, }) TabMain:Button({ Title = "▶ Play Best Move NOW", Desc = "Immediately plays best move for current turn", Callback = function() cfg.enabled = true botRunning = false playBestMove() end, }) TabMain:Button({ Title = "🎁 Claim All Tasks NOW", Desc = "Checks and claims all completed Daily Tasks", Callback = function() claimAllTasks() end, }) -- ── Tab: Info ── local TabInfo = Window:Tab({ Title = "Info", Icon = "info" }) TabInfo:Button({ Title = "Reset Config to Defaults", Desc = "Deletes saved settings and restores defaults", Callback = function() cfg = table.clone(defaultCfg) saveConfig() WindUI:Notify({ Title = "Config Reset", Content = "Defaults restored. Re-execute script to refresh UI.", Duration = 4, Icon = "rotate-ccw", }) end, }) TabInfo:Button({ Title = "Print Game State", Desc = "Logs FEN and turn state to developer console", Callback = function() local s = session() if not s then print("[RoChessBot] No active session"); return end print(("[RoChessBot] kind=%s over=%s myColor=%s ply=%d isMyTurn=%s"):format( tostring(s.kind), tostring(s.over), tostring(s.myColor), #s.ucis, tostring(isMyTurn()) )) print("[RoChessBot] FEN: " .. s.engine:getFen()) end, }) TabInfo:Button({ Title = "Calculate Best Move (no play)", Desc = "Calculates best move without playing it", Callback = function() local s = session() if not s or s.over then WindUI:Notify({ Title = "No active game", Duration = 2, Icon = "x" }) return end task.spawn(function() local uci, info = Bot.think(s.startFen, table.clone(s.ucis), { rating = 3000, depth = cfg.depth, noise = 0, blunder = 0 }) local score = info and tostring(info.score) or "?" print(("[RoChessBot] Best: %s (score: %s)"):format(tostring(uci), score)) WindUI:Notify({ Title = "Best Move: " .. tostring(uci), Content = "Score: " .. score, Duration = 4, Icon = "brain", }) end) end, }) TabMain:Select() WindUI:Notify({ Title = "RoChess Bot Ready!", Content = "Settings auto-saved to RoChess_Bot_Config.json.", Duration = 5, Icon = "check", }) print("[RoChessBot] ✅ Fully initialized with auto-save config!")