theninthbit

computercraft_blackjack2_display

Jan 6th, 2021 (edited)
424
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.07 KB | None | 0 0
  1. -- https://pastebin.com/HRsfzDv1
  2. -- pastebin get HRsfzDv1 startup
  3.  
  4. -- autoloader config
  5. -- pastebin get XcX1FQmw startup
  6. -- {pastebin='HRsfzDv1 ', program='display'}
  7.  
  8. pcall(require, 'computercraft')
  9.  
  10. function readConfig()
  11.   if not fs.exists('displayConfig') then
  12.     print('no display config')
  13.     return {}
  14.   end
  15.  
  16.   local file = fs.open('displayConfig', 'r')--.fakeResult(fileHandle)
  17.   local data = file.readAll()
  18.   file.close()
  19.   return textutils.unserialize(data)
  20. end
  21.  
  22. function connectRednet()
  23.   for k,v in pairs(redstone.getSides()) do
  24.     if peripheral.getType(v) == 'modem' then  
  25.         rednet.open(v)
  26.         return
  27.     end
  28.   end
  29.   print('modem not found')
  30.   return false
  31. end
  32.  
  33. function connectMonitor()
  34.   for k,v in pairs(redstone.getSides()) do
  35.     if peripheral.getType(v) == 'monitor' then  
  36.         return peripheral.wrap(v)
  37.     end
  38.   end
  39.   print('monitor not found')
  40.   return false
  41. end
  42.  
  43. function delay(seconds)
  44.     -- safe version of 'sleep' - will requeue dropped events
  45.     local timer = os.startTimer(seconds)
  46.     local q = {}
  47.     while true do
  48.         local data = {os.pullEvent()}
  49.         if data[1] == "timer" and data[2] == timer then
  50.             break
  51.         else
  52.             table.insert(q, data)
  53.         end
  54.     end
  55.     for i,v in ipairs(q) do
  56.         os.queueEvent(unpack(v))
  57.     end
  58. end
  59.  
  60. function drawGreen(display, configs)
  61.   display.setBackgroundColor(colors.green)
  62.   display.setTextColor(colors.white)
  63.   display.setTextScale(.5)
  64.   display.clear()
  65.  
  66.   -- 5x7
  67.   display.setCursorPos(1,1)
  68.   for i=1,10 do
  69.     writeln(display, string.rep(" ",14*configs.size))
  70.   end  
  71. end
  72.  
  73. function playerClick(x)
  74.   -- 1-18, 19-40, 41-63, 64-85
  75.   if x <= 18 then
  76.     return 1
  77.   elseif x <= 40 then
  78.     return 2
  79.   elseif x <= 62 then
  80.     return 3
  81.   end
  82.   return 4
  83. end
  84.  
  85.  
  86. -- returns isBust, isAnyCountEQ21, isBlackjack, value
  87. function check21OrBust(hand)
  88.   local counts = {0}
  89.   for i=1, table.getn(hand) do
  90.     local handValue = hand[i]%13
  91.     for j=1, table.getn(counts) do
  92.       if handValue < 10 and handValue > 1 then
  93.         counts[j] = counts[j] + handValue
  94.       end
  95.       if handValue >= 10 or handValue == 0 then
  96.         counts[j] = counts[j] + 10
  97.       end
  98.       if handValue == 1 then
  99.         counts[j] = counts[j] + 1
  100.         table.insert(counts, counts[j] + 10) -- this is +11. +10 ontop of +1
  101.       end
  102.     end
  103.   end
  104.   print(textutils.serialize(counts))
  105.  
  106.   local isAnyCountLTE21 = false
  107.   local isAnyCountEQ21 = false
  108.   local isCardCount2 = table.getn(hand) == 2
  109.   local value = counts[1]
  110.   for k=1, table.getn(counts) do
  111.     if counts[k] <= 21 then isAnyCountLTE21 = true end
  112.     if counts[k] == 21 then isAnyCountEQ21 = true end
  113.     if counts[k] > value and counts[k] <= 21 then
  114.       value = counts[k]
  115.     end
  116.   end
  117.  
  118.   return not isAnyCountLTE21, isAnyCountEQ21, isAnyCountEQ21 and isCardCount2, value
  119. end
  120.  
  121. function drawJoins(display, players, configs)
  122.   local startPos = {-1,19,41,64}
  123.   drawGreen(display, configs)
  124.   for i=1, configs.size do
  125.     if players[i]==nil then
  126.       display.setBackgroundColor(colors.blue)
  127.       drawBtn(display, 6+startPos[i], 4, 'join')
  128.     elseif players[i].errors then
  129.       display.setBackgroundColor(colors.blue)
  130.       drawBtn(display, 2+startPos[i], 4, players[i].errors[1])
  131.       drawBtn(display, 2+startPos[i], 5, players[i].errors[2])
  132.     elseif players[i].player then
  133.       display.setBackgroundColor(colors.green)
  134.       display.setCursorPos(6+startPos[i],4)
  135.       display.write(players[i].player)
  136.       display.setCursorPos(6+startPos[i],5)
  137.       display.write('joined')
  138.     end
  139.   end
  140. end
  141.  
  142. function writeln(display, text)
  143.   local x,y = display.getCursorPos()
  144.   display.write(text)
  145.   display.setCursorPos(x, y+1)
  146. end
  147.  
  148. function drawBtn(display, x, y, text)
  149.   display.setCursorPos(x,y)
  150.   display.write(string.rep(" ",string.len(text)+2))
  151.   display.setCursorPos(x+1,y)
  152.   display.write(text)
  153. end
  154.  
  155. function drawBet(display, players, currentIndex)
  156.   local startPos = {1,19,41,64}
  157.   for i=1, currentIndex-1 do
  158.     if players[i]~=nil then
  159.       display.setCursorPos(startPos[i],10)
  160.       display.setTextColor(colors.white)
  161.       display.setBackgroundColor(colors.green)
  162.       display.write('bet: $'..players[i].bet)
  163.     end
  164.   end
  165. end
  166. function drawBettingScreen(display, player, configs)
  167.   drawGreen(display, configs)
  168.   local startPos = {1,19,41,64}
  169.   display.setCursorPos(startPos[player.order], 2)
  170.  
  171.   writeln(display, player.player)
  172.   writeln(display, 'balance: $'..player.balance)
  173.   writeln(display, 'bet: $'..player.bet)
  174.  
  175.   display.setBackgroundColor(colors.blue)
  176.   if configs.min_bet ~= player.bet then
  177.     drawBtn(display, startPos[player.order], 7, '-10')
  178.   end
  179.   if player.balance-(player.bet+10) >= 0 then
  180.     drawBtn(display, startPos[player.order]+11, 7, '+10')
  181.   end
  182.   if player.balance - player.bet >= 0 then
  183.     drawBtn(display, startPos[player.order]+7, 9, 'done')
  184.   end
  185.   drawBtn(display, startPos[player.order]+6, 10, 'cancel')
  186. end
  187.  
  188. function drawCard(display, pos, value, offset)
  189.   display.setBackgroundColor(colors.white)
  190.   display.setTextColor(colors.black)
  191.   if value > 26 then
  192.     display.setTextColor(colors.red)
  193.   end
  194.  
  195.   value = math.floor(value % 13)
  196.   if value == 11 then value = 'J' end
  197.   if value == 12 then value = 'Q' end
  198.   if value == 13 or value == 0 then value = 'K' end
  199.   if value == 1 then value = 'A' end
  200.  
  201.   local cardPositions = {{0,2},{3,2},{6,2},{9,2},{0,5}}
  202.   display.setCursorPos(offset + cardPositions[pos][1],cardPositions[pos][2])
  203.   if value == 10 then
  204.     display.write(tostring(value))
  205.   else
  206.     display.write(tostring(value)..' ')
  207.   end
  208.   display.setCursorPos(offset + cardPositions[pos][1],cardPositions[pos][2]+1)
  209.   display.write('  ')
  210. end
  211.  
  212. function drawHands(display, players, configs)
  213.   local startPos = {1,19,41,64}
  214.   for i=1, configs.size do
  215.     if players[i]~=nil then
  216.       for j=1, #players[i].hand do
  217.         drawCard(display, j, players[i].hand[j], startPos[i])
  218.       end
  219.      
  220.       display.setCursorPos(startPos[i],10)
  221.       display.setTextColor(colors.white)
  222.       display.setBackgroundColor(colors.green)
  223.       display.write('bet: $'..players[i].bet)
  224.      
  225.       if players[i].specialHand == 'blackjack' then
  226.         display.setBackgroundColor(colors.red)
  227.         drawBtn(display, startPos[i]+8, 9, 'black')  
  228.         drawBtn(display, startPos[i]+8, 10, 'jack!')  
  229.         display.setBackgroundColor(colors.green)
  230.       end
  231.       if players[i].specialHand == 'bust' then
  232.         display.setBackgroundColor(colors.red)
  233.         drawBtn(display, startPos[i]+9, 10, 'bust')  
  234.         display.setBackgroundColor(colors.green)
  235.       end
  236.     end
  237.   end
  238. end
  239.  
  240. function drawActionButtons(display, i, isFirstTurn )
  241.   local startPos = {1,19,41,64, 82}
  242.   display.setBackgroundColor(colors.blue)
  243.   drawBtn(display, startPos[i]+10, 6, 'hit')
  244.   if isFirstTurn then
  245.     drawBtn(display, startPos[i]+7, 8, 'double')
  246.   end
  247.   drawBtn(display, startPos[i]+8, 10, 'stand')  
  248. end
  249.  
  250. -- returns isNotDone, isHit
  251. function checkAction(x, y, player, configs)
  252.   local startPos = {1,19,41,64, 82}
  253.   print('action')
  254.   if x >= startPos[player.order] and x < startPos[player.order+1] then
  255.     if y == 6 and x > startPos[player.order] + 10 then
  256.       print('hit')
  257.     -- if hit, request card
  258.       return true, true
  259.     elseif y==8 and x > startPos[player.order] + 7 and #player.hand == 2 then
  260.       print('double')
  261.     -- if doubledown, betx2 and request card
  262.       rednet.broadcast(textutils.serialize({
  263.         action='bet',
  264.         player=player.player,
  265.         bet=player.bet,
  266.         order=player.order,
  267.       }), configs.protocol)
  268.       player.bet = player.bet*2
  269.       return false, true
  270.     elseif y==10 and x > startPos[player.order] + 8 then
  271.       print('stand')
  272.     -- if stand, is done
  273.       return false, false
  274.     end
  275.   end
  276.   return true, false
  277.  
  278. end
  279.  
  280. function drawGameScreen(display, players, configs)
  281.   drawGreen(display, configs)
  282.   drawHands(display, players, configs)
  283. end
  284.  
  285. function drawScreen(display, x0, x1)
  286.   display.setCursorPos(x0,1)
  287.   for i=1,10 do
  288.     writeln(display, string.rep(" ",x1-x0))
  289.   end  
  290. end
  291.  
  292. function drawEndScreen(display, player, dealerValue)
  293.   local startPos = {1,19,41,64, 82}
  294.   local isBust, is21, isBlackjack, value = check21OrBust(player.hand)
  295.   local screenColor = colors.green
  296.   local message = ''
  297.   --is lost
  298.   if isBust or (dealerValue <=21 and dealerValue > value) then
  299.     screenColor = colors.red
  300.     player.bet = 0
  301.     message = 'Lost!'
  302.     display.setTextColor(colors.black)
  303.   elseif (dealerValue == 0 and isBlackjack) or (dealerValue == value) then
  304.   --push
  305.     screenColor = colors.yellow
  306.     message = 'Push!'
  307.     display.setTextColor(colors.black)
  308.   elseif dealerValue == 0 then
  309.     screenColor = colors.red
  310.     player.bet = 0
  311.     message = 'Lost!'
  312.     display.setTextColor(colors.black)
  313.   elseif dealerValue>21 or dealerValue < value then
  314.     --is won
  315.     display.setTextColor(colors.white)
  316.     if isBlackjack then
  317.       message = 'BLACKJACK!'
  318.       player.bet = player.bet*2.5
  319.     else
  320.       message = 'Won!'
  321.       player.bet = player.bet*2
  322.     end
  323.   end
  324.  
  325.  
  326.   display.setBackgroundColor(screenColor)
  327.   drawScreen(display, startPos[player.order], startPos[player.order+1])
  328.   drawBtn(display,startPos[player.order], 2, message)
  329.   drawBtn(display,startPos[player.order], 3, 'won: $'..player.bet)
  330.   display.setBackgroundColor(colors.green)
  331. end
  332. -- returns isDone, isCancelled
  333. function checkBettingAction(x, y, player, configs)
  334.   local startPos = {1,19,41,64, 82}
  335.   if x >= startPos[player.order] and x < startPos[player.order+1] then
  336.     if y == 7 then
  337.       print('betting')
  338.       if x >= startPos[player.order] and x <= startPos[player.order]+5 then
  339.         if player.bet-10 >= configs.min_bet then
  340.           player.bet = player.bet-10
  341.         end
  342.       elseif x >= startPos[player.order]+11 and x <= startPos[player.order]+16 then
  343.         if player.bet+10 <= player.balance then
  344.           player.bet = player.bet+10
  345.         end
  346.       end
  347.     elseif y== 9 then
  348.       print('done')
  349.       return false, false
  350.     elseif y==10 then
  351.       print('cancelled')
  352.       return false, true
  353.     end
  354.   end
  355.   return true, false
  356. end
  357.  
  358. function main()
  359.   connectRednet()
  360.   local display = connectMonitor()
  361.   local configs = readConfig()
  362.   local state = 0
  363.   local dealerId = 0
  364.   local players = {}
  365.  
  366.   while true do
  367.     parallel.waitForAny(
  368.       function()
  369.         local sender, message, protocol = rednet.receive('ok', 60)
  370.         if protocol == 'ok' then
  371.           rednet.send(sender, configs.protocol..'-display'..configs.order, 'ok')
  372.         end
  373.       end,
  374.       function()
  375.         -- wait for joins
  376.         if state == 0 then
  377.           players = {}
  378.           print('init')
  379.           state = 0.1
  380.         end
  381.         -- wait for joins
  382.         if state == 0.1 then
  383.           parallel.waitForAny(
  384.             -- start action
  385.             function()
  386.               dealerId, message = rednet.receive(configs.protocol..'dealer', 60)
  387.               print('got dealer start')
  388.               if message == 'starting' then
  389.                 state = 1
  390.               end
  391.             end,
  392.             -- join action
  393.             function()
  394.               drawJoins(display, players, configs)
  395.               joinEvent, joinButton, joinX, joinY = os.pullEvent("monitor_touch")
  396.               rednet.broadcast(textutils.serialize({
  397.                 action='getBalance',
  398.                 order=playerClick(joinX),
  399.               }), configs.protocol)
  400.               local joinId, joinMessage = rednet.receive(configs.protocol, 60)
  401.               if joinMessage~=nil then
  402.                 local joinRequest = textutils.unserialize(joinMessage)
  403.                 if joinRequest.success then
  404.                   players[playerClick(joinX)]={
  405.                     id=joinId,
  406.                     balance=joinRequest.balance,
  407.                     order=playerClick(joinX),
  408.                     player=joinRequest.player,
  409.                     hand={},
  410.                     bet=configs.min_bet}
  411.                   print(joinRequest.player..' joined')
  412.                 else
  413.                   players[playerClick(joinX)]={errors={'stand closer', 'and click again'}}
  414.                 end
  415.               end
  416.             end)
  417.         end
  418.        
  419.         -- bet action
  420.         if state == 1 then
  421.           local betActionState = 1
  422.           -- for each player on this monitor
  423.           for betActionState=1, configs.size do
  424.             -- skip no player joined
  425.             if players[betActionState]~= nil then                
  426.               print(players[betActionState].player..' betting')
  427.               local isBetting = true
  428.               -- loop while they +/- bet
  429.               while isBetting do
  430.                 drawBettingScreen(display, players[betActionState], configs)
  431.                 drawBet(display, players, betActionState)
  432.                 local bettingEvent, bettingButton, bettingX, bettingY = os.pullEvent("monitor_touch")
  433.                 isBetting, isCancelled = checkBettingAction(bettingX, bettingY, players[betActionState], configs)
  434.                 if isCancelled then
  435.                   players[betActionState] = nil
  436.                 end
  437.               end
  438.               rednet.broadcast(textutils.serialize({
  439.                 action='bet',
  440.                 player=players[betActionState].player,
  441.                 bet=players[betActionState].bet,
  442.                 order=betActionState,
  443.               }), configs.protocol)
  444.             end
  445.           end
  446.           state = 2
  447.         end
  448.        
  449.         -- deal 1 card action
  450.         if state == 2 then
  451.           print('done betting')
  452.           local playerSize = 0
  453.           for i=1,configs.size do
  454.             if players[i] ~=nil then playerSize = playerSize + 1 end
  455.           end
  456.           drawGameScreen(display, players, configs)
  457.           print('waiting for cards')
  458.           rednet.send(dealerId, textutils.serialize({
  459.             action='done-betting',
  460.             order=configs.order,
  461.             hands=playerSize,
  462.           }), configs.protocol..'dealer')          
  463.          
  464.           local waitingForDealt = true
  465.           local dealt = {}
  466.           while waitingForDealt do
  467.             local deal1Id, deal1Message = rednet.receive(configs.protocol..'dealer', 60)
  468.             print(deal1Message)
  469.             if deal1Message ~=nil then
  470.               dealt = textutils.unserialize(deal1Message)
  471.               waitingForDealt = false
  472.             end
  473.           end
  474.           -- draw cards
  475.           local isDrawingCards = true
  476.           for i=1,configs.size do
  477.             if players[i] ~=nil then
  478.               table.insert(players[i].hand, table.remove(dealt))
  479.               drawGameScreen(display, players, configs)
  480.               delay(.3)
  481.             end
  482.           end
  483.          
  484.           rednet.send(dealerId, textutils.serialize({
  485.             action='done-dealing',
  486.             order=configs.order,
  487.           }), configs.protocol..'dealer')
  488.           state = 4
  489.         end
  490.          
  491.         -- deal 2nd card action
  492.         if state == 4 then
  493.           local waitingForDealt = true
  494.           local dealt = {}
  495.           while waitingForDealt do
  496.             local deal1Id, deal1Message = rednet.receive(configs.protocol..'dealer', 60)
  497.             print(deal1Message)
  498.             if deal1Message ~=nil then
  499.               dealt = textutils.unserialize(deal1Message)
  500.               waitingForDealt = false
  501.             end
  502.           end
  503.           -- draw cards
  504.           local isDrawingCards = true
  505.           for i=1,configs.size do
  506.             if players[i] ~=nil then
  507.               table.insert(players[i].hand, table.remove(dealt))
  508.               drawGameScreen(display, players, configs)
  509.               delay(1)
  510.             end
  511.           end
  512.          
  513.           print('sent done dealing')
  514.           rednet.send(dealerId, textutils.serialize({
  515.             action='done-dealing',
  516.             order=configs.order,
  517.           }), configs.protocol..'dealer')
  518.           state = 5
  519.         end
  520.        
  521.         -- resolve each players actions
  522.         if state==5 then
  523.           local waitingForAction = true
  524.           local dealt = {}
  525.           -- wait for dealer to start actions
  526.           while waitingForAction do
  527.             local _, actionMessage= rednet.receive(configs.protocol..'dealer', 60)
  528.             print(actionMessage)
  529.             if actionMessage == 'start-action' then
  530.               waitingForAction = false
  531.             end
  532.           end
  533.           -- do each players actions
  534.           for i=1,configs.size do
  535.             if players[i] ~=nil then
  536.               local notResolved = true
  537.               while notResolved do
  538.                 drawGameScreen(display, players, configs)
  539.                
  540.                 local isBust, is21, isBlackjack = check21OrBust(players[i].hand)
  541.                 if not isBust and not is21 and not isBlackjack then
  542.                   drawActionButtons(display, i, #players[i].hand == 2)
  543.                   local actionEvent, actionButton, actionX, actionY = os.pullEvent("monitor_touch")
  544.                   notResolved, isHit = checkAction(actionX, actionY, players[i], configs)
  545.                  
  546.                   if isHit then
  547.                     print('requesting card')
  548.                     rednet.send(dealerId, textutils.serialize({action='deal'}), configs.protocol..'dealer')
  549.                     local waitingForCard = true
  550.                     while waitingForCard do
  551.                       local _, card = rednet.receive(configs.protocol..'dealer', 30)
  552.                       if card ~=nil then
  553.                         print('got card')
  554.                         waitingForCard = false
  555.                         table.insert(players[i].hand, card)
  556.                       end
  557.                     end
  558.                   end
  559.                 else
  560.                   -- is 21 OR busted
  561.                   notResolved = false
  562.                   if isBust then
  563.                     players[i].specialHand = 'bust'
  564.                   elseif isBlackjack then
  565.                     players[i].specialHand = 'blackjack'
  566.                   end
  567.                 end
  568.                
  569.               end
  570.               drawGameScreen(display, players, configs)
  571.             end
  572.           end
  573.           -- send action is done message
  574.           print('done action')
  575.           rednet.send(dealerId, textutils.serialize({action='done-action'}), configs.protocol..'dealer')
  576.           state=6
  577.         end
  578.        
  579.         -- resolve win/loss
  580.         if state==6 then
  581.           local _, dealerValue = rednet.receive(configs.protocol..'dealer', 30)
  582.           if dealerValue then
  583.             print('dealer got:', dealerValue)
  584.            
  585.             drawGreen(display, configs)
  586.             for i=1,configs.size do
  587.               if players[i] ~=nil then
  588.                 drawEndScreen(display, players[i], dealerValue)
  589.               end
  590.             end
  591.             state = 7
  592.           end
  593.         end
  594.        
  595.         -- wait for reset or reset on timeout
  596.         if state==7 then
  597.           local _, resetValue = rednet.receive(configs.protocol..'dealer', 30)
  598.           state = 0
  599.         end
  600.       end)
  601.   end
  602.  
  603. end
  604. main()
  605.  
Add Comment
Please, Sign In to add comment