comparison engine/core/pathfinder/routepather/routepather.cpp @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 90005975cdbb
comparison
equal deleted inserted replaced
-1:000000000000 0:4a0efb7baf70
1 /***************************************************************************
2 * Copyright (C) 2005-2008 by the FIFE team *
3 * http://www.fifengine.de *
4 * This file is part of FIFE. *
5 * *
6 * FIFE is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program 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 *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
20 ***************************************************************************/
21
22 // Standard C++ library includes
23 #include <cassert>
24
25 // 3rd party library includes
26
27 // FIFE includes
28 // These includes are split up in two parts, separated by one empty line
29 // First block: files included from the FIFE root src directory
30 // Second block: files included from the same folder
31 #include "model/metamodel/grids/cellgrid.h"
32 #include "model/structures/instance.h"
33 #include "model/structures/layer.h"
34
35 #include "pathfinder/searchspace.h"
36
37 #include "routepather.h"
38 #include "routepathersearch.h"
39
40 namespace FIFE {
41 void RoutePather::setMap(Map* map) {
42 if(!map) {
43 return;
44 }
45 m_map = map;
46 }
47
48 int RoutePather::getNextLocation(const Instance* instance, const Location& target,
49 double distance_to_travel, Location& nextLocation,
50 Location& facingLocation, int session_id, int priority) {
51 assert(instance);
52 assert(instance->getLocation().getLayer() == target.getLayer());
53 if(session_id != -1) {
54 PathMap::iterator j = m_paths.find(session_id);
55 if(j != m_paths.end()) {
56 if(j->second.empty()) {
57 m_paths.erase(j);
58 return -1;
59 } else {
60 followPath(instance, j->second, distance_to_travel, nextLocation, facingLocation);
61 return session_id;
62 }
63 } else {
64 if(!sessionIdValid(session_id)) {
65 //Session id is invalid.
66 return -1;
67 }
68 }
69 return session_id;
70 }
71 SearchSpace* searchspace = getSearchSpace(target.getLayer());
72 if(!searchspace) {
73 searchspace = new SearchSpace(target.getLayer());
74 addSearchSpace(searchspace);
75 }
76 if(searchspace->isInSearchSpace(target)) {
77 session_id = m_nextFreeSessionId++;
78 RoutePatherSearch* newSearch = new RoutePatherSearch(session_id, instance->getLocation(), target, searchspace);
79 m_sessions.pushElement(SessionQueue::value_type(newSearch, priority));
80 addSessionId(session_id);
81 }
82 return session_id;
83 }
84
85 void RoutePather::update() {
86 int ticksleft = m_maxticks;
87 while(ticksleft >= 0) {
88 if(m_sessions.empty()) {
89 break;
90 }
91 Search* priority_session = m_sessions.getPriorityElement().first;
92 if(!sessionIdValid(priority_session->getSessionId())) {
93 delete priority_session;
94 m_sessions.popElement();
95 continue;
96 }
97 priority_session->updateSearch();
98 if(priority_session->getSearchStatus() == Search::search_status_complete) {
99 Path newPath = priority_session->calcPath();
100 m_paths.insert(PathMap::value_type(priority_session->getSessionId(), newPath));
101 invalidateSessionId(priority_session->getSessionId());
102 delete priority_session;
103 m_sessions.popElement();
104 } else if(priority_session->getSearchStatus() == Search::search_status_failed) {
105 invalidateSessionId(priority_session->getSessionId());
106 delete priority_session;
107 m_sessions.popElement();
108 }
109 --ticksleft;
110 }
111 }
112
113 void RoutePather::followPath(const Instance* instance, Path& path, double speed, Location& nextLocation, Location& facingLocation) {
114 Location instanceLoc = instance->getLocation();
115 ExactModelCoordinate instancePos = instanceLoc.getMapCoordinates();
116 ExactModelCoordinate facingPos = path.front().getMapCoordinates();
117 facingPos.x = facingPos.x + (facingPos.x - instancePos.x);
118 facingPos.y = facingPos.y + (facingPos.y - instancePos.y);
119 facingLocation = path.front();
120 facingLocation.setMapCoordinates(facingPos);
121 ExactModelCoordinate targetPos = path.front().getMapCoordinates();
122 CellGrid* grid = instanceLoc.getLayer()->getCellGrid();
123 double dx = (targetPos.x - instancePos.x) * grid->getXScale();
124 double dy = (targetPos.y - instancePos.y) * grid->getYScale();
125 double distance = sqrt(dx * dx + dy * dy);
126 bool pop = false;
127 if(speed > distance) {
128 speed = distance;
129 pop = true;
130 }
131 if(distance != 0)
132 {
133 instancePos.x += (dx / distance) * speed;
134 instancePos.y += (dy / distance) * speed;
135
136 } else {
137 pop = true;
138 }
139 nextLocation.setMapCoordinates(instancePos);
140 if(pop)
141 {
142 path.pop_front();
143 if(!path.empty() && instanceLoc.getLayer()->cellContainsBlockingInstance(path.front().getLayerCoordinates()))
144 {
145 //TODO: Determine if we're close enough to stop, otherwise find alternate route.
146 path.clear();
147 return;
148 }
149 }
150 }
151
152 bool RoutePather::cancelSession(const int session_id) {
153 if(session_id >= 0) {
154 PathMap::iterator i = m_paths.find(session_id);
155 if(i != m_paths.end()) {
156 m_paths.erase(i);
157 return true;
158 } else {
159 invalidateSessionId(session_id);
160 }
161 }
162 return false;
163 }
164
165 void RoutePather::addSessionId(const int sessionId) {
166 m_registeredSessionIds.push_back(sessionId);
167 }
168
169 bool RoutePather::sessionIdValid(const int sessionId) {
170 for(SessionList::const_iterator i = m_registeredSessionIds.begin();
171 i != m_registeredSessionIds.end();
172 ++i) {
173 if((*i) == sessionId) {
174 return true;
175 }
176 }
177 return false;
178 }
179
180 bool RoutePather::invalidateSessionId(const int sessionId) {
181 for(SessionList::iterator i = m_registeredSessionIds.begin();
182 i != m_registeredSessionIds.end();
183 ++i) {
184 if((*i) == sessionId) {
185 m_registeredSessionIds.erase(i);
186 return true;
187 }
188 }
189 return false;
190 }
191
192 bool RoutePather::addSearchSpace(SearchSpace* search_space) {
193 std::pair<SearchSpaceMap::iterator, bool> res = m_searchspaces.insert(SearchSpaceMap::value_type(search_space->getLayer(), search_space));
194
195 return res.second;
196 }
197
198 SearchSpace* RoutePather::getSearchSpace(Layer * const layer) {
199 SearchSpaceMap::iterator i = m_searchspaces.find(layer);
200 if(i == m_searchspaces.end()) {
201 return 0;
202 }
203 return i->second;
204 }
205 }