Advertisement
JereTheJuggler

solitaire.lua

Nov 26th, 2021
567
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 19.32 KB | None | 0 0
  1. cards = {}
  2. backColor = colors.blue
  3. tableColor = colors.lime
  4. darkTableColor = colors.green
  5. selectColor = colors.lightBlue
  6. tableText = colors.white
  7. buttonColor = colors.red
  8. buttonText = colors.black
  9. suits = {"D","C","S","H"}
  10. displayValues = {"A","2","3","4","5","6","7","8","9","T","J","Q","K"}
  11. sounds = {
  12. drawCard="dig.cloth",
  13. pickCard="random.click",
  14. deselect="note.hat",
  15. moveCard="step.cloth"
  16. }
  17.  
  18. function makeDeck ()
  19.   playsound(sounds.moveCard)
  20.   cards = {}
  21.   for s=1,4 do
  22.     for v=1,13 do
  23.       c=nil
  24.       if s == 1 or s == 4 then
  25.         c = "R"
  26.       else
  27.         c = "B"
  28.       end
  29.       if s==1 and v==1 then
  30.         table.insert(cards,{suit=s,value=v,color=c,selected=false,faceUp=false})
  31.       else
  32.         table.insert(cards,1+math.floor(math.random()*(table.getn(cards)+1)),{suit=s,value=v,color=c,selected=false,faceUp=false})
  33.       end
  34.     end
  35.   end
  36. end
  37.  
  38. tableau = {}
  39. drawPile = {}
  40. discardPile = {}
  41. width,height = term.getSize()
  42.  
  43. function dealCards ()
  44.   discardPile["cards"] = {}
  45.   drawPile["cards"] = {}
  46.   currentCard = 1
  47.   tableau = {}
  48.   for c=1,7 do
  49.     currentColumn = {}
  50.     for r=1,c do
  51.       table.insert(currentColumn,r,cards[currentCard])
  52.       currentCard = currentCard + 1
  53.     end
  54.     table.insert(tableau,c,currentColumn)
  55.     tableau[c][table.getn(tableau[c])]["faceUp"] = true
  56.   end
  57.   for c=currentCard,52 do
  58.     table.insert(drawPile.cards,cards[c])
  59.   end
  60. end
  61.  
  62. tabWindows = {}
  63. drawPile = {cards=nil,win=nil}
  64. discardPile = {cards=nil,win=window.create(term.current(),5,2,2,height-9)}
  65. foundations = {}
  66.  
  67. function drawTable ()
  68.   term.setBackgroundColor(tableColor)
  69.   term.setTextColor(tableText)
  70.   term.clear()
  71.   term.setCursorPos(1,1)
  72.   term.write("|Stock|   |------Tableau-------|   |Foundations|")
  73.   renderCloseButton()
  74.   renderNewGame()
  75.   text = "Made by JereTheJuggler"
  76.   term.setTextColor(colors.black)
  77.   term.setCursorPos(width-string.len(text)+1,height)
  78.   term.write(text)
  79.   text = "Solitaire"
  80.   term.setCursorPos(width-string.len(text)+1,height-1)
  81.   term.write(text)
  82. end
  83.  
  84. function buildWindows ()
  85.   tabWindows = {}
  86.   for i=1,7 do
  87.     table.insert(tabWindows,window.create(term.current(),12+3*(i-1),2,2,height-2))
  88.   end
  89.   foundations = {}
  90.   for f=1,4 do
  91.     table.insert(foundations,f,{suit=nil,value=nil,win=window.create(term.current(),37+3*(f-1),2,2,height-3),selected=false})
  92.   end
  93.   drawPile["cards"] = {}
  94.   drawPile["win"] = window.create(term.current(),2,2,2,height-9)
  95. end
  96. buildWindows()
  97.  
  98. closeButton = window.create(term.current(),2,height-1,9,1)
  99. function renderCloseButton ()
  100.   closeButton.setBackgroundColor(buttonColor)
  101.   closeButton.setTextColor(buttonText)
  102.   closeButton.clear()
  103.   closeButton.setCursorPos(2,1)
  104.   closeButton.write(" Close")
  105. end
  106.  
  107. newGame = window.create(term.current(),2,height-3,9,1)
  108. function renderNewGame ()
  109.   newGame.setBackgroundColor(buttonColor)
  110.   newGame.setTextColor(buttonText)
  111.   newGame.clear()
  112.   newGame.setCursorPos(2,1)
  113.   newGame.write("Restart")
  114. end
  115.  
  116. function renderAllCards ()
  117.   renderTableau()
  118.   renderFoundations()
  119.   renderDrawPile()
  120.   renderDiscardPile()
  121. end
  122.  
  123. function renderTableau (column)
  124.   startIndex,endIndex = -1,-1
  125.   if column == nil then
  126.     startIndex,endIndex = 1,7
  127.   else
  128.     startIndex,endIndex = column,column
  129.   end
  130.   for s=startIndex,endIndex do
  131.     tabWindows[s].setBackgroundColor(tableColor)
  132.     tabWindows[s].clear()
  133.     if table.getn(tableau[s]) == 0 then
  134.       tabWindows[s].setCursorPos(1,1)
  135.       renderCard(tabWindows[s],nil)
  136.     else
  137.       for c=1,table.getn(tableau[s]) do
  138.         tabWindows[s].setCursorPos(1,c)
  139.         renderCard(tabWindows[s],tableau[s][c])
  140.       end
  141.     end
  142.   end
  143. end
  144.  
  145. function renderFoundations (foundation)
  146.   startIndex = -1
  147.   endIndex = -1
  148.   if foundation == nil then
  149.     startIndex=1
  150.     endIndex=4
  151.   else
  152.     startIndex=foundation
  153.     endIndex=foundation
  154.   end
  155.   for f=startIndex,endIndex do
  156.     foundations[f].win.setBackgroundColor(tableColor)
  157.     foundations[f].win.clear()
  158.     if foundations[f].suit == nil then
  159.       foundations[f].win.setCursorPos(1,1)
  160.       renderCard(foundations[f].win,nil)
  161.     else
  162.       foundations[f].win.setCursorPos(1,1)
  163.       if foundations[f].suit == 1 or foundations[f].suit == 4 then
  164.         foundations[f].win.setTextColor(colors.red)
  165.       else
  166.         foundations[f].win.setTextColor(colors.black)
  167.       end
  168.       foundations[f].win.setBackgroundColor(colors.white)
  169.       for c=1,foundations[f].value do
  170.         foundations[f].win.setCursorPos(1,c)
  171.         if foundations[f].selected and c == foundations[f].value then
  172.           foundations[f].win.setBackgroundColor(selectColor)
  173.         end
  174.         foundations[f].win.write(displayValues[c]..suits[foundations[f].suit])
  175.       end
  176.     end
  177.   end
  178. end
  179.  
  180. function renderDrawPile ()
  181.   drawPile.win.setCursorPos(1,1)
  182.   if table.getn(drawPile.cards) == 0 then
  183.     drawPile.win.setBackgroundColor(darkTableColor)
  184.     drawPile.win.setTextColor(selectColor)
  185.     drawPile.win.write("()")
  186.   else
  187.     renderCard(drawPile.win,drawPile.cards[table.getn(drawPile.cards)])
  188.   end
  189. end
  190.  
  191. function renderDiscardPile ()
  192.   discardPile.win.setCursorPos(1,1)
  193.   if table.getn(discardPile.cards) == 0 then
  194.     renderCard(discardPile.win,nil)
  195.   else
  196.     renderCard(discardPile.win,discardPile.cards[1])
  197.   end
  198. end
  199.  
  200. function printerror (text,subtext)
  201.   p=peripheral.find("printer")
  202.   p.newPage()
  203.   p.setCursorPos(1,1)
  204.   p.write("ERROR: "..text)
  205.   if type(subtext) == "table" then
  206.     for l=1,table.getn(subtext) do
  207.       p.setCursorPos(1,1+l)
  208.       p.write(tostring(subtext[l]))
  209.     end
  210.   else
  211.     p.setCursorPos(1,2)
  212.     p.write(subtext)
  213.   end
  214.   p.endPage()
  215.   kill()
  216. end
  217.  
  218. function drawThree ()
  219.   for c=1,3 do
  220.     if table.getn(drawPile.cards) > 0 then
  221.       table.insert(discardPile.cards,1,drawPile.cards[table.getn(drawPile.cards)])
  222.       table.remove(drawPile.cards,table.getn(drawPile.cards))
  223.       discardPile.cards[1]["faceUp"] = true
  224.       renderDiscardPile()
  225.       if table.getn(drawPile.cards) == 0 then
  226.         renderDrawPile()
  227.       end
  228.       playsound(sounds.drawCard)
  229.       sleep(.25)
  230.     end
  231.   end
  232. end
  233.  
  234. function restockDrawPile ()
  235.   for c=1,table.getn(discardPile.cards) do
  236.     table.insert(drawPile.cards,c,discardPile.cards[c])
  237.     drawPile.cards[c]["faceUp"] = false
  238.   end  
  239.   discardPile["cards"] = {}
  240.   renderDrawPile()
  241.   renderDiscardPile()
  242.   playsound(sounds.drawCard)
  243. end
  244.  
  245. function playsound (sound,freq,vol)
  246.   note = peripheral.find("note_block")
  247.   if note == nil then
  248.     return
  249.   end
  250.   if freq == nil then
  251.     freq = .9
  252.   end
  253.   if vol == nil then
  254.     vol = 1.5
  255.   end
  256.   note.playSound(sound,freq,vol)
  257. end
  258.  
  259. function renderCard (win,card)
  260.   --printerror("test",{"value: "..card.value,"suit: "..card.suit,"color: "..card.color})
  261.   if card == nil then
  262.     win.setBackgroundColor(darkTableColor)
  263.     win.write("  ")
  264.   else
  265.     if card.faceUp then
  266.       if card.selected then
  267.         win.setBackgroundColor(selectColor)
  268.       else
  269.         win.setBackgroundColor(colors.white)
  270.       end
  271.       if card.color == "R" then
  272.         win.setTextColor(colors.red)
  273.       else
  274.         win.setTextColor(colors.black)
  275.       end
  276.         win.write(displayValues[card.value]..suits[card.suit])
  277.     else
  278.       win.setBackgroundColor(backColor)
  279.       win.setTextColor(colors.white)
  280.       win.write("XX")
  281.     end
  282.   end
  283. end
  284.  
  285. function clearFoundations ()
  286.   for f=1,4 do
  287.     foundations[f]["value"] = nil
  288.     foundations[f]["suit"] = nil
  289.     foundations[f]["selected"] = false
  290.   end
  291.   renderFoundations()
  292. end
  293.  
  294. selectedColumn = -1
  295. selectedCards = {}
  296. function playGame ()
  297.   makeDeck()
  298.   dealCards()
  299.   drawTable()
  300.   selectedCards = {}
  301.   renderAllCards()
  302.   selectedColumn = 0
  303.   clearFoundations()
  304.   continue = true
  305.   while continue do
  306.     for c=1,7 do
  307.       if table.getn(tableau[c]) > 0 then
  308.         if not tableau[c][table.getn(tableau[c])].faceUp then
  309.           tableau[c][table.getn(tableau[c])]["faceUp"] = true
  310.           renderTableau(c)
  311.         end
  312.       end
  313.     end
  314.     --renderTableau()
  315.     event,arg1,arg2,arg3,arg4 = os.pullEvent()
  316.     if event == "mouse_click" then
  317.       xPos = arg2
  318.       yPos = arg3
  319.       if isWithinBounds(getBounds(drawPile.win)) then
  320.         if table.getn(selectedCards) ~= 0 then
  321.           if selectedColumn == "discardPile" then
  322.             deselect(discardPile.cards)
  323.           elseif selectedColumn < 0 then
  324.             deselect(selectedColumn)
  325.           else
  326.             deselect(tableau[selectedColumn])
  327.           end
  328.         end
  329.         if table.getn(drawPile.cards) > 0 then
  330.           drawThree()
  331.         elseif table.getn(discardPile.cards) > 0 then
  332.           restockDrawPile()
  333.         end
  334.       elseif isWithinBounds(getBounds(discardPile.win)) then
  335.         if arg1 == 2 and table.getn(discardPile.cards) > 0 then
  336.           tryToMoveToFoundation("discardPile")
  337.         elseif table.getn(selectedCards) == 0 and table.getn(discardPile.cards) > 0 then
  338.           selectedColumn = "discardPile"
  339.           table.insert(selectedCards,discardPile.cards[1])
  340.           discardPile.cards[1]["selected"] = true
  341.           playsound(sounds.pickCard)
  342.           renderDiscardPile()
  343.         elseif selectedColumn == "discardPile" and table.getn(discardPile.cards) > 0 then
  344.           selectedColumn = 0
  345.           selectedCards = {}
  346.           discardPile.cards[1]["selected"] = false
  347.           playsound(sounds.deselect)
  348.           renderDiscardPile()
  349.         end
  350.       elseif isWithinBounds(getBounds(closeButton)) then
  351.         continue = false
  352.         restart = false
  353.       elseif isWithinBounds(getBounds(newGame)) then
  354.         continue = false
  355.         restart = true
  356.       else
  357.         for w=1,7 do
  358.           if isWithinBounds(getBounds(tabWindows[w])) then
  359.             if selectedColumn ~= "discardPile" and selectedColumn < 0 then
  360.               if foundations[selectedColumn*-1].suit == 1 or foundations[selectedColumn*-1].suit == 4 then
  361.                 c = "R"
  362.               else
  363.                 c = "B"
  364.               end
  365.               if foundations[selectedColumn*-1].value == tableau[w][table.getn(tableau[w])].value-1 and tableau[w][table.getn(tableau[w])].color ~= c then
  366.                 table.insert(tableau[w],table.getn(tableau[w])+1,{faceUp=true,color=c,value=foundations[selectedColumn*-1].value,suit=foundations[selectedColumn*-1].suit,selected=false})
  367.                 foundations[selectedColumn*-1]["value"] = foundations[selectedColumn*-1].value - 1
  368.                 if foundations[selectedColumn*-1].value == 0 then
  369.                   foundations[selectedColumn*-1]["suit"] = nil
  370.                   foundations[selectedColumn*-1]["value"] = nil
  371.                 end
  372.                 renderTableau(w)
  373.                
  374.               end
  375.               foundations[selectedColumn*-1]["selected"] = false
  376.               renderFoundations(selectedColumn*-1)
  377.               selectedColumn = 0
  378.               selectedCards = {}
  379.               --renderFoundations(selectedColumn*-1)
  380.             elseif table.getn(selectedCards) == 0 then
  381.               row=yPos-1
  382.               column = w
  383.               if table.getn(tableau[column]) ~= 0 then
  384.                 if arg1==2 then
  385.                   selectedColumn = w
  386.                   tryToMoveToFoundation(w)
  387.                   renderTableau(w)                
  388.                 elseif table.getn(tableau[column]) >= row then
  389.                   if tableau[column][row].faceUp then
  390.                     playsound(sounds.pickCard)
  391.                     selectedCards = {}
  392.                     for k=row,table.getn(tableau[column]) do
  393.                       table.insert(selectedCards,k-row+1,tableau[column][k])
  394.                       tableau[column][k]["selected"] = true
  395.                     end
  396.                     selectedColumn = w
  397.                     renderTableau(w)
  398.                   end
  399.                 elseif arg1 == 1 then
  400.                   m=1
  401.                   while not tableau[column][m].faceUp do
  402.                     m = m + 1
  403.                   end
  404.                   row = m
  405.                   playsound(sounds.pickCard)
  406.                   selectedCards = {}
  407.                   for k=row,table.getn(tableau[column]) do
  408.                     table.insert(selectedCards,k-row+1,tableau[column][k])
  409.                     tableau[column][k]["selected"] = true
  410.                   end
  411.                   selectedColumn = w
  412.                   renderTableau(w)                  
  413.                 end
  414.               end
  415.             else
  416.               if w == selectedColumn then
  417.                 playsound(sounds.deselect)
  418.                 deselect(tableau[selectedColumn])
  419.                 renderTableau()
  420.               else
  421.                 previousLocation = nil
  422.                 if selectedColumn == "discardPile" then
  423.                   previousLocation = discardPile.cards
  424.                 else
  425.                   previousLocation = tableau[selectedColumn]
  426.                 end
  427.                 if table.getn(tableau[w]) == 0 then
  428.                   if selectedCards[1].value == 13 then
  429.                     removeSelectedCardsFrom(previousLocation)
  430.                     if selectedColumn == "discardPile" then
  431.                       renderDiscardPile()
  432.                     end
  433.                     moveCardsTo(tableau[w])
  434.                     renderTableau(w)
  435.                   else
  436.                     playsound(sounds.deselect)
  437.                     deselect(previousLocation)
  438.                   end
  439.                 else
  440.                   topCard = tableau[w][table.getn(tableau[w])]
  441.                   if selectedCards[1].color ~= topCard.color and selectedCards[1].value == topCard.value-1 then
  442.                     removeSelectedCardsFrom(previousLocation)
  443.                     moveCardsTo(tableau[w])
  444.                     if selectedColumn == "discardPile" then
  445.                       renderDiscardPile()
  446.                     end
  447.                     renderTableau(w)
  448.                   else
  449.                     deselect(previousLocation)
  450.                   end
  451.                 end
  452.               end
  453.             end
  454.             break
  455.           end
  456.         end
  457.         for f=1,4 do
  458.           if isWithinBounds(getBounds(foundations[f].win)) then
  459.             if selectedColumn == -1 * f then
  460.               playsound(sounds.deselect)
  461.               foundations[f]["selected"] = false
  462.               renderFoundations(f)
  463.               selectedColumn = 0
  464.               selectedCards = {}
  465.             elseif table.getn(selectedCards) == 1 then
  466.               previousLocation = nil
  467.               if selectedColumn == "discardPile" then
  468.                 previousLocation = discardPile.cards
  469.               else
  470.                 previousLocation = tableau[selectedColumn]
  471.               end
  472.               if selectedCards[1].value == 1 and foundations[f].suit == nil then
  473.                 foundations[f]["suit"] = selectedCards[1].suit
  474.                 foundations[f]["value"] = 1
  475.                 removeSelectedCardsFrom(previousLocation)
  476.                 renderFoundations(f)
  477.                 if selectedColumn ~= "discardPile" then
  478.                   renderTableau(seletedColumn)
  479.                 end
  480.                 selectedCards = {}
  481.                 selectedColumn = 0
  482.               elseif foundations[f].suit ~= nil then
  483.                 if foundations[f].suit == selectedCards[1].suit and foundations[f].value == selectedCards[1].value-1 then
  484.                   foundations[f]["value"] = foundations[f].value+1
  485.                   removeSelectedCardsFrom(previousLocation)
  486.                   renderFoundations(f)
  487.                   if selectedColumn ~= "discardPile" then
  488.                     renderTableau(selectedColumn)
  489.                   end
  490.                   selectedCards = {}
  491.                   selectedColumn = 0
  492.                 end
  493.               end
  494.             elseif foundations[f].value ~= nil and table.getn(selectedCards) == 0 then
  495.               playsound(sounds.pickCard)
  496.               if foundations[f].suit == 1 or foundations[f].suit == 4 then
  497.                 c = "R"
  498.               else
  499.                 c = "B"
  500.               end
  501.               table.insert(selectedCards,1,{value=foundations[f].value,suit=foundations[f].suit,faceUp=true,selected=false,color=c})
  502.               selectedColumn = -1 * f
  503.               foundations[f]["selected"] = true
  504.               renderFoundations(f)
  505.             end
  506.             break
  507.           end
  508.         end
  509.       end
  510.     elseif event == "key" then
  511.       if arg1 == keys.backspace then
  512.         continue = false
  513.         restart = false
  514.       end
  515.     end
  516.   end
  517. end
  518.  
  519. function tryToMoveToFoundation (pile)
  520.   card = nil
  521.   if pile == "discardPile" then
  522.     selectedColumn = "discardPile"
  523.     pile = discardPile.cards
  524.     card = discardPile.cards[1]
  525.   else
  526.     pile = tableau[selectedColumn]
  527.     card = tableau[selectedColumn][table.getn(tableau[selectedColumn])]
  528.   end
  529.   moveTo = -1
  530.   for f=1,4 do
  531.     if foundations[f].suit == nil and card.value == 1 then
  532.       moveTo = f
  533.       foundations[f]["value"] = 1
  534.       foundations[f]["suit"] = card.suit
  535.       table.insert(selectedCards,1,card)
  536.       renderFoundations(f)
  537.       break
  538.     elseif foundations[f].suit ~= nil then
  539.       if foundations[f].suit == card.suit and foundations[f].value == card.value-1 then
  540.         moveTo = f
  541.         foundations[f]["value"] = foundations[f].value + 1
  542.         table.insert(selectedCards,1,card)
  543.         renderFoundations(f)
  544.       end
  545.     end
  546.   end
  547.   if moveTo ~= -1 then
  548.     playsound(sounds.moveCard)
  549.     if selectedColumn == "discardPile" then
  550.       removeSelectedCardsFrom()
  551.     else
  552.       table.remove(tableau[selectedColumn],table.getn(tableau[selectedColumn]))
  553.       renderTableau(selectedColumn)
  554.     end
  555.   end
  556.   selectedColumn = 0
  557.   selectedCards = {}
  558. end
  559.  
  560. function removeSelectedCardsFrom (location)
  561.   if selectedColumn == "discardPile" then
  562.     table.remove(discardPile.cards,1)
  563.     renderDiscardPile()
  564.   else
  565.     for i=1,table.getn(selectedCards) do
  566.       table.remove(location,table.getn(location))
  567.     end
  568.     renderTableau(selectedColumn)
  569.   end
  570. end
  571.  
  572. function deselect (location)
  573.   --playsound("note.harp")
  574.   --printerror("test",selectedColumn)
  575.   if selectedColumn == "discardPile" then
  576.     discardPile.cards[1]["selected"] = false
  577.     --renderDiscardPile()
  578.   elseif selectedColumn > 0 then
  579.     --playsound("note.harp",1.32)
  580.     for i=1,table.getn(location) do
  581.       location[i]["selected"] = false
  582.     end
  583.     renderTableau()
  584.   else
  585.     foundations[-1*selectedColumn]["selected"] = false
  586.     renderFoundations(-1*selectedColumn)
  587.   end
  588.   selectedCards = {}
  589.   selectedColumn = 0
  590. end
  591.  
  592. function moveCardsTo (location)
  593.   for i=1,table.getn(selectedCards) do
  594.     selectedCards[i]["selected"] = false
  595.     table.insert(location,table.getn(location)+1,selectedCards[i])
  596.   end
  597.   selectedCards = {}
  598.   selectedColumn = 0
  599. end
  600.  
  601. xPos,yPos = -1,-1
  602. --takes table in form {xMin,yMin,xMax,yMax}
  603. function isWithinBounds (bounds)
  604.   xMin = bounds[1]
  605.   yMin = bounds[2]
  606.   xMax = bounds[3]
  607.   yMax = bounds[4]
  608.   return (xPos >= xMin and xPos <= xMax and yPos <= yMax and yPos >= yMin)
  609. end
  610.  
  611. function getBounds (win)
  612.   xMin,yMin = win.getPosition()
  613.   winWidth,winHeight = win.getSize()
  614.   xMax = xMin+winWidth-1
  615.   yMax = yMin+winHeight-1
  616.   return {xMin,yMin,xMax,yMax}
  617. end
  618.  
  619. restart = true
  620. repeat
  621.   playGame()
  622. until restart == false
  623.  
  624. term.setBackgroundColor(colors.black)
  625. term.setTextColor(colors.white)
  626. term.clear()
  627. term.setCursorPos(1,1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement