summaryrefslogtreecommitdiff
path: root/include/algs.lua
blob: ad0016acc96d385983fa8f7e46d8eceb42521bdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
require "include.constants"
local Queue = require "include.queue"

local function can_move(x, y, map)
    return map[y][x] == MAP_SPACE
end

---@param x number
---@param y number
---@param origin table
---@param map table
---@param queue table
local function push_moves(x, y, origin, map, queue)
    -- UP
    if can_move(x, y -1, map) then
        queue:push({
            x = x,
            y = y - 1,
            origin = origin
        })
        map[y-1][x] = MAP_VISITED
    end
    -- DOWN
    if can_move(x, y +1, map) then
        queue:push({
            x = x,
            y = y + 1,
            origin = origin
        })
        map[y+1][x] = MAP_VISITED
    end
    -- LEFT
    if can_move(x - 1, y, map) then
        queue:push({
            x = x - 1,
            y = y,
            origin = origin
        })
        map[y][x - 1] = MAP_VISITED
    end
    -- RIGHT
    if can_move(x + 1, y, map) then
        queue:push({
            x = x + 1,
            y = y,
            origin = origin
        })
        map[y][x+1] = MAP_VISITED
    end
end

---
---@param start_pos table [x, y]
---@param target_pos table [x, y]
---@param map table 2D map array
---@return table best move to target [x, y]
---
local function pathfind(start_pos, target_pos, map)
    local queue = Queue:new()
    local visit_map = {}
    for k, v in ipairs(map) do
        row = {}
        for ik, iv in ipairs(v) do
            row[ik] = iv
        end
        visit_map[k] = row
    end

    push_moves(start_pos.x, start_pos.y, nil, visit_map, queue)
    while queue:empty() ~= true do
        local pos = queue:pop()
        if (pos.x == target_pos.x and pos.y == target_pos.y) then
            return { dx = pos.origin.x - start_pos.x, dy = pos.origin.y - start_pos.y }
        end
        origin = pos.origin or { x = pos.x, y = pos.y }
        push_moves(pos.x, pos.y, origin, map, queue)
    end
    return { dx = 0, dy = 0 }
end

---@param map table
local function print_map(map)
    for i = 1, #map do
        row = map[i]
        line = ""
        for j = 1, #row do
            if row[j] == MAP_WALL then
                line = line .. "# "
            else
                line = line .. "  "
            end
        end
        print(line)
    end
end

return {
    pathfind = pathfind,
    print_map = print_map,
}