Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- version = 0.43
- --Current bugs or errors:
- --None
- --Changelog
- --0.43 Improved rendering.
- --0.42 Disabled invincibility.
- --0.41 Players should now be in sync.
- --0.40 Fixed the bug that made 0.39 unplayable.
- --0.39 Added customizable amounts of players, 2-4 players can play.
- --0.38 Edited debug menu and info bar. Also edited wall graphics.
- --0.37 Fixed how trails work, all the posX data was being overwritten.
- --0.36 Graphics are hopefully fixed.
- --0.35 Graphic changes/bug fixes.
- --0.34 Added graphics? probably will have some bugs.
- --0.33 Now playerData should be converted even in non-debug mode.
- --0.32 Added background.
- --0.31 Added walls.
- --0.30 Fixed non-hosts dieing at the start of the game?
- --0.26-29 Fixed bugs.
- --0.25 Added turning.
- --0.10-0.24 No data recorded for these updates.
- --Goals
- --Find bugs and get rid of them. (Every version.)
- --Make player count customizable in-game. (v0.44)
- debug = false
- local oPE = os.pullEvent
- os.pullEvent = os.pullEventRaw
- local tronchan = 1504
- local fModem = false
- numPlayers1 = {...}
- if numPlayers1[1] then
- numPlayers = tonumber(numPlayers1[1])
- else
- numPlayers = 4
- end
- for k, v in pairs({"right","left","top","bottom","front","back"}) do
- if peripheral.getType(v) == "modem" then
- modem = peripheral.wrap(v)
- modem.open(tronchan)
- fModem = true
- end
- end
- bcols = {}
- for i = 0, 9 do
- bcols[2^i] = i
- end
- bcols[2^10] = "a"
- bcols[2^11] = "b"
- bcols[2^12] = "c"
- bcols[2^13] = "d"
- bcols[2^14] = "e"
- bcols[2^15] = "f"
- local scrx, scry = term.getSize()
- local cx, cy = math.floor(scrx/2),math.floor(scry/2)
- function tick()
- modem.transmit(UGID,12345, "TIME")
- TID = os.startTimer(0.1)
- ltime = ltime + 0.1
- if hosting and debug then
- modem.transmit(UGID, 13370, ltime)
- --time = ltime
- end
- if hosting then
- time = ltime
- end
- tC2 = 0
- for k, v in pairs(playerData) do
- tC2 = tC2 + 1
- if playerData[k].alive then
- if oCheck(playerData[k].posX, playerData[k].posY) then
- if playerData[k].invincible <= 0.9 then
- playerData[k].alive = false
- end
- end
- if playerData[k].dir == 1 then
- if not playerData[k].trail[playerData[k].posX] then
- playerData[k].trail[playerData[k].posX] = {}
- end
- playerData[k].trail[playerData[k].posX][playerData[k].posY] = "+"
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"+",playerData[k].colorID}
- if playerData[k].invincible >= 0.1 then
- playerData[k].invincible = playerData[k].invincible -0.1
- else
- if oCheck(playerData[k].posX, playerData[k].posY+1) then
- playerData[k].alive = false
- else
- playerData[k].posY = playerData[k].posY +1
- end
- end
- if playerData[k].dir == 1 then
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"^",playerData[k].colorID}
- end
- --To avoid insta-deaths I will give 1 second of invincibility.
- elseif playerData[k].dir == 2 then
- if not playerData[k].trail[playerData[k].posX] then
- playerData[k].trail[playerData[k].posX] = {}
- end
- playerData[k].trail[playerData[k].posX][playerData[k].posY] = "+"
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"+",playerData[k].colorID}
- if playerData[k].invincible >= 0.1 then
- playerData[k].invincible = playerData[k].invincible -0.1
- else
- if oCheck(playerData[k].posX+1, playerData[k].posY) then
- playerData[k].alive = false
- else
- playerData[k].posX = playerData[k].posX +1
- end
- end
- if playerData[k].dir == 2 then
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {">",playerData[k].colorID}
- end
- elseif playerData[k].dir == 3 then
- if not playerData[k].trail[playerData[k].posX] then
- playerData[k].trail[playerData[k].posX] = {}
- end
- playerData[k].trail[playerData[k].posX][playerData[k].posY] = "+"
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"+",playerData[k].colorID}
- if playerData[k].invincible >= 0.1 then
- playerData[k].invincible = playerData[k].invincible -0.1
- else
- if oCheck(playerData[k].posX, playerData[k].posY-1) then
- playerData[k].alive = false
- else
- playerData[k].posY = playerData[k].posY -1
- end
- end
- if playerData[k].dir == 3 then
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"v",playerData[k].colorID}
- end
- elseif playerData[k].dir == 4 then
- if not playerData[k].trail[playerData[k].posX] then
- playerData[k].trail[playerData[k].posX] = {}
- end
- playerData[k].trail[playerData[k].posX][playerData[k].posY] = "+"
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"+",playerData[k].colorID}
- if playerData[k].invincible >= 0.1 then
- playerData[k].invincible = playerData[k].invincible -0.1
- else
- if oCheck(playerData[k].posX-1, playerData[k].posY) then
- playerData[k].alive = false
- else
- playerData[k].posX = playerData[k].posX -1
- end
- end
- if playerData[k].dir == 4 then
- if not theGrid[playerData[k].posX] then
- theGrid[playerData[k].posX] = {}
- end
- theGrid[playerData[k].posX][playerData[k].posY] = {"<",playerData[k].colorID}
- end
- end
- else
- playerData[k].deathTime = playerData[k].deathTime + 0.1
- if playerData[k].deathTime >= 3 then
- toKill[#toKill+1] = k
- end
- end
- end
- if tC2 == 1 then
- if playerData[PID] then
- if playerData[PID].alive then
- gameResult = "won"
- contGame = false
- else
- gameResult = "won"
- contGame = false
- end
- else
- gameResult = "lost"
- contGame = false
- end
- elseif tC2 == 0 then
- if oTC2 >= 2 then
- gameResult = "tied" --Yes, I know you could die before the last 2.
- contGame = false
- end
- end
- if debug then
- if time == math.floor(time) then
- time = tostring(time)..".0"
- end
- timeLen = tostring(time).."s"
- timeLen = #timeLen
- term.setCursorPos(scrx-timeLen,scry)
- write(string.rep(" ",timeLen))
- term.setCursorPos(scrx-timeLen, scry)
- write(time.."s", scry)
- --if time == 30.0 then
- -- gameResult = "won"
- -- contGame = false
- --end
- end
- end
- function oCheck(positionX, positionY)
- if theGrid[positionX] then
- if theGrid[positionX][positionY] then
- if theGrid[positionX][positionY][1] then
- if theGrid[positionX][positionY][1] ~= "^" and theGrid[positionX][positionY][1] ~= ">" then
- if theGrid[positionX][positionY][1] ~= "v" and theGrid[positionX][positionY][1] ~= "<" then
- return true
- else return false
- end
- else return false
- end
- else return false
- end
- else return false
- end
- else return false
- end
- end
- function cPrint(text,line)
- if not line then
- ccpx, ccpy = term.getCursorPos()
- line = ccpy
- end
- local nCursorX = #text/2
- local nCursorX = cx-nCursorX
- term.setCursorPos(nCursorX, line)
- print(text)
- end
- function cWrite(text,line)
- if not line then
- ccpx, ccpy = term.getCursorPos()
- line = ccpy
- end
- local nCursorX = #text/2
- local nCursorX = cx-nCursorX
- term.setCursorPos(nCursorX, line)
- write(text)
- end
- function renderScreen() --While lots of this is based off of Pixel toast's tron,
- -- I was even viewing his code while creating this render function,
- -- so yeah, some of this is his code!
- term.setTextColor(colors.gray)
- if converted then
- for c=1,scry do
- term.setCursorPos(1,c)
- term.setTextColor(colors.gray)
- local pre = camX%3
- if (c+camY)%3==0 then
- if pre==1 then
- pre="--"
- elseif pre==2 then
- pre="-"
- else
- pre=""
- end
- tblit = pre..string.rep("+--",math.ceil(scrx/2))
- term.blit(tblit,string.rep("7",#tblit),string.rep("f",#tblit))
- else
- if pre==1 then
- pre=" "
- elseif pre==2 then
- pre=" "
- else
- pre=""
- end
- tblit = pre..string.rep("| ",math.ceil(scrx/2))
- term.blit(tblit,string.rep("7",#tblit),string.rep("f",#tblit))
- end
- for d = 1, scrx do
- if theGrid[d + camX - cx] then
- if theGrid[d + camX - cx][-c + camY + cy +1] then --Super hacky, but it works!
- term.setCursorPos(d,c)
- term.setTextColor(theGrid[d + camX - cx][-c + camY + cy +1][2])
- term.write(theGrid[d + camX - cx][-c + camY + cy +1][1])
- end
- end
- end
- end
- end
- if debug then
- tCounter = 1
- for k, v in pairs(playerData) do
- tCounter = tCounter + 1
- if playerData[k].alive then
- term.setTextColor(colors.white)
- cPrint(k.." / "..playerData[k].teamColor..": alive x: "..playerData[k].posX.." y: "..playerData[k].posY.." dir: "..playerData[k].dir,tCounter)
- if tonumber(k) == tonumber(PID) then
- --playerData[PID] = playerData[k] --No idea if this will work, maybe it will make it worse.
- if playerData[k].dir then
- if playerData[k].dir == 1 then
- cPrint("DEBUG | "..PID.." | "..playerData[PID].teamColor.." | UP".." | CamX "..camX.." CamY "..camY,1)
- elseif playerData[k].dir == 2 then
- cPrint("DEBUG | "..PID.." | "..playerData[PID].teamColor.." | RIGHT".." | CamX "..camX.." CamY "..camY,1)
- elseif playerData[k].dir == 3 then
- cPrint("DEBUG | "..PID.." | "..playerData[PID].teamColor.." | DOWN".." | CamX "..camX.." CamY "..camY,1)
- elseif playerData[k].dir == 4 then
- cPrint("DEBUG | "..PID.." | "..playerData[PID].teamColor.." | LEFT".." | CamX "..camX.." CamY "..camY,1)
- end
- end
- end
- else
- cPrint(k..": dead for "..playerData[k].deathTime.."s",tCounter)
- end
- end
- if event then
- cPrint("Last event: "..event, 6)
- end
- else
- if playerData[PID] then
- term.setTextColor(playerData[PID].colorID)
- cPrint(playerData[PID].teamColor,1)
- else
- term.setTextColor(colors.white)
- cPrint("DEAD",1)
- end
- end
- end
- function control()
- time = 0
- ltime = 0
- if debug then
- cPrint("DEBUG",1)
- else
- term.setTextColor(teamColorID)
- cPrint(teamColor)
- end
- contGame = true
- sleep(0.05)
- TID = os.startTimer(0.1)
- toKill = {}
- toConvert = {}
- converted = false
- for k, v in pairs(playerData) do
- if type(k) ~= "number" then
- toKill[#toKill+1] = k
- toConvert[#toConvert+1] = tonumber(k)
- end
- end
- while contGame do
- if tC2 then
- oTC2 = tC2
- end
- if #toConvert >= 1 then
- for a = 1, #toConvert do
- playerData[toConvert[a]] = playerData[tostring(toConvert[a])]
- end
- toConvert = {} --OH I keep trying to convert! Causing it to set the new playerData to nil!
- converted = true
- end
- if #toKill >= 1 then
- for a = 1, #toKill do
- for k, v in pairs(playerData[toKill[a]].trail) do
- for k2, v2 in pairs(playerData[toKill[a]].trail[k]) do
- theGrid[k][k2] = nil
- end
- end
- playerData[toKill[a]] = nil
- end
- toKill = {}
- end
- fCam = false
- if converted == true then
- if playerData[PID] then
- camX = playerData[PID].posX
- camY = playerData[PID].posY
- fCam = true
- end
- else
- if playerData[tostring(PID)] then
- camX = playerData[tostring(PID)].posX
- camY = playerData[tostring(PID)].posY
- fCam = true
- end
- end
- if not fCam then --Bug is before here.
- for k, v in pairs(playerData) do
- camX = playerData[k].posX
- camY = playerData[k].posY
- fCam = true
- break
- end
- end
- if not fCam then
- camX = 0
- camY = 0
- end
- term.clear()
- renderScreen()
- event, key, p2, p3, p4, p5 = os.pullEvent()
- if event == "key" then
- --Do stuff
- if playerData[PID] then
- if playerData[PID].alive then
- if key == keys.right then
- if playerData[PID].dir >= 4 then
- playerData[PID].dir = 1
- else
- playerData[PID].dir = playerData[PID].dir +1
- end
- modem.transmit(UGID,31337, "TURN_RIGHT "..PID)
- elseif key == keys.left then
- if playerData[PID].dir <= 1 then
- playerData[PID].dir = 4
- else
- playerData[PID].dir = playerData[PID].dir -1
- end
- modem.transmit(UGID,31337, "TURN_LEFT "..PID)
- end
- end
- end
- elseif event == "terminate" then
- modem.transmit(UGID, 999, "QUIT_GAME "..PID)
- gameResult = "lost"
- contGame = false
- elseif event == "timer" and key == TID and hosting then
- tick()
- elseif event == "modem_message" and p2 == UGID and p3 == 12345 and p4 == "TIME" and hosting ~= true then
- tick()
- end
- end
- end
- function connection()
- if debug then
- --cPrint("DEBUG",2)
- if true then -- hosting then
- for k, v in pairs(playerIDS) do
- print(playerIDS[k])
- end
- end
- end
- contGame = true
- playerData = {}
- for d = 1, #playerIDS do
- playerData[playerIDS[d]] = {}
- end
- tCounter = 0
- for k, v in pairs(playerData) do
- tCounter = tCounter +1
- playerData[k].dir = tCounter --1 = up, 2 = right, 3 = down, 4 = left
- playerData[k].trail = {} --So we can remove the trail upon death.
- playerData[k].alive = true
- playerData[k].deathTime = 0
- playerData[k].invincible = 0
- if tCounter == 1 then
- playerData[k].posX = 0
- playerData[k].posY = -124
- playerData[k].teamColor = "Blue"
- playerData[k].colorID = colors.blue
- elseif tCounter == 2 then
- playerData[k].posX = -124
- playerData[k].posY = 0
- playerData[k].teamColor = "Red"
- playerData[k].colorID = colors.red
- elseif tCounter == 3 then
- playerData[k].posX = 0
- playerData[k].posY = 124
- playerData[k].teamColor = "Green"
- playerData[k].colorID = colors.green
- elseif tCounter == 4 then
- playerData[k].posX = 124
- playerData[k].posY = 0
- playerData[k].teamColor = "Purple"
- playerData[k].colorID = colors.purple
- end
- end
- theGrid = {}
- for b=125,-125,-1 do
- if not theGrid[b] then
- theGrid[b] = {}
- end
- theGrid[b][-125]={"-",colors.yellow}
- end
- sleep(0)
- for b=125,-125,-1 do
- if not theGrid[b] then
- theGrid[b] = {}
- end
- theGrid[b][125]={"-",colors.yellow}
- end
- sleep(0)
- for b=125,-125,-1 do
- if not theGrid[-125] then
- theGrid[-125] = {}
- end
- theGrid[-125][b]={"|",colors.yellow}
- end
- sleep(0)
- for b=125,-125,-1 do
- if not theGrid[125] then
- theGrid[125] = {}
- end
- theGrid[125][b]={"|",colors.yellow}
- end
- sleep(0)
- theGrid[125][125] = {"=",colors.yellow}
- theGrid[125][-125] = {"=",colors.yellow}
- theGrid[-125][125] = {"=",colors.yellow}
- theGrid[-125][-125] = {"=",colors.yellow}
- while contGame do
- e, side, chan, rchan, msg, dist = os.pullEvent("modem_message")
- if chan == UGID and msg == "CONFLICT_DETECTION" then
- modem.transmit(UGID, 0, "CONFLICT")
- elseif hosting ~= true and chan == UGID and rchan == 13370 then
- time = msg
- elseif chan == UGID and string.sub(msg,1,9) == "QUIT_GAME" then
- if playerData[tonumber(string.sub(msg,11,#msg))] then
- playerData[tonumber(string.sub(msg,11,#msg))].alive = false
- end
- elseif chan == UGID and string.sub(msg,1,10) == "TURN_RIGHT" then
- PIDFrom = tonumber(string.sub(msg,12, #msg))
- if playerData[PIDFrom] then
- if playerData[PIDFrom].dir >= 4 then
- playerData[PIDFrom].dir = 1
- else
- playerData[PIDFrom].dir = playerData[PIDFrom].dir +1
- end
- end
- elseif chan == UGID and string.sub(msg,1,9) == "TURN_LEFT" then
- PIDFrom = tonumber(string.sub(msg,11, #msg))
- if playerData[PIDFrom] then
- if playerData[PIDFrom].dir <= 1 then
- playerData[PIDFrom].dir = 4
- else
- playerData[PIDFrom].dir = playerData[PIDFrom].dir -1
- end
- end
- end
- --gameResult = "won"
- --contGame = false
- --break
- end
- end
- function game()
- hosting = false
- PID = math.random(1,65535) -- Player ID, Just hope there are no conflicts.
- gameResult = nil
- timerID = os.startTimer(1)
- searchConnection = true
- UPID = math.random(1024,4096) -- Unique Ping IDentification
- foundGame = false
- modem.transmit(tronchan, UPID, numPlayers.." FIND_GAME "..PID)
- while searchConnection do
- e, p1, p2, p3, p4, p5 = os.pullEvent()
- if p1 == timerID and e == "timer" then
- break
- elseif e == "modem_message" and p2 == tronchan and p3 == UPID then
- if p4 ~= "PID_CONFLICT" then
- playerNum = tonumber(string.sub(p4, 6,6)) +1
- sNumPlayers = tonumber(string.sub(p4,8,8))
- UGID = tonumber(string.sub(p4,10,14))
- if sNumPlayers == numPlayers then
- foundGame = true
- searchConnection = false
- modem.open(UGID)
- cWrite(playerNum.."/"..numPlayers.." players found.",2)
- end
- else
- PID = math.random(1,65535)
- modem.transmit(tronchan, UPID, numPlayers.." FIND_GAME "..PID)
- end
- end
- end
- if not foundGame then
- playersFound = 1
- hosting = true
- playerIDS = {PID}
- UGID = math.random(15000,15999) --Unique Game ID, The channel we will use for this game.
- conflictFound = false
- searchConflict = true
- playerNum = 1
- while searchConflict do
- e = nil
- p1 = nil
- timerID = os.startTimer(0.5)
- modem.transmit(UGID, 0, "CONFLICT_DETECTION")
- while not e == "timer" and p1 == timerID do
- e, p1, p2, p3, p4, p5 = os.pullEvent()
- if e == "modem_message" and p2 == UGID and p4 == "CONFLICT" then
- conflictFound = true
- end
- end
- if not conflictFound then
- modem.open(UGID)
- break
- else
- UGID = math.random(15000,15999)
- conflictFound = false
- end
- end
- cWrite(playersFound.."/"..numPlayers.." players found.",2)
- while playersFound ~= numPlayers do
- e, side, chan, rchan, msg, dist = os.pullEvent("modem_message")
- if string.sub(msg,1,11) == numPlayers.." FIND_GAME" and chan == tronchan then
- PIDC = false
- for b = 1, #playerIDS do
- if string.sub(msg,13,#msg) == playerIDS[b] then
- modem.transmit(tronchan, rchan, "PID_CONFLICT")
- PIDC = true
- end
- end
- if not PIDC then
- playerIDS[#playerIDS+1] = string.sub(msg,13,#msg) --Add the player's PID to our database
- modem.transmit(tronchan, rchan, "GAME "..playersFound.."/"..numPlayers.." "..UGID)
- playersFound = playersFound+1
- cWrite(playersFound.."/"..numPlayers.." players found.",2)
- modem.transmit(UGID,playersFound,"NEW_PLAYER")
- end
- end
- end
- end
- if not hosting then
- startGame = false --Sorry for using so many global variables ;(
- while not startGame do
- e,side,chan,rchan,msg,dist = os.pullEvent()
- if chan == UGID and msg == "START_GAME" then
- startGame = true
- elseif chan == UGID and msg == "NEW_PLAYER" then
- cWrite(rchan.."/"..numPlayers.." players found.",2)
- end
- end
- else
- sleep(0.1)
- modem.transmit(UGID,0,"START_GAME")
- end
- if not hosting then
- startGame = false --Sorry for using so many global variables ;(
- while not startGame do
- e,side,chan,rchan,msg,dist = os.pullEvent()
- if chan == UGID and string.sub(msg,1,5) == "PIDs " then
- playerIDS = textutils.unserialize(string.sub(msg, 6, #msg))
- startGame = true
- end
- end
- else
- sleep(0.1)
- modem.transmit(UGID, 8, "PIDs "..textutils.serialize(playerIDS))
- end
- term.clear()
- term.setCursorPos(1,1)
- if playerNum == 1 then
- teamColor = "Blue"
- teamColorID = colors.blue
- elseif playerNum == 2 then
- teamColor = "Red"
- teamColorID = colors.red
- elseif playerNum == 3 then
- teamColor = "Green"
- teamColorID = colors.green
- elseif playerNum == 4 then
- teamColor = "Purple"
- teamColorID = colors.purple
- end
- parallel.waitForAny(control, connection)
- term.clear()
- term.setTextColor(colors.blue)
- gameMsg = "You "..gameResult.."!"
- term.setCursorPos(cx - #gameMsg,cy)
- write(gameMsg)
- sleep(5)
- end
- function drawMenu()
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1,1)
- term.setTextColor(colors.blue)
- cPrint("Tron")
- term.setTextColor(colors.white)
- selNum = #selections/2
- term.setCursorPos(1,cy-selNum)
- for a = 1, #selections do
- if curSelection == a then
- cPrint("["..selections[a].."]")
- else
- cPrint(selections[a])
- end
- end
- cWrite("v"..version,scry)
- end
- function menu()
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- selections = {"Play","Quit"}
- exitGame = false
- curSelection = 1
- drawMenu()
- if not term.isColor() then
- exitGame = true
- end
- while not exitGame do
- e,p1 = os.pullEvent("key")
- if p1 == keys.up then
- if curSelection >= #selections then
- curSelection = 1
- else
- curSelection = curSelection +1
- end
- elseif p1 == keys.down then
- if curSelection <= 1 then
- curSelection = #selections
- else
- curSelection = curSelection -1
- end
- elseif p1 == keys.enter then
- if selections[curSelection] == "Quit" then
- exitGame = true
- elseif selections[curSelection] == "Play" then
- game()
- end
- end
- drawMenu()
- end
- end
- if numPlayers <= 4 and numPlayers >= 2 then
- menu()
- else
- cPrint("You can not have less than 2 players or more than 4 players!")
- end
- term.clear()
- term.setCursorPos(1,1)
- curProgram = shell.getRunningProgram()
- if #curProgram >= 2 then
- curProgram = string.upper(string.sub(curProgram,1,1))..string.lower(string.sub(curProgram,2,#curProgram))
- else
- curProgram = string.upper(curProgram)
- end
- if term.isColor() then
- cPrint("Exited "..curProgram.." v"..version..", Thanks for playing!")
- if numPlayers >= 5 or numPlayers <= 1 then
- cPrint("You can not have less than 2 players")
- cPrint("or more than 4 players!")
- end
- else
- cPrint("You need a advanced computer for "..curProgram)
- end
- os.pullEvent = oPE
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement