Skip to content

Instantly share code, notes, and snippets.

@devilstower
Created April 29, 2012 02:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devilstower/2523657 to your computer and use it in GitHub Desktop.
Save devilstower/2523657 to your computer and use it in GitHub Desktop.
Battle Chips 0.40
Arena = class()
function Arena:init(l, b, r, t)
    self:sizeFrames(l, b, r, t)
    self.robots = {}
    self.timer = 0
end
function Arena:sizeFrames(l, b, r, t)
    self.frame = Frame(l, b, r, t)
    self.panel = Frame(l + 1, b + 1, r - 1, b + 108)
    self.stop = Frame(r - 70, b + 35, r - 30, b + 75)
end
function Arena:loadRobot(r)
    local i, nr
    nr = Robot(math.random(self.frame:width() - 90) + 30, 
    math.random(self.frame:height() - 150) + 90)
    nr.hp = r.hp
    nr.direction = math.random(4)
    for i = 1, table.maxn(r.program) do
        nr.program[i] = r.program[i]
    end
    nr.bounds = Frame(nr.x, nr.y,  nr.x + 60, nr.y + 60)
    nr.program = r.program
    nr.bump = false
    nr.radar = false
    nr.heat = 0
    nr.step = 1
    nr.wins = r.wins
    nr.losses = r.losses
    nr.name = r.name
    nr.repeatCounter = 1
    nr.points = 0
    nr.treadColor = r.treadColor
    nr.bodyColor = r.bodyColor
    nr.headColor = r.headColor
    nr.dishColor = r.dishColor
    nr.limits = self.frame
    i = table.maxn(self.robots) + 1
    self.robots[i] = nr
end
function Arena:clear()
    sound(SOUND_POWERUP, 2591)
    self.robots = {}
    self.timer = 0
end
function Arena:checkRadar(k, r)
    local i, robot
    r.radar = false
    for i, robot in ipairs(self.robots) do
        if i ~= k then
            if r.rf:overlaps(robot.bounds) and robot.hp > 0 then
                r.radar = true
            end
        end
    end
end
function Arena:checkLaser(k, r)
    local i, robot
    for i, robot in ipairs(self.robots) do
        if i ~= k then
            if r.rf:overlaps(robot.bounds) then
                if robot.hp > 0 then 
                    robot.hp = robot.hp - 1
                    r.points = r.points + 1
                    if robot.heat < 20 then 
                        robot.heat = robot.heat + 5
                    end
                end
            end
        end
    end
end
function Arena:checkCollisions(k, r)
    local i, robot
    for i, robot in ipairs(self.robots) do
        
        r.bounds:inset(-5, -5)
        if i ~= k then
            if r.bounds:overlaps(robot.bounds) then
                if robot.hp > 0 then r.bump = true end
            end
        end
        r.bounds:inset(5, 5)
    end
end
function Arena:setMatch(a, b, c, d)
    self.robots = {}
    self:loadRobot(a)
    self:loadRobot(b)
    self:loadRobot(c)
    self:loadRobot(d)
    self.timer = 100
end
function Arena:draw()
    local k, robot, liveCount
    
    pushStyle()
    fill(18, 18, 18, 255)
    self.frame:draw()
    fill(137, 126, 126, 255)
    c = color(48, 91, 137, 255)
    self.panel:inset(10, 10)
    self.panel:gloss(c)
    self.panel:inset(-10, -10)
    fill(255, 255, 255, 255)
    font("Futura-CondensedExtraBold")
    fontSize(36)
    text("Battle Chips",self.frame.left + 25, self.frame.bottom + 35)
    fill(156, 25, 28, 255)
    stroke(255, 255, 255, 255)
    self.stop:draw()
    pushMatrix()
    translate(self.frame.left, self.frame.bottom)
    liveCount = 0
    for k, robot in ipairs(self.robots) do
        if robot.hp > 0 then liveCount = liveCount + 1 end
        if robot.radarDelay > 0 then
            self:checkRadar(k, robot)
        end
        if robot.laserDelay == 5 then
            self:checkLaser(k, robot)
        end
        self:checkCollisions(k, robot)
        if robot.hp > 0 then 
            robot:run()
        end
        robot:draw()
    end
    if liveCount < 2 then 
        self.timer = self.timer - 1
    else
        self.timer = self.timer - 0.1
    end
    if self.timer < 0 then self.timer = 0 end
    popMatrix()
    font("Futura-Medium")
    fontSize(12)
    textMode(CENTER)
    for k, robot in ipairs(self.robots) do
        pushMatrix()
        translate(self.frame.right - k * 60 - 100, 
        self.frame.bottom + 50)
        scale(0.5)
        robot:drawBase()
        popMatrix()
        fill(136, 141, 149, 255)
        stroke(130, 154, 221, 255)
        rect(self.frame.right - k * 60 - 127, self.frame.bottom + 35,
        self.frame.right - k * 60 - 120, self.frame.bottom + 65)
        if robot.hp > 7 then 
            fill(72, 255, 0, 255)
        elseif robot.hp > 4 then
            fill(244, 255, 0, 255)
        else
            fill(255, 0, 13, 255)
        end
        noStroke()
        rect(self.frame.right - k * 60 - 126, self.frame.bottom + 36,
        self.frame.right - k * 60 - 121, self.frame.bottom + 36 +
        robot.hp * 3)
        fill(182, 130, 196, 255)
        text(robot.points, self.frame.right - k * 60 - 100, 
        self.frame.bottom + 20)
    end
    
    if tourney.isActive then 
        textMode(CORNER)
        font("Futura-CondensedExtraBold")
        fontSize(48)
        fill(149, 140, 140, 84)
        text("Tourney", self.frame.left + 15, self.frame.top - 70)
        text(math.floor(self.timer), 
        self.frame.left + 15, self.frame.bottom + 100)
    end
    
    popStyle()
end
function Arena:touched(touch)
    if self.frame:touched(touch) then
        return true
    end
    return false
end
Code = class()
function Code:init(short, long, hasValue, clr)
    -- you can accept and set parameters here
    self.short = short
    self.long = long
    self.hasValue = hasValue
    self.color = clr
end
CodeBench = class()
function CodeBench:init(x, y)
    -- you can accept and set parameters here
    self.x = x
    self.y = y
    self.frame = Frame(x, y, x + 500, y + 850)
    self.header = Frame(self.frame.left + 4, self.frame.top - 40,
    self.frame.right - 4, self.frame.top - 4)
    self.sockets = {}
    socket = 0
    for x = 1,2 do 
        for y = 15,1,-1 do
            socket = socket + 1
            self.sockets[socket] = 
            Socket(nil, x * 250 - 180, y * 45 + 72)
        end
    end
    self.selectedSocket = 0
    self.action = 0
    self.tokens = {}
end
function CodeBench:loadRobot(r)
    for i = 1,30 do
        self.sockets[i].code = nil
    end
    for i, p in ipairs(r.program) do
        self.sockets[i].code = p.code
        self.sockets[i].value = p.value
    end
end
function CodeBench:draw()
    pushStyle()
    fontSize(16)
    font("Futura-Medium")
    stroke(78, 128, 30, 255)
    fill(64, 154, 39, 107)
    strokeWidth(5)
    self.frame:draw()
    fill(125, 125, 125, 140)
    noStroke()
    self.header:draw()
    pushMatrix()
    translate(self.x, self.y)
    -- trace lines
    fill(255, 210, 0, 219)
    stroke(243, 191, 5, 153)
    strokeWidth(5)
    line(40, 96, 230, 96)
    line(230, 96, 230, 760)
    line(230, 760, 320, 760)
    line(290, 96, 290, 70)
    line(290, 70, 20, 70)
    line(20, 70, 20, 760)
    line(20, 760, 40, 760)
    socket = 1
    for x = 1,2 do 
        for y = 15,1,-1 do
            noStroke()
            fill(143, 143, 143, 255)
            rect(x * 250 - 210, y * 45 + 70, 
                 x * 250 - 30, y * 45 + 102)
            strokeWidth(2)
            stroke(82, 82, 82, 255)
            fill(212, 209, 205, 255)
            self.sockets[socket]:draw()
            
            noStroke()
            
            stroke(221, 175, 8, 164)
            strokeWidth(5)
            fill(89, 89, 31, 255)
            ellipse(x * 250 - 210, y * 45 + 86, 20)
            line(x * 250 - 210, y * 45 + 82, 
            x * 250 - 210, y * 45 + 50)
            fill(38, 38, 38, 255)
            text(socket, x * 250 - 200, y * 45 + 75)
            socket = socket + 1
        end
    end
    text("INSERT CHIPS TO BUILD PROGRAM", 10, 10)
    fill(255, 255, 255, 255)
    text("MAIN BOARD", 10, self.frame:height() - 30)
    popMatrix()
    popStyle()
end
function CodeBench:touched(touch)
    t =Ttouch(touch)
    t:translate(self.x, self.y - 10)
    self.action = 0
    for i = 1, table.maxn(self.sockets) do
        if self.sockets[i]:touched(t) then
            self.selectedSocket = i
            if self.sockets[i].code ~= nil then
                if t.x < self.sockets[i].frame:midX() or
                self.sockets[i].code.hasValue == false then
                    self.action = 1
                end
            end
            return true
        end
    end
    return false
end
DesignStudio = class()
function DesignStudio:init(l, b, r, t)
    -- you can accept and set parameters here
    self.frame = Frame(l, b, r, t)
    self.tb = TextBox(self.frame:midX() - 100, b + 50, 200, "")
    
    self.dishFrame = Frame(50, 900, 160, 924)
    self.dishShowSlider = false
    self.dishVCS = VColorSlider(self.dishFrame.left, self.dishFrame.top)
    
    self.headFrame = Frame(220, 900, 330, 924)
    self.headShowSlider = false
    self.headVCS = VColorSlider(self.headFrame.left, self.headFrame.top)
    
    self.bodyFrame = Frame(390, 900, 500, 924)
    self.bodyShowSlider = false
    self.bodyVCS = VColorSlider(self.bodyFrame.left, self.bodyFrame.top)
    
    self.treadFrame = Frame(560, 900, 670, 924)
    self.treadShowSlider = false
    self.treadVCS = VColorSlider(self.treadFrame.left,
     self.treadFrame.top)
    
end
function DesignStudio:setBot(bot)
    self.bot = bot
    self.tb.text = self.bot.name
end
function DesignStudio:draw()
    pushMatrix()
    font("Futura-Medium")
    fontSize(16)
    fill(107, 116, 122, 142)
    stroke(78, 83, 88, 255)
    strokeWidth(5)
    self.frame:draw()
    stroke(0, 38, 255, 255)
    strokeWidth(2)
    fill(185, 185, 185, 113)
    self.tb:draw()
    fill(255, 255, 255, 255)
    text("Dish", self.dishFrame.left, self.dishFrame.top)
    text("Head", self.headFrame.left, self.headFrame.top)
    text("Body", self.bodyFrame.left, self.bodyFrame.top)
    text("Treads", self.treadFrame.left, self.bodyFrame.top)
    
    fill(colors[self.bot.dishColor])
    self.dishFrame:draw()
    fill(colors[self.bot.headColor])
    self.headFrame:draw()
    fill(colors[self.bot.bodyColor])
    self.bodyFrame:draw()
    fill(colors[self.bot.treadColor])
    self.treadFrame:draw()
    
    if self.dishShowSlider then self.dishVCS:draw() end
    if self.headShowSlider then self.headVCS:draw() end
    if self.bodyShowSlider then self.bodyVCS:draw() end
    if self.treadShowSlider then self.treadVCS:draw() end
    
    translate(self.frame:midX() - 60, self.frame:height() - 80)
    scale(2)
    self.bot.x = 0
    self.bot.y = 0
    self.bot:draw()
    
    popMatrix()
end
function DesignStudio:touched(touch)
    self.bot.name = self.tb.text
    if self.dishFrame:touched(touch) then
        self.dishShowSlider = true
    end
    if self.dishShowSlider then
        if self.dishVCS:touched(touch) then
            self.bot.dishColor = self.dishVCS.selected
        end
    end
    if self.headFrame:touched(touch) then
        self.headShowSlider = true
    end
    if self.headShowSlider then
        if self.headVCS:touched(touch) then
            self.bot.headColor = self.headVCS.selected
        end
    end
    if self.bodyFrame:touched(touch) then
        self.bodyShowSlider = true
    end
    if self.bodyShowSlider then
        if self.bodyVCS:touched(touch) then
            self.bot.bodyColor = self.bodyVCS.selected
        end
    end
    if self.treadFrame:touched(touch) then
        self.treadShowSlider = true
    end
    if self.treadShowSlider then
        if self.treadVCS:touched(touch) then
            self.bot.treadColor = self.treadVCS.selected
        end
    end
end
Frame = class()
-- Frame 
-- ver. 1.0
-- a simple rectangle for holding controls.
-- ====================
function Frame:init(left, bottom, right, top)
    self.left = left
    self.right = right
    self.bottom = bottom
    self.top = top
end
function Frame:inset(dx, dy)
    self.left = self.left + dx
    self.right = self.right - dx
    self.bottom = self.bottom + dy
    self.top = self.top - dy
end
function Frame:offset(dx, dy)
    self.left = self.left + dx
    self.right = self.right + dx
    self.bottom = self.bottom + dy
    self.top = self.top + dy
end
    
function Frame:draw()
    pushStyle()
    rectMode(CORNERS)
    rect(self.left, self.bottom, self.right, self.top)
    popStyle()
end
function Frame:roundRect(r)
    pushStyle()
    insetPos = vec2(self.left + r,self.bottom + r)
    insetSize = vec2(self:width() - 2 * r,self:height() - 2 * r)
    rectMode(CORNER)
    rect(insetPos.x, insetPos.y, insetSize.x, insetSize.y)
    if r > 0 then
        smooth()
        lineCapMode(ROUND)
        strokeWidth(r * 2)
        line(insetPos.x, insetPos.y, 
             insetPos.x + insetSize.x, insetPos.y)
        line(insetPos.x, insetPos.y,
             insetPos.x, insetPos.y + insetSize.y)
        line(insetPos.x, insetPos.y + insetSize.y,
             insetPos.x + insetSize.x, insetPos.y + insetSize.y)
        line(insetPos.x + insetSize.x, insetPos.y,
             insetPos.x + insetSize.x, insetPos.y + insetSize.y)            
    end
    popStyle()
end
function Frame:gloss(baseclr)
    local i, t, r, g, b, y
    pushStyle()
    if baseclr == nil then baseclr = color(194, 194, 194, 255) end
    fill(baseclr)
    rectMode(CORNERS)
    rect(self.left, self.bottom, self.right, self.top)
    r = baseclr.r
    g = baseclr.g
    b = baseclr.b
    for i = 1 , self:height() / 2 do
        r = r - 1
        g = g - 1
        b = b - 1
        stroke(r, g, b, 255)
        y = (self.bottom + self.top) / 2
        line(self.left, y + i, self.right, y + i)
        line(self.left, y - i, self.right, y - i)
    end
    popStyle()
end
function Frame:shade(base, step)
    pushStyle()
    strokeWidth(1)
    for y = self.bottom, self.top do
        i = self.top - y
        stroke(base - i * step, base - i * step, base - i * step, 255)
        line(self.left, y, self.right, y)
    end
    popStyle()
end
function Frame:touched(touch)
    if touch.x >= self.left and touch.x <= self.right then
        if touch.y >= self.bottom and touch.y <= self.top then
            return true
        end
    end
    return false
end
function Frame:ptIn(x, y)
    if x >= self.left and x <= self.right then
        if y >= self.bottom and y <= self.top then
            return true
        end
    end
    return false
end
function Frame:overlaps(f)
    if self.left > f.right or self.right < f.left or
    self.bottom > f.top or self.top < f.bottom then
        return false
    else
        return true
    end
end
function Frame:width()
    return self.right - self.left
end
function Frame:height()
    return self.top - self.bottom
end
function Frame:midX()
    return (self.left + self.right) / 2
end
    
function Frame:midY()
    return (self.bottom + self.top) / 2
end
-- Batlle Chips 0.4
-- Mark Sumner
-- devilstower@gmail.com
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)
rectMode(CORNERS)
spriteMode(CORNERS)
textMode(CORNER)
function setup()
    robots = {}
    for i = 1,20 do
        robots[i] = Robot(17 + i * 70,320)
    end
    codes = {}
    codes[1] = Code("F", "Forward", false, color(140, 28, 28, 255))
    codes[2] = Code("L", "Turn Left", false, color(140, 28, 28, 255))
    codes[3] = Code("R", "Turn Right", false, color(140, 28, 28, 255))
    codes[4] = Code("B", "Reverse", false, color(140, 28, 28, 255))
    codes[5] = Code("W", "Fire Laser", false, color(140, 28, 28, 255))
    codes[6] = Code("H", "Bump", true, color(81, 83, 120, 255))
    codes[7] = Code("A", "Radar", true, color(81, 83, 120, 255))
    codes[8] = Code("D", "Damage", true, color(81, 83, 120, 255))
    codes[9] = Code("G", "Goto", true, color(48, 113, 42, 255))
    codes[10] = Code("5", "Random", true, color(48, 113, 42, 255))
    codes[11] = Code("P", "Repeat", true, color(48, 113, 42, 255))
    mode = 1
    dragToken = Token(codes[1], 0, 0)
    bench = CodeBench(35, 150)
    scheduler = TourneyOrganizer(35, 150)
    tray = TokenTray(550, 150)
    oldState = nil
    doneBtn = Frame(550, 60, WIDTH - 20, 140)
    bottomBar = Frame(0, 0, WIDTH, 50)
    codeFrame = Frame(30,100,180,200)
    designFrame = Frame(220,100,370,200)
    tourneyFrame = Frame(410,100,560,200)
    tradeFrame = Frame(600,100,750,200)
    arena = Arena(10, HEIGHT - 650, WIDTH - 10, HEIGHT - 10)
    arena:draw()
    studio = DesignStudio(20, 410, WIDTH - 20, HEIGHT - 20)
    vslider = Vslider(0,0,0)
    vcslider = VColorSlider(0,0,0)
    trader = TradingCenter()
    showSlider = false
    sliderPosition = 0
    leftBot = 1
    selectedRobot = 0
    botFrames = {}
    loadRobots()
    for i = 1,7 do
        botFrames[i] = Frame(i * 87, HEIGHT - 750, 
        i * 87 + 80, HEIGHT - 670)
    end
    leftRobot = 1
    rightBtn = Frame(WIDTH - 80, 260, WIDTH, 360)
    leftBtn = Frame(0, 260, 80, 360)
    -- tourney variables
    tourney = Tourney()
end
function saveRobots()
    local k, s, i, c
    s = table.maxn(robots)..","
    
    for i, r in ipairs(robots) do
        s = s..r.name..","..r.wins..","..r.losses..","
        s = s..r.treadColor..","..r.bodyColor..","
        s = s..r.headColor..","..r.dishColor..","
        c = table.maxn(r.program)
        s = s..c
        if i < table.maxn(robots) or c > 0 then s = s.."," end
        for k, p in ipairs(r.program) do
            if p.code ~= nil then
                s = s..k..","..p.code.short..","..p.value
                s=s..","
            else
                s = s..k..",nil"..","..p.value
                s=s..","
            end
        end
    end
    saveProjectData("BCBots", s)
end
function loadRobots()
    local k, s, i, robotCount, d, c
    local w = {}
    --displayMode(STANDARD)
    s = readProjectData("BCBots")
    --print(s)
    if s == nil then
        s = getDefault()
    end
    if s ~= nil then
        i = 0
        for k in string.gmatch(s,"([^,]+)") do
            i = i + 1
            w[i] = k
        end
        robotCount = w[1]
        top = 2
        for r = 1, robotCount do
            robots[r].name = w[top]
            robots[r].wins = tonumber(w[top + 1])
            robots[r].losses = tonumber(w[top + 2])
            robots[r].treadColor = tonumber(w[top + 3])
            robots[r].bodyColor = tonumber(w[top + 4])
            robots[r].headColor = tonumber(w[top + 5])
            robots[r].dishColor = tonumber(w[top + 6])
            programSize = tonumber(w[top + 7])
            i = 0
            if programSize > 0 then
                for i = 1, programSize do
                    socketNum = tonumber(w[i * 3 - 2 + top + 7])
                    codeShort = w[i * 3 - 1 + top + 7]
                    value = tonumber(w[i * 3 + top + 7])
                    -- find the right code
                    code = nil
                    for d, c in ipairs(codes) do
                        if c.short == codeShort then
                            code = c
                        end
                    end
                    robots[r].program[socketNum] = Socket(code, 0, 0)
                    robots[r].program[socketNum].value = value
                end
            end
            top = top + 8 + programSize * 3
        end
    end
end
function drawMain()
    pushStyle()
    fill(0, 0, 0, 255)
    stroke(0, 69, 255, 255)
    tint(249, 249, 249, 255)
    
    strokeWidth(2)
    textMode(CENTER)
    font("ArialMT")
    fontSize(12)
    for i = 1, 7 do
        fill(69, 84, 163, 78)
        botFrames[i]:draw()
        robots[i + leftRobot - 1].x = i * 87 + 10
        robots[i + leftRobot - 1].y = HEIGHT - 740
        fill(210, 208, 229, 255)
        text(robots[i + leftRobot - 1].name, i* 87 + 40, HEIGHT - 760)
    end
    textMode(CORNER)
    fill(31, 104, 38, 102)
    codeFrame:draw()
    designFrame:draw()
    tourneyFrame:draw()
    tradeFrame:draw()
    fill(255, 255, 255, 255)
    font("Futura-CondensedExtraBold")
    fontSize(24)
    text("Code",codeFrame.left + 15, codeFrame.top - 50)
    text("Design", designFrame.left + 15, designFrame.top - 50)
    text("Tourney", tourneyFrame.left + 15, tourneyFrame.top - 50)
    text("Trade", tradeFrame.left + 15, tradeFrame.top - 50)
    stroke(19, 21, 248, 255)
    strokeWidth(11)
    if leftRobot == 1 then stroke(46, 60, 171, 107) end
    line(10, 310, 50, 340)
    line(10, 310, 50, 280)
    stroke(19, 21, 248, 255)
    if leftRobot == 13 then stroke(46, 60, 171, 107) end
    line(WIDTH - 10, 310, WIDTH - 50, 340)
    line(WIDTH - 10, 310, WIDTH - 50, 280)
    strokeWidth(1)
    popStyle()
end
function draw() 
    local i, m
    noSmooth()
    background(127, 127, 127, 255)
    tint(255, 255, 255, 255)
    fill(97, 115, 86, 153)
    strokeWidth(2)
    stroke(99, 118, 94, 145)
    rect(1, 1, 200, HEIGHT)
    fill(102, 108, 98, 153)
    rect(200, 1, 366, HEIGHT)
    rect(50, 100, 190, 222)
    fill(103, 117, 93, 153)
    rect(366, 1, 555, HEIGHT)
    rect(230, 200, 350, 300)
    fill(102, 108, 98, 153)
    rect(555, 1, WIDTH, HEIGHT)
    rect(380, 70, 530, 170)
    strokeWidth(1)
    fill(127, 127, 127, 255)
    stroke(127, 120, 120, 207)
    
    bottomBar:draw()
    if mode == 1 then arena:draw() end
    
    if mode == 1 and not tourney.isActive then
        drawMain()
        
        for i = 1,7 do
            robots[i + leftRobot - 1]:draw()
        end
        
    elseif mode == 2 then
        bench:draw()
        tray:draw()
        if showSlider then
            vslider:draw()
        end
        fill(31, 104, 38, 102)
        stroke(0, 69, 255, 255)
        strokeWidth(1)
        doneBtn:draw()
        fill(255, 255, 255, 255)
        font("Futura-CondensedExtraBold")
        fontSize(24)
        text("Done", doneBtn.left + 20, doneBtn.bottom + 30)
    elseif mode == 3 then
        studio:draw()
        fill(31, 104, 38, 102)
        stroke(0, 69, 255, 255)
        strokeWidth(1)
        doneBtn:draw()
        font("Futura-CondensedExtraBold")
        fontSize(24)
        fill(255, 255, 255, 255)
        text("Done", doneBtn.left + 20, doneBtn.bottom + 45)
    elseif mode == 4 then
        scheduler:draw(robots)
        fill(31, 104, 38, 102)
        stroke(0, 69, 255, 255)
        strokeWidth(1)
        doneBtn:draw()
        font("Futura-CondensedExtraBold")
        fontSize(24)
        fill(255, 255, 255, 255)
        text("Done", doneBtn.left + 15, doneBtn.bottom + 40)
    elseif mode == 5 then
        trader:draw(robots)
        fill(31, 104, 38, 102)
        stroke(0, 69, 255, 255)
        strokeWidth(1)
        doneBtn:draw()
        font("Futura-CondensedExtraBold")
        fontSize(24)
        fill(255, 255, 255, 255)
        text("Done", doneBtn.left + 15, doneBtn.bottom + 40)
    end
    -- touch handling
    if mode == 1 then
        if CurrentTouch.state == BEGAN and 
            CurrentTouch.state ~= oldState then
            if arena.stop:touched(CurrentTouch) then
                arena:sizeFrames(10, HEIGHT - 650, 
                WIDTH - 10, HEIGHT - 10)
                arena:clear()
                tourney.isActive = false
            end
            if leftBtn:touched(CurrentTouch) and leftRobot > 1 then
                leftRobot = leftRobot - 1
            end
            if rightBtn:touched(CurrentTouch) and 
                leftRobot < 13 then
                leftRobot = leftRobot + 1
            end
            selectedRobot = 0
            -- check to see if a robot was selected
            for i = 1, 7 do
                if botFrames[i]:touched(CurrentTouch) then
                    selectedRobot = i + leftRobot - 1
                end
            end
        end
        if CurrentTouch.state == MOVING then
            if selectedRobot > 0 then 
                robots[selectedRobot].x = CurrentTouch.x - 20
                robots[selectedRobot].y = CurrentTouch.y - 20
                robots[selectedRobot]:draw()
            end
        end
        if CurrentTouch.state == ENDED 
        and CurrentTouch.state ~= oldState then
            if selectedRobot > 0 then
                if codeFrame:touched(CurrentTouch) then
                    doneBtn = Frame(550, 60, WIDTH - 20, 140)
                    bench:loadRobot(robots[selectedRobot])
                    mode = 2
                end
                if designFrame:touched(CurrentTouch) then
                    showKeyboard()
                    doneBtn = Frame(550, 310, WIDTH - 20, 400)
                    studio:setBot(robots[selectedRobot])
                    mode = 3
                end
                if tourneyFrame:touched(CurrentTouch) then
                    doneBtn = Frame(550, 60, WIDTH - 20, 140)
                    scheduler:loadRobot(selectedRobot)
                    selectedRobot = 0
                    mode = 4
                end
                if tradeFrame:touched(CurrentTouch) then
                    doneBtn = Frame(550, 60, WIDTH - 20, 140)
                    --trader:loadRobot(selectedRobot)
                    selectedRobot = 0
                    mode = 5
                end
                if arena:touched(CurrentTouch) then
                    if table.maxn(arena.robots) < 4 then
                        arena:loadRobot(robots[selectedRobot])
                    else
                        sound(SOUND_BLIT, 30424)
                    end
                end
                
            end
        end
    end
    if mode == 2 then
        if CurrentTouch.state == BEGAN and 
            CurrentTouch.state ~= oldState then
            selectedToken = 0
            -- check to see if a token was selected
            if tray:touched(CurrentTouch) then
                dragToken = Token(tray.tokens[tray.selected].code,
                CurrentTouch.x - 20, CurrentTouch.y,
                tray.tokens[tray.selected].color)
            end
            if bench:touched(CurrentTouch) then
                -- touched a socket
                c = bench.sockets[bench.selectedSocket].code
                if c ~= nil and bench.action == 0 then
                    if c.hasValue then
                        vslider = Vslider(CurrentTouch.x, 
                        CurrentTouch.y, 
                        bench.sockets[bench.selectedSocket].value)
                        showSlider = true
                    end
                end
                if c ~= nil and bench.action == 1 then
                    dragToken = 
                    Token(bench.sockets[bench.selectedSocket].code,
                    CurrentTouch.x - 20, CurrentTouch.y,
                    bench.sockets[bench.selectedSocket].color)
                    bench.sockets[bench.selectedSocket].code = nil
                end
            end
        end
        if CurrentTouch.state == MOVING then
            if dragToken ~= nil
             then 
                dragToken.x = CurrentTouch.x - 20
                dragToken.y = CurrentTouch.y
                dragToken:draw()
            end
            if showSlider then
                if vslider:touched(CurrentTouch) then 
                    bench.sockets[bench.selectedSocket].value =
                    vslider.value
                end
            end
        end
        if CurrentTouch.state == ENDED 
        and CurrentTouch.state ~= oldState then
            if dragToken ~= nil then
                if bench:touched(CurrentTouch) then
                    bench.sockets[bench.selectedSocket].code =
                    dragToken.code
                    sound(SOUND_HIT, 30249)
                end
                dragToken = nil
            end
            if showSlider then showSlider = false end
            if doneBtn:touched(CurrentTouch) then
                -- save code
                for i = 1,30 do
                    if bench.sockets[i].code ~= nil then
                        b = bench.sockets[i]
                        robots[selectedRobot].program[i] = 
                        Socket(b.code, 0, 0)
                        robots[selectedRobot].program[i].value = b.value
                    else
                        robots[selectedRobot].program[i] = 
                        Socket(nil, 0, 0)
                        robots[selectedRobot].program[i].value = 1
                    end 
                end
                saveRobots()
                mode = 1
            end
        end
    end
    if mode == 3 then
        if CurrentTouch.state == BEGAN and 
            CurrentTouch.state ~= oldState then
            -- check to see if a robot was selected
            studio:touched(CurrentTouch)
            if doneBtn:touched(CurrentTouch) then
                hideKeyboard()
                mode = 1
                saveRobots()
            end
        end
        if CurrentTouch.state == MOVING then
            studio:touched(CurrentTouch)
        end
        if CurrentTouch.state == ENDED 
        and CurrentTouch.state ~= oldState then
            studio.dishShowSlider = false
            studio.headShowSlider = false
            studio.bodyShowSlider = false
            studio.treadShowSlider = false
        end
    end
    if mode == 4 then
        if CurrentTouch.state == BEGAN and 
            CurrentTouch.state ~= oldState then
            -- check to see if a robot was selected
            scheduler:touched(CurrentTouch)
            if doneBtn:touched(CurrentTouch) then
                mode = 1
                saveRobots()
            end
            if scheduler.meleeBtn:touched(CurrentTouch) then
                mode = 1
                tourney:load(1, 
                robots[scheduler.contestants[1]], 
                robots[scheduler.contestants[2]], 
                robots[scheduler.contestants[3]],
                robots[scheduler.contestants[4]])
                tourney.isActive = true
                arena:sizeFrames(10, 60, WIDTH - 10, HEIGHT - 10)
            end
            if scheduler.oneBtn:touched(CurrentTouch) then
                mode = 1
                tourney:load(1, 
                robots[scheduler.contestants[1]], 
                robots[scheduler.contestants[2]], 
                robots[scheduler.contestants[3]],
                robots[scheduler.contestants[4]])
                tourney.isActive = true
                arena:sizeFrames(10, 60, WIDTH - 10, HEIGHT - 10)
            end
        end
        if CurrentTouch.state == MOVING then
            scheduler:touched(CurrentTouch)
        end
        if CurrentTouch.state == ENDED 
        and CurrentTouch.state ~= oldState then
            scheduler.showSlider = false
        end
    end
    if mode == 5 then
        if CurrentTouch.state == BEGAN and 
            CurrentTouch.state ~= oldState then
            -- check to see if a robot was selected
            trader:touched(CurrentTouch)
            if doneBtn:touched(CurrentTouch) then
                mode = 1
                saveRobots()
            end
        end
        if CurrentTouch.state == MOVING then
            trader:touched(CurrentTouch)
        end
        if CurrentTouch.state == ENDED 
        and CurrentTouch.state ~= oldState then
            
        end
    end
    oldState = CurrentTouch.state
    
        -- load a new match?
    if tourney.isActive and math.floor(arena.timer) <1 then
        if tourney.matchNum > 0 then
            tourney:recordScores(
            arena.robots[1].points, arena.robots[2].points,  
            arena.robots[3].points, arena.robots[4].points)
        end
        if tourney.matchNum < tourney.matchCount then
            m = {}
            m = tourney:getNextMatch()
            arena:clear()
            for i=1,4 do 
                if m[i] == nil then
                    m[i] = robots[math.random(20)]
                end
            end
            arena:setMatch(m[1], m[2], m[3], m[4])
        elseif tourney.matchNum == tourney.matchCount then
            arena.timer = 0
            tourney:draw()
        end
        
    end
end
function keyboard(key)
    if mode == 3 then
        if key ~= nil then
            if string.byte(key) == 10 then
                --
            else 
                if string.byte(key) ~= 44 then -- filter out commas
                    studio.tb:acceptKey(key)
                end
            end
        end
    end
end
Tourney = class()
function Tourney:init()
    self.matches = {}
    self.scores = {}
    self.robots = {}
    self.matchNum = 0
    self.matchCount = 1
    self.isActive = false
    self.frame = Frame(50, 500, WIDTH - 50, HEIGHT - 50)
    self.type = 0
    self.timer = 0
end
function Tourney:load(t, a, b, c, d)
    self.matchNum = 0
    self.scores = {}
    self.type = t
    self.robots = {a, b, c, d}
    if self.type == 1 then
        self.matches[1] = {a, b, c, d}
        self.matches[2] = {a, b, c, d}
        self.matches[3] = {a, b, c, d}
        self.matches[4] = {a, b, c, d}
        self.timer = 100
        self.matchNum = 0
        self.matchCount = 4
    else
        self.matches[1] = {a, d, nil, nil}
        self.matches[2] = {b, c, nil, nil}
        self.matches[3] = {a, b, nil, nil}
        self.matches[4] = {a, b, nil, nil}
        self.timer = 100
        self.matchNum = 0
        self.matchCount = 4
    end
end
function Tourney:getNextMatch()
    self.matchNum = self.matchNum + 1
    if self.matchNum <= self.matchCount then
        return self.matches[self.matchNum]
    end
end
function Tourney:recordScores(a, b, c, d)
    self.scores[self.matchNum] = {a, b, c, d}
end
function Tourney:draw()
    local bot, round, temp
    fill(192, 174, 174, 218)
    stroke(149, 111, 111, 104)
    strokeWidth(3)
    self.frame:draw()
    fill(65, 65, 65, 255)
    font("Futura-CondensedExtraBold")
    fontSize(32)
    textMode(CORNER)
    text("Tourney Results", self.frame.left + 35, self.frame.top - 50)
    
    font("Futura-Medium")
    fontSize(22)
    text("Bot", self.frame.left + 50, self.frame.top - 90)
    text("1", self.frame.left + 275, self.frame.top - 90)
    text("2", self.frame.left + 350, self.frame.top - 90)
    text("3", self.frame.left + 425, self.frame.top - 90)
    text("4", self.frame.left + 500, self.frame.top - 90)
    line(self.frame.left + 50, self.frame.top - 100,
    self.frame.left + 500, self.frame.top - 100)
    text("Total", self.frame.left + 575, self.frame.top - 90)
    for bot = 1,4 do
        textAlign(LEFT)
        text(self.matches[1][bot].name, self.frame.left + 50, 
        self.frame.top - 100 - bot * 35)
        temp = 0
        for round = 1, 4 do
            textAlign(RIGHT)
            text(self.scores[round][bot], 
            self.frame.left + 200 + round * 75, 
            self.frame.top - 100 - bot * 35)
            temp = temp + self.scores[round][bot]
        end
        text(temp, self.frame.left + 575, 
        self.frame.top - 100 - bot * 35)
    end
end
TourneyOrganizer = class()
function TourneyOrganizer:init(x, y)
    self.x = x
    self.y = y
    self.frame = Frame(x, y, x + 710, y + 850)
    self.header = Frame(self.frame.left + 4, self.frame.top - 40,
    self.frame.right - 4, self.frame.top - 4)
    self.action = 0
    self.contestantFrames = {}
    self.contestants = {}
    for i = 1,4 do
        self.contestantFrames[i] = Frame(i * 175 - 100, 800, 
        i * 175 , 880)
        self.contestants[i] = 0
    end
    self.selected = 0
    self.showSlider = false
    self.slider = VRobotSlider(self.contestantFrames[1].left,
    self.contestantFrames[1].bottom)
    self.meleeBtn = Frame(570, 570, 715, 670)
    self.oneBtn = Frame(570, 340, 715, 440)
end
function TourneyOrganizer:loadRobot(i)
    self.contestants[1] = i
end
function TourneyOrganizer:draw(robots)
    local i
    pushStyle()
    fill(233, 233, 233, 163)
    stroke(144, 136, 136, 118)
    strokeWidth(5)
    self.frame:draw()
    fill(141, 135, 135, 226)
    self.header:draw()
    stroke(84, 76, 76, 154)
    textMode(CENTER)
    strokeWidth(2)
    for i = 1,4 do
        fill(155, 180, 146, 122)
        self.contestantFrames[i]:draw()
        if self.contestants[i] > 0 then
            pushMatrix()
            translate(self.contestantFrames[i]:midX(), 
            self.contestantFrames[i]:midY())
            robots[self.contestants[i]]:drawBase()
            fontSize(16)
            fill(154, 126, 126, 224)
            font("Futura-Medium")
            text(robots[self.contestants[i]].name, 0, -55)
            popMatrix()
        else
            font("Futura-CondensedExtraBold")
            fontSize(48)
            fill(115, 115, 115, 190)
            text("?", self.contestantFrames[i]:midX(), 
            self.contestantFrames[i]:midY())
            fill(154, 126, 126, 224)
            font("Futura-Medium")
            fontSize(16)
            text("Random", self.contestantFrames[i]:midX(), 
            self.contestantFrames[i]:midY()-55)
        end
    end
    
    fill(197, 197, 197, 112)
    stroke(84, 76, 76, 154)
    strokeWidth(2)
    rect(self.frame.left + 35, 600, self.frame.left + 95, 660)
    line(self.frame.left + 95, 630, self.frame.left + 155, 630)
    rect(self.frame.left + 155, 600, self.frame.left + 215, 660)
    line(self.frame.left + 215, 630, self.frame.left + 275, 630)
    rect(self.frame.left + 275, 600, self.frame.left + 335, 660)
    line(self.frame.left + 335, 630, self.frame.left + 395, 630)
    rect(self.frame.left + 395, 600, self.frame.left + 455, 660)
    line(self.frame.left + 215, 630, self.frame.left + 275, 630)
    rect(self.frame.left + 35, 400, self.frame.left + 95, 460)
    rect(self.frame.left + 35, 270, self.frame.left + 95, 330)
    rect(self.frame.left + 135, 340, self.frame.left + 195, 400)
    rect(self.frame.left + 235, 340, self.frame.left + 295, 400)
    rect(self.frame.left + 335, 340, self.frame.left + 395, 400)
    rect(self.frame.left + 435, 400, self.frame.left + 495, 460)
    rect(self.frame.left + 435, 270, self.frame.left + 495, 330)
    line(self.frame.left + 95, 430, self.frame.left + 175, 430)
    line(self.frame.left + 95, 300, self.frame.left + 175, 300)
    line(self.frame.left + 175, 430, self.frame.left + 175, 400)
    line(self.frame.left + 175, 300, self.frame.left + 175, 340)
    line(self.frame.left + 195, 370, self.frame.left + 235, 370)
    line(self.frame.left + 295, 370, self.frame.left + 335, 370)
    line(self.frame.left + 365, 400, self.frame.left + 365, 430)
    line(self.frame.left + 365, 300, self.frame.left + 365, 340)
    line(self.frame.left + 365, 430, self.frame.left + 435, 430)
    line(self.frame.left + 365, 300, self.frame.left + 435, 300)
    fill(103, 100, 100, 136)
    fontSize(32)
    text("1", self.frame.left + 65, 630)
    text("2", self.frame.left + 185, 630)
    text("3", self.frame.left + 305, 630)
    text("4", self.frame.left + 425, 630)
    text("1", self.frame.left + 65, 430)
    text("2", self.frame.left + 65, 300)
    text("3", self.frame.left + 465, 430)
    text("4", self.frame.left + 465, 300)
    text("5", self.frame.left + 165, 370)
    text("6", self.frame.left + 365, 370)
    text("7", self.frame.left + 265, 370)
    fill(155, 180, 146, 122)
    self.meleeBtn:draw()
    self.oneBtn:draw()
    fill(127, 127, 127, 207)
    fontSize(24)
    text("Melee", self.meleeBtn.left + 45, self.meleeBtn.bottom + 80)
    text("One on One", self.oneBtn.left + 70, self.oneBtn.bottom + 80)
    font("Futura-Medium")
    fontSize(16)
    fill(234, 233, 233, 252)
    textMode(CORNER)
    text("TOURNEY ORGANIZER", self.frame.left + 15, 
    self.frame.top - 32)
    fill(0, 0, 0, 255)
    text("Contestants", self.frame.left + 20, 
    self.frame.bottom + 750)
    text("Four Round Melee", self.frame.left + 20, 
    self.frame.bottom + 530)
    text("One on One", self.frame.left + 20, 
    self.frame.bottom + 330)
    if self.showSlider then self.slider:draw(robots) end
    popStyle()
end
function TourneyOrganizer:touched(touch)
    local i
    for i = 1,4 do
        if self.contestantFrames[i]:touched(touch) then
            self.showSlider = true
            self.slider = VRobotSlider(
            self.contestantFrames[i].right,
            self.contestantFrames[i].bottom)
            self.selected = i
        end
    end
    if self.showSlider then
        if self.slider:touched(touch) then
            self.contestants[self.selected] = self.slider.selected
        end
    end
end
TradingCenter = class()
function TradingCenter:init()
    self.frame = Frame(20, 160, WIDTH - 10, HEIGHT - 20)
    self.robots = {}
    self.cards = {}
    for x = 1, 5 do
        for y = 1, 4 do
            self.cards[x + (y-1) * 5] =
            Frame(x * 140 - 100, y * 200 - 10 ,
            x * 140 + 30, y * 200 + 180)
        end
    end
    self.center = 1
end
function TradingCenter:loadRobot(r)
    self.robots[1] = r
end
function TradingCenter:draw()
    fill(174, 190, 195, 209)
    stroke(59, 111, 158, 190)
    strokeWidth(5)
    self.frame:draw()
    font("Futura-CondensedExtraBold")
    fontSize(120)
    fill(135, 171, 172, 207)
    text("Trade", 35, HEIGHT - 180)
    
    fontSize(18)
    for i = 1,20 do 
        fill(180, 195, 209, 255)
        stroke(57, 54, 54, 255)
        strokeWidth(6)
        self.cards[i]:draw() 
        self.cards[i]:inset(10, 10)
        strokeWidth(2)
        stroke(112, 113, 115, 132)
        fill(248, 248, 248, 255)
        self.cards[i]:draw() 
        self.cards[i]:inset(-10, -10)
        translate(self.cards[i]:midX() - 15, self.cards[i]:midY() + 45)
        robots[i]:drawBase()
        for c = 1, 30 do
            fill(255, 255, 255, 255)
            stroke(175, 158, 33, 255)
            noStroke()
            if robots[i].program[c] ~= nil then
                p = robots[i].program[c].code
                if p ~= nil then
                    if p.short == "F" then
                        fill(255, 0, 0, 255)
                    elseif p.short == "L" then
                        fill(255, 0, 181, 255)
                    elseif p.short == "R" then
                        fill(255, 101, 0, 255)
                    elseif p.short == "B" then
                        fill(255, 220, 0, 255)
                    elseif p.short == "W" then
                        fill(255, 0, 241, 255)
                    elseif p.short == "H" then
                        fill(14, 0, 255, 255)
                    elseif p.short == "A" then
                        fill(0, 178, 255, 255)
                    elseif p.short == "D" then
                        fill(141, 0, 255, 255)
                    elseif p.short == "G" then
                        fill(3, 255, 0, 255)
                    elseif p.short == "5" then
                        fill(0, 255, 117, 255)
                    elseif p.short == "P" then
                        fill(95, 255, 0, 255)
                    end
                end
                rect(-30, -129 + c * 3, -20, -126 + c * 3)
                v = robots[i].program[c].value
                fill(255-v * 5, 255-v * 5, 255-v * 5)
                rect(-20, -129 + c * 3, -10, -126 + c * 3)
            end
            
        end
        rotate(90)
        fill(35, 35, 35, 255)
        text(robots[i].name, -100, -70)
        resetMatrix()
    end
    
end
function TradingCenter:touched(touch)
    -- Codea does not automatically call this method
end
    colors = {}
    colors[1] = color(194, 73, 76, 255)
    colors[2] = color(192, 138, 84, 255)
    colors[3] = color(245, 245, 28, 255)
    colors[4] = color(93, 133, 53, 255) 
    colors[5] = color(42, 118, 42, 255)
    colors[6] = color(57, 144, 101, 255)
    colors[7] = color(90, 196, 196, 255)
    colors[8] = color(34, 93, 152, 255)
    colors[9] = color(54, 54, 165, 255)
    colors[10] = color(150, 104, 196, 255)
    colors[11] = color(170, 97, 170, 255)
    colors[12] = color(122, 53, 88, 255)
    colors[13] = color(214, 207, 207, 255)
    colors[14] = color(177, 157, 157, 255)
    colors[15] = color(69, 66, 66, 255)
    colors[16] = color(30, 30, 30, 255)
    
    tourney = Tourney()
function deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
        if type(object) ~= "table" then
            return object
        elseif lookup_table[object] then
            return lookup_table[object]
        end
        local new_table = {}
        lookup_table[object] = new_table
        for index, value in pairs(object) do
            new_table[_copy(index)] = _copy(value)
        end
        return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
end
function getDefault()
    local s
    s = "20,Lump,0,0,14,14,15,4,30,1,F,1,2,nil,1,3,L,1,4,nil,1,5,nil,1,6,nil,1,7,nil,1,8,nil,1,9,nil,1,10,nil,1,11,nil,1,12,nil,1,13,nil,1,14,nil,1,15,nil,1,16,nil,1,17,nil,1,18,nil,1,19,nil,1,20,nil,1,21,nil,1,22,nil,1,23,nil,1,24,nil,1,25,nil,1,26,nil,1,27,nil,1,28,nil,1,29,nil,1,30,nil,1,Turner,0,0,15,8,15,7,30,1,F,1,2,H,4,3,G,1,4,L,1,5,G,1,6,nil,1,7,nil,1,8,nil,1,9,nil,1,10,nil,1,11,nil,1,12,nil,1,13,nil,1,14,nil,1,15,nil,1,16,nil,1,17,nil,1,18,nil,1,19,nil,1,20,nil,1,21,nil,1,22,nil,1,23,nil,1,24,nil,1,25,nil,1,26,nil,1,27,nil,1,28,nil,1,29,nil,1,30,nil,1,Spinner,0,0,2,7,1,4,30,1,L,1,2,W,4,3,G,1,4,nil,1,5,nil,1,6,nil,1,7,nil,1,8,nil,1,9,nil,1,10,nil,1,11,nil,1,12,nil,1,13,nil,1,14,nil,1,15,nil,1,16,nil,1,17,nil,1,18,nil,1,19,nil,1,20,nil,1,21,nil,1,22,nil,1,23,nil,1,24,nil,1,25,nil,1,26,nil,1,27,nil,1,28,nil,1,29,nil,1,30,nil,1,Smart Spinner,0,0,1,7,1,13,30,1,L,1,2,A,4,3,G,1,4,W,1,5,G,2,6,nil,1,7,nil,1,8,nil,1,9,nil,1,10,nil,1,11,nil,1,12,nil,1,13,nil,1,14,nil,1,15,nil,1,16,nil,1,17,nil,1,18,nil,1,19,nil,1,20,nil,1,21,nil,1,22,nil,1,23,nil,1,24,nil,1,25,nil,1,26,nil,1,27,nil,1,28,nil,1,29,nil,1,30,nil,1,Killbot 1000,0,0,15,3,15,3,30,1,F,1,2,H,4,3,G,1,4,R,1,5,R,1,6,A,13,7,L,1,8,F,1,9,H,11,10,G,5,11,R,1,12,G,5,13,W,1,14,G,6,15,nil,1,16,nil,1,17,nil,1,18,nil,1,19,nil,1,20,nil,1,21,nil,1,22,nil,1,23,nil,1,24,nil,1,25,nil,1,26,nil,1,27,nil,1,28,nil,1,29,nil,1,30,nil,1,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0,Generobot,0,0,14,14,15,4,0"
    return s
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment