2019-06-29 11:37:00 +00:00
|
|
|
|
local debug = false
|
|
|
|
|
|
2019-06-28 15:13:03 +00:00
|
|
|
|
local cavern = {}
|
2019-06-29 20:18:18 +00:00
|
|
|
|
local tiletypes = {unknown = 0, empty = 1, wall = 2, orb = 3, slime = 4}
|
2019-06-28 15:13:03 +00:00
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
local visibility_map = {}
|
|
|
|
|
local remembered_cavern = {}
|
|
|
|
|
|
2019-06-28 15:13:03 +00:00
|
|
|
|
local spawn_x = nil
|
|
|
|
|
local spawn_y = nil
|
|
|
|
|
|
2019-06-29 22:04:44 +00:00
|
|
|
|
local directions = {up = 0, upleft = 1, left = 2, downleft = 3, down = 4, downright = 5, right = 6, upright = 7, inplace = 8}
|
2019-06-30 09:41:27 +00:00
|
|
|
|
|
2019-06-28 15:13:03 +00:00
|
|
|
|
local player_x = nil
|
|
|
|
|
local player_y = nil
|
|
|
|
|
local player_direction = nil
|
2019-06-30 09:41:27 +00:00
|
|
|
|
local hp = nil
|
2019-06-30 16:38:42 +00:00
|
|
|
|
local flash_player_crit_counter = 0
|
|
|
|
|
local flash_player_damaged_counter = 0
|
|
|
|
|
local player_sprite = nil
|
|
|
|
|
local player_sprite_crit = nil
|
|
|
|
|
local player_sprite_damaged = nil
|
|
|
|
|
local player_animation_flip = false
|
2019-06-30 17:40:18 +00:00
|
|
|
|
local heart_sprite = nil
|
2019-06-28 15:13:03 +00:00
|
|
|
|
|
2019-06-29 20:18:18 +00:00
|
|
|
|
local slimes = {}
|
|
|
|
|
|
2019-06-29 08:21:09 +00:00
|
|
|
|
local last_key_pressed = nil
|
|
|
|
|
local move_repeat_counter = nil
|
|
|
|
|
|
2019-06-30 08:32:50 +00:00
|
|
|
|
local gamemodes = {normal = 0, won = 1, lost = 2, config = 3}
|
|
|
|
|
local game_mode = nil
|
2019-06-29 11:37:00 +00:00
|
|
|
|
|
2019-06-30 10:21:49 +00:00
|
|
|
|
local configuration_steps = {quit = -4, restart = -3, configure = -2, autoexplore = -1}
|
2019-06-29 12:46:17 +00:00
|
|
|
|
local configuration_step = nil
|
|
|
|
|
|
2019-06-29 11:43:35 +00:00
|
|
|
|
local direction_keys = {}
|
|
|
|
|
direction_keys['i'] = directions.up
|
|
|
|
|
direction_keys['u'] = directions.upleft
|
|
|
|
|
direction_keys['j'] = directions.left
|
|
|
|
|
direction_keys['m'] = directions.downleft
|
|
|
|
|
direction_keys['k'] = directions.down
|
|
|
|
|
direction_keys['.'] = directions.downright
|
|
|
|
|
direction_keys['l'] = directions.right
|
|
|
|
|
direction_keys['o'] = directions.upright
|
2019-06-29 22:04:44 +00:00
|
|
|
|
direction_keys['space'] = directions.inplace
|
2019-06-30 10:21:49 +00:00
|
|
|
|
local control_keys = {quit = 'q', restart = 'r', configure = 'c', autoexplore = 'a'}
|
2019-06-29 11:43:35 +00:00
|
|
|
|
|
2019-06-29 12:18:55 +00:00
|
|
|
|
local win_image = nil
|
|
|
|
|
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Cavern generation
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function generateCavern()
|
|
|
|
|
repeat
|
|
|
|
|
cavern = {}
|
|
|
|
|
|
|
|
|
|
cavern.width = 80
|
|
|
|
|
cavern.height = 60
|
|
|
|
|
|
|
|
|
|
-- Create a cavern.width × cavern.height array filled with tiletypes.unknown
|
|
|
|
|
for x = 1, cavern.width do
|
|
|
|
|
local list = {}
|
|
|
|
|
for y = 1, cavern.height do
|
|
|
|
|
table.insert(list, tiletypes.unknown)
|
|
|
|
|
end
|
|
|
|
|
table.insert(cavern, list)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Fill top and bottom edges with walls
|
|
|
|
|
for x = 1, cavern.width do
|
|
|
|
|
cavern[x][1] = tiletypes.wall
|
|
|
|
|
cavern[x][cavern.height] = tiletypes.wall
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Fill the left and right edges with walls
|
|
|
|
|
for y = 1, cavern.height do
|
|
|
|
|
cavern[1][y] = tiletypes.wall
|
|
|
|
|
cavern[cavern.width][y] = tiletypes.wall
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local queue = {}
|
|
|
|
|
local size = 1
|
|
|
|
|
|
|
|
|
|
-- Limit spawn to locations not on the edge walls
|
|
|
|
|
spawn_x = math.random(2, cavern.width - 1)
|
|
|
|
|
spawn_y = math.random(2, cavern.height - 1)
|
|
|
|
|
|
|
|
|
|
cavern[spawn_x][spawn_y] = tiletypes.empty
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = spawn_x, y = spawn_y - 1})
|
|
|
|
|
table.insert(queue, {x = spawn_x, y = spawn_y + 1})
|
|
|
|
|
table.insert(queue, {x = spawn_x - 1, y = spawn_y})
|
|
|
|
|
table.insert(queue, {x = spawn_x + 1, y = spawn_y})
|
|
|
|
|
|
|
|
|
|
repeat
|
2019-06-28 18:53:56 +00:00
|
|
|
|
queue, size = stepCavernGeneration(queue, size)
|
2019-06-28 15:13:03 +00:00
|
|
|
|
until #queue == 0
|
|
|
|
|
until size > 200
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
function stepCavernGeneration(queue, size)
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- Tuning this parameter will change how open and cavernous vs. closed and corridory the
|
|
|
|
|
-- cavern will be
|
|
|
|
|
local spread_probability = 0.6
|
|
|
|
|
|
|
|
|
|
local new_queue = {}
|
|
|
|
|
local new_size = size
|
|
|
|
|
|
|
|
|
|
for i, location in ipairs(queue) do
|
|
|
|
|
if cavern[location.x][location.y] == tiletypes.unknown then
|
|
|
|
|
-- We haven't covered this tile yet
|
|
|
|
|
|
|
|
|
|
if math.random() < spread_probability then
|
|
|
|
|
-- Empty
|
|
|
|
|
cavern[location.x][location.y] = tiletypes.empty
|
|
|
|
|
size = size + 1
|
|
|
|
|
|
|
|
|
|
-- Up
|
|
|
|
|
if location.y - 1 >= 1 then
|
|
|
|
|
table.insert(new_queue, {x = location.x, y = location.y - 1})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Down
|
|
|
|
|
if location.y + 1 <= cavern.height then
|
|
|
|
|
table.insert(new_queue, {x = location.x, y = location.y + 1})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Left
|
|
|
|
|
if location.x - 1 >= 1 then
|
|
|
|
|
table.insert(new_queue, {x = location.x - 1, y = location.y})
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Right
|
|
|
|
|
if location.x + 1 <= cavern.width then
|
|
|
|
|
table.insert(new_queue, {x = location.x + 1, y = location.y})
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
-- Wall
|
|
|
|
|
cavern[location.x][location.y] = tiletypes.wall
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return new_queue, size
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Spawning objects
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function spawnPlayer()
|
|
|
|
|
player_x = spawn_x
|
|
|
|
|
player_y = spawn_y
|
|
|
|
|
|
|
|
|
|
-- Check what direction we can spawn the player
|
2019-06-29 11:10:30 +00:00
|
|
|
|
if passable(player_x, player_y + 1) then
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- There's space under, spawn facing up
|
|
|
|
|
player_direction = directions.up
|
2019-06-29 11:10:30 +00:00
|
|
|
|
elseif passable(player_x + 1, player_y) then
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- There's space to the right, spawn facing left
|
|
|
|
|
player_direction = directions.left
|
2019-06-29 11:10:30 +00:00
|
|
|
|
elseif passable(player_x - 1, player_y) then
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- There's space to the left, spawn facing right
|
|
|
|
|
player_direction = directions.right
|
2019-06-29 11:10:30 +00:00
|
|
|
|
elseif passable(player_x, player_y - 1) then
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- There's space above, spawn facing down
|
|
|
|
|
player_direction = directions.down
|
|
|
|
|
else
|
|
|
|
|
error("Cavern is weirdly generated and player cannot spawn")
|
|
|
|
|
end
|
2019-06-30 09:41:27 +00:00
|
|
|
|
|
|
|
|
|
hp = 3
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 08:45:13 +00:00
|
|
|
|
function spawnOrb()
|
|
|
|
|
local orb_x = nil
|
|
|
|
|
local orb_y = nil
|
|
|
|
|
|
|
|
|
|
repeat
|
|
|
|
|
orb_x = math.random(2, cavern.width - 1)
|
|
|
|
|
orb_y = math.random(2, cavern.height - 1)
|
2019-06-29 20:18:18 +00:00
|
|
|
|
until cavern[orb_x][orb_y] == tiletypes.empty
|
2019-06-29 08:45:13 +00:00
|
|
|
|
|
|
|
|
|
cavern[orb_x][orb_y] = tiletypes.orb
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 20:18:18 +00:00
|
|
|
|
function spawnSlimes()
|
|
|
|
|
-- Try spawning 20 slimes, but if they don't hit any location then don't care
|
2019-06-29 21:04:12 +00:00
|
|
|
|
slimes = {}
|
|
|
|
|
|
2019-06-29 20:18:18 +00:00
|
|
|
|
for i = 1, 20 do
|
|
|
|
|
local x = math.random(2, cavern.width - 1)
|
|
|
|
|
local y = math.random(2, cavern.height - 1)
|
|
|
|
|
|
|
|
|
|
if cavern[x][y] == tiletypes.empty then
|
|
|
|
|
cavern[x][y] = tiletypes.slime
|
|
|
|
|
table.insert(slimes, {x = x, y = y})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Visibility
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function generateVisibilityMap()
|
|
|
|
|
-- Start by creating a new visibility map (since we'll have to recompute everything anyways)
|
|
|
|
|
visibility_map = {}
|
|
|
|
|
for x = 1, cavern.width do
|
|
|
|
|
local list = {}
|
|
|
|
|
for y = 1, cavern.height do
|
|
|
|
|
table.insert(list, false)
|
|
|
|
|
end
|
|
|
|
|
table.insert(visibility_map, list)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Handle visibility from the head
|
|
|
|
|
local queue = {}
|
|
|
|
|
|
2019-06-28 20:35:17 +00:00
|
|
|
|
visibility_map[player_x][player_y] = true
|
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
-- ⌜^⌝
|
|
|
|
|
-- <o>
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y - 1, direction = directions.upleft})
|
|
|
|
|
table.insert(queue, {x = player_x, y = player_y - 1, direction = directions.up})
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y - 1, direction = directions.upright})
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y, direction = directions.left})
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y, direction = directions.right})
|
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
-- ⌜^
|
|
|
|
|
-- <o
|
|
|
|
|
-- ⌞v
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y - 1, direction = directions.upleft})
|
|
|
|
|
table.insert(queue, {x = player_x, y = player_y - 1, direction = directions.up})
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y, direction = directions.left})
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y + 1, direction = directions.downleft})
|
|
|
|
|
table.insert(queue, {x = player_x, y = player_y + 1, direction = directions.down})
|
|
|
|
|
elseif player_direction == directions.down then
|
|
|
|
|
-- <o>
|
|
|
|
|
-- ⌞v⌟
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y, direction = directions.left})
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y, direction = directions.right})
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = player_x - 1, y = player_y + 1, direction = directions.downleft})
|
|
|
|
|
table.insert(queue, {x = player_x, y = player_y + 1, direction = directions.down})
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y + 1, direction = directions.downright})
|
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
-- ^⌝
|
|
|
|
|
-- o>
|
|
|
|
|
-- v⌟
|
|
|
|
|
table.insert(queue, {x = player_x, y = player_y - 1, direction = directions.up})
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y - 1, direction = directions.upright})
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y, direction = directions.right})
|
|
|
|
|
|
|
|
|
|
table.insert(queue, {x = player_x, y = player_y + 1, direction = directions.down})
|
|
|
|
|
table.insert(queue, {x = player_x + 1, y = player_y + 1, direction = directions.downright})
|
|
|
|
|
else
|
|
|
|
|
error("Player facing an impossible direction")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
repeat
|
|
|
|
|
queue = stepVisibilityMapGeneration(queue)
|
|
|
|
|
until #queue == 0
|
|
|
|
|
|
|
|
|
|
-- Handle "visibility" from the feet
|
|
|
|
|
local body_x, body_y = getBodyLocation()
|
|
|
|
|
|
2019-06-28 20:35:17 +00:00
|
|
|
|
visibility_map[body_x][body_y] = true
|
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
-- <x>
|
|
|
|
|
-- v
|
|
|
|
|
visibility_map[body_x - 1][body_y] = true
|
|
|
|
|
visibility_map[body_x + 1][body_y] = true
|
|
|
|
|
|
|
|
|
|
visibility_map[body_x][body_y + 1] = true
|
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
-- ^
|
|
|
|
|
-- x>
|
|
|
|
|
-- v
|
|
|
|
|
visibility_map[body_x][body_y - 1] = true
|
|
|
|
|
|
|
|
|
|
visibility_map[body_x + 1][body_y] = true
|
|
|
|
|
|
|
|
|
|
visibility_map[body_x][body_y + 1] = true
|
|
|
|
|
elseif player_direction == directions.down then
|
|
|
|
|
-- ^
|
|
|
|
|
-- <x>
|
|
|
|
|
visibility_map[body_x][body_y - 1] = true
|
|
|
|
|
|
|
|
|
|
visibility_map[body_x - 1][body_y] = true
|
|
|
|
|
visibility_map[body_x + 1][body_y] = true
|
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
-- ^
|
|
|
|
|
-- <x
|
|
|
|
|
-- v
|
|
|
|
|
visibility_map[body_x][body_y - 1] = true
|
|
|
|
|
|
|
|
|
|
visibility_map[body_x - 1][body_y] = true
|
|
|
|
|
|
|
|
|
|
visibility_map[body_x][body_y + 1] = true
|
|
|
|
|
else
|
|
|
|
|
error("Player facing an impossible direction")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function stepVisibilityMapGeneration(queue)
|
|
|
|
|
-- Do a modified floodfill, where each cell will only expand in its given direction, not
|
|
|
|
|
-- every direction like in a normal floodfill
|
|
|
|
|
local new_queue = {}
|
|
|
|
|
|
|
|
|
|
for i, item in ipairs(queue) do
|
2019-06-28 21:23:42 +00:00
|
|
|
|
if item.direction == directions.up then
|
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 18:53:56 +00:00
|
|
|
|
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.left then
|
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 18:53:56 +00:00
|
|
|
|
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.down then
|
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 18:53:56 +00:00
|
|
|
|
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.right then
|
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 18:53:56 +00:00
|
|
|
|
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.upleft then
|
|
|
|
|
-- Check that we could have gotten here also by moving only 4-ways
|
|
|
|
|
--
|
|
|
|
|
-- The possible cases are:
|
|
|
|
|
-- (o represents old position, x is new, and # is a wall)
|
|
|
|
|
--
|
|
|
|
|
-- x x# x x#
|
|
|
|
|
-- o o #o #o
|
|
|
|
|
--
|
|
|
|
|
-- In the first three, the movement is possible, but in the last one
|
|
|
|
|
-- it is not. We can therefore check whether the movement is valid
|
|
|
|
|
-- by testing if either the cell to our right or below us (the
|
|
|
|
|
-- directions opposite to the ones in an up.left movement) is empty
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x + 1, item.y) or seethrough(item.x, item.y + 1) then
|
2019-06-28 21:23:42 +00:00
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 20:59:41 +00:00
|
|
|
|
-- ⌜^
|
|
|
|
|
-- ⌜ <x
|
|
|
|
|
table.insert(new_queue, {x = item.x - 1, y = item.y - 1, direction = directions.upleft})
|
|
|
|
|
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
|
|
|
|
|
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
|
|
|
|
|
end
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.downleft then
|
|
|
|
|
-- See under item.direction == directions.upleft
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x + 1, item.y) or seethrough(item.x, item.y - 1) then
|
2019-06-28 21:23:42 +00:00
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 20:59:41 +00:00
|
|
|
|
-- ⌞ <x
|
|
|
|
|
-- ⌞v
|
|
|
|
|
table.insert(new_queue, {x = item.x - 1, y = item.y, direction = directions.left})
|
|
|
|
|
table.insert(new_queue, {x = item.x - 1, y = item.y + 1, direction = directions.downleft})
|
|
|
|
|
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
|
|
|
|
|
end
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.downright then
|
|
|
|
|
-- See under item.direction == directions.upleft
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x - 1, item.y) or seethrough(item.x, item.y - 1) then
|
2019-06-28 21:23:42 +00:00
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 20:59:41 +00:00
|
|
|
|
-- ⌟ x>
|
|
|
|
|
-- v⌟
|
|
|
|
|
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
|
|
|
|
|
table.insert(new_queue, {x = item.x, y = item.y + 1, direction = directions.down})
|
|
|
|
|
table.insert(new_queue, {x = item.x + 1, y = item.y + 1, direction = directions.downright})
|
|
|
|
|
end
|
2019-06-28 21:23:42 +00:00
|
|
|
|
end
|
|
|
|
|
elseif item.direction == directions.upright then
|
|
|
|
|
-- See under item.direction == directions.upleft
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x - 1, item.y) or seethrough(item.x, item.y + 1) then
|
2019-06-28 21:23:42 +00:00
|
|
|
|
visibility_map[item.x][item.y] = true
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if seethrough(item.x, item.y) then
|
2019-06-28 20:59:41 +00:00
|
|
|
|
-- ^⌝
|
|
|
|
|
-- ⌝ x>
|
|
|
|
|
table.insert(new_queue, {x = item.x, y = item.y - 1, direction = directions.up})
|
|
|
|
|
table.insert(new_queue, {x = item.x + 1, y = item.y - 1, direction = directions.upright})
|
|
|
|
|
table.insert(new_queue, {x = item.x + 1, y = item.y, direction = directions.right})
|
|
|
|
|
end
|
2019-06-28 18:53:56 +00:00
|
|
|
|
end
|
2019-06-28 20:59:41 +00:00
|
|
|
|
else
|
2019-06-28 21:23:42 +00:00
|
|
|
|
error("Visibility floodfill item travelling in an impossible direction")
|
2019-06-28 18:53:56 +00:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return new_queue
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function initializeRememberedCavern()
|
|
|
|
|
remembered_cavern = {}
|
|
|
|
|
for x = 1, cavern.width do
|
|
|
|
|
local list = {}
|
|
|
|
|
for y = 1, cavern.height do
|
|
|
|
|
table.insert(list, nil)
|
|
|
|
|
end
|
|
|
|
|
table.insert(remembered_cavern, list)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function rememberVisible()
|
|
|
|
|
for x, list in ipairs(visibility_map) do
|
|
|
|
|
for y, visible in ipairs(list) do
|
|
|
|
|
if visible then
|
|
|
|
|
remembered_cavern[x][y] = cavern[x][y]
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 11:10:30 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Collision
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
function passable(x, y)
|
|
|
|
|
return cavern[x][y] == tiletypes.empty or cavern[x][y] == tiletypes.orb
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 20:18:18 +00:00
|
|
|
|
function seethrough(x, y)
|
|
|
|
|
return cavern[x][y] == tiletypes.empty or cavern[x][y] == tiletypes.orb or cavern[x][y] == tiletypes.slime
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 11:37:00 +00:00
|
|
|
|
function collidedPlayerOrb()
|
|
|
|
|
local body_x, body_y = getBodyLocation()
|
|
|
|
|
return cavern[player_x][player_y] == tiletypes.orb or cavern[body_x][body_y] == tiletypes.orb
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Player helper functions
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function getBodyLocation(x, y, facing)
|
|
|
|
|
if x == nil then x = player_x end
|
|
|
|
|
if y == nil then y = player_y end
|
|
|
|
|
if facing == nil then facing = player_direction end
|
|
|
|
|
|
|
|
|
|
if facing == directions.up then
|
|
|
|
|
-- Facing up, body is down
|
|
|
|
|
return x, y + 1
|
|
|
|
|
elseif facing == directions.left then
|
|
|
|
|
-- Facing left, body is right
|
|
|
|
|
return x + 1, y
|
|
|
|
|
elseif facing == directions.down then
|
|
|
|
|
-- Facing down, body is up
|
|
|
|
|
return x, y - 1
|
|
|
|
|
elseif facing == directions.right then
|
|
|
|
|
-- Facing right, body is left
|
|
|
|
|
return x - 1, y
|
|
|
|
|
else
|
|
|
|
|
error("Player facing an impossible direction")
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function movePlayer(direction)
|
|
|
|
|
local dx = 0
|
|
|
|
|
local dy = 0
|
|
|
|
|
local new_direction = direction
|
|
|
|
|
|
|
|
|
|
-- If we are moving backwards, keep the old direction of facing
|
|
|
|
|
if player_direction == directions.up and direction == directions.down or
|
|
|
|
|
player_direction == directions.down and direction == directions.up or
|
|
|
|
|
player_direction == directions.left and direction == directions.right or
|
|
|
|
|
player_direction == directions.right and direction == directions.left then
|
|
|
|
|
new_direction = player_direction
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if direction == directions.up then
|
|
|
|
|
dy = -1
|
|
|
|
|
elseif direction == directions.down then
|
|
|
|
|
dy = 1
|
|
|
|
|
elseif direction == directions.left then
|
|
|
|
|
dx = -1
|
|
|
|
|
elseif direction == directions.right then
|
|
|
|
|
dx = 1
|
|
|
|
|
elseif direction == directions.upleft then
|
2019-06-28 17:31:03 +00:00
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
dx = -1
|
|
|
|
|
new_direction = directions.left
|
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
dy = -1
|
|
|
|
|
new_direction = directions.up
|
|
|
|
|
elseif player_direction == directions.down then
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- ## ##
|
|
|
|
|
-- x# xo#
|
|
|
|
|
-- #o# # #
|
|
|
|
|
dy = -1
|
|
|
|
|
new_direction = directions.right
|
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
-- # # #x#
|
|
|
|
|
-- #xo #o
|
|
|
|
|
-- ## ##
|
|
|
|
|
dx = -1
|
|
|
|
|
new_direction = directions.down
|
|
|
|
|
else
|
2019-06-28 18:53:56 +00:00
|
|
|
|
error("Player facing an impossible direction")
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
|
|
|
|
elseif direction == directions.downleft then
|
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
-- #o# # #
|
|
|
|
|
-- x# xo#
|
|
|
|
|
-- ## ##
|
|
|
|
|
dy = 1
|
|
|
|
|
new_direction = directions.right
|
2019-06-28 17:31:03 +00:00
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
dy = 1
|
|
|
|
|
new_direction = directions.down
|
|
|
|
|
elseif player_direction == directions.down then
|
|
|
|
|
dx = -1
|
|
|
|
|
new_direction = directions.left
|
2019-06-28 15:13:03 +00:00
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
-- ## ##
|
|
|
|
|
-- #xo #o
|
|
|
|
|
-- # # #x#
|
|
|
|
|
dx = -1
|
|
|
|
|
new_direction = directions.up
|
|
|
|
|
else
|
2019-06-28 18:53:56 +00:00
|
|
|
|
error("Player facing an impossible direction")
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
|
|
|
|
elseif direction == directions.downright then
|
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
-- #o# # #
|
|
|
|
|
-- #x #ox
|
|
|
|
|
-- ## ##
|
|
|
|
|
dy = 1
|
|
|
|
|
new_direction = directions.left
|
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
-- ## ##
|
|
|
|
|
-- ox# o#
|
|
|
|
|
-- # # #x#
|
|
|
|
|
dx = 1
|
|
|
|
|
new_direction = directions.up
|
2019-06-28 17:31:03 +00:00
|
|
|
|
elseif player_direction == directions.down then
|
|
|
|
|
dx = 1
|
|
|
|
|
new_direction = directions.right
|
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
dy = 1
|
|
|
|
|
new_direction = directions.down
|
2019-06-28 15:13:03 +00:00
|
|
|
|
else
|
2019-06-28 18:53:56 +00:00
|
|
|
|
error("Player facing an impossible direction")
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
|
|
|
|
elseif direction == directions.upright then
|
2019-06-28 17:31:03 +00:00
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
dx = 1
|
|
|
|
|
new_direction = directions.right
|
2019-06-28 15:13:03 +00:00
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
-- # # #x#
|
|
|
|
|
-- ox# o#
|
|
|
|
|
-- ## ##
|
|
|
|
|
dx = 1
|
|
|
|
|
new_direction = directions.down
|
2019-06-28 17:31:03 +00:00
|
|
|
|
elseif player_direction == directions.down then
|
|
|
|
|
-- ## ##
|
|
|
|
|
-- #x #ox
|
|
|
|
|
-- #o# # #
|
|
|
|
|
dy = -1
|
|
|
|
|
new_direction = directions.left
|
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
dy = -1
|
|
|
|
|
new_direction = directions.up
|
2019-06-28 15:13:03 +00:00
|
|
|
|
else
|
2019-06-28 18:53:56 +00:00
|
|
|
|
error("Player facing an impossible direction")
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
error("Player moving in an impossible direction")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local body_x, body_y = getBodyLocation(player_x + dx, player_y + dy, new_direction)
|
|
|
|
|
|
2019-06-29 11:10:30 +00:00
|
|
|
|
if passable(player_x + dx, player_y + dy) and passable(body_x, body_y) then
|
2019-06-28 15:13:03 +00:00
|
|
|
|
player_x = player_x + dx
|
|
|
|
|
player_y = player_y + dy
|
|
|
|
|
player_direction = new_direction
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 08:21:09 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Gameloop functions
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
function newGame()
|
2019-06-29 11:37:00 +00:00
|
|
|
|
game_mode = gamemodes.normal
|
2019-06-29 08:21:09 +00:00
|
|
|
|
generateCavern()
|
2019-06-29 08:45:13 +00:00
|
|
|
|
|
2019-06-29 08:21:09 +00:00
|
|
|
|
spawnPlayer()
|
2019-06-29 08:45:13 +00:00
|
|
|
|
spawnOrb()
|
2019-06-29 20:18:18 +00:00
|
|
|
|
spawnSlimes()
|
2019-06-29 08:45:13 +00:00
|
|
|
|
|
2019-06-29 08:21:09 +00:00
|
|
|
|
generateVisibilityMap()
|
|
|
|
|
initializeRememberedCavern()
|
2019-06-29 11:37:00 +00:00
|
|
|
|
|
|
|
|
|
if collidedPlayerOrb() then
|
|
|
|
|
game_mode = gamemodes.won
|
|
|
|
|
end
|
2019-06-29 08:21:09 +00:00
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 20:18:18 +00:00
|
|
|
|
function moveSlimes()
|
2019-06-29 20:35:02 +00:00
|
|
|
|
for i, slime in pairs(slimes) do
|
2019-06-29 20:18:18 +00:00
|
|
|
|
local dx = 0
|
|
|
|
|
local dy = 0
|
|
|
|
|
|
|
|
|
|
local to_player_dx = player_x - slime.x
|
|
|
|
|
local to_player_dy = player_y - slime.y
|
2019-06-29 20:51:52 +00:00
|
|
|
|
if math.abs(to_player_dx) + math.abs(to_player_dy) <= 5 and math.random() < 0.7 then
|
|
|
|
|
-- If at max 5 moves away from player, book for it (likely)
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if math.abs(to_player_dx) > math.abs(to_player_dy) then
|
|
|
|
|
-- Needs to move more in the horizontal direction → move horizontally
|
|
|
|
|
if to_player_dx < 0 then
|
|
|
|
|
dx = -1
|
|
|
|
|
else
|
|
|
|
|
dx = 1
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
-- Otherwise move vertically
|
|
|
|
|
if to_player_dy < 0 then
|
|
|
|
|
dy = -1
|
|
|
|
|
else
|
|
|
|
|
dy = 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
local movement = math.random(0, 3)
|
|
|
|
|
if movement == 0 then
|
|
|
|
|
-- Up
|
|
|
|
|
dy = -1
|
|
|
|
|
elseif movement == 1 then
|
|
|
|
|
-- Left
|
|
|
|
|
dx = -1
|
|
|
|
|
elseif movement == 2 then
|
|
|
|
|
-- Down
|
|
|
|
|
dy = 1
|
|
|
|
|
elseif movement == 3 then
|
|
|
|
|
-- Right
|
|
|
|
|
dx = 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- We test for empty instead of using passable(), since we are overwriting a tile
|
|
|
|
|
if cavern[slime.x + dx][slime.y + dy] == tiletypes.empty then
|
|
|
|
|
cavern[slime.x + dx][slime.y + dy] = tiletypes.slime
|
|
|
|
|
cavern[slime.x][slime.y] = tiletypes.empty
|
|
|
|
|
slimes[i] = {x = slime.x + dx, y = slime.y + dy}
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 20:35:02 +00:00
|
|
|
|
function killSlime()
|
|
|
|
|
local body_x, body_y = getBodyLocation()
|
|
|
|
|
|
|
|
|
|
for i, slime in pairs(slimes) do
|
|
|
|
|
if slime.x == player_x and slime.y == player_y or slime.x == body_x and slime.y == body_y then
|
|
|
|
|
cavern[slime.x][slime.y] = tiletypes.empty
|
|
|
|
|
slimes[i] = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 08:21:09 +00:00
|
|
|
|
function step(direction)
|
2019-06-29 11:37:00 +00:00
|
|
|
|
if game_mode == gamemodes.normal then
|
|
|
|
|
rememberVisible()
|
2019-06-29 20:18:18 +00:00
|
|
|
|
|
2019-06-29 22:04:44 +00:00
|
|
|
|
if direction ~= directions.inplace then
|
|
|
|
|
movePlayer(direction)
|
|
|
|
|
end
|
2019-06-29 20:18:18 +00:00
|
|
|
|
moveSlimes()
|
|
|
|
|
|
2019-06-29 11:37:00 +00:00
|
|
|
|
generateVisibilityMap()
|
|
|
|
|
|
|
|
|
|
if collidedPlayerOrb() then
|
|
|
|
|
game_mode = gamemodes.won
|
|
|
|
|
end
|
2019-06-29 20:18:18 +00:00
|
|
|
|
|
2019-06-30 09:44:53 +00:00
|
|
|
|
local body_x, body_y = getBodyLocation()
|
|
|
|
|
if cavern[body_x][body_y] == tiletypes.slime then
|
|
|
|
|
killSlime()
|
|
|
|
|
hp = hp - 1
|
|
|
|
|
if hp == 0 then
|
2019-06-30 16:38:42 +00:00
|
|
|
|
flash_player_damaged_counter = 1
|
2019-06-30 09:44:53 +00:00
|
|
|
|
else
|
2019-06-30 16:38:42 +00:00
|
|
|
|
flash_player_damaged_counter = 0.2
|
2019-06-30 09:44:53 +00:00
|
|
|
|
end
|
|
|
|
|
elseif cavern[player_x][player_y] == tiletypes.slime then
|
2019-06-30 09:41:27 +00:00
|
|
|
|
killSlime()
|
|
|
|
|
if math.random() < 0.2 then
|
2019-06-30 16:38:42 +00:00
|
|
|
|
flash_player_crit_counter = 0.2
|
2019-06-29 20:35:02 +00:00
|
|
|
|
else
|
2019-06-30 09:41:27 +00:00
|
|
|
|
hp = hp - 1
|
|
|
|
|
if hp == 0 then
|
2019-06-30 16:38:42 +00:00
|
|
|
|
flash_player_damaged_counter = 1
|
2019-06-30 09:41:27 +00:00
|
|
|
|
else
|
2019-06-30 16:38:42 +00:00
|
|
|
|
flash_player_damaged_counter = 0.2
|
2019-06-30 09:41:27 +00:00
|
|
|
|
end
|
2019-06-29 20:35:02 +00:00
|
|
|
|
end
|
2019-06-29 20:18:18 +00:00
|
|
|
|
end
|
2019-06-30 16:38:42 +00:00
|
|
|
|
|
|
|
|
|
player_animation_flip = not player_animation_flip
|
2019-06-29 11:37:00 +00:00
|
|
|
|
end
|
2019-06-29 08:21:09 +00:00
|
|
|
|
end
|
|
|
|
|
|
2019-06-30 10:21:49 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Autoexplore
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function autoexplore()
|
|
|
|
|
-- Use a pathfinding algo where each unknown but accessible space gets labelled 0, and
|
|
|
|
|
-- then each known accessible space gets labelled with min(neighbours) + 1. Once we have
|
|
|
|
|
-- computed that table, we can then move towards closest unknown accessible space by
|
|
|
|
|
-- moving to our neighbouring space with lowest score
|
2019-06-30 15:37:12 +00:00
|
|
|
|
local distances = {}
|
2019-06-30 10:21:49 +00:00
|
|
|
|
for x = 1, cavern.width do
|
|
|
|
|
local list = {}
|
|
|
|
|
for y = 1, cavern.height do
|
|
|
|
|
table.insert(list, {value = nil, direction = directions.inplace})
|
|
|
|
|
end
|
|
|
|
|
table.insert(distances, list)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local queue = {}
|
|
|
|
|
function enqueue(queue, x, y, value, direction)
|
|
|
|
|
if 1 < x and x < cavern.width and
|
|
|
|
|
1 < y and y < cavern.height and
|
|
|
|
|
cavern[x][y] ~= tiletypes.wall then
|
|
|
|
|
table.insert(queue, {x = x, y = y, value = value, direction = direction})
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
function neighbors(q, x, y, v)
|
|
|
|
|
-- The directions are reversed, because they tell where to go to get to the
|
|
|
|
|
-- unexplored areas
|
|
|
|
|
enqueue(q, x, y - 1, v, directions.down)
|
|
|
|
|
enqueue(q, x - 1, y, v, directions.right)
|
|
|
|
|
enqueue(q, x, y + 1, v, directions.up)
|
|
|
|
|
enqueue(q, x + 1, y, v, directions.left)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
for x, list in ipairs(visibility_map) do
|
|
|
|
|
for y, visible in ipairs(list) do
|
|
|
|
|
if not visible and remembered_cavern[x][y] == nil then
|
|
|
|
|
distances[x][y] = {value = 0, direction = directions.inplace}
|
|
|
|
|
neighbors(queue, x, y, 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
repeat
|
|
|
|
|
local new_queue = {}
|
|
|
|
|
for i, item in ipairs(queue) do
|
|
|
|
|
-- Write the lowest distance to each tile
|
|
|
|
|
if distances[item.x][item.y].value == nil or distances[item.x][item.y].value > item.value then
|
|
|
|
|
distances[item.x][item.y] = {value = item.value, direction = item.direction}
|
|
|
|
|
neighbors(new_queue, item.x, item.y, item.value + 1)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
queue = new_queue
|
|
|
|
|
until #queue == 0
|
|
|
|
|
|
2019-06-30 15:37:12 +00:00
|
|
|
|
local direction = distances[player_x][player_y].direction
|
|
|
|
|
|
|
|
|
|
local body_x, body_y = getBodyLocation()
|
|
|
|
|
-- If we are backing up, consider feet
|
|
|
|
|
if player_direction == directions.up and direction == directions.down then
|
|
|
|
|
direction = distances[body_x][body_y].direction
|
|
|
|
|
if direction == directions.left then
|
|
|
|
|
direction = directions.downleft
|
|
|
|
|
elseif direction == directions.right then
|
|
|
|
|
direction = directions.downright
|
|
|
|
|
else
|
|
|
|
|
direction = directions.down
|
|
|
|
|
end
|
|
|
|
|
elseif player_direction == directions.left and direction == directions.right then
|
|
|
|
|
direction = distances[body_x][body_y].direction
|
|
|
|
|
if direction == directions.up then
|
|
|
|
|
direction = directions.upright
|
|
|
|
|
elseif direction == directions.down then
|
|
|
|
|
direction = directions.downright
|
|
|
|
|
else
|
|
|
|
|
direction = directions.right
|
|
|
|
|
end
|
|
|
|
|
elseif player_direction == directions.down and direction == directions.up then
|
|
|
|
|
direction = distances[body_x][body_y].direction
|
|
|
|
|
if direction == directions.left then
|
|
|
|
|
direction = directions.upleft
|
|
|
|
|
elseif direction == directions.right then
|
|
|
|
|
direction = directions.upright
|
|
|
|
|
else
|
|
|
|
|
direction = directions.up
|
|
|
|
|
end
|
|
|
|
|
elseif player_direction == directions.right and direction == directions.left then
|
|
|
|
|
direction = distances[body_x][body_y].direction
|
|
|
|
|
if direction == directions.up then
|
|
|
|
|
direction = directions.upleft
|
|
|
|
|
elseif direction == directions.down then
|
|
|
|
|
direction = directions.downleft
|
|
|
|
|
else
|
|
|
|
|
direction = directions.left
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
step(direction)
|
2019-06-30 10:21:49 +00:00
|
|
|
|
end
|
|
|
|
|
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
2019-06-29 12:18:55 +00:00
|
|
|
|
-- Drawing
|
2019-06-28 15:13:03 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
2019-06-29 12:18:55 +00:00
|
|
|
|
function drawCavern()
|
2019-06-30 07:49:11 +00:00
|
|
|
|
local screen_width = love.graphics.getWidth()
|
|
|
|
|
local screen_height = love.graphics.getHeight()
|
|
|
|
|
|
|
|
|
|
local width_scale = screen_width / cavern.width
|
|
|
|
|
local height_scale = screen_height / cavern.height
|
|
|
|
|
local scale = math.min(width_scale, height_scale)
|
|
|
|
|
|
|
|
|
|
local x_offset = (screen_width - cavern.width * scale) / 2
|
|
|
|
|
local y_offset = (screen_height - cavern.height * scale) / 2
|
2019-06-28 15:13:03 +00:00
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
for tile_x, list in ipairs(visibility_map) do
|
2019-06-30 07:49:11 +00:00
|
|
|
|
local x = (tile_x - 1) * scale + x_offset
|
2019-06-28 18:53:56 +00:00
|
|
|
|
for tile_y, visible in ipairs(list) do
|
2019-06-30 07:49:11 +00:00
|
|
|
|
local y = (tile_y - 1) * scale + y_offset
|
2019-06-28 15:13:03 +00:00
|
|
|
|
|
2019-06-29 11:37:00 +00:00
|
|
|
|
if visible or debug then
|
2019-06-28 18:53:56 +00:00
|
|
|
|
tile = cavern[tile_x][tile_y]
|
|
|
|
|
|
|
|
|
|
if tile == tiletypes.empty then
|
|
|
|
|
love.graphics.setColor(0, 0, 0)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-28 18:53:56 +00:00
|
|
|
|
elseif tile == tiletypes.wall then
|
|
|
|
|
love.graphics.setColor(1, 1, 1)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 08:45:13 +00:00
|
|
|
|
elseif tile == tiletypes.orb then
|
|
|
|
|
love.graphics.setColor(0.5, 0.3, 0.3)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 08:45:13 +00:00
|
|
|
|
love.graphics.setColor(0, 1, 0)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
love.graphics.circle('fill', x + 0.5 * scale, y + 0.5 * scale, 0.7 * scale/2)
|
2019-06-29 20:18:18 +00:00
|
|
|
|
elseif tile == tiletypes.slime then
|
2019-06-29 22:08:13 +00:00
|
|
|
|
love.graphics.setColor(0, 0, 0)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 22:25:32 +00:00
|
|
|
|
love.graphics.setColor(1, 1, 0)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
love.graphics.circle('fill', x + 0.5 * scale, y + 0.5 * scale, 0.8 * scale/2)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x + 0.1 * scale , y + 0.5 * scale, 0.8 * scale, 0.8 * scale/2)
|
2019-06-29 20:51:52 +00:00
|
|
|
|
elseif tile == tiletypes.unknown then
|
2019-06-28 18:53:56 +00:00
|
|
|
|
love.graphics.setColor(1, 0.5, 0.5)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 20:51:52 +00:00
|
|
|
|
else
|
|
|
|
|
print("Impossible tile!!!")
|
2019-06-29 21:04:12 +00:00
|
|
|
|
love.graphics.setColor(1, 1, 0)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-28 18:53:56 +00:00
|
|
|
|
end
|
2019-06-28 15:13:03 +00:00
|
|
|
|
else
|
2019-06-28 18:53:56 +00:00
|
|
|
|
tile = remembered_cavern[tile_x][tile_y]
|
2019-06-29 08:45:13 +00:00
|
|
|
|
|
2019-06-28 18:53:56 +00:00
|
|
|
|
if tile == tiletypes.empty then
|
|
|
|
|
love.graphics.setColor(0.2, 0.2, 0.2)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-28 18:53:56 +00:00
|
|
|
|
elseif tile == tiletypes.wall then
|
2019-06-29 08:26:38 +00:00
|
|
|
|
love.graphics.setColor(0.9, 0.9, 0.9)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 08:45:13 +00:00
|
|
|
|
elseif tile == tiletypes.orb then
|
|
|
|
|
love.graphics.setColor(0.4, 0.4, 0.4)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 08:45:13 +00:00
|
|
|
|
love.graphics.setColor(0.2, 0.7, 0.2)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
love.graphics.circle('fill', x + 0.5 * scale, y + 0.5 * scale, 0.7 * scale/2)
|
2019-06-29 20:18:18 +00:00
|
|
|
|
elseif tile == tiletypes.slime then
|
2019-06-29 22:08:13 +00:00
|
|
|
|
love.graphics.setColor(0.2, 0.2, 0.2)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-29 22:25:32 +00:00
|
|
|
|
love.graphics.setColor(0.7, 0.7, 0.2)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
love.graphics.circle('fill', x + 0.5 * scale, y + 0.5 * scale, 0.8 * scale/2)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x + 0.1 * scale , y + 0.5 * scale, 0.8 * scale, 0.8 * scale/2)
|
2019-06-28 18:53:56 +00:00
|
|
|
|
else
|
2019-06-29 12:51:33 +00:00
|
|
|
|
love.graphics.setColor(0.7, 0.5, 0.5)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x, y, scale, scale)
|
2019-06-28 18:53:56 +00:00
|
|
|
|
end
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
2019-06-29 20:18:18 +00:00
|
|
|
|
|
|
|
|
|
if debug and tile_x == player_x and tile_y == player_y then
|
|
|
|
|
love.graphics.setColor(1, 1, 0)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.rectangle('fill', x + 0.5 * scale, y + 0.5 * scale, scale/2, scale/2)
|
2019-06-29 20:18:18 +00:00
|
|
|
|
end
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
|
|
|
|
end
|
2019-06-29 12:18:55 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function drawPlayer()
|
2019-06-30 07:49:11 +00:00
|
|
|
|
local screen_width = love.graphics.getWidth()
|
|
|
|
|
local screen_height = love.graphics.getHeight()
|
|
|
|
|
|
|
|
|
|
local width_scale = screen_width / cavern.width
|
|
|
|
|
local height_scale = screen_height / cavern.height
|
|
|
|
|
local scale = math.min(width_scale, height_scale)
|
|
|
|
|
|
|
|
|
|
local x_offset = (screen_width - cavern.width * scale) / 2
|
|
|
|
|
local y_offset = (screen_height - cavern.height * scale) / 2
|
2019-06-28 15:13:03 +00:00
|
|
|
|
|
2019-06-30 16:38:42 +00:00
|
|
|
|
local x = (player_x - 1) * scale + x_offset
|
|
|
|
|
local y = (player_y - 1) * scale + y_offset
|
|
|
|
|
|
|
|
|
|
local sprite = nil
|
|
|
|
|
if flash_player_damaged_counter > 0 then
|
|
|
|
|
sprite = player_sprite_damaged
|
|
|
|
|
elseif flash_player_crit_counter > 0 then
|
|
|
|
|
sprite = player_sprite_crit
|
2019-06-30 09:41:27 +00:00
|
|
|
|
else
|
2019-06-30 16:38:42 +00:00
|
|
|
|
sprite = player_sprite
|
2019-06-30 09:41:27 +00:00
|
|
|
|
end
|
2019-06-28 15:13:03 +00:00
|
|
|
|
|
2019-06-30 16:38:42 +00:00
|
|
|
|
local rotation = nil
|
|
|
|
|
if player_direction == directions.up then
|
|
|
|
|
rotation = 0
|
2019-06-30 16:46:33 +00:00
|
|
|
|
if player_animation_flip then
|
|
|
|
|
x = x + scale
|
|
|
|
|
end
|
2019-06-30 16:38:42 +00:00
|
|
|
|
elseif player_direction == directions.left then
|
|
|
|
|
rotation = math.pi * 1.5
|
2019-06-30 16:46:33 +00:00
|
|
|
|
if not player_animation_flip then
|
|
|
|
|
y = y + scale
|
|
|
|
|
end
|
2019-06-30 16:38:42 +00:00
|
|
|
|
elseif player_direction == directions.down then
|
|
|
|
|
rotation = math.pi
|
2019-06-30 16:46:33 +00:00
|
|
|
|
if not player_animation_flip then
|
|
|
|
|
x = x + scale
|
|
|
|
|
y = y + scale
|
|
|
|
|
else
|
|
|
|
|
y = y + scale
|
|
|
|
|
end
|
2019-06-30 16:38:42 +00:00
|
|
|
|
elseif player_direction == directions.right then
|
|
|
|
|
rotation = math.pi * 0.5
|
2019-06-30 16:46:33 +00:00
|
|
|
|
if not player_animation_flip then
|
|
|
|
|
x = x + scale
|
|
|
|
|
else
|
|
|
|
|
x = x + scale
|
|
|
|
|
y = y + scale
|
|
|
|
|
end
|
2019-06-30 16:38:42 +00:00
|
|
|
|
else
|
|
|
|
|
error("Player facing a direction without usable sprite")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- Our sprite image is drawn assuming 16 pixels per tile
|
|
|
|
|
love.graphics.setColor(1, 1, 1)
|
|
|
|
|
if not player_animation_flip then
|
2019-06-30 16:46:33 +00:00
|
|
|
|
love.graphics.draw(sprite, x, y, rotation, scale/16, scale/16)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
else
|
2019-06-30 16:46:33 +00:00
|
|
|
|
love.graphics.draw(sprite, x, y, rotation, -scale/16, scale/16)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
end
|
2019-06-28 15:13:03 +00:00
|
|
|
|
end
|
2019-06-29 12:18:55 +00:00
|
|
|
|
|
2019-06-30 09:41:27 +00:00
|
|
|
|
function drawHP()
|
|
|
|
|
local screen_width = love.graphics.getWidth()
|
|
|
|
|
local screen_height = love.graphics.getHeight()
|
|
|
|
|
|
|
|
|
|
local width_scale = screen_width / cavern.width
|
|
|
|
|
local height_scale = screen_height / cavern.height
|
|
|
|
|
local scale = math.min(width_scale, height_scale)
|
|
|
|
|
|
|
|
|
|
local x_offset = (screen_width - cavern.width * scale) / 2
|
|
|
|
|
local y_offset = (screen_height - cavern.height * scale) / 2
|
|
|
|
|
|
|
|
|
|
for i = 1, hp do
|
|
|
|
|
local x = (i - 1) * scale + x_offset
|
|
|
|
|
local y = y_offset
|
|
|
|
|
|
2019-06-30 17:40:18 +00:00
|
|
|
|
love.graphics.draw(heart_sprite, x, y, 0, scale/16, scale/16)
|
2019-06-30 09:41:27 +00:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 12:18:55 +00:00
|
|
|
|
function drawWin()
|
|
|
|
|
local img_width, img_height = win_image:getDimensions()
|
|
|
|
|
|
|
|
|
|
local screen_width = love.graphics.getWidth()
|
|
|
|
|
local screen_height = love.graphics.getHeight()
|
|
|
|
|
|
|
|
|
|
local width_scale = screen_width / img_width
|
|
|
|
|
local height_scale = screen_height / img_height
|
|
|
|
|
local scale = math.min(width_scale, height_scale)
|
|
|
|
|
|
2019-06-30 07:49:11 +00:00
|
|
|
|
local x_offset = (screen_width - img_width * scale) / 2
|
|
|
|
|
local y_offset = (screen_height - img_height * scale) / 2
|
2019-06-29 12:18:55 +00:00
|
|
|
|
|
|
|
|
|
love.graphics.setColor(1, 1, 1)
|
2019-06-30 07:49:11 +00:00
|
|
|
|
love.graphics.draw(win_image, x_offset, y_offset, 0, scale, scale)
|
2019-06-29 12:18:55 +00:00
|
|
|
|
end
|
|
|
|
|
|
2019-06-30 08:32:50 +00:00
|
|
|
|
function drawLoss()
|
|
|
|
|
local width = 54
|
|
|
|
|
local height = 140
|
|
|
|
|
|
|
|
|
|
local screen_width = love.graphics.getWidth()
|
|
|
|
|
local screen_height = love.graphics.getHeight()
|
|
|
|
|
|
|
|
|
|
local width_scale = screen_width / width
|
|
|
|
|
local height_scale = screen_height / height
|
|
|
|
|
local scale = math.min(width_scale, height_scale)
|
|
|
|
|
|
|
|
|
|
local x_offset = (screen_width - width * scale) / 2
|
|
|
|
|
local y_offset = (screen_height - height * scale) / 2
|
|
|
|
|
|
|
|
|
|
local vertices = {18, 20, 0, 40, 0, 60, 6, 80, 12, 100, 18, 120, 36, 120, 42, 100, 48, 80, 54, 60, 54, 40, 36, 20}
|
|
|
|
|
|
|
|
|
|
local transformed_vertices = {}
|
|
|
|
|
for i = 1, #vertices, 2 do
|
|
|
|
|
local x = vertices[i] * scale + x_offset
|
|
|
|
|
local y = vertices[i + 1] * scale + y_offset
|
|
|
|
|
|
|
|
|
|
transformed_vertices[i] = x
|
|
|
|
|
transformed_vertices[i + 1] = y
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
love.graphics.setColor(0.6, 0.3, 0.2)
|
|
|
|
|
love.graphics.polygon('fill', transformed_vertices)
|
|
|
|
|
|
|
|
|
|
love.graphics.setColor(1, 1, 1)
|
|
|
|
|
local lines = {27, 40, 27, 80, 18, 50, 36, 50}
|
|
|
|
|
for i = 1, #lines, 4 do
|
|
|
|
|
local sx = lines[i] * scale + x_offset
|
|
|
|
|
local sy = lines[i + 1] * scale + y_offset
|
|
|
|
|
local ex = lines[i + 2] * scale + x_offset
|
|
|
|
|
local ey = lines[i + 3] * scale + y_offset
|
|
|
|
|
|
|
|
|
|
love.graphics.line(sx, sy, ex, ey)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 12:46:17 +00:00
|
|
|
|
function drawConfig()
|
|
|
|
|
local text = nil
|
|
|
|
|
if configuration_step == configuration_steps.quit then
|
|
|
|
|
text = "Quit"
|
|
|
|
|
elseif configuration_step == configuration_steps.restart then
|
|
|
|
|
text = "Restart"
|
|
|
|
|
elseif configuration_step == configuration_steps.configure then
|
|
|
|
|
text = "Button configuration"
|
2019-06-30 10:21:49 +00:00
|
|
|
|
elseif configuration_step == configuration_steps.autoexplore then
|
|
|
|
|
text = "Autoexplore"
|
2019-06-29 12:46:17 +00:00
|
|
|
|
elseif configuration_step == directions.up then
|
|
|
|
|
text = "Up"
|
|
|
|
|
elseif configuration_step == directions.upleft then
|
|
|
|
|
text = "Up-Left"
|
|
|
|
|
elseif configuration_step == directions.left then
|
|
|
|
|
text = "Left"
|
|
|
|
|
elseif configuration_step == directions.downleft then
|
|
|
|
|
text = "Down-Left"
|
|
|
|
|
elseif configuration_step == directions.down then
|
|
|
|
|
text = "Down"
|
|
|
|
|
elseif configuration_step == directions.downright then
|
|
|
|
|
text = "Down-Right"
|
|
|
|
|
elseif configuration_step == directions.right then
|
|
|
|
|
text = "Right"
|
|
|
|
|
elseif configuration_step == directions.upright then
|
|
|
|
|
text = "Up-Right"
|
2019-06-29 22:04:44 +00:00
|
|
|
|
elseif configuration_step == directions.inplace then
|
|
|
|
|
text = "Do nothing for a turn"
|
2019-06-29 12:46:17 +00:00
|
|
|
|
else
|
|
|
|
|
error("Impossible configuration step")
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
love.graphics.setColor(1, 1, 1)
|
|
|
|
|
love.graphics.print(text)
|
|
|
|
|
end
|
|
|
|
|
|
2019-06-29 12:18:55 +00:00
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
-- Callbacks
|
|
|
|
|
-- ------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
function love.load()
|
|
|
|
|
math.randomseed(os.time())
|
|
|
|
|
|
|
|
|
|
newGame()
|
|
|
|
|
|
|
|
|
|
win_image = love.graphics.newImage("win_image.png")
|
2019-06-30 16:38:42 +00:00
|
|
|
|
|
|
|
|
|
player_sprite = love.graphics.newImage("sprite.png")
|
|
|
|
|
player_sprite_crit = love.graphics.newImage("sprite_crit.png")
|
|
|
|
|
player_sprite_damaged = love.graphics.newImage("sprite_damaged.png")
|
2019-06-30 17:40:18 +00:00
|
|
|
|
|
|
|
|
|
heart_sprite = love.graphics.newImage("heart.png")
|
2019-06-29 12:18:55 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function love.update(dt)
|
|
|
|
|
if move_repeat_counter ~= nil and move_repeat_counter > 0 then
|
|
|
|
|
move_repeat_counter = move_repeat_counter - dt
|
2019-06-30 15:46:09 +00:00
|
|
|
|
if move_repeat_counter <= 0 and last_key_pressed ~= nil then
|
|
|
|
|
love.keypressed(last_key_pressed)
|
2019-06-29 12:18:55 +00:00
|
|
|
|
end
|
|
|
|
|
end
|
2019-06-30 09:41:27 +00:00
|
|
|
|
|
2019-06-30 16:38:42 +00:00
|
|
|
|
if flash_player_crit_counter > 0 then
|
|
|
|
|
flash_player_crit_counter = flash_player_crit_counter - dt
|
2019-06-30 09:41:27 +00:00
|
|
|
|
end
|
2019-06-30 16:38:42 +00:00
|
|
|
|
if flash_player_damaged_counter > 0 then
|
|
|
|
|
flash_player_damaged_counter = flash_player_damaged_counter - dt
|
|
|
|
|
if hp == 0 and flash_player_damaged_counter <= 0 and game_mode ~= gamemodes.won then
|
2019-06-30 09:41:27 +00:00
|
|
|
|
game_mode = gamemodes.lost
|
|
|
|
|
end
|
|
|
|
|
end
|
2019-06-29 12:18:55 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function love.keypressed(key)
|
2019-06-29 12:46:17 +00:00
|
|
|
|
if game_mode == gamemodes.config then
|
|
|
|
|
-- This is a hack. Each "enum value" corresponds to an integer, and we are iterating
|
2019-06-29 22:04:44 +00:00
|
|
|
|
-- through them. -3 to -1 are control keys, and 0 to 8 are direction keys
|
|
|
|
|
if configuration_step >= directions.up and configuration_step <= directions.inplace then
|
2019-06-29 12:46:17 +00:00
|
|
|
|
direction_keys[key] = configuration_step
|
|
|
|
|
elseif configuration_step == configuration_steps.quit then
|
|
|
|
|
control_keys.quit = key
|
|
|
|
|
elseif configuration_step == configuration_steps.restart then
|
|
|
|
|
control_keys.restart = key
|
|
|
|
|
elseif configuration_step == configuration_steps.configure then
|
|
|
|
|
control_keys.configure = key
|
2019-06-30 10:21:49 +00:00
|
|
|
|
elseif configuration_step == configuration_steps.autoexplore then
|
|
|
|
|
control_keys.autoexplore = key
|
2019-06-29 12:46:17 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
configuration_step = configuration_step + 1
|
2019-06-29 22:04:44 +00:00
|
|
|
|
if configuration_step > directions.inplace then
|
2019-06-29 12:46:17 +00:00
|
|
|
|
game_mode = gamemodes.normal
|
|
|
|
|
end
|
|
|
|
|
else
|
2019-06-30 15:46:09 +00:00
|
|
|
|
if last_key_pressed == key then
|
|
|
|
|
-- Repeat faster after the initial threshold for repetition has been met
|
|
|
|
|
move_repeat_counter = 0.1
|
|
|
|
|
else
|
|
|
|
|
move_repeat_counter = 0.3
|
|
|
|
|
end
|
2019-06-29 12:46:17 +00:00
|
|
|
|
|
|
|
|
|
if key == control_keys.configure and game_mode == gamemodes.normal then
|
2019-06-29 22:12:46 +00:00
|
|
|
|
direction_keys = {}
|
2019-06-29 12:46:17 +00:00
|
|
|
|
game_mode = gamemodes.config
|
|
|
|
|
configuration_step = configuration_steps.quit
|
|
|
|
|
elseif key == control_keys.quit then
|
|
|
|
|
love.event.quit()
|
|
|
|
|
elseif key == control_keys.restart then
|
|
|
|
|
newGame()
|
2019-06-30 10:21:49 +00:00
|
|
|
|
elseif key == control_keys.autoexplore then
|
|
|
|
|
autoexplore()
|
2019-06-30 15:46:09 +00:00
|
|
|
|
last_key_pressed = key
|
2019-06-29 12:46:17 +00:00
|
|
|
|
elseif direction_keys[key] ~= nil then
|
|
|
|
|
step(direction_keys[key])
|
2019-06-30 15:46:09 +00:00
|
|
|
|
last_key_pressed = key
|
2019-06-29 12:55:33 +00:00
|
|
|
|
elseif key == 'pause' then
|
2019-06-29 12:54:56 +00:00
|
|
|
|
debug = not debug
|
2019-06-29 12:46:17 +00:00
|
|
|
|
end
|
2019-06-29 12:18:55 +00:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function love.keyreleased(key)
|
|
|
|
|
if last_key_pressed == key then
|
2019-06-30 15:46:09 +00:00
|
|
|
|
last_key_pressed = nil
|
2019-06-29 12:18:55 +00:00
|
|
|
|
move_repeat_counter = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function love.draw()
|
|
|
|
|
if game_mode == gamemodes.normal then
|
|
|
|
|
drawCavern()
|
2019-06-29 20:18:18 +00:00
|
|
|
|
if not debug then
|
|
|
|
|
drawPlayer()
|
|
|
|
|
end
|
2019-06-30 09:41:27 +00:00
|
|
|
|
drawHP()
|
2019-06-29 12:18:55 +00:00
|
|
|
|
elseif game_mode == gamemodes.won then
|
|
|
|
|
drawWin()
|
2019-06-30 08:32:50 +00:00
|
|
|
|
elseif game_mode == gamemodes.lost then
|
|
|
|
|
drawLoss()
|
2019-06-29 12:46:17 +00:00
|
|
|
|
elseif game_mode == gamemodes.config then
|
|
|
|
|
drawConfig()
|
2019-06-29 12:18:55 +00:00
|
|
|
|
else
|
|
|
|
|
error("Impossible game mode")
|
|
|
|
|
end
|
|
|
|
|
end
|