Skip to content

Instantly share code, notes, and snippets.

@devilstower
Created June 27, 2012 03:36
Show Gist options
  • Save devilstower/3001221 to your computer and use it in GitHub Desktop.
Save devilstower/3001221 to your computer and use it in GitHub Desktop.
Battle chips 26 Jun 12 / part 1
Arena = class()
function Arena:init(l, b, r, t)
    self.robots = {}
    self.timer = 0
    self.tourney = false
    self.gameOver = false
    self.game = 1
    self.pulse = 0
    self.pulseDirection = 2
    self.skeet = {}
    self.walls = {}
    self.tracks = {}
    self.launchTime = ElapsedTime
    self:sizeFrames(l, b, r, t)
end
function Arena:sizeFrames(l, b, r, t)
    -- define bounds for the arena
    self.frame = Frame(l, b, r, t)
    self.panel = Frame(l + 1, t - 90, r - 1, t - 1)
    self.stop = Frame(r - 70, t - 65, r - 30, t - 25)
    self.field = Frame(l + 5, b + 20, r - 5, t - 90)
    self.launch = Frame(self.frame:midX() - 30, self.frame.bottom - 15,
    self.frame:midX() + 30, self.frame.bottom + 30)
    for i,r in ipairs(self.robots) do
        r.limits = self.field
    end
end
function Arena:loadRobot(r, x, y)
    -- copy a robot into the arena, and set up for action
    -- much of this is only needed because deep copy is losing
    -- table order.
    local i, nr
    
   -- nr = Robot(math.random(self.field:width() - 90) + 30, 
   -- math.random(self.field:height() - 90) + 30)
    nr = Robot(x, y)
    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.head = r.head
    nr.dish = r.dish
    nr.body = r.body
    nr.tread = r.tread
    nr.limits = self.field
    i = #self.robots + 1
    -- design stuff here for now. should probably move.
    nr.speed = r.tread * 4 - (r.body - 1)
    nr.turnDelay = r.tread * 15 - 10
    nr.shield = (r.head - 1) * 3.5
    nr.repairRate = 1 / r.head
    nr.weaponStrength = nr.dish * 2.5 - 2
    self.robots[i] = nr
    self.robots[i]:createImage()
end
function Arena:copyRobot(r)
    -- copy using deepcopy
    -- seems to have trouble with otder of code
    local i, nr
    nr = deepcopy(r)
    nr.direction = math.random(4)
    nr.bounds = Frame(nr.x, nr.y,  nr.x + 60, nr.y + 60)
    nr.bump = false
    nr.radar = false
    nr.heat = 0
    nr.step = 1
    nr.points = 0
    i = table.maxn(self.robots) + 1
    self.robots[i] = nr
end
function Arena:skeetMatch(r)
    self.game = 2
    self.robots ={}
    self.tracks = {}
    self.walls = {}
    self:loadRobot(r, arena.field:midX(), arena.field:midY())
    self.robots[1].bounds = Frame(self.robots[1].x, 
    self.robots[1].y,  self.robots[1].x + 60, self.robots[1].y + 60)
    self.skeet[1] = Skeet(30, 30, self.field)
    self.skeet[2] = Skeet(30, self.field:height() / 2, self.field)
    self.skeet[3] = Skeet(30, self.field:height() - 30, self.field)
    self.skeet[4] = Skeet(self.field:width() / 2, 
    self.field:height() - 30, self.field)
    self.skeet[5] = Skeet(self.field:width() - 30, 
    self.field:height() - 30, self.field)
    self.skeet[6] = Skeet(self.field:width() - 30, 
    self.field:height() / 2, self.field)
    self.skeet[7] = Skeet(self.field:width() - 30, 30, self.field)
    self.skeet[8] = Skeet(self.field:width() / 2, 30, self.field)
    self.timer = 300
    self.tourney = true
end
function Arena:mazeRace(r)
    self.game = 3
    self:loadRobot(r, 10, 10)
    self.robots[1].bounds = Frame(self.robots[1].x, 
    self.robots[1].y,  self.robots[1].x + 60, self.robots[1].y + 60)
    self.robots[1].dir = 3
    -- base walls
    self.walls[1] = Frame(80, 10, 81, self.field:height() - 80)
    self.walls[2] = Frame(160, 90, 161, self.field:height() + 20)
    self.walls[3] = Frame(240, 10, 241, self.field:height() - 80)
    self.walls[4] = Frame(325, 510, 326, self.field:height())
    self.walls[5] = Frame(245, 415, 400, 416)
    self.walls[6] = Frame(325, 505, 480, 506)
    self.walls[7] = Frame(485, 340, 486, 500)
    self.walls[8] = Frame(325, 330, 580, 331)
    self.walls[9] = Frame(325, 90, 326, 330)
    self.walls[10] = Frame(405, 10, 406, 235)
    self.walls[11] = Frame(500, 85, 501, 235)
    self.walls[12] = Frame(580, 85, 581, 330)
    self.walls[13] = Frame(500, 80, 660, 81)
    self.walls[14] = Frame(660, 85, 661, 330)
    self.walls[15] = Frame(575, 410, self.field:width(), 411)
    self.walls[16] = Frame(570, 415, 571, self.field:height() - 80)
    self.walls[17] = Frame(405, 585, 565, 586)
    self.walls[18] = Frame(405, 590, 406, self.field:height() - 80)
    self.walls[19] = Frame(485, 670, 486, self.field:height() + 20)
    self.walls[20] = Frame(660, 505, 661, self.field:height() + 20)
    
    self.tracks = {}
    self.tracks[1] = Track(40, 300, 0)
    self.tracks[2] = Track(40, 600, 0)
    self.tracks[3] = Track(40, 820, -45)
    self.tracks[4] = Track(120, 820, 225)
    self.tracks[5] = Track(120, 500, 180)
    self.tracks[6] = Track(120, 200, 180)
    self.tracks[7] = Track(120, 50, 225)
    self.tracks[8] = Track(200, 50, -45)
    self.tracks[9] = Track(200, 500, 0)
    self.tracks[10] = Track(200, 830, -45)
    self.tracks[11] = Track(280, 830, 225)
    self.tracks[12] = Track(280, 455, 225)
    self.tracks[13] = Track(440, 455, 225)
    self.tracks[14] = Track(440, 375, 225)
    self.tracks[15] = Track(285, 375, 135)
    self.tracks[16] = Track(285, 50, 225)
    self.tracks[17] = Track(365, 50, -45)
    self.tracks[18] = Track(365, 280, -45)
    self.tracks[19] = Track(445, 280, 225)
    self.tracks[20] = Track(450, 50, 225)
    self.tracks[21] = Track(705, 50, -45)
    self.tracks[22] = Track(705, 370, 45)
    self.tracks[23] = Track(525, 370, 45)
    self.tracks[24] = Track(525, 540, 45)
    self.tracks[25] = Track(365, 540, 45)
    self.tracks[26] = Track(365, 830, -45)
    self.tracks[27] = Track(445, 830, 225)
    self.tracks[28] = Track(445, 625, 225)
    self.tracks[29] = Track(525, 625, -45)
    self.tracks[30] = Track(525, 830, -45)
    self.tracks[31] = Track(615, 830, 225)
    self.tracks[32] = Track(615, 625, 180)
    self.tracks[33] = Track(615, 460, 225)
    self.tracks[34] = Track(700, 460, -45)
    self.tracks[35] = Track(700, 830, 0)
    
    self.timer = 1000
    self.tourney = true
end
function Arena:clear()
    -- pop robots from arena
    sound(SOUND_POWERUP, 2591)
    self.robots = {}
    self.skeet = {}
    self.walls = {}
    self.tracks = {}
    self.timer = 0
    self.game = 1
    self.gameOver = false
    self.tourney  = false
    
end
function Arena:testBounds(type, num, bounds)
    for i, r in ipairs(self.robots) do
        if type ~= 1 or num ~= i then 
            if r.bounds:overlaps(bounds) and r.hp > 0 then
                if r.bounds.left < bounds.left then
                    return 1
                elseif r.bounds.left > bounds.left then
                    return 2
                elseif r.bounds.top < bounds.top then
                    return 3
                elseif r.bounds.top > bounds.left then
                    return 4
                end
            end
        end
    end
    for i, s in ipairs(self.skeet) do
        if (type ~= 2 or num ~= i) and s.active == 1 then
            if s.bounds:overlaps(bounds) then
                if s.bounds.left < bounds.left then
                    return 1
                elseif s.bounds.left > bounds.left then
                    return 2
                elseif s.bounds.top < bounds.top then
                    return 3
                elseif s.bounds.top > bounds.left then
                    return 4
                end
            end
        end
    end
    return 0
end
function Arena:checkRadar(k, r)
    local i, robot
    r.radar = false
    -- trim against walls
    for i, wall in ipairs(self.walls) do
        if r.rf:overlaps(wall) then
            if r.direction == 1 then
                r.rf.top = wall.bottom
            elseif r.direction == 2 then
                r.rf.right = wall.left
            elseif r.direction == 3 then
                r.rf.bottom = wall.top
            elseif r.direction == 4 then
                r.rf.left = wall.right
            end
        end
    end
    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
    for i, skeet in ipairs(self.skeet) do
        if r.rf:overlaps(skeet.bounds) and skeet.active == 1 then
            r.radar = true
        end
    end
    for i, track in ipairs(self.tracks) do
        if r.rf:overlaps(track.bounds) and track.active == 1 then
            r.radar = true
        end
    end
    pushStyle()
    fill(90, 181, 230, 74)
    noStroke()
    r.rf:draw()
    popStyle()
    r.fireRadar = false
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 
                    -- distance between
                    --d = robot.bounds.
                    robot.hp = robot.hp - r.weaponStrength
                    r.points = r.points + 1
                    if robot.heat < 20 then 
                        robot.heat = robot.heat + 5
                    end
                end
            end
        end
    end
    for i, s in ipairs(self.skeet) do 
        if r.rf:overlaps(s.bounds) and s.active == 1 then
            r.points = r.points + 1
            s.active = 2
        end
    end
    r.fireLaser = false
end
function Arena:checkCollisions(k, r)
    local i, b
      -- test outer walls
    if r.x < 5 then
        r.x = r.oldX
        r.bump = true
    elseif r.x > self.field:width() - 50 then
        r.x = r.oldX
        r.bump = true
    elseif r.y < 5 then
        r.y = r.oldY
        r.bump = true
    elseif r.y > self.field:height() - 30 then
        r.y = r.oldY
        r.bump = true
    end
    
    -- test interior walls
    for w, wall in ipairs(self.walls) do
        --wall:draw()
        if r.bounds:overlaps(wall) then
            r.bump = true
            r.y = r.oldY
            r.x = r.oldX
            --displayMode(STANDARD)
            --print(w)
        end
    end
    
    -- test tracks
    -- track collisions do not activate the bump sensor
    for i, track in ipairs(self.tracks) do 
        if r.bounds:overlaps(track.bounds) and track.active == 1 then
            r.points = r.points + 1
            track.active = 2
            sound(SOUND_POWERUP, 7170)
        end
    end
    
    -- test other bot collisions
    b = self:testBounds(1, k, r.bounds) 
    if b == 1 then
    -- hit from left
        if r.x < self.field:width() - 60 then r.x = r.x + 5 end
    elseif b == 2 then
    -- hit from right
        if r.x > 30 then r.x = r.x - 5 end
    elseif b == 1 then
    -- hit from bottom
        if r.y < self.field:height() - 30 then r.y = r.y + 5 end
    elseif b == 1 then
    -- hit from top
        if r.y > 30 then r.y = r.y - 5 end
    end 
    if b > 0 then r.bump = true end
end
function Arena:checkSkeetCollisions(k, s)
    local i, b
    
    b = self:testBounds(2, k, s.bounds) 
    if b > 0 then
        s.dx = - s.dx
        s.dy = - s.dy
    end
end
function Arena:setMatch(a, b, c, d)
    self.robots = {}
    self:loadRobot(a, 60, 60)
    self:loadRobot(b, 60, self.field:height() - 60)
    self:loadRobot(c, self.field:width() - 60, 60)
    self:loadRobot(d, self.field:width() - 60, self.field:height() - 60)
    self.timer = 100
end
function Arena:drawPen(r)
    local prevX, prevY, prevStatus, i, p
    prevStatus = false
    pushStyle()
    stroke(111, 333 - self.pulse, 111, 111)
    for i, p in ipairs(r.pen) do
        if prevStatus then
            line(prevX, prevY, p.x, p.y)
        end
        prevX = p.x
        prevY = p.y
        prevStatus = p.status
    end
    popStyle()
end
function Arena:draw()
    local k, robot, liveCount, i
    
    -- base elements
    pushStyle()
    stroke(255, 255, 255, 255)
    strokeWidth(2)
    noFill()
    self.frame:draw()
    self.panel:inset(10, 10)
    self.panel:draw()
    self.panel:inset(-10, -10)
    line(20, 40, WIDTH - 20, 40)
    
    if self.game == 2 then
        if self.robots[1].points == 8 or self.timer == 0 then
            self.gameOver = true
        end
    end
    
    if self.game == 3 then
        if self.robots[1].points == 30 or self.timer == 0 then
            self.gameOver = true
        end
        
    end
        
    self.stop:draw()
    for i = 1,3 do
        y = self.field.bottom + self.field:height() / 4 * i
        line(self.field.left, y, self.field.left + 10, y)
        line(self.field.right - 10, y, self.field.right, y)
    end
    self.pulse = self.pulse + self.pulseDirection
    if self.pulse > 255 or self.pulse < 0 then
        self.pulseDirection = 0 - self.pulseDirection
    end
    stroke(255, 55, 55, self.pulse)
    ellipse(self.stop:midX(), self.stop:midY(), 30)
    ellipse(self.stop:midX(), self.stop:midY(), 20)
    fill(255, 255, 255, 255)
    fontSize(36)
    text("Battle Chips",self.panel.left + 50, self.panel.top - 60)
    noFill()
    stroke(255, 255, 255, 255)
    pushMatrix()
    translate(self.panel.left + 32, self.panel.top - 40)
    for i = 0, 8 do
        rotate(i * 45)
        rect(-3,0,3,15)
    end
    fill(25, 27, 46, 255)
    ellipse(0, 0, 25)
    popMatrix()
    fill(255, 255, 255, 255)
    
    -- translate to field
    pushMatrix()
    translate(self.frame.left, self.frame.bottom)
    
    if not self.gameOver then
        -- draw walls
        stroke(111 + self.pulse, 111 + self.pulse, 255, 
        111 + self.pulse)
        for i, w in ipairs(self.walls) do
            w:draw()
        end
        
        -- draw skeet
        for i, s in ipairs(self.skeet) do
            if s.active <  10 then
                s:draw()
                self:checkSkeetCollisions(i, s)
            end
        end
        
        -- draw tracks
        for t, track in ipairs(self.tracks) do
            if track.active <  10 then
                track:draw()
            end
        end
        
        -- draw robots
        noSmooth()
        liveCount = 0
        for k, robot in ipairs(self.robots) do
            self:drawPen(robot)
            if robot.hp > 0 then liveCount = liveCount + 1 end
            if robot.fireRadar then
                self:checkRadar(k, robot)
            end
            if robot.fireLaser then
                self:checkLaser(k, robot)
            end
            self:checkCollisions(k, robot)
            robot:draw(1)
            if robot.hp > 0 then 
                robot:run()
            else 
                robot.hp = 0
            end
            
        end
        if liveCount < 2 and self.game == 4 then 
            self.timer = self.timer - 1
        else
            self.timer = self.timer - 0.1
        end
        if self.timer < 0 then self.timer = 0 end
        popMatrix()
        fontSize(12)
        textMode(LEFT)
        for k, robot in ipairs(self.robots) do
            
            if self.game < 2 then
                fill(159, 201, 223, 255)
                text(robot.name, 30, 900)
                s = robot.step - 30 * math.floor(robot.step / 30)
                if robot.program[robot.step] ~= nil and 
                   robot.program[robot.step].code ~= nil then
                    --displayMode(STANDARD)
                    
                    s = s.."  "..robot.program[robot.step].code.long1
                    --print(s)
                else
                    fill(223, 174, 174, 255)
                    s = s.."  NIL"
                end
                x = math.floor(robot.step / 30) * 250 + 50
                y = 850 - robot.step * 15 + 
                math.floor(robot.step / 30) * 450
                text(s, x, y)
            end
            x = self.frame.right - k * 60 - 100
            y = self.panel.bottom + 35
            sprite(robot.img, x - 15, y, x + 15, y + 30)
            
            fill(26, 26, 26, 255)
            stroke(130, 154, 221, 255)
            rect(self.frame.right - k * 60 - 127, 
            self.panel.bottom + 35,
            self.frame.right - k * 60 - 120, self.panel.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.panel.bottom + 36,
            self.frame.right - k * 60 - 121, self.panel.bottom + 36 +
            robot.hp * 3)
            fill(248, 248, 248, 255)
            text(robot.points, self.frame.right - k * 60 - 100, 
            self.panel.bottom + 25)
        end
        
        if self.tourney then 
            textMode(CORNER)
            fontSize(48)
            fill(218, 214, 214, 81)
            if self.game == 1 then
                text("Melee", self.field.left + 15, self.field.top - 60)
            end
            if self.game == 2 then
                text("Skeet", self.field.left + 15, self.field.top - 60)
            end
            if self.game == 3 then
                text("Maze", self.field.left + 15, self.field.top - 60)
            end
            text(math.floor(self.timer), 
            self.frame.left + 15, self.field.bottom)
        else
            strokeWidth(1)
            stroke(255, 255, 255, 255)
            line(self.field:midX() - 5, self.field.bottom , 
            self.field:midX() + 5, self.field.bottom )
            line(self.field:midX(), self.field.bottom + 5, 
            self.field:midX(), self.field.bottom - 5)
            line(self.field:midX() - 5, self.field.bottom + 5, 
            self.field:midX() + 5, self.field.bottom  - 5)
            line(self.field:midX() - 5, self.field.bottom - 5, 
            self.field:midX() + 5, self.field.bottom  + 5)
        end
    else 
    -- game over
        if self.game == 2 then
            self.robots[1].x = 100
            self.robots[1].y = 700
            self.robots[1]:draw(1)
            fontSize(32)
            text("Skeet Results", 100, 800)
            fontSize(24)
            text(self.robots[1].name, 200, 700)
            text("Skeet destroyed", 100, 600)
            text("Time remaining", 100, 500)
            text("Total Score", 100, 400)
            text(self.robots[1].points, 500, 600)
            text(math.floor(self.timer), 500, 500)
            score = self.robots[1].points * 10 + math.floor(self.timer)
            text(score, 500, 400)
        end
        if self.game == 3 then
            self.robots[1].x = 100
            self.robots[1].y = 700
            self.robots[1]:draw(1)
            fontSize(32)
            text("Maze Results", 100, 800)
            fontSize(24)
            text(self.robots[1].name, 200, 700)
            text("Tracks stomped", 100, 600)
            text("Time remaining", 100, 500)
            text("Total Score", 100, 400)
            text(self.robots[1].points, 500, 600)
            text(math.floor(self.timer), 500, 500)
            score = self.robots[1].points * 5 + math.floor(self.timer)
            text(score, 500, 400)
        end
    end
    popStyle()
end
function Arena:touched(touch)
    if self.launch:touched(touch) and 
        ElapsedTime > self.launchTime + 1 then
        sound(SOUND_POWERUP, 26548)
        self.skeet[#self.skeet + 1] = Skeet(self.field:midX(), 
        20, self.field)
        self.launchTime = ElapsedTime
    end
    if self.frame:touched(touch) then
        return true
    end
    return false
end
BigButton = class()
function BigButton:init(t, x, y)
    self.text = t
    self.frame = Frame(x, y, x + 140, y + 80)
    self.active = true
end
function BigButton:draw()
    if self.active then
        stroke(255, 255, 255, 255)
    else
        stroke(93, 95, 125, 255)
    end
    strokeWidth(2)
    noFill()
    self.frame:draw()
    if self.active then
        fill(255, 255, 255, 255)
    else
        fill(98, 100, 134, 255)
    end
    fontSize(24)
    textMode(CORNER)
    text(self.text, self.frame.left + 20, self.frame.top - 40)
end
function BigButton:touched(touch)
    return self.frame:touched(touch)
end
Code = class()
function Code:init(short, long1, long2, hasValue, clr)
    -- you can accept and set parameters here
    self.short = short
    self.long1 = long1
    self.long2 = long2
    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 - 30,
    self.frame.right - 4, self.frame.top - 4)
    self.mini = {}
    for i = 1, 3 do
        self.mini[i] = Frame(35 + (i - 1) * 180, 35,
        170 + (i - 1) * 180, 105)
    end
    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 + 71)
            self.sockets[socket + 30] = 
            Socket(nil, x * 250 - 180, y * 45 + 71)
            self.sockets[socket + 60] = 
            Socket(nil, x * 250 - 180, y * 45 + 71)
        end
    end
    self.selectedSocket = 0
    self.action = 0
    self.tokens = {}
    self.pulse = 0
    self.board = 1
end
function CodeBench:loadRobot(r)
    local i, p
    for i = 1,90 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()
    local x, y
    pushStyle()
    fontSize(16)
    tint(27, 27, 27, 255)
    sprite(boardImg, self.frame.left, self.frame.bottom, 
        self.frame.right, self.frame.top)
        
    stroke(249, 249, 249, 255)
    noFill()
    strokeWidth(2)
    for i = 1,3 do
        sprite(boardImg, self.mini[i].left, self.mini[i].bottom, 
        self.mini[i].right, self.mini[i].top)
        self.mini[i]:draw()
    end
    
    self.frame:draw()
    fill(87, 87, 87, 221)
    noStroke()
    tint(172, 195, 221, 255)
    sprite(chipImg, self.header.left, self.header.bottom, 
        self.header.right, self.header.top)
        
    --self.header:draw()
    pushMatrix()
    translate(self.x, self.y)
    -- trace lines
    fill(255, 210, 0, 219)
    stroke(127, 127, 127, 255)
    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)
    
    
    strokeWidth(1)
    stroke(185, 185, 185, 255)
    fill(189, 189, 189, 255)
    line(0, self.frame:height() + 15, self.frame:width()/2 - 10,
     self.frame:height() + 15)
    line(self.frame:width()/2 + 70, self.frame:height() + 15, 
    self.frame:width(), self.frame:height() + 15)
    line(0, self.frame:height() + 10, 0, self.frame:height() + 20)
    line(self.frame:width(), self.frame:height() + 10, 
    self.frame:width(), self.frame:height() + 20)
    text("3.54 cm", self.frame:width()/2, self.frame:height() + 5)
    line(-15, 0, -15, self.frame:height() / 2 - 10)
    line(-15, self.frame:height(), -15, self.frame:height() / 2 + 70)
    line(-20, self.frame:height(), -10, self.frame:height())
    line(-20, 0, -10, 0)
    
    rotate(90)
    text("7.80 cm", self.frame:height() / 2 , 5)
    rotate(-90)
    fontSize(12)
    if self.board == 1 then
        text("Use only GR-32 chips", 10, 10)
        text("RMS9000", 400 , 10)
        text("24V 17.5A   REV.B", 200 , 10)
        text("X1", 200 , 200)
    elseif self.board == 2 then
        text("Must be used with RMS9000 Mainboard", 10, 10)
        text("RDB9000-A", 400 , 10)
        fill(25, 27, 46, 255)
        strokeWidth(3)
        rect(470,50,500,90)
        noStroke()
        rect(490,53,505,87)
    elseif self.board == 3 then
        text("Must be used with RMS9000 Mainboard", 10, 10)
        text("RDB9000-B", 400 , 10)
        fill(25, 27, 46, 255)
        strokeWidth(3)
        ellipse(485,40,10)
        ellipse(485,100,10)
        rect(470,50,500,90)
        noStroke()
        rect(490,53,505,87)
        
    end
    socket = 1 + (self.board - 1) * 30
    for x = 1,2 do 
        for y = 15,1,-1 do
            noStroke()
            fill(175, 170, 189, 255)
            rect(x * 250 - 210, y * 45 + 70, 
                 x * 250 - 30, y * 45 + 102)
                
            strokeWidth(2)
            stroke(82, 82, 82, 255)
            fill(30, 28, 26, 255)
            self.sockets[socket]:draw()
            
            noStroke()
            
            stroke(127, 127, 127, 255)
            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)
            if self.sockets[socket].code 
            ~= nil then
                stroke(250, 21, 13, 255)
                fill(75, 75, self.pulse, 255)
                ellipse(x * 250 - 210, y * 45 + 86, 10)
            end
            fill(0, 0, 0, 255)
            text(socket - (self.board - 1) * 30,
             x * 250 - 200, y * 45 + 78)
            socket = socket + 1
        end
    end
    fill(255, 255, 255, 255)
    
    fontSize(16)
    if self.board == 1 then
        text("MAIN BOARD", 10, self.frame:height() - 25)
    elseif self.board == 2 then
        text("DAUGHTERBOARD A", 10, self.frame:height() - 25)
    elseif self.board == 3 then
        text("DAUGHTERBOARD B", 10, self.frame:height() - 25)
    end
    popMatrix()
    strokeWidth(1)
    stroke(193, 193, 193, 255)
    line(self.mini[self.board].left - 20, self.mini[self.board].bottom,
    self.mini[self.board].left - 10, self.mini[self.board].bottom)
    line(self.mini[self.board].left - 15, self.mini[self.board].bottom,
    self.mini[self.board].left - 15, self.mini[self.board].top)
    line(self.mini[self.board].left - 20, self.mini[self.board].top,
    self.mini[self.board].left - 10, self.mini[self.board].top)
    
    line(self.mini[self.board].left, self.mini[self.board].top + 20,
    self.mini[self.board].left + 25, self.mini[self.board].top + 20)
    line(self.mini[self.board].right, self.mini[self.board].top + 20,
    self.mini[self.board].right - 25, self.mini[self.board].top + 20)
    line(self.mini[self.board].left, self.mini[self.board].top + 25,
    self.mini[self.board].left, self.mini[self.board].top + 15)
    line(self.mini[self.board].right, self.mini[self.board].top + 25,
    self.mini[self.board].right, self.mini[self.board].top + 15)
    fill(171, 171, 171, 255)
    text("Selected", self.mini[self.board].left + 30, 
    self.mini[self.board].top + 12)
    popStyle()
    text("Main", self.mini[1].left + 10, self.mini[1]:height())
    text("A", self.mini[2].left + 10, self.mini[2]:height())
    text("B", self.mini[3].left + 10, self.mini[3]:height())
    self.pulse = self.pulse + 5
    if self.pulse > 255 then self.pulse = 1 end
end
function CodeBench:touched(touch)
    local i, t, first, last
    t =Ttouch(touch)
    t:translate(self.x, self.y - 10)
    self.action = 0
    first = 1 + (self.board - 1) * 30
    last = first + 29
    for i = first, last 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)
    -- boundary
    self.frame = Frame(l, b, r, t)
    
    -- textbox for name
    self.tb = TextBox(self.frame:midX() - 160, b + 30, 200, "")
    
    -- color selector & frame
    self.colorFrame = Frame(150, 600, 260, 624)
    self.showColorSlider = false
    self.colorVCS = VColorSlider(self.colorFrame.left, 
    self.colorFrame.top)
    
    -- side tabs
    self.dishBtn = OpenBtn("Dish", self.frame.left, 
    self.frame.top - 80)
    self.headBtn = OpenBtn("Head", self.frame.left, 
    self.frame.top - 115)
    self.bodyBtn = OpenBtn("Body", self.frame.left, 
    self.frame.top - 150)
    self.treadBtn = OpenBtn("Treads", self.frame.left, 
    self.frame.top - 185)
    self.dishBtn.selected = true
    
    -- catalog area
    self.catalogFrame = Frame(120, 500, 750, 955)
    
    -- selected item
    self.selectRect = {}
    self.selectRect[1] = Frame(120, 650, 320, 955 )
    self.selectRect[2] = Frame(320, 650, 520, 955 )
    self.selectRect[3] = Frame(520, 650, 720, 955 )
    self.page = 1
end
function DesignStudio:drawDishes()
    local x, y
    x = self.selectRect[1]:midX()
    y = self.selectRect[1]:midY() + 50
    stroke(colors[self.bot.dishColor])
    
    line(x - 5, y, x, y + 20)
    line(x + 5, y, x, y + 20)
    line(x - 30, y + 10, x - 20, y + 5)
    line(x - 20, y + 5, x, y)
    line(x + 30, y + 10, x + 20, y + 5)
    line(x + 20, y + 5, x, y)
    line(x, y + 20, x, y + 30)
    ellipse(x, y + 20, 5)
    fill(255, 255, 255, 255)
    
    text("Laserator X-49", x, y + 50)
    text("20m", x, y - 70)
    text("100kw", x, y - 90)
    text("10cycles", x, y - 110)
    
    noFill()
    x = self.selectRect[2]:midX()
    y = self.selectRect[2]:midY() + 50
    rect(x - 5, y, x + 5, y + 25)
    line(x - 20, y, x, y)
    line(x + 20, y, x, y)
    line(x - 30, y + 15, x, y)
    line(x + 30, y + 15, x, y)
    fill(255, 255, 255, 255)
    text("Thumperator Max", x, y + 50)
    text("7m", x, y - 70)
    text("250kw", x, y - 90)
    text("15cycles", x, y - 110)
    
    noFill()
    x = self.selectRect[3]:midX()
    y = self.selectRect[3]:midY() + 50
    line(x - 20, y, x + 20, y)
    line(x - 15, y + 5, x + 15, y + 5)
    line(x - 10, y + 10, x + 10, y + 10)
    line(x - 5, y + 15, x + 5, y + 15)
    line(x, y, x, y + 30)
    ellipse(x, y + 35, 10)
    fill(255, 255, 255, 255)
    text("Zapmaster 1000", x, y + 50)
    text("3m", x, y - 70)
    text("500kw", x, y - 90)
    text("15cycles", x, y - 110)
    fill(colors[self.bot.dishColor])
    self.colorFrame:draw()
    
    textMode(CORNER)
    fill(255, 255, 255, 255)
    text("Dish units include both radar and weaponry.", 300, 625)
    text("Some units have a long range, but cause ", 300, 600)
    text("light damage. Others deliver a harder blow ", 300, 575)
    text("but can only do so at short range.", 300, 550)
    
    stroke(201, 201, 201, 255)
    x = self.selectRect[self.bot.dish].left + 20
    y = self.selectRect[self.bot.dish].bottom + 85
    line(x, y, x, y + 175)
    line(x - 5, y, x + 5, y)
    line(x - 5, y + 175, x + 5, y + 175)
    line(x + 10, y - 20, x + 40, y - 20)
    line(x + 125, y - 20, x + 160, y - 20)
    line(x + 10, y - 25, x + 10, y - 15)
    line(x + 160, y - 25, x + 160, y - 15)
    fill(209, 209, 209, 255)
    text("Selected", x + 45, y - 30)
end
function DesignStudio:drawHeads()
    local x, y
    
    x = self.selectRect[1]:midX()
    y = self.selectRect[1]:midY() + 50
    stroke(colors[self.bot.headColor])
    ellipse(x, y, 30)
    rect(x - 15, y - 5, x - 13, y + 5)
    rect(x + 15, y - 5, x + 13, y + 5)
    line(x - 15, y, x - 20, y)
    line(x + 15, y, x + 20, y)
    fill(255, 255, 255, 255)
    text("Cool Bean", x, y + 50)
    text("10hds", x, y - 70)
    text("0.0 shield", x, y - 90)
    noFill()
    x = self.selectRect[2]:midX()
    y = self.selectRect[2]:midY() + 50
    ellipse(x, y, 30)
    ellipse(x, y, 25)
    line(x+5,y+5,x-5,y-5)
    line(x+5,y-5,x-5,y+5)
    fill(255, 255, 255, 255)
    text("Bubble Boyo", x, y + 50)
    text("3hds", x, y - 70)
    text("3.5 shield", x, y - 90)
    
    noFill()
    x = self.selectRect[3]:midX()
    y = self.selectRect[3]:midY() + 50
    ellipse(x, y, 30)
    ellipse(x, y + 10, 25, 10)
    ellipse(x, y + 15, 15, 5)
    line(x - 15, y - 5, x - 25, y - 15)
    line(x + 15, y - 5, x + 25, y - 15)
    fill(255, 255, 255, 255)
    text("Headvantage", x, y + 50)
    text("1hds", x, y - 70)
    text("5.5 shield", x, y - 90)
    
    textMode(CORNER)
    fill(255, 255, 255, 255)
    text("Head units both generate shields and help to ", 300, 625)
    text("automatically repair bots when damaged. Those ", 300, 600)
    text("units that provide the best shields are slow", 300, 575)
    text("at repairs, while the best repair units have", 300, 550)
    text("weak shields.", 300, 525)
    fill(colors[self.bot.headColor])
    self.colorFrame:draw()
    
    stroke(201, 201, 201, 255)
    x = self.selectRect[self.bot.head].left + 20
    y = self.selectRect[self.bot.head].bottom + 85
    line(x, y, x, y + 175)
    line(x - 5, y, x + 5, y)
    line(x - 5, y + 175, x + 5, y + 175)
    line(x + 10, y - 20, x + 40, y - 20)
    line(x + 125, y - 20, x + 160, y - 20)
    line(x + 10, y - 25, x + 10, y - 15)
    line(x + 160, y - 25, x + 160, y - 15)
    fill(209, 209, 209, 255)
    text("Selected", x + 45, y - 30)
end
function DesignStudio:drawTreads()
    local i, x, y
    
    x = self.selectRect[1]:midX()
    y = self.selectRect[1]:midY() + 50
    stroke(colors[self.bot.treadColor])
    ellipse(x + 20,y -20, 20)
    ellipse(x + 20, y -20, 20, 5)
    ellipse(x-20, y-20, 20)
    ellipse(x-20, y-20, 20, 5)
    ellipse(x-20, y+20, 20)
    ellipse(x-20, y+20, 20, 5)
    ellipse(x+20, y+20, 20)
    ellipse(x+20, y+20, 20, 5)
    line(x-20, y-11, x, y)
    line(x-17, y-14, x, y)
    line(x+20, y-11, x, y)
    line(x+17, y-14, x, y)
    line(x-20, y+11, x, y)
    line(x-17, y+14, x, y)
    line(x+20, y+11, x, y)
    line(x+17, y+14, x, y)
    fill(255, 255, 255, 255)
    text("Spinomatic", x, y + 50)
    text("90dpc", x, y - 70)
    text("10kph", x, y - 90)
    noFill()
    
    x = self.selectRect[2]:midX()
    y = self.selectRect[2]:midY() + 50
    rect(x - 15, y - 2, x + 15, y + 2)
    ellipse(x, y - 4, 15)
    line(x - 15, y - 10, x + 15, y - 10)
    rect(x - 30, y - 30, x - 15, y + 30)
    rect(x + 15, y - 30, x + 30, y + 30)
    
    for i = 0,7 do
        line(x + 15, y - 30 + i * 8, x + 30, y - 30 + i * 8)
        line(x - 30, y - 30 + i * 8, x - 15, y - 30 + i * 8)
    end
    
    fill(255, 255, 255, 255)
    text("Tanktrak T11", x, y + 50)
    text("45dpc", x, y - 70)
    text("25kph", x, y - 90)
    
    noFill()
    x = self.selectRect[3]:midX()
    y = self.selectRect[3]:midY() + 50
    rect(x - 30, y + 10, x - 20, y + 30)
    rect(x + 20, y + 10, x + 30, y + 30)
    rect(x - 30, y - 30, x - 20, y - 10)
    rect(x + 20, y - 30, x + 30, y - 10)
    ellipse(x - 25, y + 20, 15, 25)
    ellipse(x - 25, y - 20, 15, 25)
    ellipse(x + 25, y + 20, 15, 25)
    ellipse(x + 25, y - 20, 15, 25)
    rect(x - 20, y - 22, x + 20, y - 16)
    rect(x - 20, y + 22, x + 20, y + 16)
    
    fill(255, 255, 255, 255)
    text("Hard Wheelz", x, y + 50)
    text("15dpc", x, y - 70)
    text("50kph", x, y - 90)
    
    textMode(CORNER)
    fill(255, 255, 255, 255)
    text("Treads provide the means for bots to move ", 300, 625)
    text("around the arena. Some units are capable of ", 300, 600)
    text("turning rapidly, but are slow getting from ", 300, 575)
    text("A to B. Other systems sacrifice agility for", 300, 550)
    text("raw speed.", 300, 525)
    fill(colors[self.bot.treadColor])
    self.colorFrame:draw()
    
    stroke(201, 201, 201, 255)
    x = self.selectRect[self.bot.tread].left + 20
    y = self.selectRect[self.bot.tread].bottom + 85
    line(x, y, x, y + 175)
    line(x - 5, y, x + 5, y)
    line(x - 5, y + 175, x + 5, y + 175)
    line(x + 10, y - 20, x + 40, y - 20)
    line(x + 125, y - 20, x + 160, y - 20)
    line(x + 10, y - 25, x + 10, y - 15)
    line(x + 160, y - 25, x + 160, y - 15)
    fill(209, 209, 209, 255)
    text("Selected", x + 45, y - 30)
end
function DesignStudio:drawBodies()
    local x, y
    
    x = self.selectRect[1]:midX()
    y = self.selectRect[1]:midY() + 50
    stroke(colors[self.bot.bodyColor])
    ellipse(x - 20, y, 15, 15)
    ellipse(x + 20, y, 15, 15)
    fill(25, 27, 46, 255)
    ellipse(x, y, 40, 20)
    fill(255, 255, 255, 255)
    text("LightWay C", x, y + 50)
    text("10mm", x, y - 70)
    text("47kg", x, y - 90)
    
    fill(25, 27, 46, 255)
    x = self.selectRect[2]:midX()
    y = self.selectRect[2]:midY() + 50
    rect(x - 25, y - 10, x + 25, y + 10)
    ellipse(x - 25, y, 20)
    ellipse(x + 25, y, 20)
    rect(x - 15, y - 15, x + 15, y - 10)
    
    
    fill(255, 255, 255, 255)
    text("Steel Trunk", x, y + 50)
    text("20mm", x, y - 70)
    text("90kg", x, y - 90)
    
    fill(25, 27, 46, 255)
    x = self.selectRect[3]:midX()
    y = self.selectRect[3]:midY() + 50
    ellipse(x - 20, y, 30, 30)
    ellipse(x + 20, y, 30, 30)
    rect(x - 20, y - 15, x + 20, y + 15)
    ellipse(x, y, 40, 30)
    
    fill(255, 255, 255, 255)
    text("ToughBugger II", x, y + 50)
    text("50mm", x, y - 70)
    text("250kg", x, y - 90)
    
    textMode(CORNER)
    fill(255, 255, 255, 255)
    text("Body units protect the bot from damage and  ", 300, 625)
    text("allow it to absorb more blows before failing. ", 300, 600)
    text("However, as armor increases in weight, it ", 300, 575)
    text("reduces both the speed of movement and of", 300, 550)
    text("turning.", 300, 525)
    fill(colors[self.bot.bodyColor])
    self.colorFrame:draw()
    
    stroke(201, 201, 201, 255)
    x = self.selectRect[self.bot.body].left + 20
    y = self.selectRect[self.bot.body].bottom + 85
    line(x, y, x, y + 175)
    line(x - 5, y, x + 5, y)
    line(x - 5, y + 175, x + 5, y + 175)
    line(x + 10, y - 20, x + 40, y - 20)
    line(x + 125, y - 20, x + 160, y - 20)
    line(x + 10, y - 25, x + 10, y - 15)
    line(x + 160, y - 25, x + 160, y - 15)
    fill(201, 201, 201, 255)
    text("Selected", x + 45, y - 30)
end
function DesignStudio:setBot(bot)
    self.bot = bot
    self.tb.text = self.bot.name
end
function DesignStudio:draw()
    pushMatrix()
    fontSize(18)
    noFill()
    stroke(255, 255, 255, 255)
    strokeWidth(2)
    stroke(0, 38, 255, 255)
    strokeWidth(2)
    fill(185, 185, 185, 113)
    self.tb:draw()
    fill(255, 255, 255, 255)
    text("Color", self.colorFrame.left, self.colorFrame.top)
    fontSize(24)
    text("Design Studio", self.frame.left + 120, self.frame.top - 35)
    
    fill(colors[self.bot.dishColor])
    self.colorFrame:draw()
    
    noFill()
    stroke(255, 255, 255, 255)
    strokeWidth(2)
    self.catalogFrame:draw()
    rect(self.catalogFrame.left, self.catalogFrame.top,
    self.catalogFrame.right, self.catalogFrame.top + 50)
    rect(self.catalogFrame.left, self.catalogFrame.bottom - 90,
    self.catalogFrame.right, self.catalogFrame.bottom)
    
    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()+ 90 , self.frame:height() - 170)
    
    self.bot.x = 0
    self.bot.y = 0
    self.bot:draw(1)
    
    popMatrix()
    self.headBtn:draw()
    self.dishBtn:draw()
    self.bodyBtn:draw()
    self.treadBtn:draw()
    fontSize(16)
    textMode(CENTER)
    strokeWidth(1.1)
    if self.page == 1 then
        self:drawDishes()
    end
    if self.page == 2 then
        self:drawHeads()
    end
    if self.page == 3 then
        self:drawBodies()
    end
    if self.page == 4 then
        self:drawTreads()
    end
    if self.showColorSlider then
        self.colorVCS:draw()
    end
end
function DesignStudio:clearSelected()
    self.dishBtn.selected = false
    self.headBtn.selected = false
    self.bodyBtn.selected = false
    self.treadBtn.selected = false
end
    
function DesignStudio:touched(touch)
    local i
    self.bot.name = self.tb.text
    if self.colorFrame:touched(touch) then
        self.showColorSlider = true
    end
    if self.showColorSlider then
        if self.colorVCS:touched(touch) then
            if self.page == 1 then 
                self.bot.dishColor = self.colorVCS.selected
            end
            if self.page == 2 then 
                self.bot.headColor = self.colorVCS.selected
            end
            if self.page == 3 then 
                self.bot.bodyColor = self.colorVCS.selected
            end
            if self.page == 4 then 
                self.bot.treadColor = self.colorVCS.selected
            end
        end
    end
    if self.dishBtn:touched(touch) then
        self.page = 1
        self:clearSelected()
        self.dishBtn.selected = true
    end
    if self.headBtn:touched(touch) then
        self.page = 2
        self:clearSelected()
        self.headBtn.selected = true
    end
    if self.bodyBtn:touched(touch) then
        self.page = 3
        self:clearSelected()
        self.bodyBtn.selected = true
    end
    if self.treadBtn:touched(touch) then
        self.page = 4
        self:clearSelected()
        self.treadBtn.selected = true
    end
    for i = 1,3 do
        if self.selectRect[i]:touched(touch) then
            sound(SOUND_SHOOT, 46433)
            if self.page == 1 then self.bot.dish = i end
            if self.page == 2 then self.bot.head = i end
            if self.page == 3 then self.bot.body = i end
            if self.page == 4 then self.bot.tread = i end
        end
    end
end
Divider = class()
function Divider:init(name, l, t, r, b)
    self.name = name
    self.frame = Frame(l, t, r, b)
end
function Divider:draw()
    pushStyle()
    strokeWidth(1)
    stroke(247, 247, 247, 255)
    tint(143, 203, 223, 255)
    sprite(chipImg, self.frame.left, self.frame.bottom, 
    self.frame.right, self.frame.top)
    fill(255, 255, 255, 255)
    text(self.name, self.frame.left + 10, self.frame.bottom + 5)
    noFill()
    self.frame:draw()
    popStyle()
end
function Divider:touched(touch)
    return self.frame:touched(touch)
end
-- Batlle Chips 26 Jun 12
-- Mark Sumner
-- devilstower@gmail.com
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)
rectMode(CORNERS)
spriteMode(CORNERS)
textMode(CORNER)
noSmooth()
font("Copperplate")
function setup()
    local y, x, i
    
    -- create background images
    gridImg = image(200, 200)
    fill(25, 27, 46, 255)
    stroke(255, 255, 255, 25)
    setContext(gridImg)
    noStroke()
    rect(0,0,200,200)
    strokeWidth(1)
    r = HEIGHT/WIDTH
    for y = 0, 59 do
        line(0, y * 4, 200, y * 4)
    end
    for x = 0,39 do
        line(x * 4 * r, 0, x * 4 * r, 200)
    end
    
    -- chip texture
    setContext()
    chipImg = image(145, 30)
    fill(79, 79, 79, 255)
    stroke(131, 123, 123, 135)
    strokeWidth(1)
    setContext(chipImg)
    rect(0,0,200,200)
    for y = 0, 20 do
        line(0, y * 3, 200, y * 3)
    end
    for x = 0,70 do
        line(x * 3, 0, x * 3 + 30, 200)
    end
    setContext()
    
    -- circut board texture
    boardImg = image(200, 200)
    fill(255, 255, 255, 255)
    strokeWidth(1)
    setContext(boardImg)
    rect(0,0,200,200)
    stroke(29, 54, 30, 135)
    for x = 0, 200 do
        line(x * 2, 0, x * 2, 200)
    end
    stroke(72, 72, 72, 135)
    for x = 0, 200 do
        line(0, x * 2, 200, x * 2)
    end
    setContext()
    
    -- robot array
    robots = {}
    for i = 1,20 do
        robots[i] = Robot(17 + i * 70,300)
    end
    
    -- definition of program codes
    codes = {}
    color(219, 11, 10, 255)
    codes[1] = Code("F", "Forward", "", false, color(219, 11, 10, 255))
    codes[2] = Code("L", "Turn", "Left", false, color(219, 11, 10, 255))
    codes[3] = Code("R", "Turn", "Right", 
    false, color(219, 11, 10, 255))
    codes[4] = Code("B", "Reverse", "", false, color(219, 11, 10, 255))
    codes[5] = Code("W", "Fire!", "", 
    false, color(251, 215, 9, 255))
    codes[6] = Code("H", "Bump", "", true, color(95, 99, 229, 255))
    codes[7] = Code("A", "Radar", "", true, color(95, 99, 229, 255))
    codes[8] = Code("I", "Radar", "Right", 
    true, color(95, 99, 229, 255))
    codes[9] = Code("T", "Radar", "Left", 
    true, color(95, 99, 229, 255))
    codes[10] = Code("D", "Damage", "", true, color(95, 99, 229, 255))
    codes[11] = Code("G", "Goto", "", true, color(31, 195, 17, 255))
    codes[12] = Code("5", "Random", "", true, color(31, 195, 17, 255))
    codes[13] = Code("P", "Repeat", "", true, color(31, 195, 17, 255))
    codes[14] = Code("+", "Shields", "On", false, 
    color(251, 215, 9, 255))
    codes[15] = Code("-", "Shields", "Off", false, 
    color(251, 215, 9, 255))
    codes[16] = Code("E", "Conduct", "Repairs", 
    false, color(251, 215, 9, 255))
    codes[17] = Code("1", "Board", "A", false, color(42, 251, 8, 255))
    codes[18] = Code("2", "Board", "B", false, color(42, 251, 8, 255))
    codes[19] = Code("S", "Sound", "Horn", false,
     color(251, 215, 9, 255))
    codes[20] = Code("v", "Pen", "Down", false,
     color(251, 215, 9, 255))
    codes[21] = Code("^", "Pen", "Up", false,
     color(251, 215, 9, 255))
    mode = 1
    dragToken = Token(codes[1], 0, 0)
    bench = CodeBench(35, 150)
    scheduler = TourneyOrganizer(35, 150)
    tray = TokenTray(550, 150)
    oldState = nil
    doneBtn = BigButton("Done", 550, 25)
    doneBtn.frame.right = doneBtn.frame.right + 60
    codeBtn = BigButton("Code", 220, 100)
    designBtn = BigButton("Design", 30, 100)
    tourneyBtn = BigButton("Compete", 410, 100)
    tradeBtn = BigButton("Trade", 600, 100)
    
    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, 200, 
        i * 87 + 80, 300)
    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
        r.wins = r.body * 10 + r.tread
        r.losses = r.head * 10 + r.dish
        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])
            robots[r].body = math.floor(robots[r].wins / 10)
            robots[r].head = math.floor(robots[r].losses / 10)
            robots[r].tread = math.fmod(robots[r].wins , 10)
            robots[r].dish = math.fmod(robots[r].losses , 10)
            if robots[r].body == 0 then robots[r].body = 2 end
            if robots[r].head == 0 then robots[r].head = 1 end
            if robots[r].tread == 0 then robots[r].tread = 2 end
            if robots[r].dish == 0 then robots[r].dish = 1 end
            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()
    local i
    pushStyle()
    fill(0, 0, 0, 255)
    stroke(0, 69, 255, 255)
    tint(249, 249, 249, 255)
    
    strokeWidth(2)
    textMode(CENTER)
    
    fontSize(12)
    stroke(255, 255, 255, 255)
    for i = 1, 7 do
        noFill()
        noStroke()
        botFrames[i]:draw()
        robots[i + leftRobot - 1].x = botFrames[i].left + 10
        robots[i + leftRobot - 1].y = botFrames[i]:midY()
        fill(255, 255, 255, 255)
        text(robots[i + leftRobot - 1].name, botFrames[i]:midX(),
         botFrames[i].bottom+32)
    end
    codeBtn:draw()
    designBtn:draw()
    tourneyBtn:draw()
    tradeBtn:draw()
    
    textMode(CORNER)
    stroke(255, 255, 255, 255)
    
    fill(255, 255, 255, 255)
    stroke(213, 213, 213, 255)
    strokeWidth(1)
    line(arena.frame.left, arena.frame.bottom - 15,
    arena.frame:midX() - 50, arena.frame.bottom - 15)
    line(arena.frame.right, arena.frame.bottom - 15,
    arena.frame:midX() + 60, arena.frame.bottom - 15)
    line(arena.frame.left, arena.frame.bottom - 20,
    arena.frame.left, arena.frame.bottom - 10)
    line(arena.frame.right, arena.frame.bottom - 20,
    arena.frame.right, arena.frame.bottom - 10)
    fontSize(16)
    text("10.3 meters", arena.frame:midX() - 45, 
    arena.frame.bottom - 25)
    stroke(255, 255, 255, 255)
    strokeWidth(1)
    if leftRobot > 1 then 
        line(10, 280, 50, 310)
        line(10, 280, 50, 250)
        line(50, 310, 50, 250)
    end
    if leftRobot < 13 then 
        line(WIDTH - 10, 280, WIDTH - 50, 310)
        line(WIDTH - 10, 280, WIDTH - 50, 250)
        line(WIDTH - 50, 250, WIDTH - 50, 310)
    end
    strokeWidth(1)
    popStyle()
end
function draw() 
    local i, m
    noSmooth()
    background(255, 255, 255, 255)
    tint(255, 255, 255, 255)
    sprite(gridImg, 0, 0, WIDTH, HEIGHT)
    
    if mode == 1 then 
        arena:draw() 
    end
    
    if mode == 1 and arena.game == 1 then
        drawMain()
        for i = 1,7 do
            s = math.abs(4 - i) / 10
            robots[i + leftRobot - 1]:draw(1)
        end
    elseif mode == 2 then
        bench:draw()
        tray:draw()
        if showSlider then
            vslider:draw()
        end
        doneBtn:draw()
        
    elseif mode == 3 then
        studio:draw()
        doneBtn:draw()
    elseif mode == 4 then
        scheduler:draw(robots)
        doneBtn:draw()
    elseif mode == 5 then
        trader:draw(robots)
        doneBtn:draw()
    end
    -- touch handling
    if mode == 1 then
        if CurrentTouch.state == BEGAN and 
            CurrentTouch.state ~= oldState then
            if arena:touched(CurrentTouch) then
            end
            if arena.stop:touched(CurrentTouch) then
                arena:sizeFrames(10, HEIGHT - 650, 
                WIDTH - 10, HEIGHT - 10)
                arena:clear()
            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(1)
            end
        end
        if CurrentTouch.state == ENDED 
        and CurrentTouch.state ~= oldState then
            if selectedRobot > 0 then
                if codeBtn:touched(CurrentTouch) then
                    bench:loadRobot(robots[selectedRobot])
                    mode = 2
                end
                if designBtn:touched(CurrentTouch) then
                    showKeyboard()
                    doneBtn.frame.top = 380
                    doneBtn.frame.bottom = 300
                    studio:setBot(robots[selectedRobot])
                    mode = 3
                end
                if tourneyBtn:touched(CurrentTouch) then
                    scheduler:loadRobot(selectedRobot)
                    selectedRobot = 0
                    mode = 4
                end
                if tradeBtn:touched(CurrentTouch) then
                    trader:loadRobot(selectedRobot)
                    selectedRobot = 0
                    mode = 5
                end
                if arena:touched(CurrentTouch) then
                    if table.maxn(arena.robots) < 4 then
                        arena:loadRobot(robots[selectedRobot],
                        CurrentTouch.x, 111)
                    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
            for i = 1,3 do 
                if bench.mini[i]:touched(CurrentTouch) then
                    if bench.board ~= i then
                        bench.board = i
                        sound(DATA, "ZgNAZgBBASw/EiBhpHA9PqcNdD6dNtA9GAADTRUtLU4wP3wA")
                    end
                end
            end
            if showSlider then showSlider = false end
            if doneBtn:touched(CurrentTouch) then
                -- save code
                for i = 1,90 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
                doneBtn.frame.top = 140
                doneBtn.frame.bottom = 60
                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.showColorSlider = 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
                arena:clear()
                for i = 1, 4 do
                    if scheduler.contestants[i] == 0 then
                        scheduler.contestants[i] = math.random(20)
                    end
                end
                arena:loadRobot(robots[scheduler.contestants[1]],
                60, 60)
                arena:loadRobot(robots[scheduler.contestants[2]],
                60, arena.field:height() - 60)
                arena:loadRobot(robots[scheduler.contestants[3]],
                arena.field:height() - 60, arena.field:height() - 60)
                arena:loadRobot(robots[scheduler.contestants[4]],
                arena.field:height() - 60, 60)
                arena.game = 4
                arena.tourney = true
                arena:sizeFrames(10, 60, WIDTH - 10, HEIGHT - 10)
            end
            if scheduler.skeetBtn:touched(CurrentTouch) then
                mode = 1
                arena:sizeFrames(10, 60, WIDTH - 10, HEIGHT - 10)
                arena:skeetMatch(robots[scheduler.contestants[1]])
            end
            if scheduler.mazeBtn:touched(CurrentTouch) then
                mode = 1
                arena:sizeFrames(10, 60, WIDTH - 10, HEIGHT - 10)
                arena:mazeRace(robots[scheduler.contestants[1]])
            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
    
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
PenPoint = class()
function PenPoint:init(x, y, s)
    -- just a little way to doodle
    self.x = x
    self.y = y
    self.status = s
end
Robot = class()
    
function Robot:init(x, y)
    -- position and bounds
    self.penStart = false
    self.penStatus = false
    self.pen = {}
    self.x = x
    self.y = y
    self.oldX = x
    self.oldY = y
    self.bounds = Frame(0,0,0,0)
    self.direction = 0
    self.fromDir = 0
    self.toDir = 0
    
    -- code related values
    self.program = {}
    for i = 1, 30 do self.program[i] = nil end
    self.step = 1
    self.aEntry = 1
    self.bEntry = 1
    
    -- sensor values
    self.bump = false
    self.radar = false
    self.treadTick = 0
    self.fireLaser = false
    self.fireRadar = false
    self.delay = 0
    
    -- tourney-telated values
    self.hp = 10
    self.damage = self.hp
    self.wins = 0
    self.losses = 0
    self.heat = 0
    self.repeatCounter = 1
    self.points = 0
    self.redirectValue = 0
    self.rf = Frame(0,0,0,0)
    self.limits = Frame(0,0,0,0)
    
    -- design-related values
    self.name = "Generobot"
    self.treadColor = 14
    self.bodyColor = 14
    self.headColor = 15
    self.dishColor = 4
    self.head = 1
    self.dish = 1
    self.body = 2
    self.tread = 2
    self.range = 20
    self.speed = 5
    self.turnDelay = 5
    self.turnTarget = 1
    self.flameTimer = 0
    self.shield = 0
    self.repairRate = 0
    self.img = image(60, 60)
    
end
function Robot:createImage()
    -- create an image of the bot for use in menus, etc
    pushMatrix()
    strokeWidth(2)
    translate(30,30)
    setContext(self.img)
    self:drawBase()
    setContext()
    popMatrix()
end
function Robot:redirect(v)
    -- set correct step number depending on board
    if self.step > 60 then
        return v + 60
    elseif self.step > 30 then
        return v + 30
    else
        return v
    end
end
function Robot:createDetectionFrame(dir)
    -- used by radar and laser
    if dir == 1 then
        -- up
        self.rf = Frame(self.x + 24, self.y + 36, 
        self.x + 36, self.range *  60)
        if self.rf.top > self.limits:height() then
            self.rf.top = self.limits:height()
        end
    elseif dir == 2 then
        -- right
        self.rf = Frame(self.x + 33, self.y + 24, 
        self.x + self.range *  60, self.y + 36)
        if self.rf.right > self.limits:width() then
            self.rf.right = self.limits:width()
        end
    elseif dir == 3 then
        -- down
        self.rf = Frame(self.x + 24, self.y - self.range *  60, 
        self.x + 36, self.y + 33)
        if self.rf.bottom < 0 then
            self.rf.bottom = 0
        end
    elseif dir == 4 then
        -- left
        self.rf = Frame(self.x - self.range *  60, self.y + 24, 
        self.x + 33, self.y + 36)
        if self.rf.left < 0 then
            self.rf.left = 0
        end
    end
end
function Robot:drawLaser()
    -- create the rectangle for laser fire
    if self.rf == nil then 
        self:createDetectionFrame(self.direction)
    end
    noStroke()
    fill(212, 60, 55, 92)
    self.rf:draw()
    sound(SOUND_SHOOT, 9773)
end
function Robot:drawRadar(dir)
    -- create the rectangle for radar detection
    self:createDetectionFrame(dir)
    --noStroke()
    --fill(81, 85, 175, 50)
    --self.rf:draw()
    --sound(SOUND_JUMP, 9772)
end
function Robot:run()
    local p, rf, redirected
    --displayMode(STANDARD)
    if self.delay > 0 then
        self.delay = self.delay - 1
        return true
    end
    self.hp = self.hp + self.repairRate / 100
    if self.hp > 10 then self.hp = 10 end
    if self.radar then 
        self.step = self.redirectValue
        --sound(SOUND_HIT, 17131)
        self.radar = false
    end
    -- get executable token
    p = self.program[self.step]
    redirected = false
    if p == nil or p.code == nil then
        if self.step > 60 then 
            self.step = self.bEntry + 1
        elseif self.step > 30 then
            self.step = self.aEntry + 1
        else   
            self.step = 1
        end
        redirected = true
        return false
    end
    -- execute control
    if p.code.short == "G" then
        -- Goto
        self.step = self:redirect(p.value)
        redirected = true
    elseif p.code.short == "5" then
        -- 50/50 random
        if math.random(2) > 1 then
            self.step = self:redirect(p.value)
            redirected = true   
        end 
    elseif p.code.short == "P" then
        -- repeat
        if self.repeatCounter < p.value then 
            self.repeatCounter = self.repeatCounter + 1
            self.step = self.step - 1
            redirected = true   
        else
            self.repeatCounter = 1
        end 
    -- check sensors
    elseif p.code.short == "D" then
        -- damage sensor
        if self.hp < self. damage then
            self.damage = self.hp
            self.step = self:redirect(p.value)
            redirected = true
        end
    elseif p.code.short == "H" then
        -- bump sensor
        if self.bump then 
            self.step = self:redirect(p.value)
            sound(SOUND_HIT, 17131)
            redirected = true
        end
        self.bump = false
    elseif p.code.short == "A" then
        -- radar sensor
        self:drawRadar(self.direction)
        self.delay = 5
        self.fireRadar = true
        self.redirectValue = self:redirect(p.value)
    elseif p.code.short == "I" then
        -- radar sensor right
        i = self.direction + 1
        if i > 4 then i = 1 end
        self:drawRadar(i)
        self.delay = 5
        self.fireRadar = true
        self.redirectValue = self:redirect(p.value)
    elseif p.code.short == "T" then
        -- radar sensor left
        i = self.direction - 1
        if i < 1 then i = 4 end
        self:drawRadar(i)
        self.delay = 5
        self.fireRadar = true
        self.redirectValue = self:redirect(p.value)
    -- take action
    elseif p.code.short == "F" then
        -- Forward
        self.treadTick = self.treadTick + 1
        if self.treadTick > 9 then
            self.treadTick = 0
        end
        if not self.bump then
            self.oldX = self.x
            self.oldY = self.y
            if self.direction == 1 then
                self.y = self.y + self.speed
            elseif self.direction == 2 then
                self.x = self.x + self.speed
            elseif self.direction == 3 then
                self.y = self.y - self.speed
            elseif self.direction == 4 then
                self.x = self.x - self.speed
            end
            if self.penStart then
                self.pen[#self.pen + 1] = 
                PenPoint(self.x + 30, self.y + 30, self.penStatus)
            end
        end
    elseif p.code.short == "B" then
        -- Reverse
        self.treadTick = self.treadTick - 1
        if self.treadTick < 0 then
            self.treadTick = 9
        end
        if not self.bump then
            self.oldX = self.x
            self.oldY = self.y
            if self.direction == 3 then
                self.y = self.y + self.speed
            elseif self.direction == 4 then
                self.x = self.x + self.speed
            elseif self.direction == 1 then
                self.y = self.y - self.speed
            elseif self.direction == 2 then
                self.x = self.x - self.speed
            end
            if self.penStart then
                self.pen[#self.pen + 1] = 
                PenPoint(self.x + 30, self.y + 30, self.penStatus)
            end
        end
    elseif p.code.short == "L" then
        self.direction = self.direction - 1
        if self.direction == 0 then self.direction = 4 end
        self.delay = self.delay + self.turnDelay
    elseif p.code.short == "R" then
        self.direction = self.direction + 1
        if self.direction == 5 then self.direction = 1 end
        self.delay = self.delay + self.turnDelay
    elseif p.code.short == "W" then
        -- fire laser
        self.delay = self.dish * 15
        self.fireLaser = true
        self:drawLaser()
    elseif p.code.short == "1" then
        -- Daughterboard A
        if self.step < 31 then
            self.aEntry = self.step
        end
        self.step = 31
        redirected = true
    elseif p.code.short == "2" then
        -- Daughterboard B
        if self.step < 61 then 
            self.bEntry = self.step
        end
        self.step = 61
        redirected = true
    elseif p.code.short == "S" then
        -- Sound Horn
        sound(SOUND_RANDOM, 19024)
    elseif p.code.short == "v" then
        -- pen down
        self.penStart = true
        self.penStatus = true
    elseif p.code.short == "^" then
        -- pen up
        self.penStart = true
        self.penStatus = false
    end
    -- step forward
    if not redirected then
        self.step = self.step + 1
    end
    self.treadTick = self.treadTick + 1
    if self.treadTick > 9 then
        self.treadTick = 0
    end
end
function Robot:draw(size)
    local i
    -- draw
    pushMatrix()
    translate(self.x + 30, self.y + 30)
    scale(size)
    if self.direction == 2 then
        rotate(270)
    elseif self.direction == 3 then
        rotate(180)
    elseif self.direction == 4 then
        rotate(90)
    end 
    strokeWidth(1)
    self:drawBase()
    popMatrix()
    self.bounds.left = self.x
    self.bounds.right = self.x + 60
    self.bounds.top = self.y + 60
    self.bounds.bottom = self.y
    if self.heat > 0 then self.heat = self.heat - 0.1 end
end
function Robot:drawDish(x, y)
    c1 = colors[self.dishColor]
    c2 = color(c1.r + self.heat * 22, c1.g, c1.b)
    stroke(c2)
    fill(backClr)
    if self.dish == 1 then
        line(x - 3, y, x, y + 15)
        line(x + 3, y, x, y + 15)
        line(x - 20, y + 7, x - 15, y + 3)
        line(x - 15, y + 3, x, y)
        line(x + 20, y + 7, x + 15, y + 3)
        line(x + 15, y + 3, x, y)
        line(x, y + 15, x, y + 20)
        ellipse(x, y + 15, 3)
        self.range = 20
    end
    if self.dish == 2 then
        rect(x - 3, y, x + 3, y + 20)
        line(x - 15, y, x, y)
        line(x + 15, y, x, y)
        line(x - 20, y + 10, x, y)
        line(x + 20, y + 10, x, y)
        self.range = 7
    end
    if self.dish == 3 then
        line(x - 15, y, x + 15, y)
        line(x - 10, y + 3, x + 10, y + 3)
        line(x - 7, y + 7, x + 7, y + 7)
        line(x - 3, y + 10, x + 3, y + 10)
        line(x, y, x, y + 20)
        ellipse(x, y + 20, 7)
        self.range = 3
    end
end
function Robot:drawHead(x, y)
    c1 = colors[self.headColor]
    c2 = color(c1.r + self.heat * 22, c1.g, c1.b)
    stroke(c2)
    fill(backClr)
    if self.head == 1 then
        ellipse(x, y, 30)
        ellipse(x, y, self.treadTick * 2)
        rect(x - 15, y - 5, x - 15, y + 5)
        rect(x + 15, y - 5, x + 15, y + 5)
        line(x - 15, y, x - 20, y)
        line(x + 15, y, x + 20, y)
    end
    if self.head == 2 then
        ellipse(x, y, 30)
        ellipse(x, y, 20)
        rotate(self.treadTick * 9)
        line(x+6,y+6,x-6,y-6)
        line(x+6,y-6,x-6,y+6)
        rotate(self.treadTick * -9)
    end
    if self.head == 3 then
        ellipse(x, y, 30)
        ellipse(x, y + 10, 20, 10)
        ellipse(x, y + 10, 15, 5)
        line(x - 15, y - 5, x - 20, y - 15) 
        line(x + 15, y - 5, x + 20, y - 15)
        fill(255, 0, 0, 255)
        ellipse(x, y + 5, 20, self.treadTick * 2)
    end
end
function Robot:drawBody(x, y)
    c1 = colors[self.bodyColor]
    c2 = color(c1.r + self.heat * 22, c1.g, c1.b)
    stroke(c2)
    fill(backClr)
    if self.body == 1 then
        ellipse(x, y, 40, 20)
        ellipse(x - 20, y, 15, 15)
        ellipse(x + 20, y, 15, 15)
    end
    if self.body == 2 then
        rect(x - 25, y - 10, x + 25, y + 10)
        ellipse(x - 25, y, 20)
        ellipse(x + 25, y, 20)
        rect(x - 15, y - 15, x + 15, y - 10)
    end
    if self.body == 3 then
        ellipse(x - 20, y, 30, 30)
        ellipse(x + 20, y, 30, 30)
        rect(x - 20, y - 15, x + 20, y + 15)
        ellipse(x, y, 40, 30)
    end
end
function Robot:drawTreads(x, y)
    local i
    c1 = colors[self.treadColor]
    c2 = color(c1.r + self.heat * 22, c1.g, c1.b)
    stroke(c2)
    fill(backClr)
    if self.tread == 1 then
        ellipse(20, -20, 20)
        ellipse(20, -20, 20, 5 + self.treadTick)
        ellipse(-20, -20, 20)
        ellipse(-20, -20, 20, 5 + self.treadTick)
        ellipse(-20, 20, 20)
        ellipse(-20, 20, 20, 5 + self.treadTick)
        ellipse(20, 20, 20)
        ellipse(20, 20, 20, 5 + self.treadTick)
        line(-20, -11, 0, 2)
        line(-17, -14, 0, -2)
        line(20, -11, 0, 2)
        line(17, -14, 0, -2)
        line(-20, 11, 0, 2)
        line(-17, 14, 0, -2)
        line(20, 11, 0, 2)
        line(17, 14, 0, -2)
    end
    if self.tread == 2 then
        rect(-30, -30, -15, 30)
        rect(15, -30, 30, 30)
        for i = 0,5 do
            line(-30, i * 10 - 30 + self.treadTick, 
               -15, i * 10 - 30 + self.treadTick)
            line(15, i * 10 -30 + self.treadTick, 
               30, i * 10 - 30 + self.treadTick)
        end
    end
    if self.tread == 3 then
        rect(-30, -30, -15, -15)
        rect(-27, -33, -17, -12)
        rect(15, -30, 30, -15)
        rect(17, -33, 27, -12)
        rect(-30, 15, -15, 30)
        rect(-27, 12, -17, 33)
        rect(15, 15, 30, 30)
        rect(17, 12, 27, 33)
        rect(-15, 20, 15, 25)
        rect(-15, -20, 15, -25)
        rect(-3, -10, 3, -20)
        rect(-3, 10, 3, 20)
        line(-27, self.treadTick - 30 + self.treadTick, 
        -17, self.treadTick - 30 + self.treadTick)
        line(17, self.treadTick - 30 + self.treadTick, 
        27, self.treadTick - 30 + self.treadTick)
        line(17, self.treadTick + 15 + self.treadTick, 
        27, self.treadTick + 15 + self.treadTick)
        line(-27, self.treadTick + 15 + self.treadTick, 
        -17, self.treadTick + 15 + self.treadTick)
    end
end
function Robot:drawBase()
    pushStyle()
    self:drawTreads(0, 0)
    self:drawBody(0, 0)
    self:drawHead(0, 0)
    self:drawDish(0, 10)
    popStyle()
end
TourneyOrganizer = class()
function TourneyOrganizer:init(x, y)
    local i
    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.robothonBtn = BigButton("Quartet", 570, 400)
    self.skeetBtn = BigButton("Skeet", 75, 600)
    self.mazeBtn = BigButton("Maze", 240, 600)
    self.chaseBtn = BigButton("Chase", 405, 600)
    self.meleeBtn = BigButton("Melee", 570, 600)
    --self.mazeBtn.active = false
    self.chaseBtn.active = false
    self.robothonBtn.active = false
end
function TourneyOrganizer:loadRobot(i)
    self.contestants[1] = i
end
function TourneyOrganizer:draw(robots)
    local i
    pushStyle()
    noFill()
    strokeWidth(2)
    stroke(246, 246, 246, 255)
    self.frame:draw()
    self.header:draw()
    textMode(CENTER)
    strokeWidth(1)
    for i = 1,4 do
        stroke(255, 255, 255, 255)
        noFill()
        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(255, 255, 255, 224)
            text(robots[self.contestants[i]].name, 0, -55)
            popMatrix()
        else
            fontSize(48)
            fill(115, 115, 115, 190)
            text("?", self.contestantFrames[i]:midX(), 
            self.contestantFrames[i]:midY())
            fill(154, 126, 126, 224)
            fontSize(16)
            text("Random", self.contestantFrames[i]:midX(), 
            self.contestantFrames[i]:midY()-55)
        end
    end
    fill(165, 165, 188, 255)
    stroke(147, 153, 173, 255)
    strokeWidth(1)
    line(self.contestantFrames[2].left, 
    self.contestantFrames[1].top + 20,
    self.contestantFrames[2].left + 145, 
    self.contestantFrames[1].top + 20)
    line(self.contestantFrames[2].left, 
    self.contestantFrames[1].top + 15,
    self.contestantFrames[2].left, 
    self.contestantFrames[1].top + 25)
    line(self.contestantFrames[4].left - 45, 
    self.contestantFrames[1].top + 20,
    self.contestantFrames[4].right, 
    self.contestantFrames[1].top + 20)
    line(self.contestantFrames[4].right, 
    self.contestantFrames[1].top + 15,
    self.contestantFrames[4].right, 
    self.contestantFrames[1].top + 25)
    text("Melee Opponents", self.contestantFrames[3]:midX(), 
    self.contestantFrames[1].top + 20)
    noFill()
    stroke(255, 255, 255, 154)
    strokeWidth(2)
    rect(self.frame.left + 35, 400, self.frame.left + 95, 460)
    line(self.frame.left + 95, 430, self.frame.left + 155, 430)
    rect(self.frame.left + 155, 400, self.frame.left + 215, 460)
    line(self.frame.left + 215, 430, self.frame.left + 275, 430)
    rect(self.frame.left + 275, 400, self.frame.left + 335, 460)
    line(self.frame.left + 335, 430, self.frame.left + 395, 430)
    rect(self.frame.left + 395, 400, self.frame.left + 455, 460)
    line(self.frame.left + 215, 430, self.frame.left + 275, 430)
    fill(255, 255, 255, 255)
    fontSize(32)
    text("1", self.frame.left + 65, 430)
    text("2", self.frame.left + 185, 430)
    text("3", self.frame.left + 305, 430) 
    text("4", self.frame.left + 425, 430)
    
    self.meleeBtn:draw()
    self.skeetBtn:draw()
    self.mazeBtn:draw()
    
    stroke(113, 102, 159, 255)
    fill(109, 111, 169, 255)
    
    self.chaseBtn:draw()
    self.robothonBtn:draw()
    fontSize(16)
    textMode(CORNER)
    text("TOURNEY ORGANIZER", self.frame.left + 15, 
    self.frame.top - 32)
    text("Four Event Robothon", 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment