ldd-CC/tron.lua

1652 lines
40 KiB
Lua
Raw Normal View History

2018-11-14 21:26:04 +00:00
--[[
TRON Light Cycle Game
programmed by LDDestroier
2018-11-20 22:32:14 +00:00
wget https://raw.githubusercontent.com/LDDestroier/CC/master/tron.lua
2018-11-14 21:26:04 +00:00
--]]
2018-11-14 17:01:01 +00:00
local port = 701
2019-01-13 04:00:25 +00:00
local kioskMode = false
2019-01-13 04:52:14 +00:00
local useLegacyMouseControl = false
2018-11-13 20:02:55 +00:00
local scr_x, scr_y = term.getSize()
local scr_mx, scr_my = scr_x / 2, scr_y / 2
local isColor = term.isColor()
-- lower value = faster game. I'd reccommend 0.1 for SMP play.
local gameDelayInit = 0.05
-- draws the names of players onscreen
local doDrawPlayerNames = true
-- if doDrawPlayerNames, also draws your own name
local doRenderOwnName = false
-- whether or not to use term.current().setVisible, which speeds things up at the cost of multishell
local useSetVisible = true
-- determines which grid is used
local gridID = 3
2018-11-14 21:37:31 +00:00
2018-11-14 22:27:21 +00:00
local initGrid = {
x1 = -40,
y1 = -40,
x2 = 40,
y2 = 40,
border = "F",
voidcol = "e",
2018-11-13 20:02:55 +00:00
forecol = "8",
backcol = "7",
edgecol = "0"
}
2018-11-14 01:09:15 +00:00
local resetPlayers = function()
2018-11-16 15:34:40 +00:00
return {
2018-11-14 01:09:15 +00:00
[1] = {
num = 1,
x = -3,
2018-11-14 01:09:15 +00:00
y = -5,
direction = -1,
char = "F",
2018-11-14 01:09:15 +00:00
color = {
colors.blue,
colors.blue,
colors.blue,
colors.cyan,
colors.cyan,
colors.lightBlue,
colors.lightBlue,
colors.cyan,
colors.cyan
},
dead = false,
trailLevel = 10,
trailMax = 20,
trailRegen = 0.1,
putTrail = true,
name = "BLU",
initName = "BLU"
2018-11-14 01:09:15 +00:00
},
[2] = {
num = 2,
x = 3,
2018-11-14 01:09:15 +00:00
y = -5,
direction = -1,
char = "~",
2018-11-14 01:09:15 +00:00
color = {
colors.red,
colors.red,
colors.red,
colors.orange,
colors.orange,
colors.yellow,
colors.yellow,
colors.orange,
colors.orange
},
dead = false,
trailLevel = 10,
trailMax = 20,
trailRegen = 0.1,
putTrail = true,
name = "RED",
initName = "RED"
2018-11-14 01:09:15 +00:00
}
}
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 = {
2019-03-01 04:47:51 +00:00
["skynet"] = false, -- use Skynet HTTP multiplayer
["quick"] = false, -- start one game immediately
["griddemo"] = false, -- only move the grid
2019-03-01 04:47:51 +00:00
["--update"] = false, -- updates TRON to the latest version
["--gridID"] = "number" -- grid ID to use
}
local gridFore, gridBack
local gridList = {
[1] = {
{
"+-------",
"| ",
"| ",
"| ",
"| "
},
{
"+------------",
"| ",
"| ",
"| ",
"| ",
"| ",
"| ",
"| "
}
},
[2] = {
{
" / ",
" / ",
" / ",
" / ",
"/__________"
},
{
" / ",
" / ",
" / ",
" / ",
" / ",
" / ",
" / ",
"/_______________"
}
},
[3] = {
{
"+- -+------",
"| | ",
" | ",
". | ",
"+------+- --",
"| | ",
"| ",
"| . ",
},
{
"+- -+--------",
"| | ",
" | ",
" | ",
" | ",
"| | ",
"+--------+- -",
"| | ",
"| ",
"| ",
"| ",
"| | ",
}
},
[4] = {
{
" /\\ ",
" / \\ ",
" / \\ ",
"/ \\",
"\\ /",
" \\ / ",
" \\ / ",
" \\/ ",
},
{
" /\\ ",
" / \\ ",
" / \\ ",
" / \\ ",
" / \\ ",
"/ \\",
"\\ /",
" \\ / ",
" \\ / ",
" \\ / ",
" \\ / ",
" \\/ ",
}
}
}
local argList = interpretArgs({...}, argData)
local useSkynet = argList["skynet"]
local useOnce = argList["quick"]
local doGridDemo = argList["griddemo"]
2019-03-01 04:47:51 +00:00
local doUpdateGame = argList["--update"]
if gridList[argList["--gridID"]] then
gridID = argList["--gridID"]
end
local argumentName = argList[1]
local skynetPath = "skynet"
local skynetURL = "https://raw.githubusercontent.com/osmarks/skynet/master/client.lua"
if argumentName then
2019-02-26 06:43:41 +00:00
argumentName = argumentName:sub(1, 15) -- gotta enforce that limit
end
local modem, skynet
2019-03-01 04:49:50 +00:00
if not doGridDemo then
if useSkynet then
if fs.exists(skynetPath) then
skynet = dofile(skynetPath)
skynet.open(port)
else
2019-03-01 04:49:50 +00:00
local prog = http.get(skynetURL)
if prog then
local file = fs.open(skynetPath, "w")
file.write(prog.readAll())
file.close()
skynet = dofile(skynetPath)
skynet.open(port)
else
error("Could not download Skynet.")
end
end
else
2019-03-01 04:49:50 +00:00
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
2018-11-16 15:34:40 +00:00
end
local transmit = function(port, message)
if useSkynet then
skynet.send(port, message)
else
modem.transmit(port, port, message)
end
2018-11-16 15:34:40 +00:00
end
local gamename = ""
local isHost
local waitingForGame = true
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
2018-11-16 15:34:40 +00:00
local termwrite, termclear = term.write, term.clear
2018-11-16 15:34:40 +00:00
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
2018-11-16 15:34:40 +00:00
local tsv = function(visible)
2018-12-04 00:26:08 +00:00
if term.current().setVisible and useSetVisible then
2018-11-16 15:34:40 +00:00
term.current().setVisible(visible)
end
end
local round = function(num, places)
return math.floor(num * 10^places) / 10^places
end
-- used in skynet matches if you are player 2
local ping = 0
2018-11-28 17:15:39 +00:00
local copyTable
copyTable = function(tbl, ...)
2018-11-16 15:34:40 +00:00
local output = {}
for k,v in pairs(tbl) do
if type(v) == "table" then
2018-11-28 17:15:39 +00:00
output[k] = copyTable(v)
2018-11-16 15:34:40 +00:00
else
output[k] = v
end
end
for i = 1, #arg do
output[#output+1] = arg[i]
end
return output
end
2018-11-28 17:15:39 +00:00
grid = copyTable(initGrid)
2018-11-16 15:34:40 +00:00
2018-11-28 17:15:39 +00:00
local you, nou = 1, 2
2018-11-16 15:34:40 +00:00
2018-11-28 17:15:39 +00:00
local keysDown, netKeysDown = {}, {}
local miceDown = {}
2018-11-28 17:15:39 +00:00
local lastDirectionPressed, netLastDirectionPressed
2018-11-16 15:34:40 +00:00
-- 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()
2018-11-14 01:09:15 +00:00
local images = {
logo = {
{
" •ƒƒƒƒƒƒƒƒƒ•—ƒƒƒƒƒƒƒ‹‹ ‡‡ƒƒƒ‹‹ Ÿ‹ •ƒƒ•",
" •ƒƒƒ”€—ƒƒƒ•‚ƒƒƒƒƒ‹€€€Š —€Ÿƒƒƒ€” •‚‚ •€€•",
" •€• ‚‚ƒƒ•€€—€€€”€€••€€‹‹ •€€•",
" •€• —ƒ”‹“ƒƒ‹€€€•€€•€€€•€€••€•ˆƒ€€•",
" •€• •€• ‚‹€€‹€Š€‹‡€Ÿ…•€• ‚‚€•",
" •€• •€• ‹€‚‹ ‹‹€€€Ÿ‡‡ •€• ‹‹•",
"   Š ‚‹‡  ‚…",
},
{
" f7777777777777777777f f77777f 7f f777",
" f99979999979999999999f 799999799 77f7 f997",
2018-11-17 00:21:12 +00:00
" 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",
2018-11-17 00:21:12 +00:00
" 997 f7777799 799f99997 799f",
" 997 997f9997fff799 799f997ff7999f",
" 997 997 f7999fff999777997f997 f799f",
" 997 997 f9997 f7999977f 997 f7f",
" fff fff ffff fffffff fff ff",
}
},
win = {
{
2018-11-15 00:51:52 +00:00
"€•€€€€€€€••€€€€€€€€Š€€€€•€€€•",
"€•€€€€€€€•‚€€•€ƒ€€€‚€€•€€€•",
"€•€€‡€€€•€€€€•€€€€•‹€‹€•€€€•",
"€•ŸŸ€‹€€•€€€€•€€€€•€‚‚…€€€•",
"€‚€‡€‚‚€•Ÿ€€•€€€•€€€‹€€€",
"€Ÿ€€€€‹€••€€€€€€€€•€€€€•€€€•",
},
{
2018-11-17 00:21:12 +00:00
"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",
},
{
2018-11-17 00:21:12 +00:00
"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 = {
{
2018-11-15 00:51:52 +00:00
"€•€€€€€€Ÿ€€€‚€€€€€€‚€€€€€€€€",
"€•€€€€€€€Ÿ€‚€€€—€€€‚ƒ€€•€€€‚ƒ",
"€•€€€€€€€•€€€•€€€€ƒƒƒƒ‹€€‚ƒƒƒ”€",
"€•€€€€€€€•€€€•€€‚ƒƒƒƒ€€€—ƒƒƒ€",
"€•€€€€€€€‚€Ÿ€€€€€…€€€•€€€Ÿ",
"€€€€€€€€‚€€€Ÿ€€€€€€Ÿ€€€€€€€€",
},
{
2018-11-17 00:21:12 +00:00
"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",
},
{
2018-11-17 00:21:12 +00:00
"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 = {
{
2018-11-15 00:51:52 +00:00
"€€€€€€€••€€€€€€€€€€€€€€€",
"€€€€•€€€‚€•€€€ƒ€€•€€€€ƒ",
"€€€€•€€€€€€•€€€€€€‚ƒƒƒ”€",
"€€€€•€€€€€€•€€€€€€—ƒƒƒ€",
"€€€€•€€€Ÿ€•€€€€€•€€€€",
"€€€€•€€€•€€€€€€€€€€€€€€€",
},
{
2018-11-17 00:21:12 +00:00
"77888800 0000000 0888877",
" 88 00 0 0 08 7",
" 88 0 0 7 ",
" 88 0 088887 ",
" 88 0 0 08 ",
" 88 0000000 0888877",
},
{
2018-11-17 00:21:12 +00:00
"7788880 00000000 0888877",
" 8 00 0 ",
" 8 00 08888 ",
" 8 00 0 ",
" 8 0 00 0 0 7",
" 8 00000000 0888877",
},
2018-11-28 17:15:39 +00:00
},
timeout = {
{
"—ƒƒƒƒ•—ƒƒƒƒ•—ƒ›Ÿ†ƒ•—ƒƒƒ”",
"“€—Œ…“€—Œ…•€€€€••€ŒŒž",
" •€•€€…€••€˜•€••€ˆŒŽ",
" •€•€€•€€€€••€•€•€••€€€•",
" ‚ƒƒ€€ƒƒƒƒƒƒƒ€ƒƒƒƒƒƒƒ",
" —ƒƒƒƒ••ƒ”•ƒ”•ƒƒƒƒ”",
" •€œ”€••€••€•ŠŒ”€œŽ",
" •€Š•€••€•…€• €•€•",
" •€€€€••€€€€• €•€•",
" ƒƒƒƒƒ‚ƒƒƒƒƒ€€ƒƒ",
},
{
"00000000000000ff0000000f",
"0fff000fff000ff0ff00f000",
"0ffffffffff00f000f00ffff",
" fffff0ffff00f0f0f00ffff",
" 000ff000000000f00000000",
" 000000f0ff0ff0000f",
" 0f00f0ffffff000f00",
" 0ff0f0ffffff7f0f0",
" 0ffff0ffffff7f0f0",
" 000000000000ff000",
},
{
"ffffffffffffff00fffffff0",
" 0f0fff0f0ffffffffffffff",
" 0f0ff00f00ffffffffff000",
" 0f0fffffffffffffffffff0",
" fffffffffffffffffffffff",
" ffffff0f00f00ffff0",
" ffffff0f00f0ffffff",
" ff0fff0f00f0fffff",
" ffffff0ffff0fffff",
" fffffffffffffffff",
},
}
}
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]
-- remove all that white bullshit that artifacts on cc:tweaked
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) .. "f" .. 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) .. "f" .. v[3][y]:sub(x + 1)
end
end
end
end
2018-11-16 03:33:29 +00:00
end
local drawImage = function(im, x, y)
2018-11-16 15:34:40 +00:00
local cx, cy = termgetCursorPos()
termsetBackgroundColor( tocolors[initGrid.voidcol] )
termsetTextColor( tocolors[initGrid.voidcol] )
for iy = 1, #im[1] do
2018-11-15 16:56:27 +00:00
for ix = 1, #im[1][iy] do
2018-11-16 15:34:40 +00:00
termsetCursorPos(x+(ix-1),y+(iy-1))
2018-11-15 16:56:27 +00:00
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),
im[3][iy]:sub(ix,ix)
)
2018-11-15 16:56:27 +00:00
end
end
end
2018-11-16 15:34:40 +00:00
termsetCursorPos(cx,cy)
end
local deadGuys = {}
2018-11-14 01:09:15 +00:00
local trail = {}
local lastTrails = {}
2018-11-16 20:52:36 +00:00
isPuttingDown = false
2018-11-14 01:09:15 +00:00
local putTrailXY = function(x, y, p)
trail[y] = trail[y] or {}
trail[y][x] = {
player = p,
2018-11-14 01:09:15 +00:00
age = 0
}
end
local putTrail = function(p)
putTrailXY(p.x, p.y, p.num)
end
2018-11-14 01:09:15 +00:00
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
2018-11-14 01:09:15 +00:00
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
2018-11-13 20:02:55 +00:00
local control, revControl = {
2018-11-13 21:35:25 +00:00
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
2018-11-13 21:35:25 +00:00
gridFore, gridBack = table.unpack(gridList[gridID])
2018-11-13 20:17:08 +00:00
2018-11-14 01:09:15 +00:00
local dirArrow = {
[-1] = "^",
[0] = ">",
[1] = "V",
[2] = "<"
}
local cwrite = function(text, y, xdiff, wordPosCheck)
wordPosCheck = wordPosCheck or #text
termsetCursorPos(mathfloor(scr_x / 2 - (#text + (xdiff or 0)) / 2), y or (scr_y - 2))
term.write(text)
return (scr_x / 2) - (#text / 2) + wordPosCheck
end
2018-11-14 01:09:15 +00:00
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
2018-11-14 01:09:15 +00:00
end
2018-11-15 17:17:45 +00:00
--draws grid and background at scroll 'x' and 'y', along with trails and players
2018-11-16 15:36:19 +00:00
local drawGrid = function(x, y, onlyDrawGrid, useSetVisible)
2019-02-23 07:54:57 +00:00
tsv(false)
2018-11-16 15:34:40 +00:00
x, y = mathfloor(x + 0.5), mathfloor(y + 0.5)
2018-11-13 20:02:55 +00:00
local bg = {{},{},{}}
local foreX, foreY
local backX, backY
local adjX, adjY
local trailChar, trailColor, trailAge, isPlayer, isPredict
2018-11-13 20:02:55 +00:00
for sy = 1, scr_y do
bg[1][sy] = ""
bg[2][sy] = ""
bg[3][sy] = ""
for sx = 1, scr_x do
2018-11-14 01:09:15 +00:00
adjX = (sx + x)
adjY = (sy + y)
foreX = 1 + (sx + x) % #gridFore[1]
foreY = 1 + (sy + y) % #gridFore
2018-11-16 15:34:40 +00:00
backX = 1 + mathfloor(sx + (x / 2)) % #gridBack[1]
backY = 1 + mathfloor(sy + (y / 2)) % #gridBack
2018-11-14 01:09:15 +00:00
trailChar, trailColor, trailAge = getTrail(adjX, adjY)
isPlayer = false
isPredict = false
2018-11-15 17:17:45 +00:00
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
2018-11-15 17:17:45 +00:00
end
2018-11-14 01:09:15 +00:00
end
end
if isPlayer and (not onlyDrawGrid) and (not doesIntersectBorder(adjX, adjY)) then
2018-11-14 01:09:15 +00:00
bg[1][sy] = bg[1][sy] .. dirArrow[player[isPlayer].direction]
bg[2][sy] = bg[2][sy] .. toblit[player[isPlayer].color[1]]
2018-11-13 20:39:29 +00:00
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
2018-11-13 20:02:55 +00:00
else
2018-11-15 17:17:45 +00:00
if (not onlyDrawGrid) and trailChar and trailColor then
2018-11-14 01:09:15 +00:00
trailColor = trailColor[1 + ((trailAge - 1) % #trailColor)]
bg[1][sy] = bg[1][sy] .. trailChar
bg[2][sy] = bg[2][sy] .. toblit[trailColor]
2018-11-13 20:02:55 +00:00
bg[3][sy] = bg[3][sy] .. grid.voidcol
else
2018-11-15 17:17:45 +00:00
if (not onlyDrawGrid) and (adjX < grid.x1 or adjX > grid.x2 or adjY < grid.y1 or adjY > grid.y2) then
2018-11-14 01:09:15 +00:00
bg[1][sy] = bg[1][sy] .. " "
bg[2][sy] = bg[2][sy] .. grid.voidcol
bg[3][sy] = bg[3][sy] .. grid.voidcol
2018-11-15 17:17:45 +00:00
elseif (not onlyDrawGrid) and doesIntersectBorder(adjX, adjY) then
2018-11-14 01:09:15 +00:00
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
2018-11-13 20:02:55 +00:00
end
end
end
end
for sy = 1, scr_y do
2018-11-16 15:34:40 +00:00
termsetCursorPos(1,sy)
termblit(
bg[1][sy],
bg[2][sy],
bg[3][sy]
)
2018-11-13 20:02:55 +00:00
end
2018-11-28 17:15:39 +00:00
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 + (scrollX + scrollAdjX), adjY + (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))
2018-11-28 17:15:39 +00:00
end
end
end
end
2019-02-23 07:54:57 +00:00
tsv(true)
2018-11-13 20:02:55 +00:00
end
local render = function(useSetVisible, netTime)
2018-11-14 01:09:15 +00:00
local p = player[you]
drawGrid(scrollX + scrollAdjX, scrollY + scrollAdjY, false, useSetVisible)
2018-11-16 15:34:40 +00:00
termsetCursorPos(1,1)
termsetTextColor(player[you].color[1])
2018-11-28 17:15:39 +00:00
termsetBackgroundColor(tocolors[grid.voidcol])
2018-11-16 20:53:11 +00:00
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 = (os.epoch("utc") - netTime)
2019-02-26 06:43:41 +00:00
term.setTextColor(colors.white)
term.write(" " .. tostring(ping) .. " ms")
end
term.setTextColor(colors.white)
end
local pleaseWait = function()
local periods = 1
local maxPeriods = 5
2018-11-16 15:34:40 +00:00
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
2018-11-14 01:09:15 +00:00
end
2018-11-15 00:28:01 +00:00
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 "
2018-11-16 15:34:40 +00:00
scrollX = player[you].x - mathfloor(scr_x / 2)
scrollY = player[you].y - mathfloor(scr_y / 2)
2018-11-15 00:30:05 +00:00
for i = 3, 1, -1 do
render(true)
2018-11-16 15:34:40 +00:00
termsetTextColor(colors.white)
2018-11-20 22:50:00 +00:00
for x = 1, #cMessage+1 do
2018-11-20 22:47:29 +00:00
termsetCursorPos(-1 + x + mathfloor(scr_x / 2 - (#cMessage + #cName) / 2), mathfloor(scr_y / 2) + 2)
2018-11-20 22:50:00 +00:00
if cMessage:sub(x,x) ~= " " and x <= #cMessage then
2018-11-20 22:47:29 +00:00
termwrite(cMessage:sub(x,x))
end
end
2018-11-16 15:34:40 +00:00
termsetTextColor(col)
termwrite(player[you].name)
2018-11-16 15:34:40 +00:00
termsetTextColor(colors.white)
termsetCursorPos(mathfloor(scr_x / 2 - 2), mathfloor(scr_y / 2) + 4)
termwrite(i .. "...")
2018-11-15 00:28:01 +00:00
sleep(1)
end
end
local makeMenu = function(x, y, options, doAnimate, scrollInfo, _cpos)
local cpos = _cpos or 1
2018-11-13 21:35:25 +00:00
local cursor = "> "
local gsX, gsY = (scrollInfo or {})[2] or 0, (scrollInfo or {})[3] or 0
local step = (scrollInfo or {})[1] or 0
2018-11-15 17:17:45 +00:00
local lastPos = cpos
if not doAnimate then
2018-11-16 15:34:40 +00:00
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
2018-11-15 17:17:45 +00:00
end
2018-11-15 05:38:39 +00:00
local rend = function()
2018-11-15 17:17:45 +00:00
if doAnimate then
2018-11-16 15:34:40 +00:00
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
2018-11-15 17:17:45 +00:00
end
2018-11-13 21:35:25 +00:00
for i = 1, #options do
if i == cpos then
2018-11-16 15:34:40 +00:00
termsetCursorPos(x, y + (i - 1))
termsetTextColor(colors.white)
termwrite(cursor .. options[i])
2018-11-13 21:35:25 +00:00
else
2018-11-15 17:17:45 +00:00
if i == lastPos then
2018-11-16 15:34:40 +00:00
termsetCursorPos(x, y + (i - 1))
termwrite((" "):rep(#cursor))
2018-11-15 17:17:45 +00:00
lastPos = nil
else
2018-11-16 15:34:40 +00:00
termsetCursorPos(x + #cursor, y + (i - 1))
2018-11-15 17:17:45 +00:00
end
2018-11-16 15:34:40 +00:00
termsetTextColor(colors.gray)
termwrite(options[i])
2018-11-13 21:35:25 +00:00
end
end
end
local gstID, evt = mathrandom(1,65535)
2018-11-15 17:17:45 +00:00
if doAnimate then
os.queueEvent("timer", gstID)
end
rend()
2018-11-14 01:09:15 +00:00
while true do
evt = {os.pullEvent()}
if evt[1] == "key" then
if evt[2] == keys.up then
2018-11-15 17:17:45 +00:00
lastPos = cpos
2018-11-14 22:27:21 +00:00
cpos = (cpos - 2) % #options + 1
2018-11-14 01:09:15 +00:00
elseif evt[2] == keys.down then
2018-11-15 17:17:45 +00:00
lastPos = cpos
2018-11-14 21:42:14 +00:00
cpos = (cpos % #options) + 1
2018-11-15 17:17:45 +00:00
elseif evt[2] == keys.home then
lastPos = cpos
cpos = 1
elseif evt[2] == keys["end"] then
lastPos = cpos
cpos = #options
2018-11-14 01:09:15 +00:00
elseif evt[2] == keys.enter then
return cpos, {step, gsX, gsY}
2018-11-14 01:09:15 +00:00
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)
rend()
end
end
2018-11-15 17:17:45 +00:00
elseif evt[1] == "timer" and evt[2] == gstID then
2018-11-16 19:17:51 +00:00
gstID = os.startTimer(gameDelayInit)
2018-12-04 00:26:08 +00:00
drawGrid(gsX, gsY, true)
2018-11-15 17:17:45 +00:00
step = step + 1
2018-11-16 15:34:40 +00:00
if mathceil(step / 100) % 2 == 1 then
2018-11-15 17:17:45 +00:00
gsX = gsX + 1
else
gsY = gsY - 1
end
rend()
end
if lastPos ~= cpos then
rend()
end
end
end
local nameChange = function(scrollInfo)
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
2019-02-26 06:43:41 +00:00
local maxSize = 15
local evt
2019-02-26 06:43:41 +00:00
-- this has no functional significance. just some shoutouts
local specialNames = {
["blu"] = colors.blue,
["red"] = colors.red,
["ldd"] = colors.orange,
["lddestroier"] = colors.orange,
["3d6"] = colors.lime,
["lyqyd"] = colors.red,
["squiddev"] = colors.cyan,
["oeed"] = colors.green,
["dog"] = colors.purple,
["nothy"] = colors.lightGray,
["kepler"] = colors.cyan,
["crazed"] = colors.lightBlue,
2019-02-26 06:43:41 +00:00
["ape"] = colors.brown,
["everyos"] = 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,
["kingdaro"] = colors.blue,
["valithor"] = colors.orange,
["logandark"] = colors.lightGray
}
local prevName = argumentName or player[you].initName
for x = 1, #prevName do
buff[x] = prevName:sub(x, x)
cpos = cpos + 1
end
term.setCursorBlink(true)
local rend = function()
2019-02-26 06:46:12 +00:00
if table.concat(buff):upper() == "GASTER" then
os.reboot() -- lol
end
drawGrid(gsX, gsY, true)
term.setTextColor(colors.white)
cwrite("Enter your name.", 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
2018-11-14 01:09:15 +00:00
end
end
2018-11-13 21:35:25 +00:00
end
local titleScreen = function()
2018-11-16 15:34:40 +00:00
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
options = {
"Grid Demo",
"Change Name",
"Change Grid",
"Back..."
}
while true do
choice, scrollInfo = makeMenu(2, scr_y - #menuOptions, menuOptions, true, scrollInfo)
if choice == 1 then
return "start"
elseif choice == 2 then
return "help"
elseif choice == 3 then
local _cpos
while true do
choice, scrollInfo = makeMenu(14, scr_y - #menuOptions, options, true, scrollInfo, _cpos)
_cpos = choice
if choice == 1 then
return "demo"
elseif choice == 2 then
local newName = nameChange(scrollInfo)
if #newName > 0 then
2019-02-26 06:43:41 +00:00
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
break
end
end
elseif choice == 4 then
return "exit"
end
2018-11-14 01:09:15 +00:00
end
2018-11-13 21:35:25 +00:00
end
2018-11-14 01:09:15 +00:00
local cleanExit = function()
2018-11-16 15:34:40 +00:00
termsetBackgroundColor(colors.black)
termsetTextColor(colors.white)
termclear()
termsetCursorPos(1,1)
2018-11-14 21:31:24 +00:00
print("Thanks for playing!")
2018-11-14 01:09:15 +00:00
end
2018-11-13 21:35:25 +00:00
2019-01-13 04:52:14 +00:00
local parseMouseInput = function(button, x, y, direction)
local output = false
local cx = x - scr_mx
local cy = y - scr_my
2019-01-13 04:52:14 +00:00
if useLegacyMouseControl then -- outdated mouse input
cx = cx * (scr_y / scr_x)
if cx > cy then
if -cx > cy then
output = "up"
else
output = "right"
end
else
2019-01-13 04:52:14 +00:00
if -cx < cy then
output = "down"
else
output = "left"
end
end
else
2019-01-13 04:52:14 +00:00
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
2018-11-13 20:39:29 +00:00
local getInput = function()
local evt
local mkey = -1
2018-11-13 20:39:29 +00:00
while true do
evt = {os.pullEvent()}
2018-11-14 01:09:15 +00:00
if lockInput then
keysDown = {}
miceDown = {}
2018-11-14 01:09:15 +00:00
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
2018-11-14 01:09:15 +00:00
keysDown[evt[2]] = true
elseif evt[1] == "key_up" then
keysDown[evt[2]] = false
2019-01-13 04:52:14 +00:00
elseif evt[1] == "mouse_click" or (useLegacyMouseControl and evt[1] == "mouse_drag") then
2019-01-13 04:08:38 +00:00
if evt[1] == "mouse_drag" then
keysDown[mkey] = false
end
miceDown[evt[2]] = {evt[3], evt[4]}
2019-01-13 04:52:14 +00:00
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
2019-01-13 04:52:14 +00:00
mkey = parseMouseInput(evt[2], evt[3], evt[4], player[you].direction) or -1
keysDown[mkey] = false
end
2018-11-13 20:39:29 +00:00
end
end
end
2018-11-14 01:09:15 +00:00
2018-11-14 21:31:24 +00:00
local scrollToPosition = function(x, y)
2018-11-14 01:09:15 +00:00
for i = 1, 16 do
scrollX = (scrollX + x - (scr_x/2)) / 2
scrollY = (scrollY + y - (scr_y/2)) / 2
render(true)
2018-11-14 21:37:31 +00:00
sleep(0.05)
2018-11-14 01:09:15 +00:00
end
end
2018-11-13 20:39:29 +00:00
local gridDemo = function()
2018-11-14 01:40:32 +00:00
keysDown = {}
miceDown = {}
scrollX, scrollY = math.floor(scr_x * -0.5), math.floor(scr_y * -0.75)
2018-11-13 20:39:29 +00:00
while true do
if keysDown[keys.left] then
2018-11-14 01:09:15 +00:00
scrollX = scrollX - 1
2018-11-13 20:39:29 +00:00
end
if keysDown[keys.right] then
2018-11-14 01:09:15 +00:00
scrollX = scrollX + 1
2018-11-13 20:39:29 +00:00
end
if keysDown[keys.up] then
2018-11-14 01:09:15 +00:00
scrollY = scrollY - 1
2018-11-13 20:39:29 +00:00
end
if keysDown[keys.down] then
2018-11-14 01:09:15 +00:00
scrollY = scrollY + 1
2018-11-13 20:39:29 +00:00
end
2018-11-14 01:34:28 +00:00
if keysDown[keys.q] then
return "end"
end
drawGrid(scrollX, scrollY, false, true)
2018-11-14 01:09:15 +00:00
ageTrails()
2018-11-14 21:31:24 +00:00
sleep(gameDelay)
2018-11-13 20:39:29 +00:00
end
2018-11-13 20:02:55 +00:00
end
2018-11-14 01:09:15 +00:00
2018-11-15 05:21:43 +00:00
local sendInfo = function(gameID)
2018-11-16 15:34:40 +00:00
transmit(port, {
player = isHost and player or nil,
2018-11-27 22:42:41 +00:00
name = player[you].name,
2018-11-16 20:52:36 +00:00
putTrail = isPuttingDown,
gameID = gameID,
time = os.epoch("utc"),
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")
2018-11-14 21:09:32 +00:00
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
2018-11-15 05:21:43 +00:00
sendInfo(gamename)
2018-11-14 01:09:15 +00:00
end
2018-11-14 01:34:28 +00:00
if deadGuys[you] or deadGuys[nou] then
2018-11-16 15:34:40 +00:00
termsetTextColor(colors.white)
2018-11-14 01:34:28 +00:00
if deadGuys[you] and deadGuys[nou] then
2018-11-30 00:46:29 +00:00
os.queueEvent("tron_complete", "tie", isHost, player[nou].name)
2018-11-14 01:34:28 +00:00
scrollToPosition(player[nou].x, player[nou].y)
scrollToPosition(player[you].x, player[you].y)
parallel.waitForAny(function() imageAnim(images.tie) end, waitForKey)
2018-11-14 01:34:28 +00:00
return "end"
else
if deadGuys[you] then
scrollX, scrollY = player[nou].x - scr_x / 2, player[nou].y - scr_y / 2
2018-11-30 00:46:29 +00:00
os.queueEvent("tron_complete", "lose", isHost, player[nou].name)
scrollToPosition(player[you].x, player[you].y)
parallel.waitForAny(function() imageAnim(images.lose) end, waitForKey)
2018-11-14 01:34:28 +00:00
return "end"
elseif deadGuys[nou] then
2018-11-30 00:46:29 +00:00
os.queueEvent("tron_complete", "win", isHost, player[nou].name)
2018-11-14 01:34:28 +00:00
scrollToPosition(player[nou].x, player[nou].y)
parallel.waitForAny(function() imageAnim(images.win) end, waitForKey)
2018-11-14 01:34:28 +00:00
return "end"
end
end
end
end
local moveTick = function(doSend)
local p
for i = 1, #player do
p = player[i]
if not p.dead then
2018-11-15 06:28:54 +00:00
if isHost then
p.x = p.x + mathfloor(mathcos(mathrad(p.direction * 90)))
p.y = p.y + mathfloor(mathsin(mathrad(p.direction * 90)))
if 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
putTrail(p)
lastTrails[#lastTrails+1] = {p.x, p.y, p.num}
if #lastTrails > #player then
tableremove(lastTrails, 1)
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
2018-11-15 06:28:54 +00:00
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
2018-11-15 05:21:43 +00:00
p.direction = 2
return true
elseif (lastDir == control.right) and (checkDir or p.direction) ~= 2 then
2018-11-15 05:21:43 +00:00
p.direction = 0
return true
elseif (lastDir == control.up) and (checkDir or p.direction) ~= 1 then
2018-11-15 05:21:43 +00:00
p.direction = -1
return true
elseif (lastDir == control.down) and (checkDir or p.direction) ~= -1 then
2018-11-15 05:21:43 +00:00
p.direction = 1
return true
elseif isPuttingDown == keysDown[control.release] then
return true
else
return false
end
2018-11-14 01:09:15 +00:00
end
local game = function()
2018-11-14 17:01:01 +00:00
local outcome
local p, np, timeoutID, tID, evt, netTime
2018-11-14 01:09:15 +00:00
while true do
netTime = nil
if isHost then
sleep(gameDelay)
else
2018-11-28 17:15:39 +00:00
timeoutID = os.startTimer(3)
repeat
evt, tID = os.pullEvent()
until evt == "move_tick" or (evt == "timer" and tID == timeoutID)
if evt == "timer" then
2018-11-30 00:46:29 +00:00
os.queueEvent("tron_complete", "timeout", isHost, player[nou].name)
2018-11-28 17:15:39 +00:00
parallel.waitForAny(function() imageAnim(images.timeout) end, waitForKey)
return
elseif evt == "move_tick" then
netTime = tID
2018-11-28 17:15:39 +00:00
end
end
p = player[you]
np = player[nou]
if isHost then
setDirection(p, nil, control[lastDirectionPressed])
setDirection(np, nil, control[netLastDirectionPressed])
2018-11-16 20:52:36 +00:00
p.putTrail = not keysDown[control.release]
2018-11-15 05:30:02 +00:00
else
setDirection(p, nil, control[lastDirectionPressed])
2018-11-16 20:52:36 +00:00
isPuttingDown = not keysDown[control.release]
sendInfo(gamename)
2018-11-14 01:09:15 +00:00
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
2018-11-14 01:09:15 +00:00
end
2018-11-14 01:09:15 +00:00
scrollAdjX = scrollAdjX * 0.8
scrollAdjY = scrollAdjY * 0.8
if isHost then
outcome = moveTick(true)
else
outcome = deadAnimation(false)
end
ageTrails()
2018-11-14 01:09:15 +00:00
if outcome == "end" then
return
else
2018-11-16 15:34:40 +00:00
scrollX = p.x - mathfloor(scr_x / 2)
scrollY = p.y - mathfloor(scr_y / 2)
render(true, (not isHost) and netTime)
2018-11-14 01:09:15 +00:00
end
end
end
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
if channel == port and type(msg) == "table" then
if type(msg.gameID) == "string" then
if waitingForGame and (type(msg.time) == "number") then
-- called while waiting for match
if msg.time < os.epoch("utc") then
isHost = false
you, nou = nou, you
2018-11-16 21:28:49 +00:00
gamename = msg.gameID
2018-11-16 19:17:51 +00:00
gameDelay = tonumber(msg.gameDelay) or gameDelayInit
2018-11-28 17:15:39 +00:00
grid = msg.grid or copyTable(initGrid)
2018-11-16 21:28:49 +00:00
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
2018-11-16 15:34:40 +00:00
transmit(port, {
player = player,
gameID = gamename,
time = isHost and (-math.huge) or (math.huge),
name = argumentName,
2018-11-14 22:27:21 +00:00
grid = initGrid
})
waitingForGame = false
netKeysDown = {}
os.queueEvent("new_game", gameID)
2018-11-27 22:46:39 +00:00
return gameID
elseif msg.gameID == gamename then
-- called during gameplay
2018-11-27 22:44:11 +00:00
if not isHost then
if type(msg.player) == "table" then
2018-11-27 22:42:41 +00:00
player[nou].name = msg.name or player[nou].name
player = msg.player
if msg.trail then
for i = 1, #msg.trail do
putTrailXY(unpack(msg.trail[i]))
end
end
deadGuys = msg.deadGuys
os.queueEvent("move_tick", msg.time)
end
2018-11-27 22:44:11 +00:00
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
2018-11-15 05:38:39 +00:00
local helpScreen = function()
2018-11-16 15:34:40 +00:00
termsetBackgroundColor(colors.black)
termsetTextColor(colors.white)
termclear()
termsetCursorPos(1,2)
2018-11-14 21:26:04 +00:00
print([[
Move with arrow keys.
Pan the camera with WASD.
Hold SPACE to create gaps.
This takes fuel, which will
recharge over time..
If you're P2 (red), a gray circle
will indicate where you'll turn,
to help with Skynet's netlag.
2018-11-14 21:26:04 +00:00
That's basically it.
Press any key to go back.
]])
waitForKey(0.25)
end
2018-11-27 22:28:31 +00:00
local startGame = function()
2018-11-28 17:15:39 +00:00
-- reset all info between games
keysDown = {}
miceDown = {}
scrollAdjX = 0
scrollAdjY = 0
2018-11-28 17:15:39 +00:00
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
transmit(port, {
player = player,
gameID = gamename,
gameDelay = gameDelayInit,
time = os.epoch("utc"),
name = argumentName,
2018-11-28 17:15:39 +00:00
grid = initGrid
})
rVal = parallel.waitForAny( pleaseWait, networking )
sleep(0.1)
player[you].name = argumentName or player[you].initName
2018-11-28 17:15:39 +00:00
if rVal == 2 then
startCountdown()
parallel.waitForAny( getInput, game, networking )
end
2018-11-27 22:28:31 +00:00
end
local decision
local main = function()
2018-11-28 17:15:39 +00:00
local rVal
while true do
decision = titleScreen()
lockInput = false
if decision == "start" then
2018-11-27 22:28:31 +00:00
startGame()
elseif decision == "help" then
helpScreen()
elseif decision == "demo" then
parallel.waitForAny( getInput, gridDemo )
elseif decision == "exit" then
return cleanExit()
end
2018-11-14 01:09:15 +00:00
end
2018-11-14 21:09:32 +00:00
end
2019-03-01 04:47:51 +00:00
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)
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)
2018-11-27 22:28:31 +00:00
else
if useSkynet then
parallel.waitForAny(main, skynet.listen)
skynet.socket.close()
else
main()
end
2018-11-27 22:28:31 +00:00
end
end