File: prog_finder.lua

package info (click to toggle)
fillets-ng-data 1.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 180,924 kB
  • sloc: makefile: 2
file content (100 lines) | stat: -rw-r--r-- 2,897 bytes parent folder | download | duplicates (8)
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

dir_no = 0
dir_up = 1
dir_down = 2
dir_left = 3
dir_right = 4

-- -----------------------------------------------------------------
function getDirShift(dir)
    local shiftX, shiftY = 0, 0
    if dir == dir_left then
        shiftX = -1
    elseif dir == dir_right then
        shiftX = 1
    elseif dir == dir_up then
        shiftY = -1
    elseif dir == dir_down then
        shiftY = 1
    end
    return shiftX, shiftY
end

-- -----------------------------------------------------------------
local function isFreePlace(model, locX, locY)
    for x = locX, locX + model:getW() - 1 do
        for y = locY, locY + model:getH() - 1 do
            if not model_equals(-1, x, y) and not model_equals(model.index, x, y) then
                return false
            end
        end
    end
    return true
end

-- -----------------------------------------------------------------
local function tryPlace(data, place)
    local locX = place.x
    local locY = place.y

    result = false
    if nil == data.closed[locX] then
        data.closed[locX] = {}
    end
    if not data.closed[locX][locY] then
        data.closed[locX][locY] = true
        if isFreePlace(data.model, locX, locY) then
            result = true
        end
    end
    return result
end

-- -----------------------------------------------------------------
local function isInRect(x, y, w, h, destX, destY)
    return x <= destX and destX < x + w and y <= destY and destY < y + h
end
-- -----------------------------------------------------------------
function findDir(model, destX, destY)
    -- Breadth-first search
    -- Find starting dir to the destination
    -- Return dir_no when there is no free path
    local locX, locY = model:getLoc()
    local w = model:getW()
    local h = model:getH()

    if isInRect(locX, locY, w, h, destX, destY) then
        return dir_no
    end
    if not model_equals(-1, destX, destY) then
        return dir_no
    end

    local data = {}
    data.closed = {}
    data.closed[locX] = {}
    data.closed[locX][locY] = true
    data.model = model

    local fifo = {}
    table.insert(fifo, {dir=dir_left, x=locX - 1, y=locY})
    table.insert(fifo, {dir=dir_right, x=locX + 1, y=locY})
    table.insert(fifo, {dir=dir_up, x=locX, y=locY - 1})
    table.insert(fifo, {dir=dir_down, x=locX, y=locY + 1})

    while table.getn(fifo) > 0 do
        local place = table.remove(fifo, 1)
        if tryPlace(data, place) then
            if isInRect(place.x, place.y, w, h, destX, destY) then
                return place.dir
            end

            table.insert(fifo, {dir=place.dir, x=place.x - 1, y=place.y})
            table.insert(fifo, {dir=place.dir, x=place.x + 1, y=place.y})
            table.insert(fifo, {dir=place.dir, x=place.x, y=place.y - 1})
            table.insert(fifo, {dir=place.dir, x=place.x, y=place.y + 1})
        end
    end
    return dir_no
end