Built-in programs

pong
network pong for two
Type this at the prompt of a computer to copy it onto the medium:
> examples pong > edit pong
The program
-- PONG for two players on two computers linked by data cable, radio
-- modems or Wi-Fi. First computer: pong host Second one: pong join
-- Up/down arrows (or W/S) move your paddle. First to 5 wins. Ctrl+T quits.
-- The host moves the ball and sends the whole state 10 times a second;
-- the other computer only sends its paddle.
local mode = arg[1]
if mode ~= "host" and mode ~= "join" then
print("Usage: pong host or pong join")
return
end
local W, H, PAD, WIN = 40, 15, 4, 5 -- field, paddle height, winning score
local me = {y = 6}
local other = {y = 6}
local left, right = me, other -- the host plays on the left
if mode == "join" then left, right = other, me end
local ball = {x = 20, y = 8, dx = 1, dy = 1, wait = 10}
local score = {left = 0, right = 0}
local peer = nil
local running = true
-- 1. Find the other player
if mode == "host" then
print("Waiting for a player (pong join)...")
while peer == nil do
local m = net.receive()
if m.channel == "pong" and m.data == "join" then
peer = m.sender
net.send(peer, "hello", "pong")
end
end
else
print("Looking for a game (pong host)...")
while peer == nil do
net.broadcast("join", "pong")
local m = net.receive(1) -- nil after 1 second without message
if m and m.channel == "pong" and m.data == "hello" then peer = m.sender end
end
end
-- 2. The ball: only the host moves it
function serve(dir)
ball.x = W // 2
ball.y = H // 2
ball.dx = dir
if math.random(2) == 1 then ball.dy = 1 else ball.dy = -1 end
ball.wait = 10 -- one second before the serve
end
function hit(paddle, y)
return y >= paddle.y and y < paddle.y + PAD
end
function step()
if ball.wait > 0 then
ball.wait = ball.wait - 1
return
end
local nx = ball.x + ball.dx
local ny = ball.y + ball.dy
if ny < 1 or ny > H then -- bounce on the walls
ball.dy = -ball.dy
ny = ball.y + ball.dy
end
if nx == 1 and hit(left, ny) then
ball.dx = 1
nx = ball.x + 1
elseif nx == W and hit(right, ny) then
ball.dx = -1
nx = ball.x - 1
elseif nx < 1 then
score.right = score.right + 1
serve(1)
return
elseif nx > W then
score.left = score.left + 1
serve(-1)
return
end
ball.x = nx
ball.y = ny
end
-- 3. Drawing, on both computers
function draw()
term.clear()
term.set_fg(term.colors.yellow)
term.set_cursor(W // 2 - 2, 1)
term.write(score.left .. " - " .. score.right)
term.set_fg(term.colors.white)
term.set_cursor(1, 2)
term.write(string.rep("=", W + 2))
term.set_cursor(1, H + 3)
term.write(string.rep("=", W + 2))
for i = 0, PAD - 1 do
term.set_cursor(2, left.y + 2 + i)
term.write("#")
term.set_cursor(W + 1, right.y + 2 + i)
term.write("#")
end
term.set_fg(term.colors.orange)
term.set_cursor(ball.x + 1, ball.y + 2)
term.write("O")
term.set_fg(term.colors.white)
end
-- 4. The game loop: keys, messages, and a timer every 0.1 s
local timer = os.start_timer(0.1)
while running do
local e = os.pull_event() -- any event
if e.name == "key" or e.name == "char" then
local k = e.key or e.char
if (k == "up" or k == "w" or k == "z") and me.y > 1 then me.y = me.y - 1 end
if (k == "down" or k == "s") and me.y < H - PAD + 1 then me.y = me.y + 1 end
if mode == "join" then net.send(peer, {y = me.y}, "pong") end
elseif e.name == "message" and e.sender == peer and type(e.data) == "table" then
local d = e.data
other.y = d.y
if mode == "join" then -- the host sends the whole state
ball.x = d.bx
ball.y = d.by
score.left = d.sl
score.right = d.sr
end
elseif e.name == "timer" and e.id == timer then
timer = os.start_timer(0.1)
if mode == "host" then
step()
net.send(peer, {y = me.y, bx = ball.x, by = ball.y, sl = score.left, sr = score.right}, "pong")
end
draw()
if score.left >= WIN or score.right >= WIN then running = false end
end
end
term.set_cursor(1, H + 4)
local mine = score.left
if mode == "join" then mine = score.right end
if mine >= WIN then
print("You win!")
else
print("You lose!")
end