GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/navigationmanager.cpp Lines: 1 60 1.7 %
Date: 2021-03-17 Branches: 0 52 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2013-2019  The ManaPlus Developers
4
 *  Copyright (C) 2019-2021  Andrei Karas
5
 *
6
 *  This file is part of The ManaPlus Client.
7
 *
8
 *  This program is free software; you can redistribute it and/or modify
9
 *  it under the terms of the GNU General Public License as published by
10
 *  the Free Software Foundation; either version 2 of the License, or
11
 *  any later version.
12
 *
13
 *  This program is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *  GNU General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU General Public License
19
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#include "navigationmanager.h"
23
24
#include "enums/resources/map/blockmask.h"
25
26
#include "resources/map/map.h"
27
#include "resources/map/metatile.h"
28
#include "resources/map/walklayer.h"
29
30
#include "debug.h"
31
32
static const int blockWalkMask = (BlockMask::WALL |
33
    BlockMask::AIR |
34
    BlockMask::WATER);
35
36
#ifndef DYECMD
37
namespace
38
{
39
    struct Cell final
40
    {
41
        Cell(const int x0, const int y0) :
42
            x(x0),
43
            y(y0)
44
        {
45
        }
46
47
        A_DEFAULT_COPY(Cell)
48
49
        int x;
50
        int y;
51
    };
52
}  // namespace
53
#endif  // DYECMD
54
55
NavigationManager::NavigationManager()
56
{
57
}
58
59
NavigationManager::~NavigationManager()
60
{
61
}
62
63
#ifndef DYECMD
64
Resource *NavigationManager::loadWalkLayer(const Map *const map)
65
{
66
    if (map == nullptr)
67
        return nullptr;
68
69
    const int width = map->getWidth();
70
    const int height = map->getHeight();
71
    if (width < 2 || height < 2)
72
        return nullptr;
73
    WalkLayer *const walkLayer = new WalkLayer(width, height);
74
75
    const MetaTile *const tiles = map->getMetaTiles();
76
    int *const data = walkLayer->getData();
77
    if ((tiles == nullptr) || (data == nullptr))
78
        return walkLayer;
79
80
    int x = 0;
81
    int y = 0;
82
    int num = 1;
83
    while (findWalkableTile(x, y, width, height, tiles, data))
84
    {
85
        fillNum(x, y, width, height, num, tiles, data);
86
        num ++;
87
    }
88
89
    return walkLayer;
90
}
91
92
void NavigationManager::fillNum(int x, int y,
93
                                const int width,
94
                                const int height,
95
                                const int num,
96
                                const MetaTile *const tiles,
97
                                int *const data)
98
{
99
    STD_VECTOR<Cell> cells;
100
    cells.push_back(Cell(x, y));
101
    while (!cells.empty())
102
    {
103
        const Cell cell = cells.back();
104
        cells.pop_back();
105
        int ptr;
106
        x = cell.x;
107
        y = cell.y;
108
        data[x + width * y] = num;
109
        if (x > 0)
110
        {
111
            ptr = (x - 1) + width * y;
112
            if (data[ptr] == 0)
113
            {
114
                if ((tiles[ptr].blockmask & blockWalkMask) == 0)
115
                    cells.push_back(Cell(x - 1, y));
116
                else
117
                    data[ptr] = -num;
118
            }
119
        }
120
        if (x < width - 1)
121
        {
122
            ptr = (x + 1) + width * y;
123
            if (data[ptr] == 0)
124
            {
125
                if ((tiles[ptr].blockmask & blockWalkMask) == 0)
126
                    cells.push_back(Cell(x + 1, y));
127
                else
128
                    data[ptr] = -num;
129
            }
130
        }
131
        if (y > 0)
132
        {
133
            ptr = x + width * (y - 1);
134
            if (data[ptr] == 0)
135
            {
136
                if ((tiles[ptr].blockmask & blockWalkMask) == 0)
137
                    cells.push_back(Cell(x, y - 1));
138
                else
139
                    data[ptr] = -num;
140
            }
141
        }
142
        if (y < height - 1)
143
        {
144
            ptr = x + width * (y + 1);
145
            if (data[ptr] == 0)
146
            {
147
                if ((tiles[ptr].blockmask & blockWalkMask) == 0)
148
                    cells.push_back(Cell(x, y + 1));
149
                else
150
                    data[ptr] = -num;
151
            }
152
        }
153
    }
154
}
155
156
bool NavigationManager::findWalkableTile(int &x1, int &y1,
157
                                         const int width,
158
                                         const int height,
159
                                         const MetaTile *const tiles,
160
                                         const int *const data)
161
{
162
    for (int y = 0; y < height; y ++)
163
    {
164
        const int y2 = y * width;
165
        for (int x = 0; x < width; x ++)
166
        {
167
            const int ptr = x + y2;
168
            if (((tiles[ptr].blockmask & blockWalkMask) == 0) &&
169
                data[ptr] == 0)
170
            {
171
                x1 = x;
172
                y1 = y;
173
                return true;
174
            }
175
        }
176
    }
177
    return false;
178
2
}
179
#endif  // DYECMD