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

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