--!name Snake
--!icon snake
--!category Games
-- Turn-based Snake for e-ink: each press moves the snake one square.
-- The arrows turn and step; OK steps straight on. No timer, so the panel
-- only refreshes when you press something.

local W, H = 10, 14
local body, dir, food, score, dead

local function cell(x, y)
  for i = 1, #body do
    if body[i][1] == x and body[i][2] == y then return true end
  end
  return false
end

local function place_food()
  for _ = 1, 200 do
    local x, y = math.random(1, W), math.random(1, H)
    if not cell(x, y) then
      food = {x, y}
      return
    end
  end
end

local function new_game()
  body = {{5, 7}, {5, 8}, {5, 9}}
  dir = {0, -1}
  score = 0
  dead = false
  place_food()
end

-- One square forward in the current direction.
local function step()
  local hx, hy = body[1][1] + dir[1], body[1][2] + dir[2]
  if hx < 1 or hy < 1 or hx > W or hy > H or cell(hx, hy) then
    dead = true
    return
  end
  table.insert(body, 1, {hx, hy})
  if hx == food[1] and hy == food[2] then
    score = score + 1
    place_food()
  else
    table.remove(body)
  end
end

function start()
  math.randomseed(os.time())
  snail.tick(0)
  new_game()
end

local TURNS = {up = {0, -1}, down = {0, 1}, left = {-1, 0}, right = {1, 0}}

function key(k)
  if dead then
    if k == "ok" then new_game() end
    return
  end
  local t = TURNS[k]
  if t then
    -- Turning straight back into your own neck isn't a move.
    if t[1] == -dir[1] and t[2] == -dir[2] then return end
    dir = t
    step()
  elseif k == "ok" then
    step()
  end
end

function draw()
  snail.title("Snake  " .. tostring(score))
  if dead then
    snail.text("Game over. You ate " .. tostring(score) .. ".")
    snail.small("OK plays again")
    snail.hint("OK restart")
    return
  end
  -- snail.board draws the grid: rows split by "/", "#" solid (body),
  -- "@" marked (head), "*" disc (food), "." empty, and "o" outlined squares
  -- round the edge, so you can see the wall you'd crash into.
  local rows = {}
  for y = 0, H + 1 do
    local line = {}
    for x = 0, W + 1 do
      local c = "."
      if x == 0 or y == 0 or x == W + 1 or y == H + 1 then c = "o"
      elseif food[1] == x and food[2] == y then c = "*"
      elseif body[1][1] == x and body[1][2] == y then c = "@"
      elseif cell(x, y) then c = "#" end
      line[#line + 1] = c
    end
    rows[#rows + 1] = table.concat(line)
  end
  snail.board(table.concat(rows, "/"))
  snail.hint("Arrows turn and move   OK straight on")
end
