Drum_Stick

black_jack

Nov 10th, 2025 (edited)
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.81 KB | Gaming | 0 0
  1. sleep(2)
  2.  
  3. -- Peripheral Setup / Make sure to adjust your peripheral names
  4. local monitor = peripheral.wrap("monitor_10") -- Main game monitor
  5. local actionMonitor = peripheral.wrap("monitor_11") -- Stand/Hit monitor
  6. local bidMonitor = peripheral.wrap("monitor_14") -- Higher/Lower Bid monitor
  7. local playerDetector = peripheral.find("playerDetector") -- Player Detector peripheral
  8. local speaker = peripheral.wrap("left") -- Speaker for sound effects
  9.  
  10. -- API URL
  11. local API_URL = "http://<API_IP>:3000/balance/"
  12.  
  13. -- Constants
  14. local BLACKJACK_MULTIPLIER = 1.5
  15. local WIN_DELAY = 3 -- Delay before displaying the result in seconds
  16. local BET_INCREMENT = 5 -- Bet increment
  17. local MAX_BET = 500 -- Maximum bet allowed
  18.  
  19. -- Game State
  20. local currentBet = 5
  21. local currentPlayer = nil
  22.  
  23. -- Split Monitor Rendering
  24. local function splitMonitor(monitor, leftText, rightText)
  25.     local width, height = monitor.getSize()
  26.     local midX = math.floor(width / 2)
  27.  
  28.     monitor.clear()
  29.  
  30.     for y = 1, height do
  31.         monitor.setCursorPos(midX, y)
  32.         monitor.write("|")
  33.     end
  34.  
  35.     monitor.setCursorPos(2, math.floor(height / 2)) -- Left side
  36.     monitor.write(leftText)
  37.     monitor.setCursorPos(midX + 2, math.floor(height / 2)) -- Right side
  38.     monitor.write(rightText)
  39. end
  40.  
  41. -- Render Monitors with Dynamic Button Texts
  42. local function renderMonitors(state)
  43.     if state == "welcome" then
  44.         -- Welcome screen: Display "Exit" and "Play", clear bid monitor
  45.         Monitor.clear() -- Clear Exit/Play text
  46.         bidMonitor.clear() -- Clear Higher/Lower text
  47.     elseif state == "betting" then
  48.         -- Betting screen: Display "Exit" and "Play", and allow Higher/Lower
  49.         splitMonitor(actionMonitor, "Exit", "Play")
  50.         splitMonitor(bidMonitor, "Higher", "Lower")
  51.     elseif state == "game" then
  52.         -- Gameplay: Display "Stand" and "Hit", and allow Higher/Lower
  53.         splitMonitor(actionMonitor, "Stand", "Hit")
  54.         splitMonitor(bidMonitor, "Higher", "Lower")
  55.     end
  56. end
  57.  
  58. -- API Helper Functions
  59. local function getPlayerBalance(playerName)
  60.     local response = http.get(API_URL .. playerName)
  61.     if response then
  62.         local data = response.readAll()
  63.         response.close()
  64.         local result = textutils.unserializeJSON(data)
  65.         return result and result.coins or 0
  66.     end
  67.     return 0
  68. end
  69.  
  70. local function updatePlayerBalance(playerName, newBalance)
  71.     local body = textutils.serializeJSON({ coins = newBalance })
  72.     http.post(API_URL .. playerName, body, { ["Content-Type"] = "application/json" })
  73. end
  74.  
  75. -- Input Handler for Split Monitors
  76. local function waitForMonitorClick(gameStarted)
  77.     while true do
  78.         local event, side, x, y = os.pullEvent("monitor_touch")
  79.  
  80.         -- Action Monitor (Monitor 11: Exit/Play or Stand/Hit)
  81.         if side == peripheral.getName(actionMonitor) then
  82.             local width, height = actionMonitor.getSize()
  83.             local midX = math.floor(width / 2)
  84.             if x <= midX then
  85.                 return gameStarted and "stand" or "exit"
  86.             else
  87.                 return gameStarted and "hit" or "play"
  88.             end
  89.  
  90.         -- Bid Monitor (Monitor 14: Higher/Lower)
  91.         elseif side == peripheral.getName(bidMonitor) then
  92.             local width, height = bidMonitor.getSize()
  93.             local midX = math.floor(width / 2)
  94.             if x <= midX then
  95.                 return "higherBid"
  96.             else
  97.                 return "lowerBid"
  98.             end
  99.         end
  100.     end
  101. end
  102.  
  103. -- Helper Functions
  104. local function calculateHandValue(hand)
  105.     local value, aces = 0, 0
  106.     for _, card in ipairs(hand) do
  107.         if tonumber(card) then
  108.             value = value + tonumber(card)
  109.         elseif card == "A" then
  110.             value, aces = value + 11, aces + 1
  111.         else
  112.             value = value + 10
  113.         end
  114.     end
  115.     while value > 21 and aces > 0 do
  116.         value, aces = value - 10, aces - 1
  117.     end
  118.     return value
  119. end
  120.  
  121. local function drawCard(monitor, x, y, cardValue)
  122.     local cardArt
  123.     if cardValue == "10" then
  124.         cardArt = {
  125.             " _____ ",
  126.             "|10   |",
  127.             "|     |",
  128.             "|  10 |",
  129.             "|     |",
  130.             "|___10|"
  131.         }
  132.     else
  133.         cardArt = {
  134.             " _____ ",
  135.             "|%s    |",
  136.             "|     |",
  137.             "|  %s  |",
  138.             "|     |",
  139.             "|____%s|"
  140.         }
  141.     end
  142.    
  143.     local displayValue = cardValue == "10" and "10" or string.sub(cardValue, 1, 1)
  144.     local middle = " " .. (cardValue == "A" and "^" or " ") .. " "
  145.     for i, line in ipairs(cardArt) do
  146.         monitor.setCursorPos(x, y + i - 1)
  147.         monitor.write(line:format(displayValue, middle, displayValue))
  148.     end
  149. end
  150.  
  151.  
  152. local function displayGame(playerHand, dealerHand, betAmount, showAllDealerCards)
  153.     local width, height = monitor.getSize()
  154.     local centerX = math.floor(width / 2)
  155.     local centerY = math.floor(height / 2)
  156.    
  157.     -- Set green background for gameplay
  158.     monitor.setBackgroundColor(colors.green)
  159.     monitor.clear()
  160.     monitor.setTextColor(colors.white)
  161.  
  162.     -- Display the bet amount at the top center
  163.     local betText = "Bet: " .. betAmount .. " Coins"
  164.     monitor.setCursorPos(centerX - math.floor(string.len(betText) / 2), 1)
  165.     monitor.write(betText)
  166.  
  167.     -- Calculate hand values
  168.     local playerHandValue = calculateHandValue(playerHand)
  169.     local dealerHandValue = calculateHandValue(dealerHand)
  170.  
  171.     -- Calculate dynamic card positions
  172.     local cardWidth = 8
  173.     local maxCards = math.min(#playerHand, 5) -- Adjust spacing for more cards
  174.     local playerStartX = centerX - (math.ceil(maxCards / 2) * cardWidth) + 4
  175.     local playerY = centerY - 6
  176.  
  177.     -- Display Player's Hand with Value
  178.     local playerHandText = "Your Hand (" .. playerHandValue .. "):"
  179.     monitor.setCursorPos(centerX - math.floor(string.len(playerHandText) / 2), playerY - 1)
  180.     monitor.write(playerHandText)
  181.     for i, card in ipairs(playerHand) do
  182.         drawCard(monitor, playerStartX + (i - 1) * cardWidth, playerY, card)
  183.     end
  184.  
  185.     -- Calculate dealer card positions
  186.     local dealerStartX = centerX - (math.ceil(#dealerHand / 2) * cardWidth) + 4
  187.     local dealerY = playerY + 8
  188.  
  189.     -- Display Dealer's Hand
  190.     local dealerHandText = "Dealer's Hand:"
  191.     monitor.setCursorPos(centerX - math.floor(string.len(dealerHandText) / 2), dealerY - 1)
  192.     monitor.write(dealerHandText)
  193.     for i, card in ipairs(dealerHand) do
  194.         if not showAllDealerCards and i > 1 then
  195.             drawCard(monitor, dealerStartX + (i - 1) * cardWidth, dealerY, "?")
  196.         else
  197.             drawCard(monitor, dealerStartX + (i - 1) * cardWidth, dealerY, card)
  198.         end
  199.     end
  200.  
  201.     -- Reset background color
  202.     monitor.setBackgroundColor(colors.black)
  203. end
  204.  
  205.  
  206. -- Centered Menu Text Function
  207. local function displayCenteredMenuText(lines)
  208.     local width, height = monitor.getSize()
  209.     local centerX = math.floor(width / 2)
  210.     local centerY = math.floor(height / 2)
  211.  
  212.     monitor.setBackgroundColor(colors.black)
  213.     monitor.clear()
  214.     monitor.setTextColor(colors.white)
  215.  
  216.     -- Center each line of text
  217.     for i, line in ipairs(lines) do
  218.         monitor.setCursorPos(centerX - math.floor(string.len(line) / 2), centerY - #lines / 2 + i - 1)
  219.         monitor.write(line)
  220.     end
  221. end
  222.  
  223.  
  224. -- Game Logic
  225. local function playBlackjack()
  226.     speaker.playSound("minecraft:block.note_block.harp")
  227.  
  228.     -- Create a deck
  229.     local values = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}
  230.     local function drawCardValue() return values[math.random(1, #values)] end
  231.  
  232.     local playerHand, dealerHand = {drawCardValue(), drawCardValue()}, {drawCardValue(), drawCardValue()}
  233.     local playerBlackjack = false
  234.     local dealerBlackjack = false
  235.  
  236.     -- Check if the player starts with Blackjack
  237.     if calculateHandValue(playerHand) == 21 and #playerHand == 2 then
  238.         playerBlackjack = true
  239.         displayGame(playerHand, dealerHand, currentBet, false) -- Draw the player and dealer cards first
  240.         monitor.setCursorPos(1, 12)
  241.         monitor.write("Blackjack! You Win!")
  242.        
  243.         -- Play the ding-ding sound effect AFTER the image is drawn
  244.         for _ = 1, 10 do
  245.             speaker.playSound("minecraft:block.note_block.bell")
  246.             sleep(0.2) -- Short pause between dings
  247.         end
  248.     end
  249.  
  250.  
  251.     -- Check if the dealer starts with Blackjack
  252.     if calculateHandValue(dealerHand) == 21 and #dealerHand == 2 then
  253.         dealerBlackjack = true
  254.     end
  255.  
  256.     -- End the game immediately if either the player or dealer has Blackjack
  257.     if playerBlackjack or dealerBlackjack then
  258.         displayGame(playerHand, dealerHand, currentBet, true) -- Show all cards
  259.         monitor.setCursorPos(1, 12)
  260.         if playerBlackjack and dealerBlackjack then
  261.             speaker.playSound("minecraft:block.note_block.bass")
  262.             monitor.write("Push! Both have Blackjack!")
  263.         elseif dealerBlackjack then
  264.             speaker.playSound("minecraft:block.note_block.banjo")
  265.             monitor.write("Dealer Wins! Blackjack!")
  266.             updatePlayerBalance(currentPlayer, getPlayerBalance(currentPlayer) - currentBet)
  267.         elseif playerBlackjack then
  268.             speaker.playSound("minecraft:block.note_block.chime")
  269.             monitor.write("Blackjack! You Win!")
  270.             updatePlayerBalance(currentPlayer, getPlayerBalance(currentPlayer) + math.ceil(currentBet * BLACKJACK_MULTIPLIER))
  271.         end
  272.         sleep(WIN_DELAY)
  273.         return
  274.     end
  275.  
  276.     -- Player's turn
  277.     while calculateHandValue(playerHand) <= 21 do
  278.         displayGame(playerHand, dealerHand, currentBet, false)
  279.         local action = waitForMonitorClick(true) -- Pass `true` for gameStarted
  280.         if action == "hit" then
  281.             speaker.playSound("minecraft:block.note_block.pling")
  282.             table.insert(playerHand, drawCardValue())
  283.         elseif action == "stand" then
  284.             speaker.playSound("minecraft:block.note_block.bass")
  285.             break
  286.         end
  287.     end
  288.  
  289.     -- Dealers turn
  290.     while calculateHandValue(dealerHand) < 17 do
  291.         table.insert(dealerHand, drawCardValue())
  292.     end
  293.  
  294.     -- Reveal all cards and determine winner
  295.     local playerValue, dealerValue = calculateHandValue(playerHand), calculateHandValue(dealerHand)
  296.     displayGame(playerHand, dealerHand, currentBet, true)
  297.  
  298.     if playerValue > 21 or (dealerValue <= 21 and dealerValue > playerValue) then
  299.         speaker.playSound("minecraft:block.note_block.banjo")
  300.         monitor.setCursorPos(1, 12)
  301.         monitor.write("Dealer Wins!")
  302.         updatePlayerBalance(currentPlayer, getPlayerBalance(currentPlayer) - currentBet)
  303.     elseif dealerValue > 21 or playerValue > dealerValue then
  304.         speaker.playSound("minecraft:block.note_block.xylophone")
  305.         monitor.setCursorPos(1, 12)
  306.         monitor.write("You Win!")
  307.         updatePlayerBalance(currentPlayer, getPlayerBalance(currentPlayer) + currentBet)
  308.     else
  309.         speaker.playSound("minecraft:block.note_block.bass")
  310.         monitor.setCursorPos(1, 12)
  311.         monitor.write("Push! It's a tie.")
  312.     end
  313.     sleep(WIN_DELAY)
  314. end
  315.  
  316. -- Game Logic
  317. local function canPlayerPlay(playerName, betAmount)
  318.     local balance = getPlayerBalance(playerName)
  319.     if balance < betAmount then
  320.         return false, "Insufficient balance! You need at least " .. betAmount .. " Coins to play."
  321.     end
  322.     return true
  323. end
  324.  
  325. -- Main Loop
  326. while true do
  327.     renderMonitors("welcome") -- Render Welcome Screen
  328.  
  329.     -- Display homescreen
  330.     monitor.clear()
  331.     monitor.setCursorPos(1, 1)
  332.     displayCenteredMenuText({
  333.         "Welcome to Blackjack!",
  334.         "Right-click the Green Block to login."
  335.     })
  336.    
  337.     -- Wait for player to register
  338.     local _, username = os.pullEvent("playerClick")
  339.     currentPlayer = username
  340.     local playerBalance = getPlayerBalance(username)
  341.  
  342.     -- Betting screen
  343.     renderMonitors("betting") -- Show Higher/Lower buttons
  344.     speaker.playSound("minecraft:block.note_block.bell")
  345.  
  346.     while true do
  347.         -- Refresh homescreen
  348.         monitor.clear()
  349.         monitor.setCursorPos(1, 1)
  350.         displayCenteredMenuText({
  351.             "Player: " .. username,
  352.             "Balance: " .. playerBalance .. " Coins",
  353.             "Current Bet: " .. currentBet .. " Coins",
  354.             "",
  355.             "Use Higher/Lower to adjust bet.",
  356.             "Press Play to start or Exit to quit."
  357.         })
  358.  
  359.         local action = waitForMonitorClick(false)
  360.  
  361.         if action == "higherBid" then
  362.             speaker.playSound("minecraft:block.note_block.snare")
  363.             currentBet = math.min(currentBet + BET_INCREMENT, MAX_BET)
  364.         elseif action == "lowerBid" then
  365.             speaker.playSound("minecraft:block.note_block.bass")
  366.             currentBet = math.max(currentBet - BET_INCREMENT, BET_INCREMENT)
  367.         elseif action == "play" then
  368.             -- Check if the player can play
  369.             local canPlay, errorMessage = canPlayerPlay(username, currentBet)
  370.             if not canPlay then
  371.                 -- Show error message
  372.                 displayCenteredMenuText({
  373.                     errorMessage,
  374.                     "",
  375.                     "Adjust your bet or exit to the main menu."
  376.                 })
  377.                 speaker.playSound("minecraft:block.note_block.bass")
  378.                 sleep(2) -- Allow the player to read the message
  379.             else
  380.                 renderMonitors("game") -- Switch to gameplay screen
  381.                 playBlackjack()
  382.                 playerBalance = getPlayerBalance(username)
  383.                 renderMonitors("betting") -- Return to betting after round
  384.             end
  385.         elseif action == "exit" then
  386.             speaker.playSound("minecraft:block.note_block.bass")
  387.             break -- Exit to main menu
  388.         end
  389.     end
  390. end
Add Comment
Please, Sign In to add comment