Advertisement
BombBloke

Card API (ComputerCraft)

May 4th, 2014
2,011
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 29.94 KB | None | 0 0
  1. -- +---------------------+------------+---------------------+
  2. -- |                     |            |                     |
  3. -- |                     |  Card API  |                     |
  4. -- |                     |            |                     |
  5. -- +---------------------+------------+---------------------+
  6.  
  7. local version = "Version 0.3.0"
  8.  
  9. -- A ComputerCraft API for card games, by Jeffrey Alexander (aka Bomb Bloke).
  10. -- http://www.computercraft.info/forums2/index.php?/topic/18480-bbcards
  11.  
  12. ---------------------------------------------
  13. ------------Variable Declarations------------
  14. ---------------------------------------------
  15.  
  16. local line = {{16,16,16,16,16},{16,16,17,16,16},{17,16,16,16,17},{17,16,17,16,17},{16,17,16,17,16}}   -- Row templates for numbered cards.
  17. local numbered = {{2,1,1,1,2},{2,1,2,1,2},{3,1,1,1,3},{3,1,2,1,3},{3,1,3,1,3},{3,2,3,1,3},            -- Numbered cards, 2-10.
  18.     {3,2,3,2,3},{4,1,4,1,4},{3,5,3,5,3}}
  19.  
  20. local freeCell = {{12,7,12,7,12,7,12},{7,16,16,16,16,16,7},{12,16,16,16,16,16,12},                    -- A free cell.
  21.     {7,16,16,16,16,16,7},{12,16,16,16,16,16,12},{7,16,16,16,16,16,7},{12,7,12,7,12,7,12}}
  22.  
  23. local ace, back, royal
  24. local value = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"}
  25. local suit = {["colour"] = {colours.black,colours.red,colours.black,colours.red}}
  26.  
  27. if _HOST then
  28.     ace = {{{{32,159,131,144,32},{159,129,32,130,144},{129,32,32,32,130},{144,135,32,139,159},{32,136,143,132,32}},
  29.     {"000f0","00f0f","0fff0","0ffff","0fff0"},{"0ff00","ffff0","fffff","f0f00","00000"}},  -- Spades.
  30.     {{{159,139,32,135,144},{151,129,32,32,32},{146,32,32,32,159},{130,32,32,32,129},{32,130,143,129,32}},
  31.     {"00006","60666","06666","66666","06660"},{"66060","06666","66660","06660","00000"}},  -- Hearts.
  32.     {{{32,135,131,139,32},{159,139,32,135,144},{32,130,32,129,32},{139,129,32,130,135},{32,136,143,132,32}},
  33.     {"00000","0ffff","f0f0f","fffff","0fff0"},{"0fff0","f0f00","fffff","00f00","00000"}},  -- Clubs.
  34.     {{{32,159,131,144,32},{159,32,32,32,144},{32,32,32,32,32},{130,32,32,32,129},{32,130,143,129,32}},
  35.     {"000e0","0eeee","eeeee","eeeee","0eee0"},{"0ee00","eeee0","eeeee","0eee0","00000"}}}  -- Diamonds.
  36.    
  37.     for j = 1, #ace do
  38.         local rows = ace[j][1]
  39.         for i = 1, 5 do rows[i] = string.char(unpack(rows[i])) end
  40.     end
  41.    
  42.     suit.symbol = {string.char(6),string.char(3),string.char(5),string.char(4)}
  43.    
  44.     -- Flipped cards (higher res):
  45.     back = {{{{150,131,131,131,131,131,150},{149,129,135,131,139,130,149},{149,140,32,140,32,140,149,},{149,135,32,136,137,137,149},
  46.         {149,159,129,32,32,32,149},{149,32,135,144,132,146,149},{154,143,143,143,143,143, 154}},
  47.         {"5555554","5e111ee","50b0b0b","5b3fff3","5339999","599ccc4","4444445"},
  48.         {"4411145","e144415","bbbbbb5","b333335","3999995","9944445","5555554"}},
  49.  
  50.         {{{150,131,131,131,131,131,150},{149,129,32,32,32,130,149},{149,129,131,131,131,130,149},{149,32,129,32,130,32,149},
  51.         {149,32,144,32,159,32,149},{149,144,143,143,143,159,149},{154,143,143,143,143,143,154}},
  52.         {"777777b","7300033","7011100","7414140","7414f40","7044440","b000007"},
  53.         {"b33e337","3000007","0144417","04f4f47","04f4147","0411107","777777b"}},
  54.        
  55.         {{{150,131,131,131,131,131,150},{149,32,32,159,140,153,149},{149,32,143,143,143,32,149},{149,158,148,32,32,130,149},
  56.         {149,138,129,32,32,32,149},{149,130,143,143,143,129,149},{154,143,143,143,143,143,154}},
  57.         {"ffffff7","f777847","f77f777","ff8ff77","f80fff7","ffffff7","777777f"},
  58.         {"777777f","777871f","77f7f7f","77fffff","7ffffff","777777f","ffffff7"}},
  59.        
  60.         {{{151,131,131,140,131,131,148},{149,129,32,32,32,130,149},{149,32,129,32,130,32,149},{149,32,136,32,132,32,149},
  61.         {149,32,144,32,159,32,149},{149,144,32,32,32,159,149},{138,143,143,140,143,143,133}},
  62.         {"888788e","8abbbae","8bb8bb7","8b88877","8bb87b7","8abbbbe","ee777ee"},
  63.         {"ee787e8","ebbbbb8","7b787b8","7b78778","7b78bb8","ebbbba8","8888888"}},
  64.        
  65.         {{{150,131,131,131,131,131,150},{149,156,140,140,140,147,149},{149,149,153,32,32,149,149},{149,149,32,32,32,149,149},
  66.         {149,138,143,143,143,133,149},{149,143,143,143,141,142,149},{154,143,143,143,143,143,154}},
  67.         {"777777f","74444ff","740ffff","71fffff","7ffffff","744444f","ffffff7"},
  68.         {"ffffff7","fffff47","fffff47","fffff17","f444447","ffffff7","777777f"}},
  69.        
  70.         {{{150,131,131,131,131,131,150},{149,129,130,143,129,130,149},{149,151,129,32,32,32,149},{149,130,32,32,32,32,149},
  71.         {149,148,32,32,32,151,149},{149,32,139,32,135,32,149},{154,143,143,143,143,143,154}},
  72.         {"2222226","2444446","2e0eeee","20eeeee","24eeee6","24eee46","6666662"},
  73.         {"6666662","6eeeee2","e0eeee2","eeeeee2","6eeee42","644e442","2222226"}},
  74.        
  75.         {{{150,131,131,131,131,131,150},{149,158,32,140,32,146,149},{149,32,132,153,136,32,149},{149,145,153,140,153,157,149},
  76.         {149,32,132,153,136,32,149},{149,146,32,140,32,158,149},{154,143,143,143,143,143,154}},
  77.         {"777777b","79bbbbb","7bbbbb9","7b9bb3b","7bbbbb9","7bbbb9b","bbbbbb7"},
  78.         {"bbbbbb7","bbb3b97","9b393b7","b3b39b7","9b393b7","b9b3bb7","777777b"}},
  79.        
  80.         {{{150,131,131,131,131,131,150},{149,159,131,131,131,144,149},{149,129,150,32,32,130,149},{149,139,143,131,143,135,149},
  81.         {149,144,32,131,32,159,149},{149,130,143,143,143,129,149},{154,143,143,143,143,143,154}},
  82.         {"ccccccb","cb9b9c9","c90ee9b","ceeeee9","c90700b","c800089","b9b9b9c"},
  83.         {"b9b9b9c","9ceeebc","beeeeec","9ff7ffc","b00009c","9b9b9bc","ccccccb"}}}
  84.    
  85.     for j = 1, #back do
  86.         local rows = back[j][1]
  87.         for i = 1, 7 do rows[i] = string.char(unpack(rows[i])) end
  88.     end
  89.    
  90.     royal = {{{{144,146,130,32,32},{159,129,32,135,32},{129,129,133,132,32},{132,132,131,159,144},{144,131,131,159,129}},
  91.         {"0e000","0e440","04f60","0a60e","03344"},{"ece00","44400","46600","fff46","14100"}},  -- Jack.
  92.         {{{144,139,32,32,32},{159,129,130,144,32},{159,151,133,132,32},{151,132,131,159,144},{144,131,131,159,129}},
  93.         {"00000","000e0","ecf60","c8602","0aadd"},{"44000","eee00","c6600","fffd6","bdb00"}},  -- Queen.
  94.         {{{146,143,158,32,32},{129,133,133,32,32},{144,129,133,132,32},{136,130,131,159,144},{144,131,131,159,129}},
  95.         {"0e400","08800","07f60","9660a","01133"},{"44000","77700","76600","fff36","e3e00"}}}  -- King.
  96.    
  97.     for j = 1, #royal do
  98.         local rows = royal[j][1]
  99.         for i = 1, 5 do rows[i] = string.char(unpack(rows[i])) end
  100.     end
  101. else
  102.     ace = {{{16,16,15,16,16},{16,15,15,15,16},{15,15,15,15,15},{15,16,15,16,15},{16,16,15,16,16}},  -- Spades.
  103.         {{16,6,16,6,16},{6,6,6,6,6},{6,6,6,6,6},{16,6,6,6,16},{16,16,6,16,16}},                 -- Hearts.
  104.         {{16,7,7,7,16},{16,16,7,16,16},{7,16,7,16,7},{7,7,7,7,7},{16,16,7,16,16}},              -- Clubs.
  105.         {{16,16,14,16,16},{16,14,14,14,16},{14,14,14,14,14},{16,14,14,14,16},{16,16,14,16,16}}} -- Diamonds.
  106.    
  107.     suit.symbol = {"^","v","+","<"}
  108.    
  109.     -- Flipped cards (lower res):
  110.     back = {{"bbbbbbb","b3b3b3b","bb3b3bb","b3b3b3b","bb3b3bb","b3b3b3b","bbbbbbb"},
  111.     {"4111114","e14441e","bbbbbbb","b333333","3399999","9944444","4444444"},
  112.     {"ffeeeff","0000000","0444440","04f4f40","04f4f40","0444440","0000000"},
  113.     {"8888888","8f0fff8","8ff0ff8","8f0fff8","8fffff8","8fffff8","8888888"},
  114.     {"8d5d8d5","5ffdff8","dffdffc","5ddfd5d","d8fffdd","8dfdfd8","5cddd5d"},
  115.     {"9977799","9bbbbb9","7b777b7","7b77777","7b777b7","9bbbbb9","9977799"},
  116.     {"77778e7","7778777","77fff77","7fffff7","7fffff7","77fff77","7777777"},
  117.     {"7ee7ee7","e0eeeee","eeeeeee","eeeeeee","7eeeee7","77eee77","777e777"}}
  118.    
  119.     for i = 1, #back do for y = 1, 7 do
  120.         local temp = {}
  121.         for x = 1, 7 do if back[i][y]:byte(x) < 58 then temp[x] = back[i][y]:byte(x) - 48 else temp[x] = back[i][y]:byte(x) - 87 end end
  122.         back[i][y] = temp
  123.     end end
  124.    
  125.     royal = {{{14,14,14,16,16},{16,4,4,16,16},{4,6,6,16,17},{15,15,15,16,14},{1,4,1,4,16}},      -- Jack.
  126.         {{4,4,16,16,16},{16,14,14,16,16},{14,6,6,16,17},{15,15,15,16,4},{11,13,11,13,16}},   -- Queen.
  127.         {{4,4,4,16,16},{7,7,7,16,16},{7,6,6,16,17},{15,15,15,16,10},{14,3,14,3,16}}}         -- King.
  128. end
  129.  
  130. local dealtCards, cell, cellWindow = 0, {}, {}
  131. local deck, cardBack, selected, resizeCell
  132.  
  133. local outline ={{156,140,140,140,140,140,148},{149, 32, 32, 32, 32, 32,149},{149, 32, 32, 32, 32, 32,149},{149, 32, 32, 32, 32, 32,149},
  134.     {149, 32, 32, 32, 32, 32,149},{149, 32, 32, 32, 32, 32,149},{141,140,140,140,140,140,133}}
  135.  
  136. for y = 1, 7 do for x = 1, 7 do outline[y][x] = string.char(outline[y][x]) end end
  137.  
  138. local BGColour, CardBGColour, selectionColour = colours.green, colours.white, colours.cyan
  139.  
  140. ---------------------------------------------
  141. ------------  Exposed Variables  ------------
  142. ---------------------------------------------
  143.  
  144. spade, heart, club, diamond, spades, hearts, clubs, diamonds, straight, up, left, down, right = 1, 2, 3, 4, 1, 2, 3, 4, 0, 1, 2, 3, 4
  145. victoryPile, drawPile, discardPile, temporary = 1, 2, 3, 4
  146.  
  147. ---------------------------------------------
  148. ------------Function Declarations------------
  149. ---------------------------------------------
  150.  
  151. local function drawSelectionRectangle()
  152.     local cellX1, cellY1 = cellWindow[deck[selected].cell].xPos, cellWindow[deck[selected].cell].yPos
  153.     local cellX2, cellY2 = cellX1 + cellWindow[deck[selected].cell].width, cellY1 + cellWindow[deck[selected].cell].height
  154.    
  155.     paintutils.drawLine(cellX1+deck[selected].xPos-2, cellY1+deck[selected].yPos-2, cellX2,                       cellY1+deck[selected].yPos-2, selectionColour)
  156.     paintutils.drawLine(cellX1+deck[selected].xPos-2, cellY1+deck[selected].yPos-1, cellX1+deck[selected].xPos-2, cellY2-1,                     selectionColour)   
  157.     paintutils.drawLine(cellX2,                       cellY1+deck[selected].yPos-1, cellX2,                       cellY2-1,                     selectionColour)   
  158.     paintutils.drawLine(cellX1+deck[selected].xPos-2, cellY2,                       cellX2,                       cellY2,                       selectionColour)
  159. end
  160.  
  161. local function drawCell(targetCell, xMin, yMin, xMax, yMax)
  162.     if not cellWindow[targetCell].visible then return end
  163.    
  164.     xMin = xMin or 1
  165.     yMin = yMin or 1
  166.     xMax = xMax or 7
  167.     yMax = yMax or 7
  168.  
  169.     resizeCell(targetCell,7,7)
  170.  
  171.     if _HOST then term.setBackgroundColor(BGColour) end
  172.     for y = yMin, yMax do
  173.         term.setCursorPos(cellWindow[targetCell].xPos+xMin-1,cellWindow[targetCell].yPos+y-1)
  174.         for x = xMin, xMax do
  175.             if _HOST then
  176.                 term.setTextColor(freeCell[y][x] == 16 and BGColour or bit.blshift(1,freeCell[y][x]))
  177.             else
  178.                 term.setBackgroundColor(freeCell[y][x] == 16 and BGColour or bit.blshift(1,freeCell[y][x]))
  179.             end
  180.             term.write(_HOST and outline[y][x] or " ")
  181.         end
  182.     end
  183. end
  184.  
  185. function renderCard(cardValue, cardSuit, xPos, yPos, cardFaceDown)
  186.     if cardFaceDown then
  187.         local back = back[cardBack]
  188.        
  189.         for y = 1, 7 do
  190.             term.setCursorPos(xPos,yPos+y-1)
  191.             if _HOST then
  192.                 term.blit(back[1][y], back[2][y], back[3][y])
  193.             else
  194.                 local row = back[y]
  195.                 for x = 1, 7 do
  196.                     term.setBackgroundColor(bit.blshift(1,row[x]))
  197.                     term.write(" ")
  198.                 end
  199.             end
  200.         end
  201.        
  202.         return
  203.     end
  204.    
  205.     local side = suit.symbol[cardSuit]..value[cardValue]..string.rep(" ",6-#value[cardValue])
  206.  
  207.     term.setTextColor(suit.colour[cardSuit])
  208.     term.setBackgroundColor(CardBGColour)
  209.    
  210.     for y = 1, 7 do
  211.         term.setCursorPos(xPos,yPos+y-1)
  212.         for x = 1, 7 do if y == 1 then
  213.             term.write(side)
  214.             break
  215.         elseif y == 7 then
  216.             term.write(side:reverse())
  217.             break
  218.         else if x == 1 then
  219.             term.write(side:sub(y,y))
  220.         elseif x == 7 then
  221.             term.write(side:reverse():sub(y,y))
  222.         else if cardValue == 1 then
  223.             local ace = ace[cardSuit]
  224.            
  225.             if _HOST then
  226.                 term.blit(ace[1][y-1]:sub(x-1,x-1),ace[2][y-1]:sub(x-1,x-1),ace[3][y-1]:sub(x-1,x-1))
  227.             else
  228.                 if ace[y-1][x-1] ~= 16 then
  229.                     term.setBackgroundColor(bit.blshift(1,ace[y-1][x-1]))
  230.                     term.write(" ")
  231.                     term.setBackgroundColor(CardBGColour)
  232.                 else term.write(" ") end
  233.             end
  234.         elseif cardValue > 10 then
  235.             local royal = royal[cardValue-10]
  236.            
  237.             if _HOST then
  238.                 if x == 6 and y == 4 then
  239.                     term.write(suit.symbol[cardSuit])
  240.                 else term.blit(royal[1][y-1]:sub(x-1,x-1),royal[2][y-1]:sub(x-1,x-1),royal[3][y-1]:sub(x-1,x-1)) end
  241.             else
  242.                 if royal[y-1][x-1] < 17 then
  243.                     if royal[y-1][x-1] < 16 then
  244.                         term.setBackgroundColor(bit.blshift(1,royal[y-1][x-1]))
  245.                         term.write(" ")
  246.                         term.setBackgroundColor(CardBGColour)
  247.                     else term.write(" ") end               
  248.                 else term.write(suit.symbol[cardSuit]) end
  249.             end
  250.         else term.write(line[numbered[cardValue-1][y-1]][x-1] == 16 and " " or suit.symbol[cardSuit]) end end end end
  251.     end
  252. end
  253.  
  254. local function drawCard(card, xMin, yMin, xMax, yMax)
  255.     if not cellWindow[deck[card].cell].visible then return end
  256.    
  257.     xMin = xMin or 1
  258.     yMin = yMin or 1
  259.     xMax = xMax or 7
  260.     yMax = yMax or 7
  261.    
  262.     if deck[card].faceDown then
  263.         local back = back[cardBack]
  264.        
  265.         for y = yMin, yMax do
  266.             term.setCursorPos(cellWindow[deck[card].cell].xPos+deck[card].xPos+xMin-2,cellWindow[deck[card].cell].yPos+deck[card].yPos+y-2)
  267.             if _HOST then
  268.                 term.blit(back[1][y]:sub(xMin, xMax), back[2][y]:sub(xMin, xMax), back[3][y]:sub(xMin, xMax))
  269.             else
  270.                 local row = back[y]
  271.                 for x = xMin, xMax do
  272.                     term.setBackgroundColor(bit.blshift(1,row[x]))
  273.                     term.write(" ")
  274.                 end
  275.             end
  276.         end
  277.        
  278.         return
  279.     end
  280.    
  281.     local side = suit.symbol[deck[card].suit]..value[deck[card].value]..string.rep(" ",6-#value[deck[card].value])
  282.  
  283.     term.setTextColor(suit.colour[deck[card].suit])
  284.     term.setBackgroundColor(CardBGColour)
  285.    
  286.     for y = yMin, yMax do
  287.         term.setCursorPos(cellWindow[deck[card].cell].xPos+deck[card].xPos+xMin-2,cellWindow[deck[card].cell].yPos+deck[card].yPos+y-2)
  288.         for x = xMin, xMax do if y == 1 then
  289.             term.write(side:sub(xMin,xMax))
  290.             break
  291.         elseif y == 7 then
  292.             term.write(side:reverse():sub(xMin,xMax))
  293.             break
  294.         else if x == 1 then
  295.             term.write(side:sub(y,y))
  296.         elseif x == 7 then
  297.             term.write(side:reverse():sub(y,y))
  298.         else if deck[card].value == 1 then
  299.             local ace = ace[deck[card].suit]
  300.            
  301.             if _HOST then
  302.                 term.blit(ace[1][y-1]:sub(x-1,x-1),ace[2][y-1]:sub(x-1,x-1),ace[3][y-1]:sub(x-1,x-1))
  303.             else
  304.                 if ace[y-1][x-1] ~= 16 then
  305.                     term.setBackgroundColor(bit.blshift(1,ace[y-1][x-1]))
  306.                     term.write(" ")
  307.                     term.setBackgroundColor(CardBGColour)
  308.                 else term.write(" ") end
  309.             end
  310.         elseif deck[card].value > 10 then
  311.             local royal = royal[deck[card].value-10]
  312.            
  313.             if _HOST then
  314.                 if x == 6 and y == 4 then
  315.                     term.write(suit.symbol[deck[card].suit])
  316.                 else term.blit(royal[1][y-1]:sub(x-1,x-1),royal[2][y-1]:sub(x-1,x-1),royal[3][y-1]:sub(x-1,x-1)) end
  317.             else
  318.                 if royal[y-1][x-1] < 17 then
  319.                     if royal[y-1][x-1] < 16 then
  320.                         term.setBackgroundColor(bit.blshift(1,royal[y-1][x-1]))
  321.                         term.write(" ")
  322.                         term.setBackgroundColor(CardBGColour)
  323.                     else term.write(" ") end               
  324.                 else term.write(suit.symbol[deck[card].suit]) end
  325.             end
  326.         else term.write(line[numbered[deck[card].value-1][y-1]][x-1] == 16 and " " or suit.symbol[deck[card].suit]) end end end end
  327.     end
  328. end
  329.  
  330. local function redrawCell(targetCell)
  331.     if not cellWindow[targetCell].visible then return end
  332.    
  333.     if cell[targetCell].visibleCards > 0 then
  334.         local temp = cell[targetCell].topCard
  335.         for j = 1, cell[targetCell].visibleCards do
  336.             drawCard(temp,1,1,cell[targetCell].stackDirection == left and 1 or 7, cell[targetCell].stackDirection == down and 1 or 7)
  337.             temp = deck[temp].onCard
  338.         end
  339.         if cell[targetCell].stackDirection ~= straight then drawCard(cell[targetCell].topCard,cell[targetCell].stackDirection == left and 2 or 1, cell[targetCell].stackDirection == down and 2 or 1, 7, 7) end
  340.     else drawCell(targetCell) end
  341. end
  342.  
  343. function redraw(x1, y1, x2, y2, ignoreSelected)
  344.     term.setBackgroundColor(BGColour)
  345.    
  346.     if not x1 then
  347.         term.clear()
  348.         for i = 1, #cell do redrawCell(i) end
  349.         if selected and not ignoreSelected then drawSelectionRectangle() end
  350.         return
  351.     end
  352.    
  353.     for y = y1, y2 do
  354.         term.setCursorPos(x1,y)
  355.         term.write(string.rep(" ", x2 - x1 + 1))
  356.     end
  357.    
  358.     for i = 1, #cell do if not (x1 > cellWindow[i].xPos + cellWindow[i].width - 1 or x2 < cellWindow[i].xPos or y1 > cellWindow[i].yPos + cellWindow[i].height - 1 or y2 < cellWindow[i].yPos) then
  359.         redrawCell(i)
  360.         if selected and deck[selected].cell == i and not ignoreSelected then drawSelectionRectangle() end
  361.     end end
  362. end
  363.  
  364. function resizeCell(targetCell, width, height)  -- Actually local via forward declaration.
  365.     local oldWidth, oldHeight = cellWindow[targetCell].width, cellWindow[targetCell].height
  366.     cellWindow[targetCell].width, cellWindow[targetCell].height = width, height
  367.     if width < oldWidth then redraw(cellWindow[targetCell].xPos+width, cellWindow[targetCell].yPos, cellWindow[targetCell].xPos+oldWidth-1, cellWindow[targetCell].yPos+height-1) end
  368.     if height < oldHeight then redraw(cellWindow[targetCell].xPos, cellWindow[targetCell].yPos+height, cellWindow[targetCell].xPos+oldWidth-1, cellWindow[targetCell].yPos+oldHeight-1) end
  369. end
  370.  
  371. function shuffle()
  372.     local pile, temp = {}
  373.     deck = {}
  374.     cardBack = math.random(#back)
  375.     dealtCards = 0
  376.    
  377.     for i = 1, 52 do pile[i] = i-1 end
  378.    
  379.     for i = 1, 52 do
  380.         temp = math.random(#pile)
  381.        
  382.         deck[i] = {["value"] = pile[temp]%13+1,
  383.             ["suit"] = math.floor(pile[temp]/13)+1,
  384.             ["faceDown"] = false}
  385.        
  386.         table.remove(pile,temp)
  387.     end
  388.    
  389.     term.setBackgroundColor(BGColour)
  390.     term.clear()
  391.     selected = nil
  392.    
  393.     for i = 1, #cell do
  394.         cell[i].visibleCards = 0
  395.         cell[i].topCard = nil
  396.         drawCell(i)
  397.     end
  398. end
  399.  
  400. function reset()
  401.     cell = {}
  402.     shuffle()
  403. end
  404.  
  405. function displayCell(targetCell, visible)
  406.     cellWindow[targetCell].visible = visible
  407.     if visible then redrawCell(targetCell) end
  408. end
  409.  
  410. function dealCard(targetCell, faceDown)
  411.     local thisCard = 52 - dealtCards
  412.    
  413.     deck[thisCard].cell = targetCell
  414.     deck[thisCard].faceDown = faceDown
  415.    
  416.     if cell[targetCell].topCard then
  417.         deck[thisCard].onCard = cell[targetCell].topCard
  418.         deck[cell[targetCell].topCard].underCard = thisCard
  419.     end
  420.    
  421.     cell[targetCell].topCard = thisCard
  422.     cell[targetCell].visibleCards = cell[targetCell].stackDirection == straight and 1 or (cell[targetCell].visibleCards + 1)
  423.     dealtCards = dealtCards + 1
  424.    
  425.     if deck[thisCard].onCard and cell[targetCell].stackDirection > 0 then
  426.         if cell[targetCell].stackDirection == left then
  427.             deck[thisCard].xPos = deck[deck[thisCard].onCard].xPos+1
  428.             deck[thisCard].yPos = deck[deck[thisCard].onCard].yPos
  429.             resizeCell(targetCell,cell[targetCell].visibleCards+6,7)
  430.         else
  431.             deck[thisCard].xPos = deck[deck[thisCard].onCard].xPos
  432.             deck[thisCard].yPos = deck[deck[thisCard].onCard].yPos+1
  433.             resizeCell(targetCell,7,cell[targetCell].visibleCards+6)
  434.         end
  435.     else deck[thisCard].xPos, deck[thisCard].yPos = 1, 1 end
  436.    
  437.     drawCard(thisCard)
  438. end
  439.  
  440. function getRemainingDeckSize() return 52 - dealtCards end
  441.  
  442. function save(gameType)
  443.     local cellPositions = {}
  444.     for i=1,#cellWindow do cellPositions[i] = {cellWindow[i].xPos, cellWindow[i].yPos} end
  445.     local saveData = {gameType,deck,cell,cellPositions}
  446.    
  447.     local saveFile = fs.open("bbcards.sav","w")
  448.     saveFile.writeLine(textutils.serialize(saveData))
  449.     saveFile.close()
  450. end
  451.  
  452. function load()
  453.     local saveFile = fs.open("bbcards.sav","r")
  454.     local saveData = textutils.unserialize(saveFile.readAll())
  455.     saveFile.close()
  456.    
  457.     deck = saveData[2]
  458.     cell = saveData[3]
  459.     local cellPositions, temp = saveData[4]
  460.    
  461.     term.setBackgroundColor(BGColour)
  462.     term.clear()
  463.     selected = nil
  464.    
  465.     cellWindow = {}
  466.    
  467.     for i = 1, #cell do
  468.         cellWindow[i] = {["xPos"] = cellPositions[i][1],
  469.             ["yPos"] = cellPositions[i][2],
  470.             ["width"] = cell[i].stackDirection == left and (6 + cell[i].visibleCards) or 7,
  471.             ["height"] = cell[i].stackDirection == down and (6 + cell[i].visibleCards) or 7,
  472.             ["visible"] = true}
  473.        
  474.         redrawCell(i)
  475.     end
  476.    
  477.     return saveData[1]
  478. end
  479.  
  480. function straightenCell(targetCell)
  481.     if cell[targetCell].visibleCards > 1 then
  482.         local curCard = cell[targetCell].topCard
  483.         for i=1,cell[targetCell].visibleCards-1 do
  484.             deck[curCard].xPos = 1
  485.             deck[curCard].yPos = 1
  486.             curCard = deck[curCard].onCard
  487.         end
  488.        
  489.         drawCard(cell[targetCell].topCard)
  490.         cell[targetCell].visibleCards = 1
  491.         resizeCell(targetCell,7,7)
  492.     end
  493. end
  494.  
  495. function defineCell(xPos, yPos, stackDirection, cellType, param1, param2)
  496.     local thisCell = #cell+1
  497.    
  498.     cell[thisCell] = {}
  499.     cell[thisCell].visibleCards = 0
  500.     cellWindow[thisCell] = {["xPos"] = xPos, ["yPos"] = yPos, ["width"]= 7, ["height"] = 7, ["visible"] = true}
  501.    
  502.     if cellType then
  503.         cell[thisCell].special = cellType
  504.        
  505.         if cellType == drawPile then
  506.             cell[thisCell].flipTo = param1
  507.             cell[thisCell].flipAmount = param2 
  508.         elseif cellType == temporary then
  509.             cell[thisCell].visible = false
  510.         end
  511.     end
  512.    
  513.     drawCell(thisCell)
  514.    
  515.     -- 0 = Straight, 2 = Left, 3 = Down. Up / Right aren't available.
  516.     if stackDirection then
  517.         if stackDirection ~= straight and stackDirection ~= left and stackDirection ~= down then
  518.             error("Invalid cell direction: Use either card.straight (0), card.left (2) or card.down (3).",2)
  519.         end
  520.        
  521.         cell[thisCell].stackDirection = stackDirection
  522.     else cell[thisCell].stackDirection = straight end
  523. end
  524.  
  525. local function shiftCards(thisCard, targetCell, faceDown)
  526.     local fromCell, amountMoving = deck[thisCard].cell
  527.    
  528.     if cell[fromCell].visibleCards > 1 then
  529.         if cell[fromCell].stackDirection == left then
  530.             amountMoving = cell[fromCell].visibleCards - deck[thisCard].xPos + 1
  531.             resizeCell(fromCell,cell[fromCell].visibleCards>amountMoving and (6+cell[fromCell].visibleCards-amountMoving) or 7,7)
  532.         else
  533.             amountMoving = cell[fromCell].visibleCards - deck[thisCard].yPos + 1
  534.             resizeCell(fromCell,7,cell[fromCell].visibleCards>amountMoving and (6+cell[fromCell].visibleCards-amountMoving) or 7)
  535.         end
  536.     else amountMoving = 1 end
  537.    
  538.     cell[fromCell].visibleCards = cell[fromCell].visibleCards - amountMoving
  539.    
  540.     if deck[thisCard].onCard then
  541.         cell[fromCell].topCard = deck[thisCard].onCard
  542.         deck[cell[fromCell].topCard].underCard = nil
  543.        
  544.         if cell[fromCell].visibleCards == 0 then
  545.             drawCard(cell[fromCell].topCard)
  546.             cell[fromCell].visibleCards = 1
  547.         else if cell[fromCell].stackDirection == left then drawCard(cell[fromCell].topCard,2) else drawCard(cell[fromCell].topCard,1,2) end end
  548.     else
  549.         cell[fromCell].topCard = nil
  550.         drawCell(deck[thisCard].cell)
  551.     end
  552.    
  553.     deck[thisCard].onCard = cell[targetCell].topCard
  554.     if cell[targetCell].topCard then deck[cell[targetCell].topCard].underCard = thisCard end
  555.    
  556.     if cell[targetCell].stackDirection ~= straight then
  557.         cell[targetCell].visibleCards = cell[targetCell].visibleCards + amountMoving
  558.         if cell[targetCell].topCard or amountMoving > 1 then if cell[targetCell].stackDirection == left then resizeCell(targetCell,cell[targetCell].visibleCards+6,7) else resizeCell(targetCell,7,cell[targetCell].visibleCards+6) end end
  559.     else cell[targetCell].visibleCards = 1 end
  560.    
  561.     for i = 1, amountMoving do
  562.         deck[thisCard].cell = targetCell
  563.         if type(faceDown) == "boolean" then deck[thisCard].faceDown = faceDown end
  564.        
  565.         if cell[targetCell].stackDirection == left then
  566.             deck[thisCard].xPos = deck[thisCard].onCard and (deck[deck[thisCard].onCard].xPos+1) or 1
  567.             deck[thisCard].yPos = deck[thisCard].onCard and (deck[deck[thisCard].onCard].yPos) or 1
  568.             drawCard(thisCard,1,1,1)
  569.         elseif cell[targetCell].stackDirection == down then
  570.             deck[thisCard].xPos = deck[thisCard].onCard and (deck[deck[thisCard].onCard].xPos) or 1
  571.             deck[thisCard].yPos = deck[thisCard].onCard and (deck[deck[thisCard].onCard].yPos+1) or 1
  572.             drawCard(thisCard,1,1,7,1)
  573.         else
  574.             deck[thisCard].xPos = 1
  575.             deck[thisCard].yPos = 1
  576.         end
  577.        
  578.         if deck[thisCard].underCard then thisCard = deck[thisCard].underCard end
  579.     end
  580.    
  581.     if cell[targetCell].stackDirection == left then drawCard(thisCard,2) elseif cell[targetCell].stackDirection == down then drawCard(thisCard,1,2) else drawCard(thisCard) end
  582.    
  583.     cell[targetCell].topCard = thisCard
  584. end
  585.  
  586. function moveTo(thisCard, targetCell, faceDown, skipAnimation)
  587.     if not skipAnimation then
  588.         local myTimer, oldCell, myEvent = os.startTimer(0.05), deck[thisCard].cell
  589.         local xStart, yStart, xDes, yDes = cellWindow[oldCell].xPos + deck[thisCard].xPos - 1, cellWindow[oldCell].yPos + deck[thisCard].yPos - 1
  590.        
  591.         if cell[targetCell].stackDirection ~= straight and cell[targetCell].topCard then
  592.             if cell[targetCell].stackDirection == left then
  593.                 xDes, yDes = cellWindow[targetCell].xPos + deck[cell[targetCell].topCard].xPos - 1, cellWindow[targetCell].yPos
  594.             else xDes, yDes = cellWindow[targetCell].xPos, cellWindow[targetCell].yPos + deck[cell[targetCell].topCard].yPos - 1 end
  595.         else xDes, yDes = cellWindow[targetCell].xPos, cellWindow[targetCell].yPos end
  596.        
  597.         local xPos1 = math.floor(xStart + (xDes - xStart) / 3)
  598.         local yPos1 = math.floor(yStart + (yDes - yStart) / 3)
  599.         local xPos2 = math.floor(xStart + (xDes - xStart) * 2 / 3)
  600.         local yPos2 = math.floor(yStart + (yDes - yStart) * 2 / 3)
  601.  
  602.         defineCell(xPos1, yPos1, cell[oldCell].stackDirection, temporary)
  603.         shiftCards(thisCard, #cell, faceDown)
  604.         local width = cell[#cell].visibleCards + 5
  605.         displayCell(#cell, true)
  606.  
  607.         repeat myEvent = {os.pullEvent()} until myEvent[1] == "timer" and myEvent[2] == myTimer
  608.         myTimer = os.startTimer(0.05)
  609.        
  610.         cellWindow[#cell].xPos = xPos2
  611.         cellWindow[#cell].yPos = yPos2
  612.         cellWindow[#cell].stackDirection = cell[targetCell].stackDirection
  613.         if cell[targetCell].stackDirection == straight then cell[#cell].visibleCards = 1 end
  614.         resizeCell(#cell, 1 + (cell[targetCell].stackDirection == left and width or 6), 1 + (cell[targetCell].stackDirection == down and width or 6))
  615.         redrawCell(#cell)
  616.         redraw(xPos1, yPos1, xPos1 + (cell[oldCell].stackDirection == left and width or 6), yPos1 + (cell[oldCell].stackDirection == down and width or 6))
  617.  
  618.         repeat myEvent = {os.pullEvent()} until myEvent[1] == "timer" and myEvent[2] == myTimer
  619.        
  620.         displayCell(#cell, false)
  621.         shiftCards(thisCard, targetCell, faceDown)
  622.         cell[#cell] = nil
  623.         redraw(xPos2, yPos2, xPos2 + (cell[targetCell].stackDirection == left and width or 6), yPos2 + (cell[targetCell].stackDirection == down and width or 6))
  624.     else shiftCards(thisCard, targetCell, faceDown) end
  625. end
  626.  
  627. function select(targetCard, hidden)
  628.     selected = targetCard
  629.     if not hidden then drawSelectionRectangle() end
  630. end
  631.  
  632. function getSelected() return selected end
  633.  
  634. function deselect()
  635.     if selected then
  636.         local cellX, cellY = cellWindow[deck[selected].cell].xPos, cellWindow[deck[selected].cell].yPos
  637.         redraw(cellX+deck[selected].xPos-2,cellY+deck[selected].yPos-2,cellX+cellWindow[deck[selected].cell].width,cellY+cellWindow[deck[selected].cell].height,true)
  638.         selected = nil
  639.     end
  640. end
  641.  
  642. function getSpecial(targetCell) return cell[targetCell].special end
  643.  
  644. function getTopCard(targetCell) return cell[targetCell].topCard end
  645.  
  646. function getTarget(targetCell) return cell[targetCell].flipTo end
  647.  
  648. function getFlipAmount(targetCell) return cell[targetCell].flipAmount end
  649.  
  650. function getValue(targetCard) return deck[targetCard].value end
  651.  
  652. function getSuit(targetCard) return deck[targetCard].suit end
  653.  
  654. function isFaceDown(targetCard) return deck[targetCard].faceDown end
  655.  
  656. function setFaceDown(targetCard, faceDown)
  657.     deck[targetCard].faceDown = faceDown
  658.     drawCard(targetCard)
  659. end
  660.  
  661. function getHigherCard(targetCard) return deck[targetCard].underCard end
  662.  
  663. function getLowerCard(targetCard) return deck[targetCard].onCard end
  664.  
  665. function checkClick(xPos,yPos)
  666.     local cellX1, cellY1, cellX2, cellY2   
  667.     for thisCell = 1, #cell do
  668.         cellX1, cellY1 = cellWindow[thisCell].xPos, cellWindow[thisCell].yPos
  669.         cellX2, cellY2 = cellX1 + cellWindow[thisCell].width - 1, cellY1 + cellWindow[thisCell].height - 1
  670.        
  671.         if xPos >= cellX1 and xPos <= cellX2 and yPos >= cellY1 and yPos <= cellY2 then
  672.             local thisCard = cell[thisCell].topCard
  673.            
  674.             if cell[thisCell].visibleCards > 1 then
  675.                 if cell[thisCell].stackDirection == left and xPos < cellX2 - 6 then
  676.                     for i = 1, cellX2-xPos-6 do thisCard = deck[thisCard].onCard end
  677.                 elseif cell[thisCell].stackDirection == down and yPos < cellY2 - 6 then
  678.                     for i = 1, cellY2-yPos-6 do thisCard = deck[thisCard].onCard end
  679.                 end
  680.             end
  681.            
  682.             return thisCard, thisCell
  683.         end
  684.     end
  685. end
  686.  
  687. function victoryAnimation(monSide)
  688.     local curCard, counter, xDir, yDir, myEvent = {}, 1, -(math.random(15) / 10 + 0.5), math.random(30) / 10
  689.     local xSize, ySize = term.getSize()
  690.    
  691.     for i = 1, #cell do if cell[i].special == victoryPile then curCard[#curCard+1] = getTopCard(i) end end
  692.     local xPos, yPos = cellWindow[deck[curCard[counter]].cell].xPos + deck[curCard[counter]].xPos - 1, cellWindow[deck[curCard[counter]].cell].yPos + deck[curCard[counter]].yPos - 1
  693.    
  694.     local myTimer = os.startTimer(0.05)
  695.     while true do
  696.         if xPos < -6 or xPos > xSize then
  697.             curCard[counter] = card.getLowerCard(curCard[counter])
  698.             counter = counter == #curCard and 1 or (counter + 1)
  699.            
  700.             if not curCard[counter] then return end
  701.            
  702.             xPos, yPos = cellWindow[deck[curCard[counter]].cell].xPos + deck[curCard[counter]].xPos - 1, cellWindow[deck[curCard[counter]].cell].yPos + deck[curCard[counter]].yPos - 1
  703.             xDir, yDir = -(math.random(15) / 10 + 0.5), math.random(30) / 10
  704.             if math.random(4) == 4 then xDir = -xDir end
  705.             if math.random(4) == 4 then yDir = -yDir end
  706.         end
  707.        
  708.         myEvent = {os.pullEvent()}
  709.        
  710.         if myEvent[1] == "timer" and myEvent[2] == myTimer then
  711.             renderCard(getValue(curCard[counter]), getSuit(curCard[counter]), math.floor(xPos), yPos > ySize - 6 and ySize - 6 or math.floor(yPos))
  712.             xPos, yPos = xPos + xDir, yPos + yDir
  713.             if yPos > ySize - 6 then yDir = -yDir else if yDir > 0 then yDir = yDir + 0.5 else yDir = yDir + 0.7 end end
  714.             myTimer = os.startTimer(0.05)
  715.         elseif myEvent[1] == "key" or myEvent[1] == "mouse_click" or (monSide and myEvent[1] == "monitor_touch" and monSide == myEvent[2]) then
  716.             return
  717.         end
  718.     end
  719. end
  720.  
  721. ---------------------------------------------
  722. ------------         Init        ------------
  723. ---------------------------------------------
  724.  
  725. if fs.exists("\\cards") and fs.isDir("\\cards") then
  726.     local fileList, myLine = fs.list("\\cards")
  727.    
  728.     for i = 1, #fileList do if not fs.isDir("\\cards\\"..fileList[i]) then
  729.         local myFile = fs.open("\\cards\\"..fileList[i],"r")
  730.  
  731.         back[#back+1] = {}
  732.         for y = 1, 7 do
  733.             back[#back][y] = {}
  734.             myLine = myFile.readLine()
  735.             for x = 1, 7 do if myLine:byte(x) < 58 then back[#back][y][x] = myLine:byte(x) - 48 else back[#back][y][x] = myLine:byte(x) - 87 end end
  736.         end
  737.        
  738.         myFile.close()
  739.     end end
  740. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement