1 /***************************************************************************
2  *   Copyright (C) 2005-2019 by the FIFE team                              *
3  *   http://www.fifengine.net                                              *
4  *   This file is part of FIFE.                                            *
5  *                                                                         *
6  *   FIFE is free software; you can redistribute it and/or                 *
7  *   modify it under the terms of the GNU Lesser General Public            *
8  *   License as published by the Free Software Foundation; either          *
9  *   version 2.1 of the License, or (at your option) any later version.    *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the                 *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // 3rd party library includes
25 
26 // FIFE includes
27 // These includes are split up in two parts, separated by one empty line
28 // First block: files included from the FIFE root src directory
29 // Second block: files included from the same folder
30 #include "util/log/logger.h"
31 #include "model/metamodel/object.h"
32 #include "model/structures/layer.h"
33 #include "model/structures/location.h"
34 
35 #include "route.h"
36 
37 namespace FIFE {
38 
39 	static Logger _log(LM_STRUCTURES);
40 
Route(const Location & start,const Location & end)41 	Route::Route(const Location& start, const Location& end):
42 		m_status(ROUTE_CREATED),
43 		m_startNode(start),
44 		m_endNode(end),
45 		m_walked(0),
46 		m_sessionId(-1),
47 		m_rotation(0),
48 		m_replanned(false),
49 		m_ignoresBlocker(false),
50 		m_costId(""),
51 		m_object(NULL) {
52 	}
53 
~Route()54 	Route::~Route() {
55 	}
56 
setRouteStatus(RouteStatusInfo status)57 	void Route::setRouteStatus(RouteStatusInfo status) {
58 		if (m_status != status) {
59 			m_status = status;
60 		}
61 	}
62 
getRouteStatus()63 	RouteStatusInfo Route::getRouteStatus() {
64 		return m_status;
65 	}
66 
setStartNode(const Location & node)67 	void Route::setStartNode(const Location& node) {
68 		m_startNode = node;
69 		if (m_status != ROUTE_CREATED) {
70 			m_status = ROUTE_CREATED;
71 			if (!m_path.empty()) {
72 				m_path.clear();
73 			}
74 			m_walked = 1;
75 		}
76 	}
77 
getStartNode()78 	const Location& Route::getStartNode() {
79 		return m_startNode;
80 	}
81 
setEndNode(const Location & node)82 	void Route::setEndNode(const Location& node) {
83 		if (m_status != ROUTE_CREATED) {
84 			m_status = ROUTE_CREATED;
85 			if (!m_path.empty()) {
86 				m_startNode = *m_current;
87 				m_path.clear();
88 			}
89 			m_walked = 1;
90 		}
91 		m_endNode = node;
92 	}
93 
getEndNode()94 	const Location& Route::getEndNode() {
95 		return m_endNode;
96 	}
97 
getCurrentNode()98 	const Location& Route::getCurrentNode() {
99 		if (m_path.empty()) {
100 			return m_startNode;
101 		}
102 		if (m_current == m_path.end()) {
103 			return m_path.back();
104 		}
105 		return *m_current;
106 	}
107 
getPreviousNode()108 	const Location& Route::getPreviousNode() {
109 		if (m_path.empty()) {
110 			return m_startNode;
111 		}
112 		if (m_current != m_path.begin()) {
113 			--m_current;
114 			const Location& loc = *m_current;
115 			++m_current;
116 			return loc;
117 		}
118 		return *m_current;
119 	}
120 
getNextNode()121 	const Location& Route::getNextNode() {
122 		if (m_path.empty()) {
123 			return m_startNode;
124 		}
125 		if (m_current != m_path.end()) {
126 			++m_current;
127 			if (m_current != m_path.end()) {
128 				const Location& loc = *m_current;
129 				--m_current;
130 				return loc;
131 			}
132 			--m_current;
133 		}
134 		return *m_current;
135 	}
136 
walkToNextNode(int32_t step)137 	bool Route::walkToNextNode(int32_t step) {
138 		if (m_path.empty() || step == 0) {
139 			return false;
140 		}
141 
142 		int32_t pos = static_cast<int32_t>(m_walked) + step;
143 		if (pos > static_cast<int32_t>(m_path.size()) || pos < 0) {
144 			return false;
145 		}
146 		if (step > 0) {
147 			for (int32_t i = 0; i < step; ++i, ++m_current);
148 		} else {
149 			for (int32_t i = 0; i > step; --i, --m_current);
150 		}
151 		m_walked += step;
152 
153 		return true;
154 	}
155 
reachedEnd()156 	bool Route::reachedEnd() {
157 		if (m_path.empty()) {
158 			return true;
159 		}
160 		return m_current == m_path.end();
161 	}
162 
setPath(const Path & path)163 	void Route::setPath(const Path& path) {
164 		m_path = path;
165 		if (!m_path.empty()) {
166 			m_status = ROUTE_SOLVED;
167 			m_current = m_path.begin();
168 			m_startNode = m_path.front();
169 			m_endNode = m_path.back();
170 		}
171 		if (!isMultiCell()) {
172 			m_replanned = false;
173 		}
174 		m_walked = 1;
175 	}
176 
getPath()177 	Path Route::getPath() {
178 		return m_path;
179 	}
180 
cutPath(uint32_t length)181 	void Route::cutPath(uint32_t length) {
182 		if (length == 0) {
183 			if (!m_path.empty()) {
184 				m_startNode = *m_current;
185 				m_endNode = *m_current;
186 				m_path.clear();
187 				m_current = m_path.end();
188 			}
189 			m_status = ROUTE_CREATED;
190 			m_walked = 1;
191 			m_replanned = true;
192 			return;
193 		} else if (length >= m_path.size()) {
194 			return;
195 		}
196 
197 		uint32_t newend = m_walked + length - 1;
198 		if (newend > m_path.size()) {
199 			return;
200 		}
201 
202 		m_path.resize(newend);
203 		m_endNode = m_path.back();
204 		m_replanned = true;
205 	}
206 
setReplanned(bool replanned)207 	void Route::setReplanned(bool replanned) {
208 		m_replanned = replanned;
209 	}
210 
isReplanned()211 	bool Route::isReplanned() {
212 		return m_replanned;
213 	}
214 
getPathLength()215 	uint32_t Route::getPathLength() {
216 		return m_path.size();
217 	}
218 
getWalkedLength()219 	uint32_t Route::getWalkedLength() {
220 		return m_walked;
221 	}
222 
setSessionId(int32_t id)223 	void Route::setSessionId(int32_t id) {
224 		m_sessionId = id;
225 	}
226 
getSessionId()227 	int32_t Route::getSessionId() {
228 		return m_sessionId;
229 	}
230 
setRotation(int32_t rotation)231 	void Route::setRotation(int32_t rotation) {
232 		m_rotation = rotation;
233 	}
234 
getRotation()235 	int32_t Route::getRotation() {
236 		return m_rotation;
237 	}
238 
setCostId(const std::string & cost)239 	void Route::setCostId(const std::string& cost) {
240 		m_costId = cost;
241 	}
242 
getCostId()243 	const std::string& Route::getCostId() {
244 		return m_costId;
245 	}
246 
isMultiCell()247 	bool Route::isMultiCell() {
248 		if (m_object) {
249 			return m_object->isMultiObject();
250 		}
251 		return false;
252 	}
253 
setOccupiedArea(const std::vector<ModelCoordinate> & area)254 	void Route::setOccupiedArea(const std::vector<ModelCoordinate>& area) {
255 		m_area = area;
256 	}
257 
getOccupiedArea()258 	const std::vector<ModelCoordinate>& Route::getOccupiedArea() {
259 		return m_area;
260 	}
261 
getOccupiedCells(int32_t rotation)262 	std::vector<ModelCoordinate> Route::getOccupiedCells(int32_t rotation) {
263 		if (m_object) {
264 			return m_object->getMultiObjectCoordinates(rotation);
265 		}
266 		std::vector<ModelCoordinate> coords;
267 		return coords;
268 	}
269 
getZStepRange()270 	int32_t Route::getZStepRange() {
271 		if (!m_object) {
272 			return -1;
273 		}
274 		return m_object->getZStepRange();
275 	}
276 
isAreaLimited()277 	bool Route::isAreaLimited() {
278 		if (m_object) {
279 			if (!m_object->getWalkableAreas().empty()) {
280 				return true;
281 			}
282 		}
283 		return false;
284 	}
285 
getLimitedAreas()286 	const std::list<std::string> Route::getLimitedAreas() {
287 		std::list<std::string> areas;
288 		if (m_object) {
289 			areas = m_object->getWalkableAreas();
290 		}
291 		return areas;
292 	}
293 
setDynamicBlockerIgnored(bool ignore)294 	void Route::setDynamicBlockerIgnored(bool ignore) {
295 		m_ignoresBlocker = ignore;
296 	}
297 
isDynamicBlockerIgnored()298 	bool Route::isDynamicBlockerIgnored() {
299 		return m_ignoresBlocker;
300 	}
301 
getBlockingPathLocations()302 	Path Route::getBlockingPathLocations() {
303 		Path p;
304 		if (!m_path.empty()) {
305 			for (PathIterator it = m_path.begin(); it != m_path.end(); ++it) {
306 				Layer* layer = (*it).getLayer();
307 				if (layer->cellContainsBlockingInstance((*it).getLayerCoordinates())) {
308 					p.push_back(*it);
309 				}
310 			}
311 		}
312 		return p;
313 	}
314 
setObject(Object * obj)315 	void Route::setObject(Object* obj) {
316 		m_object = obj;
317 	}
318 
getObject()319 	Object* Route::getObject() {
320 		return m_object;
321 	}
322 } // FIFE
323