Skyscraper 2.0
route.cpp
Go to the documentation of this file.
1/*
2 Scalable Building Simulator - Routing Objects
3 The Skyscraper Project - Version 2.0
4 Copyright (C)2004-2024 Ryan Thoryk
5 https://www.skyscrapersim.net
6 https://sourceforge.net/projects/skyscraper/
7 Contact - ryan@skyscrapersim.net
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22*/
23
24#include "globals.h"
25#include "sbs.h"
26#include "floor.h"
27#include "elevator.h"
28#include "elevatorcar.h"
29#include "profiler.h"
30#include "route.h"
31
32namespace SBS {
33
34ElevatorRoute::ElevatorRoute(ElevatorCar *car, int floor_selection)
35{
36 this->car = car;
37 this->floor_selection = floor_selection;
38}
39
40std::vector<ElevatorRoute*> SBS::GetRouteToFloor(int StartingFloor, int DestinationFloor, bool service_access)
41{
42 //get a path from a starting floor to a desination floor, as a list of elevators to ride
43 //if service_access is true, include service elevators in checks
44
45 //these function prioritize service elevators (if specified) and express elevators over local elevators
46
47 //for pathfinding to work properly, express and service elevators
48 //need to have their Type parameter set properly.
49
50 SBS_PROFILE("SBS::GetRouteToFloor");
51
52 std::vector<ElevatorRoute*> result;
53
54 Floor *start_floor = GetFloor(StartingFloor);
55 Floor *dest_floor = GetFloor(DestinationFloor);
56
57 if (!start_floor || !dest_floor || start_floor == dest_floor)
58 return result;
59
60 std::vector<int> checked_floors;
61
62 //Direct check
63 //check all express and local elevators if they directly serve destination floor
64 {
65 ElevatorRoute *route = GetDirectRoute(start_floor, DestinationFloor, service_access);
66
67 if (route)
68 {
69 result.emplace_back(route);
70 return result;
71 }
72
73 checked_floors.emplace_back(StartingFloor);
74 }
75
76 //Indirect check
77 std::vector<ElevatorRoute*> route = GetIndirectRoute(checked_floors, StartingFloor, DestinationFloor, service_access);
78
79 if (route.empty() == false)
80 return route;
81
82 //if indirect check fails, get a list of floors that are connected to the destination floor by
83 //the elevators that serve that floor, and check those floors individually to see if they are accessible
84 std::vector<int> connected = dest_floor->GetDirectFloors(false);
85
86 for (size_t i = 0; i < connected.size(); i++)
87 {
88 checked_floors.clear();
89 route = GetIndirectRoute(checked_floors, StartingFloor, connected[i], service_access);
90
91 if (route.empty() == false)
92 {
93 //append direct route
94 Floor *floor = GetFloor(connected[i]);
95 ElevatorRoute *endroute = GetDirectRoute(floor, DestinationFloor, service_access);
96
97 if (endroute)
98 route.emplace_back(endroute);
99 return route;
100 }
101 }
102
103 return route;
104}
105
106ElevatorRoute* SBS::GetDirectRoute(Floor *floor, int DestinationFloor, bool service_access)
107{
108 if (!floor)
109 return 0;
110
111 SBS_PROFILE("SBS::GetDirectRoute");
112
113 ElevatorRoute *route;
114
115 if (service_access == true)
116 {
117 route = floor->GetDirectRoute(DestinationFloor, "Service");
118 if (route)
119 return route;
120 }
121
122 route = floor->GetDirectRoute(DestinationFloor, "Express");
123 if (route)
124 return route;
125
126 route = floor->GetDirectRoute(DestinationFloor, "Local");
127 if (route)
128 return route;
129
130 return route;
131}
132
133std::vector<ElevatorRoute*> SBS::GetIndirectRoute(std::vector<int> &checked_floors, int StartingFloor, int DestinationFloor, bool service_access, bool top_level)
134{
135 //get a route to a destination floor, via elevator serviced floors
136
137 //this function will find an indirect route to a floor, while prioritizing service and express elevators
138
139 SBS_PROFILE("SBS::GetIndirectRoute");
140
141 std::vector<ElevatorRoute*> result;
142
143 Floor *start_floor = GetFloor(StartingFloor);
144
145 if (!start_floor)
146 return result;
147
148 std::vector<int> list, list_express, list_local;
149
150 //get service elevators
151 if (service_access == true)
152 start_floor->GetElevatorList(list, false, false, true);
153
154 //get express elevators
155 start_floor->GetElevatorList(list_express, false, true, false);
156 list.insert(list.end(), list_express.begin(), list_express.end());
157
158 bool locals_checked = false;
159 bool recurse = false;
160
161 while (true)
162 {
163 for (size_t i = 0; i < list.size(); i++)
164 {
165 Elevator *elev = GetElevator(list[i]);
166
167 if (elev)
168 {
169 ElevatorCar *car = elev->GetCarForFloor(StartingFloor);
170
171 if (car)
172 {
173 //floor list needs to be checked in the direction opposite of the travel direction,
174 //if the checked elevator doesn't go beyond the destination floor
175
176 std::vector<int> floor_list;
177 if ((DestinationFloor > StartingFloor && car->GetTopFloor() < DestinationFloor) ||
178 (DestinationFloor < StartingFloor && car->GetBottomFloor() < DestinationFloor))
179 {
180 for (int j = car->GetServicedFloorCount() - 1; j >= 0; j--)
181 {
182 floor_list.emplace_back(car->GetServicedFloor(j));
183 }
184 }
185 else
186 {
187 for (int j = 0; j < car->GetServicedFloorCount(); j++)
188 {
189 floor_list.emplace_back(car->GetServicedFloor(j));
190 }
191 }
192
193 for (size_t j = 0; j < floor_list.size(); j++)
194 {
195 int number = floor_list[j];
196
197 if (number != StartingFloor)
198 {
199 if (recurse == true)
200 {
201 std::vector<ElevatorRoute*> result2 = GetIndirectRoute(checked_floors, number, DestinationFloor, service_access, false);
202
203 if (result2.empty() == false)
204 {
205 ElevatorRoute *first = new ElevatorRoute(car, number);
206 result.emplace_back(first);
207
208 for (size_t i = 0; i < result2.size(); i++)
209 {
210 result.emplace_back(result2[i]);
211 }
212 return result;
213 }
214 }
215 else
216 {
217 Floor *floor = GetFloor(number);
218
219 //see if this floor has already been checked
220 bool checked = false;
221 for (size_t i = 0; i < checked_floors.size(); i++)
222 {
223 if (checked_floors[i] == number)
224 {
225 checked = true;
226 break;
227 }
228 }
229
230 if (floor && checked == false)
231 {
232 ElevatorRoute *result2 = GetDirectRoute(floor, DestinationFloor, service_access);
233
234 if (result2)
235 {
236 ElevatorRoute *first = new ElevatorRoute(car, number);
237 result.emplace_back(first);
238 result.emplace_back(result2);
239 return result;
240 }
241
242 checked_floors.emplace_back(number);
243 }
244 }
245 }
246 }
247 }
248 }
249 }
250
251 if (top_level == false)
252 return result;
253 else
254 {
255 if (locals_checked == true && recurse == true)
256 return result;
257
258 //if still going, check local elevators
259
260 //get local elevators
261 if (locals_checked == false && recurse == true)
262 {
263 list.clear();
264 start_floor->GetElevatorList(list_local, true, false, false);
265 list.insert(list.end(), list_local.begin(), list_local.end());
266 locals_checked = true;
267 recurse = false;
268 }
269 else if (recurse == false)
270 recurse = true;
271 }
272 }
273
274 return result;
275}
276
277}
int GetServicedFloor(int index)
ElevatorCar * GetCarForFloor(int number, bool report_on_failure=false)
ElevatorRoute * GetDirectRoute(int DestinationFloor, std::string ElevatorType)
Definition floor.cpp:1785
void GetElevatorList(std::vector< int > &listing, bool get_locals=true, bool get_express=true, bool get_service=true)
Definition floor.cpp:1729
std::vector< int > GetDirectFloors(bool include_service)
Definition floor.cpp:1818
std::vector< ElevatorRoute * > GetRouteToFloor(int StartingFloor, int DestinationFloor, bool service_access=false)
Definition route.cpp:40
ElevatorRoute * GetDirectRoute(Floor *floor, int DestinationFloor, bool service_access=false)
Definition route.cpp:106
std::vector< ElevatorRoute * > GetIndirectRoute(std::vector< int > &checked_floors, int StartingFloor, int DestinationFloor, bool service_access=false, bool top_level=true)
Definition route.cpp:133
#define SBS_PROFILE(name)
Definition profiler.h:131
int floor_selection
Definition route.h:34
ElevatorRoute(ElevatorCar *car, int floor_selection)
Definition route.cpp:34
ElevatorCar * car
Definition route.h:33