Advertisement
billysback

rune

Sep 22nd, 2013
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.86 KB | None | 0 0
  1. local function createMatrix(xs, ys)
  2.     local matrix = {}
  3.     for x=1,xs do
  4.         matrix[x] = {}
  5.         for y=1,ys do
  6.             matrix[x][y] = 0
  7.         end
  8.     end
  9.     matrix.size = {xs, ys}
  10.     matrix.values = {}
  11.     matrix.setValue = function(self, is, name, cap)
  12.         local value = {}
  13.         value.inds = is
  14.         value.name = name
  15.         value.matrix = self
  16.         value.cap = cap
  17.         value.getValue = function(self)
  18.             local val = 0
  19.             for i=1,#self.inds do
  20.                 local ind = self.inds[i]
  21.                 local pos = self.matrix:getPos(ind)
  22.                 local v = self.matrix[pos[1]][pos[2]]
  23.                 if self.cap ~= nil then
  24.                     if v > self.cap then
  25.                         self.matrix[pos[1]][pos[2]] = self.cap
  26.                         v = self.cap
  27.                     end
  28.                 end
  29.                 val = val + v
  30.             end
  31.             return val
  32.         end
  33.         value.add = function(self, amt)
  34.             while amt ~= 0 do
  35.                 if amt > 0 then
  36.                     local possible = {}
  37.                     for i=1,#self.inds do
  38.                         local ind = self.inds[i]
  39.                         local pos = self.matrix:getPos(ind)
  40.                         local v = self.matrix[pos[1]][pos[2]]
  41.                         if self.cap ~= nil then
  42.                             if v < self.cap then possible[#possible + 1] = pos end
  43.                         else possible[#possible + 1] = pos end
  44.                     end
  45.                     if #possible > 0 then
  46.                         local pos = possible[math.random(#possible)]
  47.                         matrix[pos[1]][pos[2]] = matrix[pos[1]][pos[2]] + 1
  48.                     end
  49.                     amt = amt - 1
  50.                 elseif amt < 0 then
  51.                     local possible = {}
  52.                     for i=1,#self.inds do
  53.                         local ind = self.inds[i]
  54.                         local pos = self.matrix:getPos(ind)
  55.                         local v = self.matrix[pos[1]][pos[2]]
  56.                         if v > 0 then possible[#possible + 1] = pos end
  57.                     end
  58.                     if #possible > 0 then
  59.                         local pos = possible[math.random(#possible)]
  60.                         matrix[pos[1]][pos[2]] = matrix[pos[1]][pos[2]] - 1
  61.                     end
  62.                     amt = amt + 1
  63.                 end
  64.             end
  65.         end
  66.         self.values[name] = value
  67.         return value
  68.     end
  69.     matrix.getValue = function(self, name)
  70.         return self.values[name]
  71.     end
  72.     matrix.getIndex = function(self, x, y)
  73.         local index = 0
  74.         index = (self.size[1]*(x-1)) + y
  75.         return index
  76.     end
  77.     matrix.getPos = function(self, index)
  78.         local x = 1
  79.         local y = index%self.size[1]
  80.         local i = index - y
  81.         x = math.floor(i/self.size[1])
  82.         return {x, y}
  83.     end
  84.     matrix.getCode = function(self)
  85.         local code = 0
  86.         for x=1,self.size[1] do
  87.             for y=1,self.size[2] do
  88.                 code = code + self[x][y]
  89.             end
  90.         end
  91.         return code
  92.     end
  93.     matrix.place = function(self)
  94.    
  95.     end
  96.     matrix.addM = function(self, matrix)
  97.         local size = {self.size[1], self.size[2]}
  98.         if matrix.size[1] < self.size[1] then size[1] = matrix.size[1] end
  99.         if matrix.size[2] < self.size[2] then size[2] = matrix.size[2] end
  100.         local nmat = createMatrix(size[1], size[2])
  101.         for x=1,size[1] do
  102.             for y=1,size[2] do
  103.                 nmat[x][y] = self[x][y] + matrix[x][y]
  104.             end
  105.         end
  106.         nmat.values = self.values
  107.         return nmat
  108.     end
  109.    
  110.     local mt = {
  111.         __tostring = function(t)
  112.             return "matrix"
  113.         end,
  114.         __add = function(lhs, rhs)
  115.             if tostring(lhs) == "matrix" and tostring(rhs) == "matrix" then
  116.                 lhs:place()
  117.                 return lhs:addM(rhs)
  118.             else
  119.                 local t1 = type(lhs)
  120.                 local t2 = type(rhs)
  121.                 if tostring(lhs) == "matrix" then t1 = "matrix" end
  122.                 if tostring(rhs) == "matrix" then t2 = "matrix" end
  123.                 error("error adding "..t1.." to "..t2)
  124.             end
  125.         end
  126.     }
  127.     setmetatable(matrix, mt)
  128.     return matrix
  129. end
  130.  
  131. --[[
  132.  -| : health
  133. -- x: damage
  134. + |-: ???
  135. ]]
  136.  
  137. local form = {{ " ", colors.white, colors.black },
  138.               { "-", colors.white, colors.black },
  139.               { "|", colors.white, colors.black },
  140.               { "+", colors.white, colors.black },
  141.               { "x", colors.white, colors.black }}
  142. local function drawMatrix(p, matrix, col)
  143.     for i=1,matrix:getIndex(matrix.size[1], matrix.size[2]) do
  144.         local pos = matrix:getPos(i)
  145.         local i = matrix[pos[1]][pos[2]]
  146.         local text = form[i+1]
  147.         if col ~= nil then
  148.             for i=1,#text do
  149.                 if col[i] ~= nil then text[i] = col[i] end
  150.             end
  151.         end
  152.         if text == nil then text = {" ", colors.white, colors.red} end
  153.         term.setCursorPos(pos[1]+p[1]-1, pos[2]+p[2]-1)
  154.         term.setBackgroundColor(text[2])
  155.         term.setTextColor(text[3])
  156.         term.write(text[1])
  157.     end
  158. end
  159.  
  160. local power_names =
  161. {"glitched", "novice", "weak", "student", "apprentice",
  162.  "working", "average", "modest", "strong",
  163.  "professional", "expert", "master", "ultimate", "impossible"}
  164. local health_names =
  165. {"shielded", "protected", "resistant", "tanky", "immortal"}
  166. local damage_names =
  167. {"soldier", "knight", "archer", "wizard", "sorcerer", "god"}
  168. local function generateName(rune)
  169.     local power = rune:getCode()
  170.     local pname = power_names[math.max(power/3)+1].." "
  171.     -- power-name [health-class] damage-class
  172.     local hname = ""
  173.     local hclass = math.floor(rune:getValue("health"):getValue()/4)
  174.     if hclass > 0 then
  175.         hname = health_names[hclass].." "
  176.     end
  177.    
  178.     local dname = damage_names(math.max(rune:getValue("damage"):getValue()/4))
  179.     local name = pname..hname..dname
  180. end
  181.  
  182. local etyps = {
  183. ["death"] = {1, "damage"},
  184. ["death"] = {2, "heal"},
  185. ["place"] = {3, "damage"},
  186. ["place"] = {4, "heal"}
  187. }
  188. local function runEvent(rune, event)
  189.     local typ = rune:getValue("eve_type"):getValue()
  190.     local amt = rune:getValue("eve_amount"):getValue()
  191.    
  192.     local ename = etyps[event]
  193.     if ename ~= nil then
  194.         if typ == ename[1] then
  195.             local eve = ename[2]
  196.             if eve == "damage" then
  197.                 local deck = rune.deck
  198.                 if deck.enemy ~= nil then
  199.                     local edeck = deck.enemy
  200.                     if #edeck.shown > 0 then
  201.                         for i=1,#edeck.shown do
  202.                             local rune = edeck.shown[i]
  203.                             rune:getValue("health"):add(-amt)
  204.                             rune:check()
  205.                         end
  206.                     else
  207.                         edeck.health = edeck.health - amt
  208.                         edeck:check()
  209.                     end
  210.                 end
  211.             elseif eve == "heal" then
  212.                 if #deck.shown > 0 then
  213.                     for i=1,#deck.shown do
  214.                         local rune = deck.shown[i]
  215.                         rune:getValue("health"):add(amt)
  216.                     end
  217.                 end
  218.             end
  219.         end
  220.     end
  221. end
  222.  
  223. local function createRune(code, deck)
  224.     local matrix = createMatrix(4, 3)
  225.     for x=1,string.len(code) do
  226.         local i = code:sub(x, x)
  227.         local pos = matrix:getPos(x)
  228.         matrix[pos[1]][pos[2]] = i
  229.     end
  230.     matrix:setValue({1, 2, 3, 4}, "health", 4)
  231.     matrix:setValue({5, 6, 7, 8}, "damage", 4)
  232.     matrix:setValue({9}, "eve_type", 4)
  233.     matrix:setValue({10, 11, 12}, "eve_amount", 4)
  234.     matrix.name = generateName(matrix)
  235.     matrix.defense = 0
  236.     matrix.hurt = false
  237.     matrix.used = false
  238.     matrix.place = function(self)
  239.         runEvent(self, "place")
  240.     end
  241.     matrix.death = function(self)
  242.         runEvent(self, "death")
  243.     end
  244.     matrix.damage = function(self, amt)
  245.         if self.defense > 0 then
  246.             amt = math.max(amt/2)
  247.             self:getValue("health"):add(-amt)
  248.             defense = defense - 1
  249.         else
  250.             self:getValue("health"):add(-amt)
  251.         end
  252.         self.hurt = true
  253.     end
  254.     matrix.check = function(self)
  255.         if self:getValue("health"):getValue() <= 0 then
  256.             local deck = self.deck
  257.             if #deck.shown > 0 then
  258.                 local nshown = {}
  259.                 for i=1,#deck.shown do
  260.                     local rune = deck.shown[i]
  261.                     if rune ~= self then
  262.                         nshown[#nshown + 1] = rune
  263.                     else
  264.                         self:death()
  265.                     end
  266.                 end
  267.                 deck.shown = nshown
  268.             end
  269.         end
  270.     end
  271.     matrix.deck = deck
  272.     return matrix
  273. end
  274.  
  275. local on = true
  276. local winner = "nobody"
  277.  
  278. local function createDeck(name)
  279.     local deck = {}
  280.     deck.runes = {}
  281.     deck.piles = {}
  282.     deck.shown = {}
  283.     deck.enemy = nil
  284.     deck.health = 100
  285.     deck.turn = 0
  286.     deck.name = name
  287.     deck.getValue = function(self, value)
  288.         local v = 0
  289.         for i=1,#shown do
  290.             local rune = shown[i]
  291.             v = v + rune:getValue(value):getValue()
  292.         end
  293.         return v
  294.     end
  295.     deck.addRune = function(self, rune)
  296.         self.runes[#self.runes + 1] = rune
  297.     end
  298.     deck.shuffle = function(self)
  299.         local nrunes = {}
  300.         for i=1,#self.runes do
  301.             table.insert(nrunes, math.random(#nrunes + 1), self.runes[i])
  302.         end
  303.         self.runes = nrunes
  304.     end
  305.     deck.split = function(self, n)
  306.         local piles = {}
  307.         local curn = 1
  308.         for i=1,#self.runes do
  309.             if piles[curn] == nil then piles[curn] = {} end
  310.            
  311.             local pile = piles[curn]
  312.             pile[#pile + 1] = self.runes[i]
  313.            
  314.             curn = curn + 1
  315.             if curn >= n then curn = 1 end
  316.         end
  317.         self.piles = piles
  318.         for i=1,#piles do
  319.             local pile = piles[i]
  320.             local rune = pile[#pile]
  321.             self.shown[#self.shown + 1] = rune
  322.             pile[#pile] = nil
  323.         end
  324.     end
  325.     deck.sort = function(self, n)
  326.         self:shuffle()
  327.         self:split(n)
  328.     end
  329.     deck.placeRune = function(self, pileID, shownID)
  330.         if turn > 0 then
  331.             local pile = pileID
  332.             if type(pile) == "number" then pile = self.pile[pileID] end
  333.             local shown = shownID
  334.             if type(shown) == "number" then shown = self.shown[shownID] end
  335.             if pile ~= nil and shown ~= nil then
  336.                 local rune = pile[#pile]
  337.                 self.shown[shownID] = shown + rune
  338.                 pile[#pile] = nil
  339.                 turn = turn - 1
  340.                 return true
  341.             elseif pile ~= nil and shown == nil then
  342.                 local rune = pile[#pile]
  343.                 self.shown[shownID] = rune
  344.                 pile[#pile] = nil
  345.                 turn = turn - 1
  346.                 return true
  347.             end
  348.         end
  349.         return false
  350.     end
  351.     deck.attack = function(self, shownID, enemyID)
  352.         if turn > 0 then
  353.             if self.enemy ~= nil then
  354.                 local erune = enemyID
  355.                 if type(erune) == "number" then erune = self.enemy.shown[enemyID] end
  356.                 local rune = shownID
  357.                 if type(rune) == "number" then rune = self.shown[shownID] end
  358.                 if erune ~= nil and rune ~= nil then
  359.                     erune:damage(rune:getValue("damage"))
  360.                     rune.used = true
  361.                     turn = turn - 1
  362.                     return true
  363.                 end
  364.             end
  365.         end
  366.         return false
  367.     end
  368.     deck.defend = function(self, shownID)
  369.         if turn > 0 then
  370.             local rune = shownID
  371.             if type(rune) == "number" then rune = self.shown[shownID] end
  372.             if rune ~= nil then
  373.                 rune.defense = rune.defense + 1
  374.             end
  375.         end
  376.     end
  377.     deck.check = function(self)
  378.         if self.healh <= 0 then
  379.             on = false
  380.             winner = self.name
  381.         end
  382.     end
  383. end
  384.  
  385. local deck = createDeck("you")
  386. local edeck = createDeck("enemy")
  387.  
  388. local function getRuneID(name)
  389.     local nm = name:sub(1, -3)
  390.     local id = tonumber(name:sub(-1, -1))
  391.     if nm == "enemy_card" then
  392.         return edeck, edeck.shown[id], "card", id
  393.     elseif nm == "player_card" then
  394.         return deck, deck.shown[id], "card", id
  395.     elseif nm == "player_pile" then
  396.         local pile = deck.piles[id]
  397.         local rune = pile[#pile]
  398.         return deck, rune, "pile", id
  399.     end
  400.     return deck, deck.shown[id], "card"
  401. end
  402.  
  403. local tooltip = "Welcome to Runes!"
  404.  
  405. local gui = {
  406.     {"enemy_card_1", {3, 3}, {3, 3}, "An enemy rune, left click to attack"},
  407.     {"enemy_card_2", {7, 3}, {3, 3}, "An enemy rune, left click to attack"},
  408.     {"enemy_card_3", {11, 3}, {3, 3}, "An enemy rune, left click to attack"},
  409.     {"player_card_1", {3, 8}, {3, 3}, "Your rune, left click to use"},
  410.     {"player_card_2", {7, 8}, {3, 3}, "Your rune, left click to use"},
  411.     {"player_card_3", {11, 8}, {3, 3}, "Your rune, left click to use"},
  412.     {"player_pile_1", {3, 12}, {3, 4}, "Your deck, left click to use"},
  413.     {"player_pile_2", {7, 12}, {3, 4}, "Your deck, left click to use"},
  414.     {"player_pile_3", {11, 12}, {3, 4}, "Your deck, left click to use"},
  415. }
  416.  
  417. local background =
  418. {"2~~~~~~~~~~~~~1  _____                             ",
  419. "$.%%%.%%%.%%%.$ /     \\__                          ",
  420. "$%***%***%***%$ |Runes/  \\                         ",
  421. "$%***%***%***%$ \\_____|by|__                       ",
  422. "$%***%***%***%$  /    \\__/  \\                      ",
  423. "$#%^%#%^%#%^%#$ | billysback|                      ",
  424. "$#%^%#%^%#%^%#$  \\__________/                      ",
  425. "$%***%***%***%$                                    ",
  426. "$%***%***%***%$  v  ____  v                        ",
  427. "$%***%***%***%$ >% / || \\ %<                       ",
  428. "$.%%%.%%% %%%.$   /\\ __ /\\                         ",
  429. "$.***.***.***.$  |  X  X  |                        ",
  430. "$.***.***.***.$  |- |xx| -|                        ",
  431. "$.***.***.***.$  |  X__X  |                        ",
  432. "$.***.***.***.$   \\/    \\/                         ",
  433. "$.............$ >% \\_||_/ %<                       ",
  434. "1~~~~~~~~~~~~~2  ^        ^                        "}
  435.  
  436. local convert = {}
  437. convert["2"] = {colors.lightGray, colors.gray, "/"}
  438. convert["1"] = {colors.lightGray, colors.gray, "\\"}
  439. convert["$"] = {colors.gray, colors.lightGray, "|"}
  440. convert["~"] = {colors.gray, colors.lightGray, "-"}
  441. convert["%"] = {colors.gray, colors.orange}
  442. convert["."] = {colors.lightGray, colors.gray, " "}
  443. convert["*"] = {colors.black, colors.gray}
  444. convert["^"] = {colors.gray, colors.red}
  445. convert["v"] = {colors.gray, colors.red}
  446. convert[">"] = {colors.gray, colors.red}
  447. convert["<"] = {colors.gray, colors.red}
  448. convert["#"] = {colors.gray, colors.yellow}
  449. convert["/"] = {colors.white, colors.lightGray}
  450. convert["\\"] = {colors.white, colors.lightGray}
  451. convert["|"] = {colors.white, colors.lightGray}
  452. convert["_"] = {colors.white, colors.lightGray}
  453. convert["-"] = {colors.white, colors.lightGray}
  454. convert["X"] = {colors.white, colors.orange}
  455. convert[" "] = {colors.white, colors.lightGray}
  456.  
  457. local function drawImage()
  458.     term.setBackgroundColor(colors.black)
  459.     term.clear()
  460.     local lines = background
  461.     if #lines > 0 then
  462.         for y=1,#lines do
  463.             local line = lines[y]
  464.             for x=1,string.len(line) do
  465.                 local char = line:sub(x,x)
  466.                 term.setCursorPos(x,y+1)
  467.                 local col = convert[char]
  468.                 if col == nil then col = {colors.black, colors.white} end
  469.                 term.setBackgroundColor(col[1])
  470.                 term.setTextColor(col[2])
  471.                 if col[3] ~= nil then char = col[3] end
  472.                 term.write(char)
  473.             end
  474.         end
  475.     end
  476. end
  477.  
  478. local function draw()
  479.     drawImage()
  480.     for i=1,#gui do
  481.         local item = gui[i]
  482.         local pos = item[2]
  483.         local d, rune, typ = getRuneID(item[1])
  484.         if rune ~= nil then
  485.             local col = {nil, nil, nil}
  486.             if rune.defense > 0 then col[2] = colors.blue end
  487.             if d == edeck then col[3] = colors.purple end
  488.             if rune.hurt then
  489.                 col[3] = colors.red
  490.                 rune.hurt = false
  491.             end
  492.             if typ == "pile" then
  493.                 col[2] = colors.black
  494.                 col[3] = colors.white
  495.                 for x=1,3 do
  496.                     term.setCursorPos(pos[1]+x-1, pos[2]+3)
  497.                     term.setBackgroundColor(colors.gray)
  498.                     term.write(" ")
  499.                 end
  500.             end
  501.             drawMatrix(pos, rune, col)
  502.         end
  503.     end
  504.     if deck.turn > 0 then
  505.         for y=2,deck.turn+1 do
  506.             term.setCursorPos(1, y)
  507.             term.setBackgroundColor(colors.green)
  508.             term.write(" ")
  509.         end
  510.     end
  511. end
  512.  
  513. local function getButton(x, y)
  514.     for i=1,#gui do
  515.         local item = gui[i]
  516.         local pos = item[2]
  517.         local size = item[3]
  518.         if x >= pos[1] and y >= pos[2] and x < pos[1]+size[1] and y < pos[2]+size[2] then
  519.             return item
  520.         end
  521.     end
  522. end
  523.  
  524. local function getMaxVal(deck, val, pile)
  525.     local id = 1
  526.     local maxVal = 0
  527.     for i=1,3 do
  528.         local rune = nil
  529.         if pile then
  530.             local pile = deck.pile[i]
  531.             rune = pile[#pile]
  532.         else
  533.             rune = deck.shown[i]
  534.         end
  535.         if rune ~= nil then
  536.             if rune.used == false then
  537.                 local v = rune:getValue(val):getValue()
  538.                 if v > maxVal then
  539.                     v = maxVal
  540.                     id = i
  541.                 end
  542.             end
  543.         end
  544.     end
  545.     return id
  546. end
  547.  
  548.  
  549. local function doAI()
  550.     while edeck.turn > 0 do
  551.         if #edeck.shown <= 0 then
  552.             local id = getMaxVal(edeck, "health", true)
  553.            
  554.             edeck:placeRune(id, 1)
  555.         elseif #deck.shown <= 0 then
  556.             local id = getMaxVal(edeck, "damage", true)
  557.             local pile = edeck.piles[id]
  558.            
  559.             edeck:attack(pile[#pile], math.random(1, 3))
  560.         else
  561.             local health1 = edeck:getValue("health")
  562.             local damage1 = edeck:getValue("damage")
  563.             local health2 = deck:getValue("health")
  564.             local damage2 = deck:getValue("damage")
  565.             local turnDmg1 = math.floor((damage1/3)*2)
  566.             local turnDmg2 = math.floor((damage2/3)*2)
  567.             if health1 < turnDmg2 then
  568.                 local id = getMaxVal(edeck, "health", true)
  569.                 edeck:placeRune(id, math.random(1, 3))
  570.             elseif health2 < turnDmg1 then
  571.                 local id = getMaxVal(edeck, "damage", false)
  572.                 local rune = edeck.shown[id]
  573.                
  574.                 edeck:attack(rune, math.random(1, 3))
  575.             elseif damage1 < damage2 then
  576.                 local id = getMaxVal(edeck, "damage", true)
  577.                 edeck:placeRune(id, math.random(1, 3))
  578.             elseif health1 < health2 then
  579.                 local id = getMaxVal(edeck, "health", true)
  580.                 edeck:placeRune(id, math.random(1, 3))
  581.             else
  582.                 local id = getMaxVal(edeck, "damage", false)
  583.                 edeck:attack(id, math.random(1, 3))
  584.             end
  585.         end
  586.         draw()
  587.     end
  588. end
  589.  
  590. local function doTurn()
  591.     local selected = nil
  592.     while deck.turn > 0 do
  593.         local event, p1, p2, p3 = os.pullEvent()
  594.         if event == "mouse_click" then
  595.             local item = getButton(p2, p3)
  596.             if p1 == 1 then
  597.                 if selected == nil then selected = item
  598.                 else
  599.                     if selected == item then
  600.                         local d, rune, typ = getRuneID(item[1])
  601.                         d:defend(rune)
  602.                         selected = nil
  603.                     else
  604.                         local d1, rune1, typ1, id1 = getRuneID(item[1])
  605.                         local d2, rune2, typ2, id2 = getRuneID(selected[1])
  606.                         if d1 == deck and d2 == edeck then
  607.                             d1:attack(rune1, rune2)
  608.                             selected = nil
  609.                         elseif d1 == d2 and d1 == deck and typ1 == "pile" and typ2 == "card" then
  610.                             d1:placeRune(id1, rune2)
  611.                             selected = nil
  612.                         end
  613.                     end
  614.                 end
  615.             elseif p1 == 2 then
  616.                 tooltip = item[4]
  617.             end
  618.         end
  619.         draw()
  620.     end
  621. end
  622.  
  623. local player_turn = true
  624. local turns = 1
  625. while on do
  626.     if player_turn then
  627.         deck.turn = turns
  628.         doTurn()
  629.     else
  630.         edeck.turn = turns
  631.         doAI()
  632.     end
  633.     player_turn = (player_turn == false)
  634. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement