author | tron |
Mon, 14 Feb 2005 18:55:10 +0000 | |
changeset 1370 | c86b2c30fd01 |
parent 1339 | 40e00c692996 |
child 1452 | a978fdcbca3e |
permissions | -rw-r--r-- |
1247 | 1 |
#include "stdafx.h" |
2 |
#include "ttd.h" |
|
1299
39c06aba09aa
(svn r1803) Move debugging stuff into files of it's own
tron
parents:
1248
diff
changeset
|
3 |
#include "debug.h" |
1247 | 4 |
#include "npf.h" |
5 |
#include "aystar.h" |
|
6 |
#include "macros.h" |
|
7 |
#include "pathfind.h" |
|
8 |
#include "station.h" |
|
9 |
#include "tile.h" |
|
1313
f1013ec3d318
(svn r1817) -Codechange: Moved depot-functions to depot.c
truelight
parents:
1299
diff
changeset
|
10 |
#include "depot.h" |
1247 | 11 |
|
12 |
AyStar _train_find_station; |
|
13 |
AyStar _train_find_depot; |
|
14 |
AyStar _road_find_station; |
|
15 |
AyStar _road_find_depot; |
|
16 |
AyStar _npf_aystar; |
|
17 |
||
18 |
/* Maps a trackdir to the bit that stores its status in the map arrays, in the |
|
19 |
* direction along with the trackdir */ |
|
20 |
const byte _signal_along_trackdir[14] = { |
|
21 |
0x80, 0x80, 0x80, 0x20, 0x40, 0x10, 0, 0, |
|
22 |
0x40, 0x40, 0x40, 0x10, 0x80, 0x20 |
|
23 |
}; |
|
24 |
||
25 |
/* Maps a trackdir to the bit that stores its status in the map arrays, in the |
|
26 |
* direction against the trackdir */ |
|
27 |
const byte _signal_against_trackdir[14] = { |
|
28 |
0x40, 0x40, 0x40, 0x10, 0x80, 0x20, 0, 0, |
|
29 |
0x80, 0x80, 0x80, 0x20, 0x40, 0x10 |
|
30 |
}; |
|
31 |
||
32 |
/* Maps a trackdir to the trackdirs that can be reached from it (ie, when |
|
33 |
* entering the next tile */ |
|
34 |
const uint16 _trackdir_reaches_trackdirs[14] = { |
|
35 |
0x1009, 0x0016, 0x1009, 0x0016, 0x0520, 0x0016, 0, 0, |
|
36 |
0x0520, 0x2A00, 0x2A00, 0x0520, 0x2A00, 0x1009 |
|
37 |
}; |
|
38 |
||
39 |
/* Maps a trackdir to all trackdirs that make 90 deg turns with it. */ |
|
40 |
const uint16 _trackdir_crosses_trackdirs[14] = { |
|
41 |
0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C, 0, 0, |
|
42 |
0x0202, 0x0101, 0x3030, 0x3030, 0x0C0C, 0x0C0C |
|
43 |
}; |
|
44 |
||
45 |
/* Maps a track to all tracks that make 90 deg turns with it. */ |
|
46 |
const byte _track_crosses_tracks[6] = { |
|
47 |
0x2, /* Track 1 -> Track 2 */ |
|
48 |
0x1, /* Track 2 -> Track 1 */ |
|
49 |
0x30, /* Upper -> Left | Right */ |
|
50 |
0x30, /* Lower -> Left | Right */ |
|
51 |
0x0C, /* Left -> Upper | Lower */ |
|
52 |
0x0C, /* Right -> Upper | Lower */ |
|
53 |
}; |
|
54 |
||
55 |
/* Maps a trackdir to the (4-way) direction the tile is exited when following |
|
56 |
* that trackdir */ |
|
57 |
const byte _trackdir_to_exitdir[14] = { |
|
58 |
0,1,0,1,2,1, 0,0, |
|
59 |
2,3,3,2,3,0, |
|
60 |
}; |
|
61 |
||
62 |
const byte _track_exitdir_to_trackdir[6][4] = { |
|
63 |
{0, 0xff, 8, 0xff}, |
|
64 |
{0xff, 1, 0xff, 9}, |
|
65 |
{2, 0xff, 0xff, 10}, |
|
66 |
{0xff, 3, 11, 0xf}, |
|
67 |
{0xff, 0xff, 4, 12}, |
|
68 |
{13, 5, 0xff, 0xff} |
|
69 |
}; |
|
70 |
||
71 |
const byte _track_direction_to_trackdir[6][8] = { |
|
72 |
{0xff, 0, 0xff, 0xff, 0xff, 8, 0xff, 0xff}, |
|
73 |
{0xff, 0xff, 0xff, 1, 0xff, 0xff, 0xff, 9}, |
|
74 |
{0xff, 0xff, 2, 0xff, 0xff, 0xff, 10, 0xff}, |
|
75 |
{0xff, 0xff, 3, 0xff, 0xff, 0xff, 11, 0xff}, |
|
76 |
{12, 0xff, 0xff, 0xff, 4, 0xff, 0xff, 0xff}, |
|
77 |
{13, 0xff, 0xff, 0xff, 5, 0xff, 0xff, 0xff} |
|
78 |
}; |
|
79 |
||
80 |
const byte _dir_to_diag_trackdir[4] = { |
|
81 |
0, 1, 8, 9, |
|
82 |
}; |
|
83 |
||
84 |
const byte _reverse_dir[4] = { |
|
85 |
2, 3, 0, 1 |
|
86 |
}; |
|
87 |
||
88 |
const byte _reverse_trackdir[14] = { |
|
89 |
8, 9, 10, 11, 12, 13, 0xFF, 0xFF, |
|
90 |
0, 1, 2, 3, 4, 5 |
|
91 |
}; |
|
92 |
||
93 |
/* The cost of each trackdir. A diagonal piece is the full NPF_TILE_LENGTH, |
|
94 |
* the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071 |
|
95 |
*/ |
|
96 |
#define NPF_STRAIGHT_LENGTH (uint)(NPF_TILE_LENGTH * 0.7071) |
|
97 |
static const uint _trackdir_length[14] = { |
|
98 |
NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, 0, 0, |
|
99 |
NPF_TILE_LENGTH, NPF_TILE_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH, NPF_STRAIGHT_LENGTH |
|
100 |
}; |
|
101 |
||
102 |
uint NTPHash(uint key1, uint key2) |
|
103 |
{ |
|
104 |
return PATHFIND_HASH_TILE(key1); |
|
105 |
} |
|
106 |
||
107 |
int32 NPFCalcZero(AyStar* as, AyStarNode* current, OpenListNode* parent) { |
|
108 |
return 0; |
|
109 |
} |
|
110 |
||
111 |
/* Calcs the heuristic to the target station (using NPFFindStationOrTileData). After |
|
112 |
* will save the heuristic into NPFFoundTargetData if it is the smallest until |
|
113 |
* now. It will then also save AyStarNode.user_data[NPF_TRACKDIR_CHOICE] in |
|
114 |
* best_trackdir |
|
115 |
*/ |
|
116 |
int32 NPFCalcStationOrTileHeuristic(AyStar* as, AyStarNode* current, OpenListNode* parent) { |
|
117 |
NPFFindStationOrTileData* fstd = (NPFFindStationOrTileData*)as->user_target; |
|
118 |
NPFFoundTargetData* ftd = (NPFFoundTargetData*)as->user_path; |
|
119 |
TileIndex from = current->tile; |
|
120 |
TileIndex to = fstd->dest_coords; |
|
121 |
uint dist = DistanceManhattan(from, to) * NPF_TILE_LENGTH; |
|
122 |
||
123 |
if (dist < ftd->best_bird_dist) { |
|
124 |
ftd->best_bird_dist = dist; |
|
125 |
ftd->best_trackdir = current->user_data[NPF_TRACKDIR_CHOICE]; |
|
126 |
} |
|
127 |
#ifdef NPF_DEBUG |
|
128 |
debug("Calculating H for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), dist); |
|
129 |
#endif |
|
130 |
return dist; |
|
131 |
} |
|
132 |
||
133 |
/* Fills AyStarNode.user_data[NPF_TRACKDIRCHOICE] with the chosen direction to |
|
134 |
* get here, either getting it from the current choice or from the parent's |
|
135 |
* choice */ |
|
136 |
void NPFFillTrackdirChoice(AyStarNode* current, OpenListNode* parent) |
|
137 |
{ |
|
138 |
if (parent->path.parent == NULL) { |
|
139 |
byte trackdir = current->direction; |
|
140 |
/* This is a first order decision, so we'd better save the |
|
141 |
* direction we chose */ |
|
142 |
current->user_data[NPF_TRACKDIR_CHOICE] = trackdir; |
|
143 |
#ifdef NPF_DEBUG |
|
144 |
debug("Saving trackdir: %#x", trackdir); |
|
145 |
#endif |
|
146 |
} else { |
|
147 |
/* We've already made the decision, so just save our parent's |
|
148 |
* decision */ |
|
149 |
current->user_data[NPF_TRACKDIR_CHOICE] = parent->path.node.user_data[NPF_TRACKDIR_CHOICE]; |
|
150 |
} |
|
151 |
||
152 |
} |
|
153 |
||
154 |
/* Will return the cost of the tunnel. If it is an entry, it will return the |
|
155 |
* cost of that tile. If the tile is an exit, it will return the tunnel length |
|
156 |
* including the exit tile. Requires that this is a Tunnel tile */ |
|
157 |
uint NPFTunnelCost(AyStarNode* current) { |
|
158 |
byte exitdir = _trackdir_to_exitdir[current->direction]; |
|
159 |
TileIndex tile = current->tile; |
|
160 |
if ( (uint)(_map5[tile] & 3) == _reverse_dir[exitdir]) { |
|
161 |
/* We just popped out if this tunnel, since were |
|
162 |
* facing the tunnel exit */ |
|
163 |
FindLengthOfTunnelResult flotr; |
|
164 |
flotr = FindLengthOfTunnel(tile, _reverse_dir[exitdir]); |
|
165 |
return flotr.length * NPF_TILE_LENGTH; |
|
166 |
//TODO: Penalty for tunnels? |
|
167 |
} else { |
|
168 |
/* We are entering the tunnel, the enter tile is just a |
|
169 |
* straight track */ |
|
170 |
return NPF_TILE_LENGTH; |
|
171 |
} |
|
172 |
} |
|
173 |
||
174 |
uint NPFSlopeCost(AyStarNode* current) { |
|
175 |
TileIndex next = current->tile + TileOffsByDir(_trackdir_to_exitdir[current->direction]); |
|
176 |
if (GetTileZ(next) > GetTileZ(current->tile)) { |
|
177 |
/* Slope up */ |
|
178 |
return _patches.npf_rail_slope_penalty; |
|
179 |
} |
|
180 |
return 0; |
|
181 |
/* Should we give a bonus for slope down? Probably not, we |
|
182 |
* could just substract that bonus from the penalty, because |
|
183 |
* there is only one level of steepness... */ |
|
184 |
} |
|
185 |
||
186 |
void NPFMarkTile(TileIndex tile) { |
|
187 |
switch(GetTileType(tile)) { |
|
188 |
case MP_RAILWAY: |
|
189 |
case MP_STREET: |
|
190 |
/* DEBUG: mark visited tiles by mowing the grass under them |
|
191 |
* ;-) */ |
|
192 |
_map2[tile] &= ~15; |
|
193 |
MarkTileDirtyByTile(tile); |
|
194 |
break; |
|
195 |
default: |
|
196 |
break; |
|
197 |
} |
|
198 |
} |
|
199 |
||
200 |
int32 NPFWaterPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) { |
|
201 |
//TileIndex tile = current->tile; |
|
202 |
int32 cost = 0; |
|
203 |
byte trackdir = current->direction; |
|
204 |
||
205 |
cost = _trackdir_length[trackdir]; /* Should be different for diagonal tracks */ |
|
206 |
||
207 |
/* TODO Penalties? */ |
|
208 |
||
209 |
return cost; |
|
210 |
} |
|
211 |
||
212 |
/* Determine the cost of this node, for road tracks */ |
|
213 |
int32 NPFRoadPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) { |
|
214 |
TileIndex tile = current->tile; |
|
215 |
int32 cost = 0; |
|
216 |
/* Determine base length */ |
|
217 |
switch (GetTileType(tile)) { |
|
218 |
case MP_TUNNELBRIDGE: |
|
219 |
if ((_map5[tile] & 0xF0)==0) { |
|
220 |
cost = NPFTunnelCost(current); |
|
221 |
break; |
|
222 |
} |
|
223 |
/* Fall through if above if is false, it is a bridge |
|
224 |
* then. We treat that as ordinary rail */ |
|
225 |
case MP_STREET: |
|
226 |
cost = NPF_TILE_LENGTH; |
|
227 |
break; |
|
228 |
default: |
|
229 |
break; |
|
230 |
} |
|
231 |
||
232 |
/* Determine extra costs */ |
|
233 |
||
234 |
/* Check for slope */ |
|
235 |
cost += NPFSlopeCost(current); |
|
236 |
||
237 |
/* Check for turns */ |
|
238 |
//TODO |
|
239 |
||
240 |
#ifdef NPF_MARKROUTE |
|
241 |
NPFMarkTile(tile); |
|
242 |
#endif |
|
243 |
#ifdef NPF_DEBUG |
|
244 |
debug("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost); |
|
245 |
#endif |
|
246 |
return cost; |
|
247 |
} |
|
248 |
||
249 |
||
250 |
/* Determine the cost of this node, for railway tracks */ |
|
251 |
int32 NPFRailPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) { |
|
252 |
TileIndex tile = current->tile; |
|
253 |
byte trackdir = current->direction; |
|
254 |
int32 cost = 0; |
|
255 |
/* Determine base length */ |
|
256 |
switch (GetTileType(tile)) { |
|
257 |
case MP_TUNNELBRIDGE: |
|
258 |
if ((_map5[tile] & 0xF0)==0) { |
|
259 |
cost = NPFTunnelCost(current); |
|
260 |
break; |
|
261 |
} |
|
262 |
/* Fall through if above if is false, it is a bridge |
|
263 |
* then. We treat that as ordinary rail */ |
|
264 |
case MP_RAILWAY: |
|
265 |
cost = _trackdir_length[trackdir]; /* Should be different for diagonal tracks */ |
|
266 |
break; |
|
267 |
case MP_STREET: /* Railway crossing */ |
|
268 |
cost = NPF_TILE_LENGTH; |
|
269 |
break; |
|
270 |
default: |
|
271 |
break; |
|
272 |
} |
|
273 |
||
274 |
/* Determine extra costs */ |
|
275 |
||
276 |
/* Ordinary track with signals */ |
|
277 |
if (IsTileType(tile, MP_RAILWAY) && (_map5[tile] & 0xC0) == 0x40) { |
|
278 |
if ((_map2[tile] & _signal_along_trackdir[trackdir]) == 0) { |
|
279 |
/* Signal facing us is red */ |
|
280 |
if (!(current->user_data[NPF_NODE_FLAGS] & NPF_FLAG_SEEN_SIGNAL)) { |
|
281 |
/* Penalize the first signal we |
|
282 |
* encounter, if it is red */ |
|
283 |
cost += _patches.npf_rail_firstred_penalty; |
|
284 |
} |
|
285 |
} |
|
286 |
current->user_data[NPF_NODE_FLAGS] |= NPF_FLAG_SEEN_SIGNAL; |
|
287 |
} |
|
288 |
||
289 |
/* Check for slope */ |
|
290 |
cost += NPFSlopeCost(current); |
|
291 |
||
292 |
/* Check for turns */ |
|
293 |
//TODO |
|
294 |
||
295 |
/* Check for occupied track */ |
|
296 |
//TODO |
|
297 |
||
298 |
/* Check for station tiles */ |
|
299 |
if (IsTileType(tile, MP_STATION)) { |
|
300 |
/* We give a station tile a penalty. Logically we would only |
|
301 |
* want to give station tiles that are not our destination |
|
302 |
* this penalty. This would discourage trains to drive through |
|
303 |
* busy stations. But, we can just give any station tile a |
|
304 |
* penalty, because every possible route will get this penalty |
|
305 |
* exactly once, on its end tile (if it's a station) and it |
|
306 |
* will therefore not make a difference. */ |
|
307 |
cost += _patches.npf_rail_station_penalty; |
|
308 |
} |
|
309 |
||
310 |
#ifdef NPF_MARKROUTE |
|
311 |
NPFMarkTile(tile); |
|
312 |
#endif |
|
313 |
#ifdef NPF_DEBUG |
|
314 |
debug("Calculating G for: (%d, %d). Result: %d", TileX(current->tile), TileY(current->tile), cost); |
|
315 |
#endif |
|
316 |
return cost; |
|
317 |
} |
|
318 |
||
319 |
/* Will find any depot */ |
|
320 |
int32 NPFFindDepot(AyStar* as, OpenListNode *current) { |
|
321 |
TileIndex tile = current->path.node.tile; |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
322 |
if (IsTileDepotType(tile, as->user_data[NPF_TYPE])) |
1247 | 323 |
return AYSTAR_FOUND_END_NODE; |
324 |
else |
|
325 |
return AYSTAR_DONE; |
|
326 |
} |
|
327 |
||
328 |
/* Will find a station identified using the NPFFindStationOrTileData */ |
|
329 |
int32 NPFFindStationOrTile(AyStar* as, OpenListNode *current) { |
|
330 |
/* If GetNeighbours said we could get here, we assume the station type |
|
331 |
* is correct */ |
|
332 |
NPFFindStationOrTileData* fstd = (NPFFindStationOrTileData*)as->user_target; |
|
333 |
TileIndex tile = current->path.node.tile; |
|
334 |
if ( (fstd->station_index == -1 && tile == fstd->dest_coords) || /* We've found the tile, or */ |
|
335 |
(IsTileType(tile, MP_STATION) && _map2[tile] == fstd->station_index) /* the station */ |
|
336 |
) |
|
337 |
return AYSTAR_FOUND_END_NODE; |
|
338 |
else |
|
339 |
return AYSTAR_DONE; |
|
340 |
} |
|
341 |
||
342 |
/* To be called when current contains the (shortest route to) the target node. |
|
343 |
* Will fill the contents of the NPFFoundTargetData using |
|
344 |
* AyStarNode[NPF_TRACKDIR_CHOICE]. |
|
345 |
*/ |
|
346 |
void NPFSaveTargetData(AyStar* as, OpenListNode* current) { |
|
347 |
NPFFoundTargetData* ftd = (NPFFoundTargetData*)as->user_path; |
|
348 |
ftd->best_trackdir = current->path.node.user_data[NPF_TRACKDIR_CHOICE]; |
|
349 |
ftd->best_path_dist = current->g; |
|
350 |
ftd->best_bird_dist = 0; |
|
351 |
ftd->node = current->path.node; |
|
352 |
} |
|
353 |
||
354 |
/* Will just follow the results of GetTileTrackStatus concerning where we can |
|
355 |
* go and where not. Uses AyStar.user_data[NPF_TYPE] as the transport type and |
|
356 |
* an argument to GetTileTrackStatus. Will skip tunnels, meaning that the |
|
357 |
* entry and exit are neighbours. Will fill AyStarNode.user_data[NPF_TRACKDIR_CHOICE] with an |
|
358 |
* appropriate value, and copy AyStarNode.user_data[NPF_NODE_FLAGS] from the |
|
359 |
* parent */ |
|
360 |
void NPFFollowTrack(AyStar* aystar, OpenListNode* current) { |
|
361 |
byte src_trackdir = current->path.node.direction; |
|
362 |
TileIndex src_tile = current->path.node.tile; |
|
363 |
byte src_exitdir = _trackdir_to_exitdir[src_trackdir]; |
|
364 |
FindLengthOfTunnelResult flotr; |
|
365 |
TileIndex dst_tile; |
|
366 |
int i = 0; |
|
367 |
uint trackdirs, ts; |
|
368 |
TransportType type = aystar->user_data[NPF_TYPE]; |
|
369 |
/* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */ |
|
370 |
aystar->num_neighbours = 0; |
|
371 |
#ifdef NPF_DEBUG |
|
372 |
debug("Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile); |
|
373 |
#endif |
|
374 |
||
375 |
/* Find dest tile */ |
|
376 |
if (IsTileType(src_tile, MP_TUNNELBRIDGE) && (_map5[src_tile] & 0xF0)==0 && (_map5[src_tile] & 3) == src_exitdir) { |
|
377 |
/* This is a tunnel. We know this tunnel is our type, |
|
378 |
* otherwise we wouldn't have got here. It is also facing us, |
|
379 |
* so we should skip it's body */ |
|
380 |
flotr = FindLengthOfTunnel(src_tile, src_exitdir); |
|
381 |
dst_tile = flotr.tile; |
|
382 |
} else { |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
383 |
if (IsTileDepotType(src_tile, type)){ |
1247 | 384 |
/* This is a road station or a train or road depot. We can enter and exit |
385 |
* those from one side only. Trackdirs don't support that (yet), so we'll |
|
386 |
* do this here. */ |
|
387 |
||
388 |
byte exitdir; |
|
389 |
/* Find out the exit direction first */ |
|
390 |
if (IsRoadStationTile(src_tile)) |
|
391 |
exitdir = GetRoadStationDir(src_tile); |
|
392 |
else /* Train or road depot. Direction is stored the same for both, in map5 */ |
|
393 |
exitdir = _map5[src_tile] & 3; /* Extract the direction from the map */ |
|
394 |
||
395 |
/* Let's see if were headed the right way */ |
|
396 |
if (src_trackdir != _dir_to_diag_trackdir[exitdir]) |
|
397 |
/* Not going out of the station/depot through the exit, but the back. No |
|
398 |
* neighbours then. */ |
|
399 |
return; |
|
400 |
} |
|
401 |
/* This a normal tile, a bridge, a tunnel exit, etc. */ |
|
402 |
dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDir(_trackdir_to_exitdir[src_trackdir])); |
|
403 |
if (dst_tile == INVALID_TILE) { |
|
404 |
/* We reached the border of the map */ |
|
405 |
/* TODO Nicer control flow for this */ |
|
406 |
return; |
|
407 |
} |
|
408 |
} |
|
409 |
||
410 |
// TODO: check correct rail type (mono, maglev, etc) |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
411 |
|
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
412 |
/* Check the owner of the tile */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
413 |
if ( |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
414 |
IsTileType(dst_tile, MP_RAILWAY) /* Rail tile */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
415 |
|| IsTileDepotType(dst_tile, TRANSPORT_ROAD) /* Road depot tile */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
416 |
|| IsTileType(dst_tile, MP_STATION) /* Station tile */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
417 |
|| IsTileDepotType(dst_tile, TRANSPORT_WATER) /* Water depot tile */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
418 |
) /* TODO: Crossings, tunnels and bridges are "public" now */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
419 |
/* The above cases are "private" tiles, we need to check the owner */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
420 |
if (!IsTileOwner(dst_tile, aystar->user_data[NPF_OWNER])) |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
421 |
return; |
1247 | 422 |
|
423 |
/* Determine available tracks */ |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
424 |
if (type == TRANSPORT_ROAD && (IsRoadStationTile(dst_tile) || IsTileDepotType(dst_tile, TRANSPORT_ROAD))){ |
1247 | 425 |
/* Road stations and depots return 0 on GTTS, so we have to do this by hand... */ |
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
426 |
byte exitdir; |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
427 |
if (IsRoadStationTile(dst_tile)) |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
428 |
exitdir = GetRoadStationDir(dst_tile); |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
429 |
else /* Road depot */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
430 |
/* Find the trackdirs that are available for a depot with this orientation. They are in both directions */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
431 |
exitdir = _map5[dst_tile] & 3; /* Extract the direction from the map */ |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
432 |
ts = (1 << _dir_to_diag_trackdir[exitdir]) |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
433 |
| (1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]); |
1247 | 434 |
} else { |
435 |
ts = GetTileTrackStatus(dst_tile, type); |
|
436 |
} |
|
437 |
trackdirs = ts & 0x3F3F; /* Filter out signal status and the unused bits */ |
|
438 |
||
439 |
#ifdef NPF_DEBUG |
|
440 |
debug("Next node: (%d, %d) [%d], possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirs); |
|
441 |
#endif |
|
442 |
/* Select only trackdirs we can reach from our current trackdir */ |
|
443 |
trackdirs &= _trackdir_reaches_trackdirs[src_trackdir]; |
|
444 |
if (_patches.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) /* Filter out trackdirs that would make 90 deg turns for trains */ |
|
445 |
trackdirs &= ~_trackdir_crosses_trackdirs[src_trackdir]; |
|
446 |
#ifdef NPF_DEBUG |
|
447 |
debug("After filtering: (%d, %d), possible trackdirs: %#x", TileX(dst_tile), TileY(dst_tile), trackdirs); |
|
448 |
#endif |
|
449 |
||
450 |
/* Enumerate possible track */ |
|
451 |
while (trackdirs != 0) { |
|
452 |
byte dst_trackdir; |
|
453 |
dst_trackdir = FindFirstBit2x64(trackdirs); |
|
454 |
trackdirs = KillFirstBit2x64(trackdirs); |
|
455 |
#ifdef NPF_DEBUG |
|
456 |
debug("Expanded into trackdir: %d, remaining trackdirs: %#x", dst_trackdir, trackdirs); |
|
457 |
#endif |
|
458 |
||
459 |
/* Check for oneway signal against us */ |
|
460 |
if (IsTileType(dst_tile, MP_RAILWAY) && (_map5[dst_tile]&0xC0) == 0x40) { |
|
461 |
// the tile has a signal |
|
462 |
byte signal_present = _map3_lo[dst_tile]; |
|
463 |
if (!(signal_present & _signal_along_trackdir[dst_trackdir])) { |
|
464 |
// if one way signal not pointing towards us, stop going in this direction. |
|
465 |
if (signal_present & _signal_against_trackdir[dst_trackdir]) |
|
466 |
break; |
|
467 |
} |
|
468 |
} |
|
469 |
{ |
|
470 |
/* We've found ourselves a neighbour :-) */ |
|
471 |
AyStarNode* neighbour = &aystar->neighbours[i]; |
|
472 |
neighbour->tile = dst_tile; |
|
473 |
neighbour->direction = dst_trackdir; |
|
474 |
/* Save user data */ |
|
475 |
neighbour->user_data[NPF_NODE_FLAGS] = current->path.node.user_data[NPF_NODE_FLAGS]; |
|
476 |
NPFFillTrackdirChoice(neighbour, current); |
|
477 |
} |
|
478 |
i++; |
|
479 |
} |
|
480 |
aystar->num_neighbours = i; |
|
481 |
} |
|
482 |
||
483 |
/* |
|
484 |
* Plan a route to the specified target (which is checked by target_proc), |
|
485 |
* from start1 and if not NULL, from start2 as well. The type of transport we |
|
486 |
* are checking is in type. |
|
487 |
* When we are looking for one specific target (optionally multiple tiles), we |
|
488 |
* should use a good heuristic to perform aystar search. When we search for |
|
489 |
* multiple targets that are spread around, we should perform a breadth first |
|
490 |
* search by specifiying CalcZero as our heuristic. |
|
491 |
*/ |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
492 |
NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner) { |
1247 | 493 |
int r; |
494 |
NPFFoundTargetData result; |
|
495 |
||
496 |
/* Initialize procs */ |
|
497 |
_npf_aystar.CalculateH = heuristic_proc; |
|
498 |
_npf_aystar.EndNodeCheck = target_proc; |
|
499 |
_npf_aystar.FoundEndNode = NPFSaveTargetData; |
|
500 |
_npf_aystar.GetNeighbours = NPFFollowTrack; |
|
501 |
if (type == TRANSPORT_RAIL) |
|
502 |
_npf_aystar.CalculateG = NPFRailPathCost; |
|
503 |
else if (type == TRANSPORT_ROAD) |
|
504 |
_npf_aystar.CalculateG = NPFRoadPathCost; |
|
505 |
else if (type == TRANSPORT_WATER) |
|
506 |
_npf_aystar.CalculateG = NPFWaterPathCost; |
|
507 |
else |
|
508 |
assert(0); |
|
509 |
||
510 |
/* Initialize Start Node(s) */ |
|
511 |
start1->user_data[NPF_TRACKDIR_CHOICE] = 0xff; |
|
512 |
start1->user_data[NPF_NODE_FLAGS] = 0; |
|
513 |
_npf_aystar.addstart(&_npf_aystar, start1); |
|
514 |
if (start2) { |
|
515 |
start2->user_data[NPF_TRACKDIR_CHOICE] = 0xff; |
|
516 |
start2->user_data[NPF_NODE_FLAGS] = NPF_FLAG_REVERSE; |
|
517 |
_npf_aystar.addstart(&_npf_aystar, start2); |
|
518 |
} |
|
519 |
||
520 |
/* Initialize result */ |
|
521 |
result.best_bird_dist = (uint)-1; |
|
522 |
result.best_path_dist = (uint)-1; |
|
523 |
result.best_trackdir = 0xff; |
|
524 |
_npf_aystar.user_path = &result; |
|
525 |
||
526 |
/* Initialize target */ |
|
527 |
_npf_aystar.user_target = target; |
|
528 |
||
529 |
/* Initialize user_data */ |
|
530 |
_npf_aystar.user_data[NPF_TYPE] = type; |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
531 |
_npf_aystar.user_data[NPF_OWNER] = owner; |
1247 | 532 |
|
533 |
/* GO! */ |
|
534 |
r = AyStarMain_Main(&_npf_aystar); |
|
535 |
assert(r != AYSTAR_STILL_BUSY); |
|
536 |
||
537 |
if (result.best_bird_dist != 0) { |
|
538 |
if (target) { |
|
539 |
DEBUG(misc, 1) ("NPF: Could not find route to 0x%x from 0x%x.", target->dest_coords, start1->tile); |
|
540 |
} else { |
|
541 |
/* Assumption: target == NULL, so we are looking for a depot */ |
|
542 |
DEBUG(misc, 1) ("NPF: Could not find route to a depot from 0x%x.", start1->tile); |
|
543 |
} |
|
544 |
||
545 |
} |
|
546 |
return result; |
|
547 |
} |
|
548 |
||
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
549 |
NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner) { |
1247 | 550 |
AyStarNode start1; |
551 |
AyStarNode start2; |
|
552 |
||
553 |
start1.tile = tile1; |
|
554 |
start2.tile = tile2; |
|
555 |
start1.direction = trackdir1; |
|
556 |
start2.direction = trackdir2; |
|
557 |
||
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
558 |
return NPFRouteInternal(&start1, &start2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner); |
1247 | 559 |
} |
560 |
||
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
561 |
NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner) { |
1247 | 562 |
AyStarNode start; |
563 |
||
564 |
assert(tile != 0); |
|
565 |
||
566 |
start.tile = tile; |
|
567 |
start.direction = trackdir; |
|
568 |
/* We set this in case the target is also the start tile, we will just |
|
569 |
* return a not found then */ |
|
570 |
start.user_data[NPF_TRACKDIR_CHOICE] = 0xff; |
|
571 |
||
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
572 |
return NPFRouteInternal(&start, NULL, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner); |
1247 | 573 |
} |
574 |
||
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
575 |
NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner) { |
1247 | 576 |
AyStarNode start; |
577 |
||
578 |
start.tile = tile; |
|
579 |
start.direction = trackdir; |
|
580 |
/* We set this in case the target is also the start tile, we will just |
|
581 |
* return a not found then */ |
|
582 |
start.user_data[NPF_TRACKDIR_CHOICE] = 0xff; |
|
583 |
||
584 |
/* perform a breadth first search. Target is NULL, |
|
585 |
* since we are just looking for any depot...*/ |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
586 |
return NPFRouteInternal(&start, NULL, NULL, NPFFindDepot, NPFCalcZero, type, owner); |
1247 | 587 |
} |
588 |
||
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
589 |
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner) { |
1247 | 590 |
/* Okay, what we're gonna do. First, we look at all depots, calculate |
591 |
* the manhatten distance to get to each depot. We then sort them by |
|
592 |
* distance. We start by trying to plan a route to the closest, then |
|
593 |
* the next closest, etc. We stop when the best route we have found so |
|
594 |
* far, is shorter than the manhattan distance. This will obviously |
|
595 |
* always find the closest depot. It will probably be most efficient |
|
596 |
* for ships, since the heuristic will not be to far off then. I hope. |
|
597 |
*/ |
|
598 |
Queue depots; |
|
599 |
int r; |
|
600 |
NPFFoundTargetData best_result; |
|
601 |
NPFFoundTargetData result; |
|
602 |
NPFFindStationOrTileData target; |
|
603 |
AyStarNode start; |
|
604 |
Depot* current; |
|
1313
f1013ec3d318
(svn r1817) -Codechange: Moved depot-functions to depot.c
truelight
parents:
1299
diff
changeset
|
605 |
Depot *depot; |
1247 | 606 |
|
607 |
init_InsSort(&depots); |
|
608 |
/* Okay, let's find all depots that we can use first */ |
|
1313
f1013ec3d318
(svn r1817) -Codechange: Moved depot-functions to depot.c
truelight
parents:
1299
diff
changeset
|
609 |
FOR_ALL_DEPOTS(depot) { |
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
610 |
/* Check if this is really a valid depot, it is of the needed type and |
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
611 |
* owner */ |
1338 | 612 |
if (IsValidDepot(depot) && IsTileDepotType(depot->xy, type) && IsTileOwner(depot->xy, owner)) |
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
613 |
/* If so, let's add it to the queue, sorted by distance */ |
1313
f1013ec3d318
(svn r1817) -Codechange: Moved depot-functions to depot.c
truelight
parents:
1299
diff
changeset
|
614 |
depots.push(&depots, depot, DistanceManhattan(tile, depot->xy)); |
1247 | 615 |
} |
616 |
||
617 |
/* Now, let's initialise the aystar */ |
|
618 |
||
619 |
/* Initialize procs */ |
|
620 |
_npf_aystar.CalculateH = NPFCalcStationOrTileHeuristic; |
|
621 |
_npf_aystar.EndNodeCheck = NPFFindStationOrTile; |
|
622 |
_npf_aystar.FoundEndNode = NPFSaveTargetData; |
|
623 |
_npf_aystar.GetNeighbours = NPFFollowTrack; |
|
624 |
if (type == TRANSPORT_RAIL) |
|
625 |
_npf_aystar.CalculateG = NPFRailPathCost; |
|
626 |
else if (type == TRANSPORT_ROAD) |
|
627 |
_npf_aystar.CalculateG = NPFRoadPathCost; |
|
628 |
else if (type == TRANSPORT_WATER) |
|
629 |
_npf_aystar.CalculateG = NPFWaterPathCost; |
|
630 |
else |
|
631 |
assert(0); |
|
632 |
||
633 |
/* Initialize target */ |
|
634 |
target.station_index = -1; /* We will initialize dest_coords inside the loop below */ |
|
635 |
_npf_aystar.user_target = ⌖ |
|
636 |
||
637 |
/* Initialize user_data */ |
|
638 |
_npf_aystar.user_data[NPF_TYPE] = type; |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
639 |
_npf_aystar.user_data[NPF_OWNER] = owner; |
1247 | 640 |
|
641 |
/* Initialize Start Node */ |
|
642 |
start.tile = tile; |
|
643 |
start.direction = trackdir; /* We will initialize user_data inside the loop below */ |
|
644 |
||
645 |
/* Initialize Result */ |
|
646 |
_npf_aystar.user_path = &result; |
|
647 |
best_result.best_path_dist = (uint)-1; |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
648 |
best_result.best_bird_dist = (uint)-1; |
1247 | 649 |
|
650 |
/* Just iterate the depots in order of increasing distance */ |
|
651 |
while ((current = depots.pop(&depots))) { |
|
652 |
/* Check to see if we already have a path shorter than this |
|
1330
5d76a0522a11
(svn r1834) - Fix: NPF does not check the owner of its target, busses try to enter other players' depots. TODO
matthijs
parents:
1313
diff
changeset
|
653 |
* depot's manhattan distance. HACK: We call DistanceManhattan |
1247 | 654 |
* again, we should probably modify the queue to give us that |
655 |
* value... */ |
|
656 |
if ( DistanceManhattan(tile, current->xy * NPF_TILE_LENGTH) > best_result.best_path_dist) |
|
657 |
break; |
|
658 |
||
659 |
/* Initialize Start Node */ |
|
660 |
/* We set this in case the target is also the start tile, we will just |
|
661 |
* return a not found then */ |
|
662 |
start.user_data[NPF_TRACKDIR_CHOICE] = 0xff; |
|
663 |
start.user_data[NPF_NODE_FLAGS] = 0; |
|
664 |
_npf_aystar.addstart(&_npf_aystar, &start); |
|
665 |
||
666 |
/* Initialize result */ |
|
667 |
result.best_bird_dist = (uint)-1; |
|
668 |
result.best_path_dist = (uint)-1; |
|
669 |
result.best_trackdir = 0xff; |
|
670 |
||
671 |
/* Initialize target */ |
|
672 |
target.dest_coords = current->xy; |
|
673 |
||
674 |
/* GO! */ |
|
675 |
r = AyStarMain_Main(&_npf_aystar); |
|
676 |
assert(r != AYSTAR_STILL_BUSY); |
|
677 |
||
678 |
/* This depot is closer */ |
|
679 |
if (result.best_path_dist < best_result.best_path_dist) |
|
680 |
best_result = result; |
|
681 |
} |
|
682 |
if (result.best_bird_dist != 0) { |
|
683 |
DEBUG(misc, 1) ("NPF: Could not find route to any depot from 0x%x.", tile); |
|
684 |
} |
|
685 |
return best_result; |
|
686 |
} |
|
687 |
||
688 |
void InitializeNPF(void) |
|
689 |
{ |
|
690 |
init_AyStar(&_npf_aystar, NTPHash, 1024); |
|
691 |
_npf_aystar.loops_per_tick = 0; |
|
692 |
_npf_aystar.max_path_cost = 0; |
|
693 |
_npf_aystar.max_search_nodes = 0; |
|
694 |
/* |
|
695 |
init_AyStar(&_train_find_station, NTPHash, 1024); |
|
696 |
init_AyStar(&_train_find_depot, NTPHash, 1024); |
|
697 |
init_AyStar(&_road_find_station, NTPHash, 1024); |
|
698 |
init_AyStar(&_road_find_depot, NTPHash, 1024); |
|
699 |
||
700 |
_train_find_station.loops_per_tick = 0; |
|
701 |
_train_find_depot.loops_per_tick = 0; |
|
702 |
_road_find_station.loops_per_tick = 0; |
|
703 |
_road_find_depot.loops_per_tick = 0; |
|
704 |
||
705 |
_train_find_station.max_path_cost = 0; |
|
706 |
_train_find_depot.max_path_cost = 0; |
|
707 |
_road_find_station.max_path_cost = 0; |
|
708 |
_road_find_depot.max_path_cost = 0; |
|
709 |
||
710 |
_train_find_station.max_search_nodes = 0; |
|
711 |
_train_find_depot.max_search_nodes = 0; |
|
712 |
_road_find_station.max_search_nodes = 0; |
|
713 |
_road_find_depot.max_search_nodes = 0; |
|
714 |
||
715 |
_train_find_station.CalculateG = NPFRailPathCost; |
|
716 |
_train_find_depot.CalculateG = NPFRailPathCost; |
|
717 |
_road_find_station.CalculateG = NPFRoadPathCost; |
|
718 |
_road_find_depot.CalculateG = NPFRoadPathCost; |
|
719 |
||
720 |
_train_find_station.CalculateH = NPFCalcStationHeuristic; |
|
721 |
_train_find_depot.CalculateH = NPFCalcStationHeuristic; |
|
722 |
_road_find_station.CalculateH = NPFCalcStationHeuristic; |
|
723 |
_road_find_depot.CalculateH = NPFCalcStationHeuristic; |
|
724 |
||
725 |
_train_find_station.EndNodeCheck = NPFFindStationOrTile; |
|
726 |
_train_find_depot.EndNodeCheck = NPFFindStationOrTile; |
|
727 |
_road_find_station.EndNodeCheck = NPFFindStationOrTile; |
|
728 |
_road_find_depot.EndNodeCheck = NPFFindStationOrTile; |
|
729 |
||
730 |
_train_find_station.FoundEndNode = NPFSaveTargetData; |
|
731 |
_train_find_depot.FoundEndNode = NPFSaveTargetData; |
|
732 |
_road_find_station.FoundEndNode = NPFSaveTargetData; |
|
733 |
_road_find_depot.FoundEndNode = NPFSaveTargetData; |
|
734 |
||
735 |
_train_find_station.GetNeighbours = NPFFollowTrack; |
|
736 |
_train_find_depot.GetNeighbours = NPFFollowTrack; |
|
737 |
_road_find_station.GetNeighbours = NPFFollowTrack; |
|
738 |
_road_find_depot.GetNeighbours = NPFFollowTrack; |
|
739 |
*/ |
|
740 |
} |
|
741 |
||
742 |
void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v) { |
|
743 |
/* Ships don't really reach their stations, but the tile in front. So don't |
|
744 |
* save the station id for ships. For roadvehs we don't store it either, |
|
745 |
* because multistop depends on vehicles actually reaching the exact |
|
746 |
* dest_tile, not just any stop of that station. |
|
747 |
* So only for train orders to stations we fill fstd->station_index, for all |
|
748 |
* others only dest_coords */ |
|
749 |
if ((v->current_order.type) == OT_GOTO_STATION && v->type == VEH_Train) { |
|
1248
60d36b03da86
(svn r1752) - Fix: MSVC acting up once again, as well as project file updates for the missing files.
darkvater
parents:
1247
diff
changeset
|
750 |
const Station* st = GetStation(v->current_order.station); |
60d36b03da86
(svn r1752) - Fix: MSVC acting up once again, as well as project file updates for the missing files.
darkvater
parents:
1247
diff
changeset
|
751 |
TileIndexDiffC center = {st->trainst_w/2, st->trainst_h/2}; |
1247 | 752 |
fstd->station_index = v->current_order.station; |
753 |
/* Let's take the center of the station as our target tile for trains */ |
|
754 |
fstd->dest_coords = TILE_ADD(st->train_tile, ToTileIndexDiff(center)); |
|
755 |
} else { |
|
756 |
fstd->dest_coords = v->dest_tile; |
|
757 |
fstd->station_index = -1; |
|
758 |
} |
|
759 |
} |