TechManDylan

CCRoulette2

Apr 30th, 2026
81
0
Never
9
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.60 KB | None | 0 0
  1. -- European Roulette Turtle Casino
  2. -- ComputerCraft / CC:Tweaked style program
  3. -- Designed for Advanced Monitor wall, 3 tall x 7 wide
  4. -- Uses a turtle as the diamond bank/payout machine
  5. -- Uses speaker if available
  6. --
  7. -- Features:
  8. -- Bet amount controls: +1 +5 +10 / -1 -5 -10 / RESET AMT
  9. -- Cash out all player credits
  10. -- Safe exit / safe cashout confirmation
  11. -- Larger bottom-positioned bet controls
  12. -- More visible zero slot color
  13. -- Persistent roulette board bets between rounds
  14. --
  15. -- Note:
  16. -- Board bets persist only while roulette.lua is running.
  17. -- They are cleared when exiting to menu or cashing out.
  18.  
  19. --------------------------------------------------
  20. -- CONFIG
  21. --------------------------------------------------
  22.  
  23. local DIAMOND_ID = "minecraft:diamond"
  24.  
  25. local RETURN_STAKE_ON_WIN = true
  26. -- true = a 1 diamond straight win pays 36 diamonds total
  27. -- false = a 1 diamond straight win pays 35 diamonds profit only
  28.  
  29. local TEXT_SCALE = 0.5
  30.  
  31. local MIN_BET = 1
  32. local MAX_BET_PER_SPACE = 999
  33. local MAX_BET_AMOUNT = 999
  34.  
  35. local SPIN_STEPS = 44
  36. local SPIN_DELAY_START = 0.035
  37. local SPIN_DELAY_END = 0.16
  38.  
  39. local CASINO_MENU_PROGRAM = "casino"
  40. local CASINO_BANK_FILE = "casino_bank_base.txt"
  41.  
  42. local TABLE_Y = 20
  43. local BOTTOM_CONTROLS_RESERVED = 12
  44.  
  45. --------------------------------------------------
  46. -- PERIPHERALS
  47. --------------------------------------------------
  48.  
  49. local mon = peripheral.find("monitor")
  50.  
  51. if not mon then
  52. error("No monitor found. Attach/wrap an advanced monitor wall.")
  53. end
  54.  
  55. local speaker = nil
  56.  
  57. for _, name in ipairs(peripheral.getNames()) do
  58. local p = peripheral.wrap(name)
  59. if p then
  60. if type(p.playNote) == "function" or type(p.playSound) == "function" then
  61. speaker = p
  62. break
  63. end
  64. end
  65. end
  66.  
  67. mon.setTextScale(TEXT_SCALE)
  68. mon.setBackgroundColor(colors.green)
  69. mon.setTextColor(colors.white)
  70. mon.clear()
  71.  
  72. local W, H = mon.getSize()
  73.  
  74. --------------------------------------------------
  75. -- UTILS
  76. --------------------------------------------------
  77.  
  78. local function clamp(v, a, b)
  79. if v < a then return a end
  80. if v > b then return b end
  81. return v
  82. end
  83.  
  84. local function writeAt(x, y, text, fg, bg)
  85. if bg then mon.setBackgroundColor(bg) end
  86. if fg then mon.setTextColor(fg) end
  87. mon.setCursorPos(x, y)
  88. mon.write(text)
  89. end
  90.  
  91. local function fillBox(x, y, w, h, bg)
  92. if w <= 0 or h <= 0 then return end
  93.  
  94. mon.setBackgroundColor(bg)
  95.  
  96. for yy = y, y + h - 1 do
  97. if yy >= 1 and yy <= H then
  98. mon.setCursorPos(x, yy)
  99. mon.write(string.rep(" ", math.max(0, math.min(w, W - x + 1))))
  100. end
  101. end
  102. end
  103.  
  104. local function centerText(x, y, w, text, fg, bg)
  105. text = tostring(text)
  106.  
  107. if #text > w then
  108. text = string.sub(text, 1, w)
  109. end
  110.  
  111. local pad = math.floor((w - #text) / 2)
  112. writeAt(x + pad, y, text, fg, bg)
  113. end
  114.  
  115. local function drawButton(x, y, w, h, label, bg, fg)
  116. fillBox(x, y, w, h, bg)
  117. local cy = y + math.floor(h / 2)
  118. centerText(x, cy, w, label, fg or colors.white, bg)
  119. end
  120.  
  121. local function inBox(px, py, box)
  122. return px >= box.x and px < box.x + box.w and py >= box.y and py < box.y + box.h
  123. end
  124.  
  125. --------------------------------------------------
  126. -- DIAMOND BANKING
  127. --------------------------------------------------
  128.  
  129. local function countDiamonds()
  130. local total = 0
  131.  
  132. for slot = 1, 16 do
  133. local d = turtle.getItemDetail(slot)
  134. if d and d.name == DIAMOND_ID then
  135. total = total + d.count
  136. end
  137. end
  138.  
  139. return total
  140. end
  141.  
  142. local function selectDiamondSlot()
  143. for slot = 1, 16 do
  144. local d = turtle.getItemDetail(slot)
  145.  
  146. if d and d.name == DIAMOND_ID and d.count > 0 then
  147. turtle.select(slot)
  148. return true
  149. end
  150. end
  151.  
  152. return false
  153. end
  154.  
  155. local function pullDiamondsFromAboveUntil(amountNeeded)
  156. local tries = 0
  157.  
  158. while countDiamonds() < amountNeeded and tries < 64 do
  159. tries = tries + 1
  160.  
  161. local pulled = turtle.suckUp(64)
  162.  
  163. if not pulled then
  164. break
  165. end
  166.  
  167. sleep(0.05)
  168. end
  169.  
  170. return countDiamonds() >= amountNeeded
  171. end
  172.  
  173. local function dropDiamondsDown(amount)
  174. local remaining = amount
  175.  
  176. while remaining > 0 do
  177. if not selectDiamondSlot() then
  178. return false, amount - remaining
  179. end
  180.  
  181. local d = turtle.getItemDetail()
  182.  
  183. if not d or d.name ~= DIAMOND_ID then
  184. return false, amount - remaining
  185. end
  186.  
  187. local toDrop = math.min(remaining, d.count)
  188. local ok = turtle.dropDown(toDrop)
  189.  
  190. if not ok then
  191. return false, amount - remaining
  192. end
  193.  
  194. remaining = remaining - toDrop
  195. sleep(0.03)
  196. end
  197.  
  198. return true, amount
  199. end
  200.  
  201. --------------------------------------------------
  202. -- SOUND
  203. --------------------------------------------------
  204.  
  205. local function playNoteSafe(instrument, volume, pitch)
  206. if not speaker then return end
  207.  
  208. instrument = instrument or "harp"
  209. volume = volume or 1
  210. pitch = pitch or 12
  211.  
  212. if type(speaker.playNote) == "function" then
  213. local ok = pcall(function()
  214. speaker.playNote(instrument, volume, pitch)
  215. end)
  216.  
  217. if ok then
  218. return
  219. end
  220. end
  221.  
  222. if type(speaker.playSound) == "function" then
  223. pcall(function()
  224. speaker.playSound("note.harp", volume, 1)
  225. end)
  226. end
  227. end
  228.  
  229. local function soundClick()
  230. playNoteSafe("hat", 0.8, 12)
  231. end
  232.  
  233. local function soundSpin()
  234. playNoteSafe("hat", 0.6, math.random(8, 18))
  235. end
  236.  
  237. local function soundWin()
  238. playNoteSafe("bell", 1, 16)
  239. sleep(0.08)
  240. playNoteSafe("bell", 1, 20)
  241. sleep(0.08)
  242. playNoteSafe("bell", 1, 24)
  243. end
  244.  
  245. local function soundLoss()
  246. playNoteSafe("bass", 1, 6)
  247. sleep(0.12)
  248. playNoteSafe("bass", 1, 4)
  249. end
  250.  
  251. --------------------------------------------------
  252. -- ROULETTE DATA
  253. --------------------------------------------------
  254.  
  255. local wheelOrder = {
  256. 0, 32, 15, 19, 4, 21, 2, 25, 17, 34,
  257. 6, 27, 13, 36, 11, 30, 8, 23, 10, 5,
  258. 24, 16, 33, 1, 20, 14, 31, 9, 22, 18,
  259. 29, 7, 28, 12, 35, 3, 26
  260. }
  261.  
  262. local redNums = {
  263. [1]=true,[3]=true,[5]=true,[7]=true,[9]=true,
  264. [12]=true,[14]=true,[16]=true,[18]=true,
  265. [19]=true,[21]=true,[23]=true,[25]=true,[27]=true,
  266. [30]=true,[32]=true,[34]=true,[36]=true
  267. }
  268.  
  269. local blackNums = {}
  270.  
  271. for n = 1, 36 do
  272. if not redNums[n] then
  273. blackNums[n] = true
  274. end
  275. end
  276.  
  277. local function numColor(n)
  278. if n == 0 then return colors.lime end
  279. if redNums[n] then return colors.red end
  280. return colors.black
  281. end
  282.  
  283. local function numTextColor(n)
  284. if n == 0 then
  285. return colors.black
  286. end
  287. return colors.white
  288. end
  289.  
  290. --------------------------------------------------
  291. -- GAME STATE
  292. --------------------------------------------------
  293.  
  294. math.randomseed(os.epoch and os.epoch("utc") or os.clock() * 100000)
  295.  
  296. local bets = {}
  297. local hitBoxes = {}
  298.  
  299. local message = "Deposit diamonds, set bet amount, tap spaces, then START SPIN."
  300. local lastResult = nil
  301. local spinning = false
  302. local wheelHighlightIndex = 1
  303.  
  304. local betAmount = 1
  305.  
  306. -- confirmMode:
  307. -- nil = normal
  308. -- "exit" = confirm exit to menu
  309. -- "cashout" = confirm clearing active bets and cashing out
  310. local confirmMode = nil
  311.  
  312. local function loadBankBase()
  313. if fs.exists(CASINO_BANK_FILE) then
  314. local f = fs.open(CASINO_BANK_FILE, "r")
  315. if f then
  316. local raw = f.readAll()
  317. f.close()
  318.  
  319. local n = tonumber(raw)
  320. if n and n >= 0 then
  321. return n
  322. end
  323. end
  324. end
  325.  
  326. return countDiamonds()
  327. end
  328.  
  329. local bankBase = loadBankBase()
  330.  
  331. local function saveBankBase()
  332. local f = fs.open(CASINO_BANK_FILE, "w")
  333. if f then
  334. f.write(tostring(math.floor(bankBase)))
  335. f.close()
  336. end
  337. end
  338.  
  339. saveBankBase()
  340.  
  341. local function totalBets()
  342. local t = 0
  343.  
  344. for _, amt in pairs(bets) do
  345. t = t + amt
  346. end
  347.  
  348. return t
  349. end
  350.  
  351. local function activeBetsShortfall()
  352. local shortfall = bankBase + totalBets() - countDiamonds()
  353.  
  354. if shortfall < 0 then
  355. shortfall = 0
  356. end
  357.  
  358. return shortfall
  359. end
  360.  
  361. local function availableCredits()
  362. local current = countDiamonds()
  363. local credits = current - bankBase - totalBets()
  364.  
  365. if credits < 0 then
  366. credits = 0
  367. end
  368.  
  369. return credits
  370. end
  371.  
  372. --------------------------------------------------
  373. -- BET AMOUNT CONTROLS
  374. --------------------------------------------------
  375.  
  376. local function changeBetAmount(delta)
  377. if spinning or confirmMode then return end
  378.  
  379. betAmount = betAmount + delta
  380. betAmount = clamp(betAmount, MIN_BET, MAX_BET_AMOUNT)
  381.  
  382. message = "Bet amount set to " .. betAmount .. " diamond(s)."
  383. soundClick()
  384. end
  385.  
  386. local function resetBetAmount()
  387. if spinning or confirmMode then return end
  388.  
  389. betAmount = 1
  390. message = "Bet amount reset to 1 diamond."
  391. soundClick()
  392. end
  393.  
  394. local function addBet(id)
  395. if spinning or confirmMode then return end
  396.  
  397. local amount = betAmount
  398.  
  399. if activeBetsShortfall() > 0 then
  400. message = "Deposit " .. activeBetsShortfall() .. " diamond(s) to cover current board first."
  401. soundLoss()
  402. return
  403. end
  404.  
  405. if availableCredits() < amount then
  406. message = "Need " .. amount .. " unbet diamond(s) to place that bet."
  407. soundLoss()
  408. return
  409. end
  410.  
  411. bets[id] = bets[id] or 0
  412.  
  413. if bets[id] + amount > MAX_BET_PER_SPACE then
  414. message = "Max bet reached on this space."
  415. soundLoss()
  416. return
  417. end
  418.  
  419. bets[id] = bets[id] + amount
  420. message = "Bet +" .. amount .. " on " .. id
  421. soundClick()
  422. end
  423.  
  424. local function clearBets()
  425. if spinning then return end
  426.  
  427. bets = {}
  428. message = "Board cleared. Set new bets or cash out."
  429. soundClick()
  430. end
  431.  
  432. --------------------------------------------------
  433. -- CASH OUT / EXIT LOGIC
  434. --------------------------------------------------
  435.  
  436. local function cashOutCredits()
  437. if spinning then
  438. message = "Cannot cash out while wheel is spinning."
  439. soundLoss()
  440. return
  441. end
  442.  
  443. local amount = availableCredits()
  444.  
  445. if amount <= 0 then
  446. message = "No unbet credits to cash out."
  447. soundLoss()
  448. return
  449. end
  450.  
  451. local ok, dropped = dropDiamondsDown(amount)
  452.  
  453. if ok then
  454. message = "Cashed out " .. dropped .. " diamond(s) below."
  455. soundWin()
  456. else
  457. message = "Cash out blocked! Dropped " .. dropped .. "/" .. amount .. "."
  458. soundLoss()
  459. end
  460.  
  461. saveBankBase()
  462. end
  463.  
  464. local function requestCashOut()
  465. if spinning then
  466. message = "Cannot cash out while wheel is spinning."
  467. soundLoss()
  468. return
  469. end
  470.  
  471. if totalBets() > 0 then
  472. confirmMode = "cashout"
  473. message = "Confirm cash out. Board bets will be cleared first."
  474. soundLoss()
  475. return
  476. end
  477.  
  478. cashOutCredits()
  479. end
  480.  
  481. local function exitToMenuNow()
  482. bets = {}
  483. confirmMode = nil
  484. saveBankBase()
  485.  
  486. mon.setBackgroundColor(colors.black)
  487. mon.setTextColor(colors.white)
  488. mon.clear()
  489.  
  490. if shell then
  491. if fs.exists(CASINO_MENU_PROGRAM) then
  492. shell.run(CASINO_MENU_PROGRAM)
  493. elseif fs.exists(CASINO_MENU_PROGRAM .. ".lua") then
  494. shell.run(CASINO_MENU_PROGRAM .. ".lua")
  495. else
  496. print("Casino menu not found.")
  497. print("Expected: " .. CASINO_MENU_PROGRAM)
  498. end
  499. end
  500.  
  501. error("Exited to casino menu", 0)
  502. end
  503.  
  504. local function requestExit()
  505. if spinning then
  506. message = "Cannot exit while wheel is spinning."
  507. soundLoss()
  508. return
  509. end
  510.  
  511. if totalBets() > 0 then
  512. confirmMode = "exit"
  513. message = "Confirm exit. Board bets will be cleared back to credits."
  514. soundLoss()
  515. else
  516. exitToMenuNow()
  517. end
  518. end
  519.  
  520. --------------------------------------------------
  521. -- BET RESOLUTION
  522. --------------------------------------------------
  523.  
  524. local function betWins(id, result)
  525. if string.sub(id, 1, 2) == "N:" then
  526. local n = tonumber(string.sub(id, 3))
  527.  
  528. if n == result then
  529. return true, 35
  530. end
  531.  
  532. return false, 0
  533. end
  534.  
  535. if id == "RED" then
  536. return redNums[result] == true, 1
  537. end
  538.  
  539. if id == "BLACK" then
  540. return blackNums[result] == true, 1
  541. end
  542.  
  543. if id == "ODD" then
  544. return result >= 1 and result <= 36 and result % 2 == 1, 1
  545. end
  546.  
  547. if id == "EVEN" then
  548. return result >= 1 and result <= 36 and result % 2 == 0, 1
  549. end
  550.  
  551. if id == "LOW" then
  552. return result >= 1 and result <= 18, 1
  553. end
  554.  
  555. if id == "HIGH" then
  556. return result >= 19 and result <= 36, 1
  557. end
  558.  
  559. if id == "D1" then
  560. return result >= 1 and result <= 12, 2
  561. end
  562.  
  563. if id == "D2" then
  564. return result >= 13 and result <= 24, 2
  565. end
  566.  
  567. if id == "D3" then
  568. return result >= 25 and result <= 36, 2
  569. end
  570.  
  571. if id == "C1" then
  572. return result >= 1 and result <= 36 and result % 3 == 1, 2
  573. end
  574.  
  575. if id == "C2" then
  576. return result >= 1 and result <= 36 and result % 3 == 2, 2
  577. end
  578.  
  579. if id == "C3" then
  580. return result >= 1 and result <= 36 and result % 3 == 0, 2
  581. end
  582.  
  583. return false, 0
  584. end
  585.  
  586. local function resolvePayout(result)
  587. local payout = 0
  588. local winningBets = 0
  589.  
  590. for id, amt in pairs(bets) do
  591. local won, odds = betWins(id, result)
  592.  
  593. if won then
  594. winningBets = winningBets + amt
  595.  
  596. if RETURN_STAKE_ON_WIN then
  597. payout = payout + (amt * (odds + 1))
  598. else
  599. payout = payout + (amt * odds)
  600. end
  601. end
  602. end
  603.  
  604. return payout, winningBets
  605. end
  606.  
  607. --------------------------------------------------
  608. -- DRAWING
  609. --------------------------------------------------
  610.  
  611. local function resetHitBoxes()
  612. hitBoxes = {}
  613. end
  614.  
  615. local function addHit(id, x, y, w, h)
  616. table.insert(hitBoxes, {
  617. id = id,
  618. x = x,
  619. y = y,
  620. w = w,
  621. h = h
  622. })
  623. end
  624.  
  625. local function drawFrame()
  626. fillBox(1, 1, W, H, colors.green)
  627.  
  628. fillBox(1, 1, W, 1, colors.black)
  629. centerText(1, 1, W, "EUROPEAN ROULETTE | DIAMOND CASINO", colors.lime, colors.black)
  630. end
  631.  
  632. local function drawWheel()
  633. local x = 2
  634. local y = 3
  635. local w = math.min(44, W - 4)
  636. local h = 12
  637.  
  638. fillBox(x, y, w, h, colors.gray)
  639. centerText(x, y, w, "ROULETTE WHEEL", colors.yellow, colors.gray)
  640.  
  641. local displaySlots = 12
  642. local start = wheelHighlightIndex
  643.  
  644. for i = 1, displaySlots do
  645. local idx = ((start + i - 2) % #wheelOrder) + 1
  646. local n = wheelOrder[idx]
  647.  
  648. local cellW = math.floor(w / displaySlots)
  649. local cx = x + (i - 1) * cellW
  650. local bg = numColor(n)
  651. local fg = numTextColor(n)
  652.  
  653. if i == math.ceil(displaySlots / 2) then
  654. bg = colors.yellow
  655. fg = colors.black
  656. end
  657.  
  658. fillBox(cx, y + 3, cellW - 1, 3, bg)
  659. centerText(cx, y + 4, cellW - 1, tostring(n), fg, bg)
  660. end
  661.  
  662. centerText(x, y + 8, w, "^^^^ BALL ^^^^", colors.white, colors.gray)
  663.  
  664. if lastResult ~= nil then
  665. local bg = numColor(lastResult)
  666. fillBox(x + math.floor(w / 2) - 6, y + 10, 12, 1, bg)
  667. centerText(x + math.floor(w / 2) - 6, y + 10, 12, "LAST: " .. tostring(lastResult), numTextColor(lastResult), bg)
  668. else
  669. centerText(x, y + 10, w, "LAST: --", colors.white, colors.gray)
  670. end
  671. end
  672.  
  673. local function drawInfoPanel()
  674. local x = 48
  675. local y = 3
  676. local w = W - x - 1
  677. local h = 16
  678.  
  679. if w < 34 then
  680. return
  681. end
  682.  
  683. fillBox(x, y, w, h, colors.black)
  684.  
  685. local shortfall = activeBetsShortfall()
  686.  
  687. writeAt(x + 2, y + 1, "Credits: " .. availableCredits(), colors.lime, colors.black)
  688. writeAt(x + 2, y + 2, "Board Bets: " .. totalBets(), colors.yellow, colors.black)
  689. writeAt(x + 2, y + 3, "Bet Amount: " .. betAmount, colors.orange, colors.black)
  690. writeAt(x + 2, y + 4, "Diamonds In Turtle: " .. countDiamonds(), colors.white, colors.black)
  691. writeAt(x + 2, y + 5, "House Bank Base: " .. bankBase, colors.lightGray, colors.black)
  692.  
  693. if shortfall > 0 then
  694. writeAt(x + 2, y + 6, "Need To Repeat: " .. shortfall, colors.red, colors.black)
  695. else
  696. writeAt(x + 2, y + 6, "Board Ready: YES", colors.lime, colors.black)
  697. end
  698.  
  699. fillBox(x + 1, y + 8, w - 2, 2, colors.gray)
  700. writeAt(x + 2, y + 8, string.sub(message, 1, w - 4), colors.white, colors.gray)
  701.  
  702. local thirdW = math.floor((w - 5) / 3)
  703.  
  704. drawButton(x + 1, y + 12, thirdW, 3, "START", colors.lime, colors.black)
  705. addHit("ACTION:START", x + 1, y + 12, thirdW, 3)
  706.  
  707. drawButton(x + 2 + thirdW, y + 12, thirdW, 3, "CLEAR", colors.red, colors.white)
  708. addHit("ACTION:CLEAR", x + 2 + thirdW, y + 12, thirdW, 3)
  709.  
  710. drawButton(x + 3 + thirdW * 2, y + 12, thirdW, 3, "MENU", colors.gray, colors.white)
  711. addHit("ACTION:EXIT", x + 3 + thirdW * 2, y + 12, thirdW, 3)
  712. end
  713.  
  714. local function drawBottomBetControls()
  715. local panelW = math.min(W - 6, 124)
  716. local x = math.floor((W - panelW) / 2)
  717. local y = H - 11
  718. local panelH = 10
  719.  
  720. fillBox(x, y, panelW, panelH, colors.black)
  721.  
  722. centerText(x, y, panelW, "BET CONTROLS | CURRENT BET AMOUNT: " .. betAmount, colors.yellow, colors.black)
  723.  
  724. local gap = 1
  725. local smallW = math.floor((panelW - 4 - gap * 2) / 3)
  726.  
  727. drawButton(x + 1, y + 1, smallW, 3, "+1", colors.lime, colors.black)
  728. addHit("BETAMT:+1", x + 1, y + 1, smallW, 3)
  729.  
  730. drawButton(x + 1 + smallW + gap, y + 1, smallW, 3, "+5", colors.lime, colors.black)
  731. addHit("BETAMT:+5", x + 1 + smallW + gap, y + 1, smallW, 3)
  732.  
  733. drawButton(x + 1 + (smallW + gap) * 2, y + 1, smallW, 3, "+10", colors.lime, colors.black)
  734. addHit("BETAMT:+10", x + 1 + (smallW + gap) * 2, y + 1, smallW, 3)
  735.  
  736. drawButton(x + 1, y + 4, smallW, 3, "-1", colors.orange, colors.black)
  737. addHit("BETAMT:-1", x + 1, y + 4, smallW, 3)
  738.  
  739. drawButton(x + 1 + smallW + gap, y + 4, smallW, 3, "-5", colors.orange, colors.black)
  740. addHit("BETAMT:-5", x + 1 + smallW + gap, y + 4, smallW, 3)
  741.  
  742. drawButton(x + 1 + (smallW + gap) * 2, y + 4, smallW, 3, "-10", colors.orange, colors.black)
  743. addHit("BETAMT:-10", x + 1 + (smallW + gap) * 2, y + 4, smallW, 3)
  744.  
  745. local halfW = math.floor((panelW - 3) / 2)
  746.  
  747. drawButton(x + 1, y + 7, halfW, 3, "RESET AMT", colors.gray, colors.white)
  748. addHit("BETAMT:RESET", x + 1, y + 7, halfW, 3)
  749.  
  750. drawButton(x + 2 + halfW, y + 7, halfW, 3, "CASH OUT", colors.yellow, colors.black)
  751. addHit("ACTION:CASHOUT", x + 2 + halfW, y + 7, halfW, 3)
  752. end
  753.  
  754. local function drawBetAmount(id, x, y, w, bg)
  755. local amt = bets[id] or 0
  756.  
  757. if amt > 0 then
  758. local s = "x" .. tostring(amt)
  759. writeAt(x + w - #s, y, s, colors.yellow, bg)
  760. end
  761. end
  762.  
  763. local function drawNumberCell(n, x, y, w, h)
  764. local bg = numColor(n)
  765. local fg = numTextColor(n)
  766.  
  767. drawButton(x, y, w, h, tostring(n), bg, fg)
  768. addHit("N:" .. tostring(n), x, y, w, h)
  769. drawBetAmount("N:" .. tostring(n), x, y + h - 1, w, bg)
  770. end
  771.  
  772. local function drawTable()
  773. local tableY = TABLE_Y
  774. local startX = 2
  775.  
  776. local cellW = math.max(4, math.floor((W - 14) / 14))
  777. cellW = clamp(cellW, 4, 8)
  778.  
  779. local cellH = 3
  780.  
  781. local zeroW = cellW
  782. local numX = startX + zeroW + 1
  783.  
  784. fillBox(1, tableY - 1, W, H - tableY - BOTTOM_CONTROLS_RESERVED, colors.green)
  785. centerText(1, tableY - 1, W, "BETS PERSIST AFTER SPIN | PRESS CLEAR TO CHANGE BOARD", colors.black, colors.green)
  786.  
  787. local zeroBg = numColor(0)
  788. local zeroFg = numTextColor(0)
  789.  
  790. drawButton(startX, tableY, zeroW, cellH * 3, "0", zeroBg, zeroFg)
  791. addHit("N:0", startX, tableY, zeroW, cellH * 3)
  792. drawBetAmount("N:0", startX, tableY + cellH * 3 - 1, zeroW, zeroBg)
  793.  
  794. for col = 1, 12 do
  795. local nums = {
  796. col * 3,
  797. col * 3 - 1,
  798. col * 3 - 2
  799. }
  800.  
  801. for row = 1, 3 do
  802. local n = nums[row]
  803. local x = numX + (col - 1) * cellW
  804. local y = tableY + (row - 1) * cellH
  805.  
  806. drawNumberCell(n, x, y, cellW - 1, cellH)
  807. end
  808. end
  809.  
  810. local colBetX = numX + 12 * cellW
  811.  
  812. drawButton(colBetX, tableY, cellW, cellH, "2:1", colors.gray, colors.white)
  813. addHit("C3", colBetX, tableY, cellW, cellH)
  814. drawBetAmount("C3", colBetX, tableY + cellH - 1, cellW, colors.gray)
  815.  
  816. drawButton(colBetX, tableY + cellH, cellW, cellH, "2:1", colors.gray, colors.white)
  817. addHit("C2", colBetX, tableY + cellH, cellW, cellH)
  818. drawBetAmount("C2", colBetX, tableY + cellH * 2 - 1, cellW, colors.gray)
  819.  
  820. drawButton(colBetX, tableY + cellH * 2, cellW, cellH, "2:1", colors.gray, colors.white)
  821. addHit("C1", colBetX, tableY + cellH * 2, cellW, cellH)
  822. drawBetAmount("C1", colBetX, tableY + cellH * 3 - 1, cellW, colors.gray)
  823.  
  824. local dozenY = tableY + cellH * 3 + 1
  825. local dozenW = cellW * 4 - 1
  826.  
  827. drawButton(numX, dozenY, dozenW, 2, "1st 12", colors.gray, colors.white)
  828. addHit("D1", numX, dozenY, dozenW, 2)
  829. drawBetAmount("D1", numX, dozenY + 1, dozenW, colors.gray)
  830.  
  831. drawButton(numX + cellW * 4, dozenY, dozenW, 2, "2nd 12", colors.gray, colors.white)
  832. addHit("D2", numX + cellW * 4, dozenY, dozenW, 2)
  833. drawBetAmount("D2", numX + cellW * 4, dozenY + 1, dozenW, colors.gray)
  834.  
  835. drawButton(numX + cellW * 8, dozenY, dozenW, 2, "3rd 12", colors.gray, colors.white)
  836. addHit("D3", numX + cellW * 8, dozenY, dozenW, 2)
  837. drawBetAmount("D3", numX + cellW * 8, dozenY + 1, dozenW, colors.gray)
  838.  
  839. local outsideY = dozenY + 3
  840.  
  841. local outsideLabels = {
  842. {"LOW", "1-18", colors.gray, colors.white},
  843. {"EVEN", "EVEN", colors.gray, colors.white},
  844. {"RED", "RED", colors.red, colors.white},
  845. {"BLACK", "BLACK", colors.black, colors.white},
  846. {"ODD", "ODD", colors.gray, colors.white},
  847. {"HIGH", "19-36", colors.gray, colors.white}
  848. }
  849.  
  850. local outsideW = math.floor((cellW * 12 - 1) / 6)
  851.  
  852. for i, b in ipairs(outsideLabels) do
  853. local id, label, bg, fg = b[1], b[2], b[3], b[4]
  854. local x = numX + (i - 1) * outsideW
  855.  
  856. drawButton(x, outsideY, outsideW - 1, 3, label, bg, fg)
  857. addHit(id, x, outsideY, outsideW - 1, 3)
  858. drawBetAmount(id, x, outsideY + 2, outsideW - 1, bg)
  859. end
  860. end
  861.  
  862. local function drawConfirmScreen()
  863. resetHitBoxes()
  864.  
  865. fillBox(1, 1, W, H, colors.black)
  866.  
  867. if confirmMode == "exit" then
  868. centerText(1, 3, W, "CONFIRM EXIT TO GAME MENU", colors.yellow, colors.black)
  869. centerText(1, 6, W, "You have " .. totalBets() .. " diamond(s) on the roulette board.", colors.white, colors.black)
  870. centerText(1, 8, W, "Leaving will clear the board state before returning to menu.", colors.lightGray, colors.black)
  871. centerText(1, 10, W, "This prevents the next player from inheriting your bets.", colors.lightGray, colors.black)
  872. elseif confirmMode == "cashout" then
  873. centerText(1, 3, W, "CONFIRM CASH OUT", colors.yellow, colors.black)
  874. centerText(1, 6, W, "You have " .. totalBets() .. " diamond(s) on the roulette board.", colors.white, colors.black)
  875. centerText(1, 8, W, "Cash out will clear the board back into credits first.", colors.lightGray, colors.black)
  876. centerText(1, 10, W, "Then all player credits will drop below the turtle.", colors.lightGray, colors.black)
  877. end
  878.  
  879. local btnW = 32
  880. local btnH = 5
  881. local gap = 6
  882. local totalW = btnW * 2 + gap
  883. local startX = math.floor((W - totalW) / 2)
  884. local y = 14
  885.  
  886. drawButton(startX, y, btnW, btnH, "CANCEL", colors.lime, colors.black)
  887. addHit("CONFIRM_CANCEL", startX, y, btnW, btnH)
  888.  
  889. if confirmMode == "exit" then
  890. drawButton(startX + btnW + gap, y, btnW, btnH, "EXIT - CLEAR BOARD", colors.red, colors.white)
  891. addHit("CONFIRM_YES", startX + btnW + gap, y, btnW, btnH)
  892. elseif confirmMode == "cashout" then
  893. drawButton(startX + btnW + gap, y, btnW, btnH, "CASH OUT ALL", colors.yellow, colors.black)
  894. addHit("CONFIRM_YES", startX + btnW + gap, y, btnW, btnH)
  895. end
  896. end
  897.  
  898. local function drawAll()
  899. if confirmMode then
  900. drawConfirmScreen()
  901. return
  902. end
  903.  
  904. resetHitBoxes()
  905. drawFrame()
  906. drawWheel()
  907. drawInfoPanel()
  908. drawTable()
  909. drawBottomBetControls()
  910. end
  911.  
  912. --------------------------------------------------
  913. -- SPIN LOGIC
  914. --------------------------------------------------
  915.  
  916. local function pickResult()
  917. return wheelOrder[math.random(1, #wheelOrder)]
  918. end
  919.  
  920. local function findWheelIndex(num)
  921. for i, n in ipairs(wheelOrder) do
  922. if n == num then
  923. return i
  924. end
  925. end
  926.  
  927. return 1
  928. end
  929.  
  930. local function spinRoulette()
  931. if spinning then return end
  932.  
  933. if totalBets() <= 0 then
  934. message = "Place at least 1 diamond bet first."
  935. soundLoss()
  936. drawAll()
  937. return
  938. end
  939.  
  940. local shortfall = activeBetsShortfall()
  941. if shortfall > 0 then
  942. message = "Deposit " .. shortfall .. " diamond(s) to repeat selected board."
  943. soundLoss()
  944. drawAll()
  945. return
  946. end
  947.  
  948. local boardBetTotal = totalBets()
  949. local unbetCreditsBeforeSpin = availableCredits()
  950.  
  951. spinning = true
  952. message = "Spinning..."
  953. drawAll()
  954.  
  955. local result = pickResult()
  956. local targetIndex = findWheelIndex(result)
  957.  
  958. for step = 1, SPIN_STEPS do
  959. wheelHighlightIndex = ((wheelHighlightIndex) % #wheelOrder) + 1
  960.  
  961. soundSpin()
  962. drawAll()
  963.  
  964. local t = step / SPIN_STEPS
  965. local delay = SPIN_DELAY_START + (SPIN_DELAY_END - SPIN_DELAY_START) * t * t
  966.  
  967. sleep(delay)
  968. end
  969.  
  970. wheelHighlightIndex = targetIndex
  971. lastResult = result
  972.  
  973. local payout, winningBets = resolvePayout(result)
  974.  
  975. if payout > 0 then
  976. message = "Result " .. result .. "! WIN pays " .. payout .. " diamonds."
  977.  
  978. drawAll()
  979. soundWin()
  980.  
  981. local enough = pullDiamondsFromAboveUntil(payout)
  982.  
  983. if enough then
  984. local ok, dropped = dropDiamondsDown(payout)
  985.  
  986. if ok then
  987. message = "Paid " .. dropped .. ". Board bets stayed selected."
  988. else
  989. message = "Payout blocked! Dropped " .. dropped .. "/" .. payout
  990. end
  991. else
  992. local available = countDiamonds()
  993. local ok, dropped = dropDiamondsDown(available)
  994.  
  995. message = "HOUSE EMPTY! Paid only " .. dropped .. "/" .. payout .. " diamonds."
  996. end
  997.  
  998. local after = countDiamonds()
  999.  
  1000. bankBase = after - unbetCreditsBeforeSpin
  1001.  
  1002. if bankBase < 0 then
  1003. bankBase = 0
  1004. end
  1005. else
  1006. bankBase = bankBase + boardBetTotal
  1007. message = "Result " .. result .. ". No winning bets. Board stayed selected."
  1008. soundLoss()
  1009. end
  1010.  
  1011. saveBankBase()
  1012.  
  1013. local repeatShortfall = activeBetsShortfall()
  1014. if repeatShortfall > 0 then
  1015. message = message .. " Deposit " .. repeatShortfall .. " to spin same board again."
  1016. else
  1017. message = message .. " Press START to spin same board again."
  1018. end
  1019.  
  1020. spinning = false
  1021. drawAll()
  1022. end
  1023.  
  1024. --------------------------------------------------
  1025. -- INPUT
  1026. --------------------------------------------------
  1027.  
  1028. local function handleConfirmTouch(x, y)
  1029. for _, box in ipairs(hitBoxes) do
  1030. if inBox(x, y, box) then
  1031. if box.id == "CONFIRM_CANCEL" then
  1032. confirmMode = nil
  1033. message = "Action cancelled."
  1034. soundClick()
  1035. drawAll()
  1036. return true
  1037. elseif box.id == "CONFIRM_YES" then
  1038. if confirmMode == "exit" then
  1039. bets = {}
  1040. confirmMode = nil
  1041. saveBankBase()
  1042. exitToMenuNow()
  1043. return true
  1044. elseif confirmMode == "cashout" then
  1045. bets = {}
  1046. confirmMode = nil
  1047. saveBankBase()
  1048. cashOutCredits()
  1049. drawAll()
  1050. return true
  1051. end
  1052. end
  1053. end
  1054. end
  1055.  
  1056. return false
  1057. end
  1058.  
  1059. local function handleTouch(x, y)
  1060. if confirmMode then
  1061. handleConfirmTouch(x, y)
  1062. return
  1063. end
  1064.  
  1065. if spinning then
  1066. return
  1067. end
  1068.  
  1069. for _, box in ipairs(hitBoxes) do
  1070. if inBox(x, y, box) then
  1071. if box.id == "ACTION:START" then
  1072. spinRoulette()
  1073. return
  1074. elseif box.id == "ACTION:CLEAR" then
  1075. clearBets()
  1076. drawAll()
  1077. return
  1078. elseif box.id == "ACTION:EXIT" then
  1079. requestExit()
  1080. drawAll()
  1081. return
  1082. elseif box.id == "ACTION:CASHOUT" then
  1083. requestCashOut()
  1084. drawAll()
  1085. return
  1086. elseif box.id == "BETAMT:+1" then
  1087. changeBetAmount(1)
  1088. drawAll()
  1089. return
  1090. elseif box.id == "BETAMT:+5" then
  1091. changeBetAmount(5)
  1092. drawAll()
  1093. return
  1094. elseif box.id == "BETAMT:+10" then
  1095. changeBetAmount(10)
  1096. drawAll()
  1097. return
  1098. elseif box.id == "BETAMT:-1" then
  1099. changeBetAmount(-1)
  1100. drawAll()
  1101. return
  1102. elseif box.id == "BETAMT:-5" then
  1103. changeBetAmount(-5)
  1104. drawAll()
  1105. return
  1106. elseif box.id == "BETAMT:-10" then
  1107. changeBetAmount(-10)
  1108. drawAll()
  1109. return
  1110. elseif box.id == "BETAMT:RESET" then
  1111. resetBetAmount()
  1112. drawAll()
  1113. return
  1114. else
  1115. addBet(box.id)
  1116. drawAll()
  1117. return
  1118. end
  1119. end
  1120. end
  1121. end
  1122.  
  1123. --------------------------------------------------
  1124. -- MAIN
  1125. --------------------------------------------------
  1126.  
  1127. drawAll()
  1128.  
  1129. while true do
  1130. local e, side, x, y = os.pullEvent()
  1131.  
  1132. if e == "monitor_touch" then
  1133. handleTouch(x, y)
  1134. elseif e == "peripheral" or e == "peripheral_detach" then
  1135. drawAll()
  1136. end
  1137. end
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Ashlalaq
    30 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • User was banned
  • User was banned
  • Pubolur
    4 days
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=tsqjimrnoe
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment