Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- TRON Light Cycle Game
- programmed by LDDestroier
- Get with:
- wget https://raw.githubusercontent.com/LDDestroier/CC/master/tron.lua
- --]]
- local port = 701
- local kioskMode = false -- disables options menu
- local useLegacyMouseControl = false -- if true, click move regions will be divided into diagonal quadrants
- local scr_x, scr_y = term.getSize()
- local scr_mx, scr_my = scr_x / 2, scr_y / 2
- local isColor = term.isColor()
- local doShowByImage = true -- show "By LDDestroier" in title
- local gameDelayInit = 0.1 -- lower value = faster game. I recommend 0.1 for SMP play.
- local doDrawPlayerNames = true -- draws the names of players onscreen
- local doRenderOwnName = false -- if doDrawPlayerNames, also draws your own name
- local useSetVisible = false -- use term.current().setVisible, which speeds things up at the cost of multishell
- local gridID = 1 -- determines which grid is used
- local mode = "menu"
- local disknet = dofile("disknet.lua")
- -- initial grid information, (hopefully) transferred to non-host players
- local initGrid = {
- x1 = -100,
- y1 = -100,
- x2 = 100,
- y2 = 100,
- border = "#",
- voidcol = "f",
- forecol = "8",
- backcol = "7",
- edgecol = "0"
- }
- local resetPlayers = function()
- return {
- [1] = {
- num = 1,
- x = -3,
- y = -5,
- direction = -1,
- char = "@",
- color = {
- colors.blue,
- colors.blue,
- colors.blue,
- colors.cyan,
- colors.cyan,
- colors.lightBlue,
- colors.lightBlue,
- colors.cyan,
- colors.cyan
- },
- dead = false,
- trailLevel = 10,
- trailMax = 10,
- trailRegen = 0.1,
- putTrail = true,
- name = "BLU",
- initName = "BLU"
- },
- [2] = {
- num = 2,
- x = 3,
- y = -5,
- direction = -1,
- char = "@",
- color = {
- colors.red,
- colors.red,
- colors.red,
- colors.orange,
- colors.orange,
- colors.yellow,
- colors.yellow,
- colors.orange,
- colors.orange
- },
- dead = false,
- trailLevel = 10,
- trailMax = 10,
- trailRegen = 0.1,
- putTrail = true,
- name = "RED",
- initName = "RED"
- }
- }
- end
- local function interpretArgs(tInput, tArgs)
- local output = {}
- local errors = {}
- local usedEntries = {}
- for aName, aType in pairs(tArgs) do
- output[aName] = false
- for i = 1, #tInput do
- if not usedEntries[i] then
- if tInput[i] == aName and not output[aName] then
- if aType then
- usedEntries[i] = true
- if type(tInput[i+1]) == aType or type(tonumber(tInput[i+1])) == aType then
- usedEntries[i+1] = true
- if aType == "number" then
- output[aName] = tonumber(tInput[i+1])
- else
- output[aName] = tInput[i+1]
- end
- else
- output[aName] = nil
- errors[1] = errors[1] and (errors[1] + 1) or 1
- errors[aName] = "expected " .. aType .. ", got " .. type(tInput[i+1])
- end
- else
- usedEntries[i] = true
- output[aName] = true
- end
- end
- end
- end
- end
- for i = 1, #tInput do
- if not usedEntries[i] then
- output[#output+1] = tInput[i]
- end
- end
- return output, errors
- end
- local argData = {
- ["skynet"] = false, -- use Skynet HTTP multiplayer
- ["quick"] = false, -- start one game immediately
- ["griddemo"] = false, -- only move the grid
- ["--update"] = false, -- updates TRON to the latest version
- ["--gridID"] = "number" -- grid ID to use
- }
- local gridFore, gridBack
- local gridList = {
- [1] = { -- broken up and cool looking
- {
- "+- -+------",
- "| | ",
- " | ",
- ". | ",
- "+------+- --",
- "| | ",
- "| ",
- "| . ",
- },
- {
- "+- -+--------",
- "| | ",
- " | ",
- " | ",
- " | ",
- "| | ",
- "+--------+- -",
- "| | ",
- "| ",
- "| ",
- "| ",
- "| | ",
- }
- },
- [2] = { -- flat diagonal sorta
- {
- " / ",
- " / ",
- " / ",
- " / ",
- "/__________"
- },
- {
- " / ",
- " / ",
- " / ",
- " / ",
- " / ",
- " / ",
- " / ",
- "/_______________"
- }
- },
- [3] = { -- basic simple grid
- {
- "+-------",
- "| ",
- "| ",
- "| ",
- "| "
- },
- {
- "+------------",
- "| ",
- "| ",
- "| ",
- "| ",
- "| ",
- "| ",
- "| "
- }
- },
- [4] = { -- diamond grid
- {
- " /\\ ",
- " / \\ ",
- " / \\ ",
- "/ \\",
- "\\ /",
- " \\ / ",
- " \\ / ",
- " \\/ ",
- },
- {
- " /\\ ",
- " / \\ ",
- " / \\ ",
- " / \\ ",
- " / \\ ",
- "/ \\",
- "\\ /",
- " \\ / ",
- " \\ / ",
- " \\ / ",
- " \\ / ",
- " \\/ ",
- }
- },
- [5] = { -- brick and mortar
- {
- "| ",
- "| ",
- "| ",
- "| ",
- "===========",
- " | ",
- " | ",
- " | ",
- " | ",
- "===========",
- },
- {
- "| ",
- "| ",
- "=======",
- " | ",
- " | ",
- "=======",
- },
- },
- [6] = { -- pain background
- {
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@ ",
- "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@SCREEN@MAX@",
- },
- {
- "%%..",
- "%%..",
- "%%..",
- "..%%",
- "..%%",
- "..%%"
- },
- },
- [7] = { -- some
- {
- " "
- },
- {
- "+-----------------------------------------------------",
- "| Somebody once told me the world is gonna roll me ",
- "| I ain't the sharpest tool in the shed / She was ",
- "| looking kind of dumb with her finger and her thumb ",
- "| In the shape of an \"L\" on her forehead / Well the ",
- "| years start coming and they don't stop coming ",
- "| Fed to the rules and I hit the ground running ",
- "| Didn't make sense not to live for fun / Your brain ",
- "| gets smart but your head gets dumb / So much to ",
- "| do, so much to see / So what's wrong with taking ",
- "| the back streets? / You'll never know if you don't ",
- "| go / You'll never shine if you don't glow / Hey ",
- "| now, you're an all-star, get your game on, go play ",
- "| Hey now, you're a rock star, get the show on, get ",
- "| paid / And all that glitters is gold / Only ",
- "| shooting stars break the mold / It's a cool place ",
- "| and they say it gets colder / You're bundled up ",
- "| now, wait till you get older / But the meteor men ",
- "| beg to differ / Judging by the hole in the ",
- "| satellite picture / The ice we skate is getting ",
- "| pretty thin / The water's getting warm so you might ",
- "| as well swim / My world's on fire, how about yours? ",
- "| That's the way I like it and I never get bored ",
- "| Hey now, you're an all-star, get your game on, go ",
- "| play / Hey now, you're a rock star, get the show ",
- "| on, get paid / All that glitters is gold / Only ",
- "| shooting stars break the mold / Hey now, you're ",
- "| an all-star, get your game on, go play / Hey now, ",
- "| you're a rock star, get the show, on get paid ",
- "| And all that glitters is gold / Only shooting ",
- "| stars... / Somebody once asked could I spare some ",
- "| change for gas? / I need to get myself away from ",
- "| this place / I said yep, what a concept / I could ",
- "| use a little fuel myself / And we could all use a ",
- "| little change / Well, the years start coming and ",
- "| they don't stop coming / Fed to the rules and I ",
- "| hit the ground running / Didn't make sense not to ",
- "| live for fun / Your brain gets smart but your head ",
- "| gets dumb / So much to do, so much to see / So ",
- "| what's wrong with taking the back streets? ",
- "| You'll never know if you don't go (go!) / You'll ",
- "| never shine if you don't glow / Hey now, you're ",
- "| an all-star, get your game on, go play / Hey now, ",
- "| you're a rock star, get the show on, get paid ",
- "| And all that glitters is gold / Only shooting ",
- "| stars break the mold / And all that glitters is ",
- "| gold / Only shooting stars break the mold ",
- }
- }
- }
- local argList = interpretArgs({...}, argData)
- local useSkynet = argList["skynet"]
- local useOnce = argList["quick"]
- local doGridDemo = argList["griddemo"]
- local doUpdateGame = argList["--update"]
- if gridList[argList["--gridID"]] then
- gridID = argList["--gridID"]
- end
- local argumentName = argList[1]
- local argumentPassword = argList[2] or ""
- if useSkynet and (not http.websocket) then
- error("Skynet is not supported on this version of ComputerCraft.")
- end
- local skynetPath = fs.combine(fs.getDir(shell.getRunningProgram()), "skynet.lua")
- local skynetURL = "https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"
- if argumentName then
- argumentName = argumentName:sub(1, 15) -- gotta enforce that limit
- end
- local toblit = {
- [0] = " ",
- [colors.white] = "0",
- [colors.orange] = "1",
- [colors.magenta] = "2",
- [colors.lightBlue] = "3",
- [colors.yellow] = "4",
- [colors.lime] = "5",
- [colors.pink] = "6",
- [colors.gray] = "7",
- [colors.lightGray] = "8",
- [colors.cyan] = "9",
- [colors.purple] = "a",
- [colors.blue] = "b",
- [colors.brown] = "c",
- [colors.green] = "d",
- [colors.red] = "e",
- [colors.black] = "f"
- }
- local tograyCol, tograyBlit = {
- [0] = 0,
- [colors.white] = colors.white,
- [colors.orange] = colors.lightGray,
- [colors.magenta] = colors.lightGray,
- [colors.lightBlue] = colors.white,
- [colors.yellow] = colors.white,
- [colors.lime] = colors.lightGray,
- [colors.pink] = colors.lightGray,
- [colors.gray] = colors.gray,
- [colors.lightGray] = colors.lightGray,
- [colors.cyan] = colors.lightGray,
- [colors.purple] = colors.gray,
- [colors.blue] = colors.gray,
- [colors.brown] = colors.gray,
- [colors.green] = colors.gray,
- [colors.red] = colors.white,
- [colors.black] = colors.black
- }, {}
- local tocolors = {}
- for k,v in pairs(toblit) do
- tocolors[v] = k
- end
- for k,v in pairs(tograyCol) do
- tograyBlit[toblit[k]] = toblit[v]
- end
- local termwrite, termclear = term.write, term.clear
- local termsetCursorPos, termgetCursorPos = term.setCursorPos, term.getCursorPos
- local tableunpack, tableremove = unpack, table.remove
- local mathfloor, mathceil, mathcos, mathsin, mathrandom, mathrad = math.floor, math.ceil, math.cos, math.sin, math.random, math.rad
- local termsetTextColor = function(col)
- return term.setTextColor(isColor and col or tograyCol[col])
- end
- local termsetBackgroundColor = function(col)
- return term.setBackgroundColor(isColor and col or tograyCol[col])
- end
- local termblit = function(char, text, back)
- if isColor then
- return term.blit(char, text, back)
- else
- return term.blit(
- char,
- text:gsub(".", tograyBlit),
- back:gsub(".", tograyBlit)
- )
- end
- end
- local tsv = function(visible)
- if term.current().setVisible and useSetVisible then
- term.current().setVisible(visible)
- end
- end
- local round = function(num, places)
- return math.floor(num * 10^places + 0.5) / 10^places
- end
- if doUpdateGame then
- print("Downloading...")
- local net = http.get("https://github.com/LDDestroier/CC/raw/master/tron.lua")
- if net then
- local file = fs.open(shell.getRunningProgram(), "w")
- file.write(net.readAll())
- file.close()
- print("Updated!")
- else
- printError("Couldn't update!")
- end
- if useOnce then
- return
- else
- sleep(0.2)
- shell.run( shell.getRunningProgram(), table.concat({...}, " "):gsub("--update", "") )
- return
- end
- end
- local cwrite = function(text, y, xdiff, wordPosCheck)
- wordPosCheck = wordPosCheck or #text
- termsetCursorPos(mathfloor(scr_x / 2 - math.floor(0.5 + #text + (xdiff or 0)) / 2), y or (scr_y - 2))
- term.write(text)
- return (scr_x / 2) - (#text / 2) + wordPosCheck
- end
- local modem, skynet
- local setUpModem = function()
- if not doGridDemo then
- --[[
- if useSkynet then
- if fs.exists(skynetPath) then
- skynet = dofile(skynetPath)
- term.clear()
- cwrite("Connecting to Skynet...", scr_y / 2)
- skynet.open(port)
- else
- term.clear()
- cwrite("Downloading Skynet...", scr_y / 2)
- local prog = http.get(skynetURL)
- if prog then
- local file = fs.open(skynetPath, "w")
- file.write(prog.readAll())
- file.close()
- skynet = dofile(skynetPath)
- cwrite("Connecting to Skynet...", 1 + scr_y / 2)
- skynet.open(port)
- else
- error("Could not download Skynet.")
- end
- end
- else
- modem = peripheral.find("modem")
- if (not modem) and ccemux then
- ccemux.attach("top", "wireless_modem")
- modem = peripheral.find("modem")
- end
- if modem then
- modem.open(port)
- else
- error("You should attach a modem.")
- end
- end
- --]]
- disknet.open(port)
- end
- end
- setUpModem()
- local transmit = function(port, message)
- disknet.send(port, message)
- --[[
- if useSkynet then
- skynet.send(port, message)
- else
- modem.transmit(port, port, message)
- end
- --]]
- end
- local gamename = ""
- local isHost
- local waitingForGame = true
- -- used in skynet matches if you are player 2
- local ping = 0
- local copyTable
- copyTable = function(tbl, ...)
- local output = {}
- for k,v in pairs(tbl) do
- if type(v) == "table" then
- output[k] = copyTable(v)
- else
- output[k] = v
- end
- end
- for i = 1, #arg do
- output[#output+1] = arg[i]
- end
- return output
- end
- grid = copyTable(initGrid)
- local you, nou = 1, 2
- local keysDown, netKeysDown = {}, {}
- local miceDown = {}
- local lastDirectionPressed, netLastDirectionPressed
- -- the scrolling of the screen
- local scrollX = 0
- local scrollY = 0
- -- used when panning with WASD
- local scrollAdjX = 0
- local scrollAdjY = 0
- local lockInput = false
- local player
- player = resetPlayers()
- local images
- if _HOST then -- need to add some NFP image replacements for older versions of CC
- images = {
- logo = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- " f7777777777777777777f f77777f 7f f777",
- " f99979999979999999999f 799999799 77f7 f997",
- " 799 79999f997 9977997f f997",
- " 799 7797777fffff997 9977997797997",
- " 799 799 799977f7797fff7997799 79797",
- " 799 799 7797f 797999997 799 797",
- " 777 777 7777 7777777 777 77",
- },
- {
- " 7999999999f9999999997 7999997 97 799f",
- " 7777997777f77777779997 997777997 997f 799f",
- " 997 f7777799 799f99997 799f",
- " 997 997f9997fff799 799f997ff7999f",
- " 997 997 f7999fff999777997f997 f799f",
- " 997 997 f9997 f7999977f 997 f7f",
- " fff fff ffff fffffff fff ff",
- }
- },
- win = {
- {
- "",
- "",
- "",
- " ",
- "",
- "",
- },
- {
- "55 55 555555 5 5 55",
- "55 5555 55 5 55 5 5 55",
- "55 5 55 55 5555 5 55",
- "55 55 55 55 55 5 5 55",
- "5 55 5 55 5 55 55 555 5",
- "555 555 555555 55 5 55",
- },
- {
- "5 5 5555555 55 55 5 ",
- "5 5 5 555 55 5 ",
- "5 5 5 5 5 55 55 5 ",
- "5 55 55 5 5 5 5555 5 ",
- "555 555 5 5 5 5 55 5 ",
- "5 5 5555555 5 55 5 ",
- }
- },
- lose = {
- {
- "",
- "",
- "",
- "",
- " ",
- "",
- },
- {
- "ee eee e eeeee eeeeeee",
- "ee eee e e ee ee ee ee",
- "ee ee e ee e e ",
- "ee ee e eeeee e eeeeee ",
- "ee e e e e e ee ",
- "eeeeeee e eeeee eeeeee eeeeeee",
- },
- {
- "e eeeeee eeeeeee eeeeeee",
- "e e ee e e ",
- "e e ee eeeeeee eeeee ",
- "e e ee ee e ",
- "e ee eee e ee e ee",
- "eeeeeee eeee eeeeee eeeeeee",
- }
- },
- tie = {
- {
- "",
- "",
- "",
- "",
- "",
- "",
- },
- {
- "77888800 0000000 0888877",
- " 88 00 0 0 08 7",
- " 88 0 0 7 ",
- " 88 0 088887 ",
- " 88 0 0 08 ",
- " 88 0000000 0888877",
- },
- {
- "7788880 00000000 0888877",
- " 8 00 0 ",
- " 8 00 08888 ",
- " 8 00 0 ",
- " 8 0 00 0 0 7",
- " 8 00000000 0888877",
- },
- },
- timeout = {
- {
- "",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- "00000000000000ff0000000f",
- "0fff000fff000ff0ff00f000",
- "0ffffffffff00f000f00ffff",
- " fffff0ffff00f0f0f00ffff",
- " 000ff000000000f00000000",
- " 000000f0ff0ff0000f",
- " 0f00f0ffffff000f00",
- " 0ff0f0ffffff7f0f0",
- " 0ffff0ffffff7f0f0",
- " 000000000000ff000",
- },
- {
- "ffffffffffffff00fffffff0",
- " 0f0fff0f0ffffffffffffff",
- " 0f0ff00f00ffffffffff000",
- " 0f0fffffffffffffffffff0",
- " fffffffffffffffffffffff",
- " ffffff0f00f00ffff0",
- " ffffff0f00f0ffffff",
- " ff0fff0f00f0fffff",
- " ffffff0ffff0fffff",
- " fffffffffffffffff",
- },
- },
- ldd = {
- {
- " ",
- " ",
- " ",
- " ",
- },
- {
- " ",
- " f7ff7f7 f fbfbbbffff9f99fff9ff9f9f9999fff9f9f",
- " 77f f7 b fbfbbfbfff9f9f f9 99ff9f9f9ffff999f",
- " 777 77 bbbbbb 999 99 9 9 99 9 9",
- },
- {
- " ",
- " 7f77f7f b bfbfbfb999f9ff999f99f9f9ff9f999f9f9",
- " 7f7 7f b bfbfbbf999f9f9 9f 9f99f9f999999f9f9",
- " fff ff ffffff fff ff f f ff f f",
- },
- }
- }
- else
- images = {
- logo = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- "7777777777 77777777 77777777 77 77",
- " 77 777 777 777 777 77",
- " 77 777 77 77 7777 77",
- " 77 7777777 77 77 77777 77",
- " 77 77 7777 77 77 77 7777",
- " 77 77 7777 777 777 77 777",
- " 77 77 7777 77777777 77 77",
- },
- {
- "9999999999 99999999 99999999 99 99",
- " 99 999 999 999 999 99",
- " 99 999 99 99 9999 99",
- " 99 9999999 99 99 99999 99",
- " 99 99 9999 99 99 99 9999",
- " 99 99 9999 999 999 99 999",
- " 99 99 9999 99999999 99 99",
- },
- },
- win = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- "77 77 777777 77 77 77",
- "77 77 777777 777 77 77",
- "77 7 77 77 7777 77 77",
- "77 777 77 77 77 77 77 77",
- "7777 7777 77 77 7777 ",
- "777 777 777777 77 777 77",
- "77 77 777777 77 77 77",
- },
- {
- "55 55 555555 55 55 55",
- "55 55 555555 555 55 55",
- "55 5 55 55 5555 55 55",
- "55 555 55 55 55 55 55 55",
- "5555 5555 55 55 5555 ",
- "555 555 555555 55 555 55",
- "55 55 555555 55 55 55",
- },
- },
- lose = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- "77 777777 77777 77777",
- "77 77777777 777777 77777",
- "77 777 777 77 77 ",
- "77 77 77 77777 7777 ",
- "77 77 77 77777 77 ",
- "77 777 777 77 77 ",
- "77777 77777777 777777 77777",
- "77777 777777 77777 77777",
- },
- {
- "ee eeeeee eeeee eeeee",
- "ee eeeeeeee eeeeee eeeee",
- "ee eee eee ee ee ",
- "ee ee ee eeeee eeee ",
- "ee ee ee eeeee ee ",
- "ee eee eee ee ee ",
- "eeeee eeeeeeee eeeeee eeeee",
- "eeeee eeeeee eeeee eeeee",
- },
- },
- tie = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- "77777777 77777777 7777777",
- " 77 77 77 ",
- " 77 77 77 ",
- " 77 77 777777 ",
- " 77 77 77 ",
- " 77 77 77 ",
- " 77 77777777 7777777",
- },
- {
- "77888800 00000000 0888877",
- " 88 00 08 ",
- " 88 00 08 ",
- " 88 00 088887 ",
- " 88 00 08 ",
- " 88 00 08 ",
- " 88 00000000 0888877",
- },
- },
- timeout = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- "7777777 777 777 777 777777",
- "7777777 777 7777 7777 777777",
- "7777777 777 777777777 777777",
- " 777 777 777777777 77777 ",
- " 777 777 777777777 777777",
- " 777 777 777777777 777777",
- " 777 777 777 777 777777",
- " ",
- " 7777777 777 777 7777777 ",
- " 7777777 777 777 7777777 ",
- " 7777777 777 777 7777777 ",
- " 777 777 777 777 777 ",
- " 777 777 777 777 777 ",
- " 7777777 7777777 777 ",
- " 7777777 7777777 777 ",
- " 7777777 7777777 777 ",
- },
- {
- "0000000 000 000 000 000000",
- "0fffff0 0f0 0ff0 0ff0 0ffff0",
- "000f000 0f0 0fff0fff0 0f0000",
- " 0f0 0f0 0f0fff0f0 0fff0 ",
- " 0f0 0f0 0f00f00f0 0f0000",
- " 0f0 0f0 0f00000f0 0ffff0",
- " 000 000 000 000 000000",
- " ",
- " 0000000 000 000 0000000 ",
- " 0fffff0 0f0 0f0 0fffff0 ",
- " 0f000f0 0f0 0f0 000f000 ",
- " 0f0 0f0 0f0 0f0 0f0 ",
- " 0f0 0f0 0f0 0f0 0f0 ",
- " 0f000f0 0f000f0 0f0 ",
- " 0fffff0 0fffff0 0f0 ",
- " 0000000 0000000 000 ",
- },
- },
- ldd = {
- {
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- " ",
- },
- {
- " 777 7 7 ",
- " 7 7 7 7 ",
- " 77 7 ",
- " 7 7 7 ",
- " 77 77 777 7 777 777 ",
- "7 7 7 7 7 77 777 7 7 7 777 ",
- "7 7 7 7 7 7 777 777 7 7 7 7 7 7 777",
- "7 7 7 7 7 77 7 7 77 7 7 7 77 7 7",
- "7 77 77 7 777 7 7 7 777 777 7 77 ",
- "777 77 7 7 7 7 777 7 7",
- " 777 7 7 7",
- },
- {
- " 777 7 7 ",
- " 7 7 7 7 ",
- " 77 7 ",
- " 7 7 7 ",
- " bb bb 777 7 999 999 ",
- "b b b b b 99 999 9 9 9 999 ",
- "b b b b b 9 999 999 9 9 9 9 9 9 999",
- "b b b b b 99 9 9 99 9 9 9 99 9 9",
- "b bb bb 9 999 9 9 9 999 999 9 99 ",
- "bbb 99 9 9 9 9 999 9 9",
- " 999 9 9 9",
- },
- }
- }
- end
- for k,v in pairs(images) do
- -- give them easy-to-access x and y sizes
- v.x = #v[1][1]
- v.y = #v[1]
- -- fix white artifacting that occurs due to " " correlating to WHITE in term.blit
- for y = 1, v.y do
- for x = 1, v.x do
- if v[2][y]:sub(x,x) ~= "" and v[3][y]:sub(x,x) ~= "" then
- if (v[2][y]:sub(x,x) == " " and v[3][y]:sub(x,x) ~= " ") then
- images[k][2][y] = v[2][y]:sub(1, x - 1) .. initGrid.voidcol .. v[2][y]:sub(x + 1)
- elseif (v[2][y]:sub(x,x) ~= " " and v[3][y]:sub(x,x) == " ") then
- images[k][3][y] = v[3][y]:sub(1, x - 1) .. initGrid.voidcol .. v[3][y]:sub(x + 1)
- end
- end
- end
- end
- end
- local drawImage = function(im, x, y)
- local cx, cy = termgetCursorPos()
- termsetBackgroundColor( tocolors[initGrid.voidcol] )
- termsetTextColor( tocolors[initGrid.voidcol] )
- for iy = 1, #im[1] do
- for ix = 1, #im[1][iy] do
- termsetCursorPos(x+(ix-1),y+(iy-1))
- if not (im[2][iy]:sub(ix,ix) == " " and im[3][iy]:sub(ix,ix) == " ") then
- termblit(
- im[1][iy]:sub(ix,ix),
- im[2][iy]:sub(ix,ix):gsub("[ f]",initGrid.voidcol),
- im[3][iy]:sub(ix,ix):gsub("[ f]",initGrid.voidcol)
- )
- end
- end
- end
- termsetCursorPos(cx,cy)
- end
- local deadGuys = {}
- local trail = {}
- local lastTrails = {}
- isPuttingDown = false
- local putTrailXY = function(x, y, p)
- trail[y] = trail[y] or {}
- trail[y][x] = {
- player = p,
- age = 0
- }
- end
- local putTrail = function(p)
- putTrailXY(p.x, p.y, p.num)
- end
- local getTrail = function(x, y)
- if trail[y] then
- if trail[y][x] then
- return player[trail[y][x].player].char, player[trail[y][x].player].color, trail[y][x].age
- end
- end
- return false
- end
- local ageTrails = function()
- for y,l in pairs(trail) do
- for x,v in pairs(l) do
- trail[y][x].age = trail[y][x].age + 1
- end
- end
- end
- local control, revControl = {
- up = keys.up,
- down = keys.down,
- left = keys.left,
- right = keys.right,
- lookUp = keys.w,
- lookDown = keys.s,
- lookLeft = keys.a,
- lookRight = keys.d,
- release = keys.space
- }, {}
- for k,v in pairs(control) do
- revControl[v] = k
- end
- gridFore, gridBack = table.unpack(gridList[gridID])
- local dirArrow = {
- [-1] = "^",
- [0] = ">",
- [1] = "V",
- [2] = "<"
- }
- local doesIntersectBorder = function(x, y)
- return mathfloor(x) == grid.x1 or mathfloor(x) == grid.x2 or mathfloor(y) == grid.y1 or mathfloor(y) == grid.y2
- end
- --draws grid and background at scroll 'x' and 'y', along with trails and players
- local drawGrid = function(x, y, onlyDrawGrid, useSetVisible)
- tsv(false)
- x, y = mathfloor(x + 0.5), mathfloor(y + 0.5)
- local bg = {{},{},{}}
- local foreX, foreY
- local backX, backY
- local adjX, adjY
- local trailChar, trailColor, trailAge, isPlayer, isPredict
- for sy = 1, scr_y do
- bg[1][sy] = ""
- bg[2][sy] = ""
- bg[3][sy] = ""
- for sx = 1, scr_x do
- adjX = (sx + x)
- adjY = (sy + y)
- foreX = 1 + (sx + x) % #gridFore[1]
- foreY = 1 + (sy + y) % #gridFore
- backX = 1 + mathfloor(sx + (x / 2)) % #gridBack[1]
- backY = 1 + mathfloor(sy + (y / 2)) % #gridBack
- trailChar, trailColor, trailAge = getTrail(adjX, adjY)
- isPlayer = false
- isPredict = false
- if not onlyDrawGrid then
- for i = 1, #player do
- if player[i].x == adjX and player[i].y == adjY then
- isPlayer = i
- break
- elseif (not isHost) and useSkynet and i == you and (
- adjX == math.floor(player[i].x + (0.02 * round(ping, 0)) * math.cos(math.rad(player[i].direction * 90))) and
- adjY == math.floor(player[i].y + (0.02 * round(ping, 0)) * math.sin(math.rad(player[i].direction * 90)))
- ) then
- isPredict = i
- break
- end
- end
- end
- if isPlayer and (not onlyDrawGrid) and (not doesIntersectBorder(adjX, adjY)) then
- bg[1][sy] = bg[1][sy] .. dirArrow[player[isPlayer].direction]
- bg[2][sy] = bg[2][sy] .. toblit[player[isPlayer].color[1]]
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- elseif isPredict and (not onlyDrawGrid) and (not doesIntersectBorder(adjX, adjY)) then
- bg[1][sy] = bg[1][sy] .. "o"
- bg[2][sy] = bg[2][sy] .. grid.forecol
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- else
- if (not onlyDrawGrid) and trailChar and trailColor then
- trailColor = trailColor[1 + ((trailAge - 1) % #trailColor)]
- bg[1][sy] = bg[1][sy] .. trailChar
- bg[2][sy] = bg[2][sy] .. toblit[trailColor]
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- else
- if (not onlyDrawGrid) and (adjX < grid.x1 or adjX > grid.x2 or adjY < grid.y1 or adjY > grid.y2) then
- bg[1][sy] = bg[1][sy] .. " "
- bg[2][sy] = bg[2][sy] .. grid.voidcol
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- elseif (not onlyDrawGrid) and doesIntersectBorder(adjX, adjY) then
- bg[1][sy] = bg[1][sy] .. grid.border
- bg[2][sy] = bg[2][sy] .. grid.voidcol
- bg[3][sy] = bg[3][sy] .. grid.edgecol
- else
- if gridFore[foreY]:sub(foreX,foreX) ~= " " then
- bg[1][sy] = bg[1][sy] .. gridFore[foreY]:sub(foreX,foreX)
- bg[2][sy] = bg[2][sy] .. grid.forecol
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- elseif gridBack[backY]:sub(backX,backX) ~= " " then
- bg[1][sy] = bg[1][sy] .. gridBack[backY]:sub(backX,backX)
- bg[2][sy] = bg[2][sy] .. grid.backcol
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- else
- bg[1][sy] = bg[1][sy] .. " "
- bg[2][sy] = bg[2][sy] .. grid.voidcol
- bg[3][sy] = bg[3][sy] .. grid.voidcol
- end
- end
- end
- end
- end
- end
- for sy = 1, scr_y do
- termsetCursorPos(1,sy)
- termblit(
- bg[1][sy],
- bg[2][sy],
- bg[3][sy]
- )
- end
- if doDrawPlayerNames and (not onlyDrawGrid) then
- for i = 1, #player do
- if doRenderOwnName or (i ~= you) then
- termsetTextColor(player[i].color[1])
- adjX = mathfloor(player[i].x - (scrollX + scrollAdjX) - (#player[i].name / 2) + 1)
- adjY = mathfloor(player[i].y - (scrollY + scrollAdjY) - 1.5)
- for cx = adjX, adjX + #player[i].name do
- if doesIntersectBorder(adjX + mathfloor(0.5 + scrollX + scrollAdjX), adjY + mathfloor(0.5 + scrollY + scrollAdjY)) then
- termsetBackgroundColor(tocolors[grid.edgecol])
- else
- termsetBackgroundColor(tocolors[grid.voidcol])
- end
- termsetCursorPos(cx, adjY)
- termwrite(player[i].name:sub(cx-adjX+1, cx-adjX+1))
- end
- end
- end
- end
- tsv(true)
- end
- local getTime = function()
- if os.epoch then
- return os.epoch("utc")
- else
- return 24 * os.day() + os.time()
- end
- end
- local render = function(useSetVisible, netTime)
- local p = player[you]
- drawGrid(scrollX + scrollAdjX, scrollY + scrollAdjY, false, useSetVisible)
- termsetCursorPos(1,1)
- termsetTextColor(player[you].color[1])
- termsetBackgroundColor(tocolors[grid.voidcol])
- term.write("P" .. you)
- term.setTextColor(colors.white)
- for x = 0, p.trailMax - 1 do
- if not (x - p.trailLevel >= -0.4) then
- if (x - p.trailLevel) > -0.7 then
- term.setTextColor(colors.gray)
- term.write("@")
- elseif (x - p.trailLevel) > -1 then
- term.setTextColor(colors.lightGray)
- term.write("@")
- else
- term.setTextColor(colors.white)
- term.write("@")
- end
- end
- end
- term.setCursorPos(1,2)
- if netTime and useSkynet then
- ping = (getTime() - netTime)
- term.setTextColor(colors.white)
- term.write(" " .. tostring(ping) .. " ms")
- end
- term.setTextColor(colors.white)
- end
- local pleaseWait = function()
- local periods = 1
- local maxPeriods = 5
- termsetBackgroundColor(colors.black)
- termsetTextColor(colors.gray)
- termclear()
- local tID = os.startTimer(0.2)
- local evt, txt
- if useSkynet then
- txt = "Waiting for Skynet game"
- else
- txt = "Waiting for modem game"
- end
- while true do
- cwrite("(Press 'Q' to cancel)", 2)
- cwrite(txt, scr_y - 2, maxPeriods)
- termwrite(("."):rep(periods))
- evt = {os.pullEvent()}
- if evt[1] == "timer" and evt[2] == tID then
- tID = os.startTimer(0.5)
- periods = (periods % maxPeriods) + 1
- term.clearLine()
- elseif evt[1] == "key" and evt[2] == keys.q then
- return
- end
- end
- end
- local startCountdown = function()
- local cName = "PLAYER " .. you
- local col = colors.white
- for k,v in pairs(colors) do
- if player[you].color[1] == v then
- cName = k:upper()
- col = v
- break
- end
- end
- local cMessage = "You are "
- scrollX = player[you].x - mathfloor(scr_x / 2)
- scrollY = player[you].y - mathfloor(scr_y / 2)
- for i = 3, 1, -1 do
- render(true)
- termsetTextColor(colors.white)
- for x = 1, #cMessage+1 do
- termsetCursorPos(-1 + x + mathfloor(scr_x / 2 - (#cMessage + #cName) / 2), mathfloor(scr_y / 2) + 2)
- if cMessage:sub(x,x) ~= " " and x <= #cMessage then
- termwrite(cMessage:sub(x,x))
- end
- end
- termsetTextColor(col)
- termwrite(player[you].name)
- termsetTextColor(colors.white)
- termsetCursorPos(mathfloor(scr_x / 2 - 2), mathfloor(scr_y / 2) + 4)
- termwrite(i .. "...")
- sleep(1)
- end
- end
- local makeMenu = function(x, fromX, y, options, doAnimate, scrollInfo, _cpos)
- local cpos = _cpos or 1
- local xmod = 0
- local cursor = "> "
- local gsX, gsY = (scrollInfo or {})[2] or 0, (scrollInfo or {})[3] or 0
- local step = (scrollInfo or {})[1] or 0
- local lastPos = cpos
- local image
- if not doAnimate then
- drawImage(images.logo, mathceil(scr_x / 2 - images.logo.x / 2), 2)
- if useSkynet then
- term.setTextColor(colors.lightGray)
- cwrite("Skynet Enabled", 2 + images.logo.y)
- end
- end
- local rend = function()
- if (step % 150 > 100) and doShowByImage then
- image = images.ldd
- else
- image = images.logo
- end
- if doAnimate then
- drawImage(
- image,
- mathceil(scr_x / 2 - image.x / 2),
- 2
- )
- if useSkynet then
- term.setTextColor(colors.lightGray)
- cwrite("Skynet Enabled", 2 + image.y)
- end
- end
- for i = 1, #options do
- if i == cpos then
- termsetCursorPos(fromX + xmod, y + (i - 1))
- termsetTextColor(colors.white)
- termwrite(cursor .. options[i])
- else
- if i == lastPos then
- termsetCursorPos(fromX + xmod, y + (i - 1))
- termwrite((" "):rep(#cursor))
- lastPos = nil
- else
- termsetCursorPos(fromX + xmod + #cursor, y + (i - 1))
- end
- termsetTextColor(colors.gray)
- termwrite(options[i])
- end
- end
- end
- local gstID, evt = mathrandom(1,65535)
- if doAnimate then
- os.queueEvent("timer", gstID)
- end
- rend()
- local tID = os.startTimer(0.05)
- while true do
- evt = {os.pullEvent()}
- if evt[1] == "key" then
- if evt[2] == keys.up then
- lastPos = cpos
- cpos = (cpos - 2) % #options + 1
- elseif evt[2] == keys.down then
- lastPos = cpos
- cpos = (cpos % #options) + 1
- elseif evt[2] == keys.home then
- lastPos = cpos
- cpos = 1
- elseif evt[2] == keys["end"] then
- lastPos = cpos
- cpos = #options
- elseif evt[2] == keys.enter then
- return cpos, {step, gsX, gsY}
- end
- elseif evt[1] == "mouse_click" then
- if evt[4] >= y and evt[4] < y+#options then
- if cpos == evt[4] - (y - 1) then
- return cpos, {step, gsX, gsY}
- else
- cpos = evt[4] - (y - 1)
- doRend = true
- end
- end
- elseif evt[1] == "timer" then
- if evt[2] == gstID then
- gstID = os.startTimer(gameDelayInit)
- drawGrid(gsX, gsY, true)
- step = step + 1
- if mathceil(step / 100) % 2 == 1 then
- gsX = gsX + 1
- else
- gsY = gsY - 1
- end
- doRend = true
- elseif evt[2] == tID then
- if x > fromX and xmod < x - fromX then
- xmod = math.min(xmod + 1, x - fromX)
- drawGrid(gsX, gsY, true)
- tID = os.startTimer(0.05)
- elseif xmod > x - fromX then
- xmod = math.max(xmod - 1, x - fromX)
- drawGrid(gsX, gsY, true)
- tID = os.startTimer(0.05)
- end
- doRend = true
- end
- end
- if lastPos ~= cpos or doRend then
- rend()
- doRend = false
- end
- end
- end
- local specialRead = function(scrollInfo, specialNames, message, preInput)
- specialNames = specialNames or {}
- local gsX, gsY = (scrollInfo or {})[2] or 0, (scrollInfo or {})[3] or 0
- local step = (scrollInfo or {})[1] or 0
- local tID = os.startTimer(gameDelayInit)
- local buff = {}
- local cpos = 1
- local maxSize = 15
- local evt
- for x = 1, #preInput do
- buff[x] = preInput:sub(x, x)
- cpos = cpos + 1
- end
- term.setCursorBlink(true)
- local rend = function()
- drawGrid(gsX, gsY, true)
- term.setTextColor(colors.white)
- cwrite(message, scr_y - 5)
- term.setTextColor(specialNames[table.concat(buff):lower()] or colors.white)
- term.setCursorPos( cwrite(table.concat(buff), scr_y - 3, nil, cpos) - 1, scr_y - 3)
- term.setTextColor(colors.white)
- end
- while true do
- evt = {os.pullEvent()}
- if evt[1] == "timer" and evt[2] == tID then
- -- render the bg
- tID = os.startTimer(gameDelayInit)
- step = step + 1
- if mathceil(step / 100) % 2 == 1 then
- gsX = gsX + 1
- else
- gsY = gsY - 1
- end
- rend()
- elseif evt[1] == "char" then
- if #buff < maxSize then
- table.insert(buff, cpos, evt[2])
- cpos = cpos + 1
- rend()
- end
- elseif evt[1] == "key" then
- if evt[2] == keys.left then
- cpos = math.max(1, cpos - 1)
- elseif evt[2] == keys.right then
- cpos = math.min(#buff + 1, cpos + 1)
- elseif evt[2] == keys.home then
- cpos = 1
- elseif evt[2] == keys["end"] then
- cpos = #buff
- elseif evt[2] == keys.backspace then
- if cpos > 1 then
- table.remove(buff, cpos - 1)
- cpos = cpos - 1
- rend()
- end
- elseif evt[2] == keys.delete then
- if buff[cpos] then
- table.remove(buff, cpos)
- rend()
- end
- elseif evt[2] == keys.enter then
- term.setCursorBlink(false)
- return table.concat(buff), {step, gsX, gsY}
- end
- end
- end
- end
- local passwordChange = function(scrollInfo)
- return specialRead(scrollInfo, {}, "Enter a password.", argumentPassword or "") or ""
- end
- local nameChange = function(scrollInfo)
- -- this has no functional significance. just some shoutouts
- local specialNames = {
- ["blu"] = colors.blue,
- ["red"] = colors.red,
- ["ldd"] = colors.orange,
- ["lddestroier"] = colors.orange,
- ["hydraz"] = colors.yellow,
- ["hugeblank"] = colors.orange,
- ["bagel"] = colors.orange,
- ["3d6"] = colors.lime,
- ["lyqyd"] = colors.red,
- ["squiddev"] = colors.cyan,
- ["oeed"] = colors.lime,
- ["dog"] = colors.purple,
- ["nothy"] = colors.lightGray,
- ["kepler"] = colors.cyan,
- ["kepler155c"] = colors.cyan,
- ["anavrins"] = colors.blue,
- ["redmatters"] = colors.red,
- ["fatmanchummy"] = colors.purple,
- ["crazed"] = colors.lightBlue,
- ["ape"] = colors.brown,
- ["everyos"] = colors.red,
- ["dan200"] = colors.lightGray,
- ["dantwohundred"] = colors.lightGray,
- ["lemmmy"] = colors.red,
- ["yemmel"] = colors.red,
- ["apemanzilla"] = colors.brown,
- ["osmarks"] = colors.green,
- ["gollark"] = colors.green,
- ["dece"] = colors.cyan,
- ["hpwebcamable"] = colors.lightGray,
- ["theoriginalbit"] = colors.blue,
- ["bombbloke"] = colors.red,
- ["kingofgamesyami"] = colors.lightBlue,
- ["pixeltoast"] = colors.lime,
- ["creator"] = colors.yellow,
- ["dannysmc"] = colors.purple,
- ["dannysmc95"] = colors.purple,
- ["kingdaro"] = colors.blue,
- ["valithor"] = colors.orange,
- ["logandark"] = colors.lightGray,
- ["lupus590"] = colors.lightGray,
- ["nitrogenfingers"] = colors.green,
- ["gravityscore"] = colors.lime,
- ["1lann"] = colors.gray,
- ["konlab"] = colors.brown,
- ["elvishjerricco"] = colors.pink
- }
- return specialRead(scrollInfo, specialNames, "Enter your name.", argumentName or player[you].initName)
- end
- local titleScreen = function()
- termclear()
- local menuOptions, options, choice, scrollInfo
- if kioskMode then
- menuOptions = {
- "Start Game",
- "How to Play",
- }
- else
- menuOptions = {
- "Start Game",
- "How to Play",
- "Options...",
- "Exit"
- }
- end
- local currentX = 2
- while true do
- choice, scrollInfo = makeMenu(2, currentX, scr_y - #menuOptions, menuOptions, true, scrollInfo)
- currentX = 2
- if choice == 1 then
- return "start"
- elseif choice == 2 then
- return "help"
- elseif choice == 3 then
- local _cpos
- while true do
- options = {
- "Grid Demo",
- "Change Name",
- "Change Grid",
- "Change Password",
- (useSkynet and "Disable" or "Enable") .. " Skynet",
- "Back..."
- }
- choice, scrollInfo = makeMenu(8, currentX, scr_y - #options, options, true, scrollInfo, _cpos)
- currentX = 8
- _cpos = choice
- if choice == 1 then
- return "demo"
- elseif choice == 2 then
- local newName = nameChange(scrollInfo)
- if #newName > 0 then
- if newName:upper() == "BLU" or newName:upper() == "RED" or newName:gsub(" ","") == "" then
- argumentName = nil
- else
- argumentName = newName
- end
- else
- argumentName = nil
- end
- elseif choice == 3 then
- gridID = (gridID % #gridList) + 1
- gridFore, gridBack = table.unpack(gridList[gridID])
- elseif choice == 4 then
- argumentPassword = passwordChange(scrollInfo)
- elseif choice == 5 then
- if http.websocket then
- useSkynet = not useSkynet
- setUpModem()
- if skynet and not useSkynet then
- skynet.socket.close()
- end
- else
- term.clear()
- term.setTextColor(colors.white)
- cwrite("Alas, this version of CC", -2 + scr_y / 2)
- cwrite("does not support Skynet.", -1 + scr_y / 2)
- term.setTextColor(colors.lightGray)
- cwrite("Use CC:Tweaked or CCEmuX", 1 + scr_y / 2)
- cwrite("instead for netplay.", 2 + scr_y / 2)
- cwrite("Press any key to go back.", 4 + scr_y / 2)
- sleep(0.1)
- os.pullEvent("key")
- end
- elseif choice == 6 then
- break
- end
- end
- elseif choice == 4 then
- return "exit"
- end
- end
- end
- local cleanExit = function()
- termsetBackgroundColor(colors.black)
- termsetTextColor(colors.white)
- termclear()
- cwrite("Thanks for playing!", 2)
- termsetCursorPos(1, scr_y)
- end
- local parseMouseInput = function(button, x, y, direction)
- local output = false
- local cx = x - scr_mx
- local cy = y - scr_my
- if useLegacyMouseControl or mode == "demo" then -- outdated mouse input, useful for grid demo though
- cx = cx * (scr_y / scr_x)
- if cx > cy then
- if -cx > cy then
- output = "up"
- else
- output = "right"
- end
- else
- if -cx < cy then
- output = "down"
- else
- output = "left"
- end
- end
- else
- cx = cx + scrollAdjX
- cy = cy + scrollAdjY
- if button == 1 then -- move player
- if direction % 2 == 0 then -- moving horizontally
- if cy > 0 then
- output = "down"
- elseif cy < 0 then
- output = "up"
- end
- else -- moving vertically
- if cx > 0 then
- output = "right"
- elseif cx < 0 then
- output = "left"
- end
- end
- elseif button == 2 then -- release trail
- output = "release"
- end
- end
- return control[output]
- end
- local getInput = function()
- local evt
- local mkey = -1
- while true do
- evt = {os.pullEvent()}
- if lockInput then
- keysDown = {}
- miceDown = {}
- else
- if evt[1] == "key" then
- if (not keysDown[evt[2]]) and (
- evt[2] == control.up or
- evt[2] == control.down or
- evt[2] == control.left or
- evt[2] == control.right
- ) then
- lastDirectionPressed = revControl[evt[2]]
- end
- keysDown[evt[2]] = true
- elseif evt[1] == "key_up" then
- keysDown[evt[2]] = false
- elseif evt[1] == "mouse_click" or (useLegacyMouseControl and evt[1] == "mouse_drag") then
- if evt[1] == "mouse_drag" then
- keysDown[mkey] = false
- end
- miceDown[evt[2]] = {evt[3], evt[4]}
- mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1
- lastDirectionPressed = revControl[mkey]
- keysDown[mkey] = true
- elseif evt[1] == "mouse_drag" then
- miceDown[evt[2]] = {evt[3], evt[4]}
- elseif evt[1] == "mouse_up" then
- keysDown[mkey] = false
- miceDown[evt[2]] = nil
- mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1
- keysDown[mkey] = false
- end
- end
- end
- end
- local scrollToPosition = function(x, y)
- for i = 1, 16 do
- scrollX = (scrollX + x - (scr_x/2)) / 2
- scrollY = (scrollY + y - (scr_y/2)) / 2
- render(true)
- sleep(0.05)
- end
- end
- local gridDemo = function()
- keysDown = {}
- miceDown = {}
- scrollX, scrollY = math.floor(scr_x * -0.5), math.floor(scr_y * -0.75)
- while true do
- if keysDown[keys.left] then
- scrollX = scrollX - 1
- end
- if keysDown[keys.right] then
- scrollX = scrollX + 1
- end
- if keysDown[keys.up] then
- scrollY = scrollY - 1
- end
- if keysDown[keys.down] then
- scrollY = scrollY + 1
- end
- if keysDown[keys.q] then
- return "end"
- end
- drawGrid(scrollX, scrollY, false, true)
- ageTrails()
- sleep(0.05)
- end
- end
- local sendInfo = function(gameID, doSendTime)
- transmit(port, {
- player = isHost and player or nil,
- name = player[you].name,
- putTrail = isPuttingDown,
- gameID = gameID,
- time = doSendTime and getTime(),
- keysDown = isHost and nil or keysDown,
- trail = isHost and lastTrails or nil,
- deadGuys = isHost and deadGuys or nil,
- lastDir = lastDirectionPressed
- })
- end
- local waitForKey = function(time, blockMouse)
- sleep(time or 0.5)
- local evt
- repeat
- evt = os.pullEvent()
- until evt == "key" or ((not blockMouse) and evt == "mouse_click")
- end
- local imageAnim = function(image)
- while true do
- drawImage(image, mathceil(scr_x / 2 - image.x / 2), mathfloor(scr_y / 2 - image.y / 2))
- sleep(0.5)
- render(true)
- sleep(0.5)
- end
- end
- local deadAnimation = function(doSend)
- for k,v in pairs(deadGuys) do
- player[k].char = "X"
- lockInput = true
- end
- if doSend then
- sendInfo(gamename, isHost)
- end
- if deadGuys[you] or deadGuys[nou] then
- termsetTextColor(colors.white)
- if deadGuys[you] and deadGuys[nou] then
- os.queueEvent("tron_complete", "tie", isHost, player[nou].name)
- scrollToPosition(player[nou].x, player[nou].y)
- scrollToPosition(player[you].x, player[you].y)
- parallel.waitForAny(function() imageAnim(images.tie) end, waitForKey)
- return "end"
- else
- if deadGuys[you] then
- scrollX, scrollY = player[nou].x - scr_x / 2, player[nou].y - scr_y / 2
- os.queueEvent("tron_complete", "lose", isHost, player[nou].name)
- scrollToPosition(player[you].x, player[you].y)
- parallel.waitForAny(function() imageAnim(images.lose) end, waitForKey)
- return "end"
- elseif deadGuys[nou] then
- os.queueEvent("tron_complete", "win", isHost, player[nou].name)
- scrollToPosition(player[nou].x, player[nou].y)
- parallel.waitForAny(function() imageAnim(images.win) end, waitForKey)
- return "end"
- end
- end
- end
- end
- local debugMoveMode = false -- only works if host
- local moveTick = function(doSend)
- local p
- local hasMoved
- for i = 1, #player do
- p = player[i]
- hasMoved = false
- if not p.dead then
- if isHost then
- if debugMoveMode then
- if (i == 1 and keysDown[control.left]) or (i == 2 and netKeysDown[control.left]) then
- p.x = p.x - 1
- hasMoved = true
- end
- if (i == 1 and keysDown[control.right]) or (i == 2 and netKeysDown[control.right]) then
- p.x = p.x + 1
- hasMoved = true
- end
- if (i == 1 and keysDown[control.up]) or (i == 2 and netKeysDown[control.up]) then
- p.y = p.y - 1
- hasMoved = true
- end
- if (i == 1 and keysDown[control.down]) or (i == 2 and netKeysDown[control.down]) then
- p.y = p.y + 1
- hasMoved = true
- end
- else
- p.x = p.x + mathfloor(mathcos(mathrad(p.direction * 90)))
- p.y = p.y + mathfloor(mathsin(mathrad(p.direction * 90)))
- hasMoved = true
- end
- if hasMoved and (doesIntersectBorder(p.x, p.y) or getTrail(p.x, p.y)) then
- p.dead = true
- deadGuys[i] = true
- else
- if p.putTrail or (p.trailLevel < 1) then
- if hasMoved then
- putTrail(p)
- lastTrails[#lastTrails+1] = {p.x, p.y, p.num}
- if #lastTrails > #player then
- tableremove(lastTrails, 1)
- end
- end
- if p.putTrail then
- p.trailLevel = math.min(p.trailLevel + p.trailRegen, p.trailMax)
- else
- p.trailLevel = math.max(p.trailLevel - 1, 0)
- end
- else
- p.trailLevel = math.max(p.trailLevel - 1, 0)
- end
- end
- end
- for a = 1, #player do
- if (a ~= i) and (player[a].x == p.x and player[a].y == p.y) then
- p.dead = true
- deadGuys[i] = true
- if (p.direction + 2) % 4 == player[a].direction % 4 then
- player[a].dead = true
- deadGuys[a] = true
- end
- break
- end
- end
- end
- end
- return deadAnimation(doSend)
- end
- local setDirection = function(p, checkDir, lastDir)
- if (lastDir == control.left) and (checkDir or p.direction) ~= 0 then
- p.direction = 2
- return true
- elseif (lastDir == control.right) and (checkDir or p.direction) ~= 2 then
- p.direction = 0
- return true
- elseif (lastDir == control.up) and (checkDir or p.direction) ~= 1 then
- p.direction = -1
- return true
- elseif (lastDir == control.down) and (checkDir or p.direction) ~= -1 then
- p.direction = 1
- return true
- elseif isPuttingDown == keysDown[control.release] then
- return true
- else
- return false
- end
- end
- local game = function()
- local outcome
- local p, np, timeoutID, tID, evt, netTime
- while true do
- netTime = nil
- if isHost then
- sleep(gameDelay)
- else
- timeoutID = os.startTimer(3)
- repeat
- evt, tID = os.pullEvent()
- until evt == "move_tick" or (evt == "timer" and tID == timeoutID)
- if evt == "timer" then
- os.queueEvent("tron_complete", "timeout", isHost, player[nou].name)
- parallel.waitForAny(function() imageAnim(images.timeout) end, waitForKey)
- return
- elseif evt == "move_tick" then
- netTime = tID
- end
- end
- p = player[you]
- np = player[nou]
- if isHost then
- setDirection(p, nil, control[lastDirectionPressed])
- setDirection(np, nil, control[netLastDirectionPressed])
- p.putTrail = not keysDown[control.release]
- else
- setDirection(p, nil, control[lastDirectionPressed])
- isPuttingDown = not keysDown[control.release]
- sendInfo(gamename, isHost)
- end
- if miceDown[3] then
- scrollAdjX = scrollAdjX + (miceDown[3][1] - scr_x / 2) / (scr_x / 4)
- scrollAdjY = scrollAdjY + (miceDown[3][2] - scr_y / 2) / (scr_y / 2.795)
- else
- if keysDown[control.lookLeft] then
- scrollAdjX = scrollAdjX - 2
- end
- if keysDown[control.lookRight] then
- scrollAdjX = scrollAdjX + 2
- end
- if keysDown[control.lookUp] then
- scrollAdjY = scrollAdjY - 1.25
- end
- if keysDown[control.lookDown] then
- scrollAdjY = scrollAdjY + 1.25
- end
- end
- scrollAdjX = scrollAdjX * 0.8
- scrollAdjY = scrollAdjY * 0.8
- if isHost then
- outcome = moveTick(true)
- else
- outcome = deadAnimation(false)
- end
- ageTrails()
- if outcome == "end" then
- return
- else
- scrollX = p.x - mathfloor(scr_x / 2)
- scrollY = p.y - mathfloor(scr_y / 2)
- render(true, (not isHost) and netTime)
- end
- end
- end
- local cTime -- current UTC time when looking for game
- local networking = function()
- local evt, side, channel, repchannel, msg, distance
- while true do
- --[[
- if useSkynet then
- evt, channel, msg = os.pullEvent("skynet_message")
- else
- evt, side, channel, repchannel, msg, distance = os.pullEvent("modem_message")
- end
- --]]
- msg, channel = disknet.receive(channel)
- if channel == port and type(msg) == "table" then
- if type(msg.gameID) == "string" then
- if waitingForGame and (type(msg.time) == "number") then
- if msg.password == argumentPassword or (argumentPassword == "" and not msg.password) then
- -- called while waiting for match
- if msg.time < cTime then
- isHost = false
- you, nou = nou, you
- gamename = msg.gameID
- gameDelay = tonumber(msg.gameDelay) or gameDelayInit
- grid = msg.grid or copyTable(initGrid)
- player = msg.player or player
- player[you].name = argumentName or player[you].initName
- else
- isHost = true
- end
- player[nou].name = msg.name or player[nou].initName
- transmit(port, {
- player = player,
- gameID = gamename,
- time = cTime,
- name = argumentName,
- password = argumentPassword,
- grid = initGrid
- })
- waitingForGame = false
- netKeysDown = {}
- os.queueEvent("new_game", gameID)
- return gameID
- end
- elseif msg.gameID == gamename then
- -- called during gameplay
- if not isHost then
- if type(msg.player) == "table" then
- player[nou].name = msg.name or player[nou].name
- player = msg.player
- if msg.trail then
- for i = 1, #msg.trail do
- putTrailXY(table.unpack(msg.trail[i]))
- end
- end
- deadGuys = msg.deadGuys
- os.queueEvent("move_tick", msg.time)
- end
- elseif type(msg.keysDown) == "table" then
- netKeysDown = msg.keysDown
- netLastDirectionPressed = msg.lastDir
- player[nou].putTrail = msg.putTrail
- player[nou].name = msg.name or "???" --player[nou].name
- end
- end
- end
- end
- end
- end
- local helpScreen = function()
- termsetBackgroundColor(colors.black)
- termsetTextColor(colors.white)
- termclear()
- termsetCursorPos(1,2)
- print([[
- Move your lightcycle with WASD
- or by tapping left click.
- Pan the camera with arrows
- or by holding middle click.
- Release the trail with spacebar
- or by holding right click.
- If you're P2 (red), a gray circle
- will indicate where you'll turn,
- to help with Skynet's netlag.
- Press any key to go back.
- ]])
- waitForKey(0.25)
- end
- local startGame = function()
- -- reset all info between games
- keysDown = {}
- miceDown = {}
- scrollAdjX = 0
- scrollAdjY = 0
- trail = {}
- deadGuys = {}
- lastDirectionPressed = nil
- netLastDirectionPressed = nil
- gameDelay = gameDelayInit
- grid = copyTable(initGrid)
- player = resetPlayers()
- you, nou = 1, 2
- gamename = ""
- for i = 1, 32 do
- gamename = gamename .. string.char(mathrandom(1,126))
- end
- waitingForGame = true
- cTime = getTime()
- transmit(port, {
- player = player,
- gameID = gamename,
- gameDelay = gameDelayInit,
- time = cTime,
- password = argumentPassword,
- name = argumentName,
- grid = initGrid
- })
- rVal = parallel.waitForAny( pleaseWait, networking )
- sleep(0.1)
- player[you].name = argumentName or player[you].initName
- if rVal == 2 then
- startCountdown()
- parallel.waitForAny( getInput, game, networking )
- end
- end
- local decision
- local main = function()
- return pcall(function()
- local rVal
- while true do
- mode = "menu"
- decision = titleScreen()
- lockInput = false
- if decision == "start" then
- mode = "game"
- if useSkynet then
- parallel.waitForAny(startGame, skynet.listen)
- else
- startGame()
- end
- elseif decision == "help" then
- mode = "help"
- helpScreen()
- elseif decision == "demo" then
- mode = "demo"
- parallel.waitForAny( getInput, gridDemo )
- elseif decision == "exit" then
- return cleanExit()
- end
- end
- end)
- end
- if doGridDemo then
- parallel.waitForAny(function()
- local step, gsX, gsY = 0, 0, 0
- while true do
- drawGrid(gsX, gsY, true)
- step = step + 1
- if mathceil(step / 100) % 2 == 1 then
- gsX = gsX + 1
- else
- gsY = gsY - 1
- end
- sleep(0.05)
- end
- end, function()
- sleep(0.1)
- local evt, key
- repeat
- evt, key = os.pullEvent("key")
- until key == keys.q
- sleep(0.1)
- end)
- else
- if useOnce then
- term.setCursorBlink(false)
- if useSkynet then
- parallel.waitForAny(startGame, skynet.listen)
- skynet.socket.close()
- else
- startGame()
- end
- term.setCursorPos(1, scr_y)
- else
- main()
- if skynet then
- skynet.socket.close()
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement