Files
@ r12304:0c02bc720761
Branch filter:
Location: cpp/openttd-patchpack/source/src/track_func.h
r12304:0c02bc720761
19.5 KiB
text/x-c
(svn r16731) -Fix [NoAI]: AIDepotList contained wrong tiles for hangars when st->xy != st->airport_tile.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 | /* $Id$ */
/** @file track_func.h Different conversion functions from one kind of track to another. */
#ifndef TRACK_FUNC_H
#define TRACK_FUNC_H
#include "core/bitmath_func.hpp"
#include "track_type.h"
#include "direction_type.h"
#include "slope_func.h"
/**
* Convert an Axis to the corresponding Track
* AXIS_X -> TRACK_X
* AXIS_Y -> TRACK_Y
* Uses the fact that they share the same internal encoding
*
* @param a the axis to convert
* @return the track corresponding to the axis
*/
static inline Track AxisToTrack(Axis a)
{
return (Track)a;
}
/**
* Maps a Track to the corresponding TrackBits value
* @param track the track to convert
* @return the converted TrackBits value of the track
*/
static inline TrackBits TrackToTrackBits(Track track)
{
return (TrackBits)(1 << track);
}
/**
* Maps an Axis to the corresponding TrackBits value
* @param a the axis to convert
* @return the converted TrackBits value of the axis
*/
static inline TrackBits AxisToTrackBits(Axis a)
{
return TrackToTrackBits(AxisToTrack(a));
}
/**
* Returns a single horizontal/vertical trackbit, that is in a specific tile corner.
*
* @param corner The corner of a tile.
* @return The TrackBits of the track in the corner.
*/
static inline TrackBits CornerToTrackBits(Corner corner)
{
extern const TrackBits _corner_to_trackbits[];
assert(IsValidCorner(corner));
return _corner_to_trackbits[corner];
}
/**
* Maps a Trackdir to the corresponding TrackdirBits value
* @param trackdir the track direction to convert
* @return the converted TrackdirBits value
*/
static inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
{
return (TrackdirBits)(1 << trackdir);
}
/**
* Removes first Track from TrackBits and returns it
*
* This function searchs for the first bit in the TrackBits,
* remove this bit from the parameter and returns the found
* bit as Track value. It returns INVALID_TRACK if the
* parameter was TRACK_BIT_NONE or INVALID_TRACK_BIT. This
* is basically used in while-loops to get up to 6 possible
* tracks on a tile until the parameter becomes TRACK_BIT_NONE.
*
* @param tracks The value with the TrackBits
* @return The first Track from the TrackBits value
* @see FindFirstTrack
*/
static inline Track RemoveFirstTrack(TrackBits *tracks)
{
if (*tracks != TRACK_BIT_NONE && *tracks != INVALID_TRACK_BIT) {
Track first = (Track)FIND_FIRST_BIT(*tracks);
ClrBit(*tracks, first);
return first;
}
return INVALID_TRACK;
}
/**
* Removes first Trackdir from TrackdirBits and returns it
*
* This function searchs for the first bit in the TrackdirBits parameter,
* remove this bit from the parameter and returns the fnound bit as
* Trackdir value. It returns INVALID_TRACKDIR if the trackdirs is
* TRACKDIR_BIT_NONE or INVALID_TRACKDIR_BIT. This is basically used in a
* while-loop to get all track-directions step by step until the value
* reaches TRACKDIR_BIT_NONE.
*
* @param trackdirs The value with the TrackdirBits
* @return The first Trackdir from the TrackdirBits value
* @see FindFirstTrackdir
*/
static inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
{
if (*trackdirs != TRACKDIR_BIT_NONE && *trackdirs != INVALID_TRACKDIR_BIT) {
Trackdir first = (Trackdir)FindFirstBit2x64(*trackdirs);
ClrBit(*trackdirs, first);
return first;
}
return INVALID_TRACKDIR;
}
/**
* Returns first Track from TrackBits or INVALID_TRACK
*
* This function returns the first Track found in the TrackBits value as Track-value.
* It returns INVALID_TRACK if the parameter is TRACK_BIT_NONE or INVALID_TRACK_BIT.
*
* @param tracks The TrackBits value
* @return The first Track found or INVALID_TRACK
* @see RemoveFirstTrack
*/
static inline Track FindFirstTrack(TrackBits tracks)
{
return (tracks != TRACK_BIT_NONE && tracks != INVALID_TRACK_BIT) ? (Track)FIND_FIRST_BIT(tracks) : INVALID_TRACK;
}
/**
* Converts TrackBits to Track.
*
* This function converts a TrackBits value to a Track value. As it
* is not possible to convert two or more tracks to one track the
* parameter must contain only one track or be the INVALID_TRACK_BIT value.
*
* @param tracks The TrackBits value to convert
* @return The Track from the value or INVALID_TRACK
* @pre tracks must contains only one Track or be INVALID_TRACK_BIT
*/
static inline Track TrackBitsToTrack(TrackBits tracks)
{
assert(tracks == INVALID_TRACK_BIT || (tracks != TRACK_BIT_NONE && KillFirstBit(tracks & TRACK_BIT_MASK) == TRACK_BIT_NONE));
return tracks != INVALID_TRACK_BIT ? (Track)FIND_FIRST_BIT(tracks & TRACK_BIT_MASK) : INVALID_TRACK;
}
/**
* Returns first Trackdir from TrackdirBits or INVALID_TRACKDIR
*
* This function returns the first Trackdir in the given TrackdirBits value or
* INVALID_TRACKDIR if the value is TRACKDIR_BIT_NONE. The TrackdirBits must
* not be INVALID_TRACKDIR_BIT.
*
* @param trackdirs The TrackdirBits value
* @return The first Trackdir from the TrackdirBits or INVALID_TRACKDIR on TRACKDIR_BIT_NONE.
* @pre trackdirs must not be INVALID_TRACKDIR_BIT
* @see RemoveFirstTrackdir
*/
static inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
{
assert((trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE);
return (trackdirs != TRACKDIR_BIT_NONE) ? (Trackdir)FindFirstBit2x64(trackdirs) : INVALID_TRACKDIR;
}
/**
* Checks if a Track is valid.
*
* @param track The value to check
* @return true if the given value is a valid track.
* @note Use this in an assert()
*/
static inline bool IsValidTrack(Track track)
{
return track < TRACK_END;
}
/**
* Checks if a Trackdir is valid.
*
* @param trackdir The value to check
* @return true if the given valie is a valid Trackdir
* @note Use this in an assert()
*/
static inline bool IsValidTrackdir(Trackdir trackdir)
{
return (TrackdirToTrackdirBits(trackdir) & TRACKDIR_BIT_MASK) != 0;
}
/*
* Functions describing logical relations between Tracks, TrackBits, Trackdirs
* TrackdirBits, Direction and DiagDirections.
*/
/**
* Find the opposite track to a given track.
*
* TRACK_LOWER -> TRACK_UPPER and vice versa, likewise for left/right.
* TRACK_X is mapped to TRACK_Y and reversed.
*
* @param t the track to convert
* @return the opposite track
*/
static inline Track TrackToOppositeTrack(Track t)
{
assert(t != INVALID_TRACK);
return (Track)(t ^ 1);
}
/**
* Maps a trackdir to the reverse trackdir.
*
* Returns the reverse trackdir of a Trackdir value. The reverse trackdir
* is the same track with the other direction on it.
*
* @param trackdir The Trackdir value
* @return The reverse trackdir
* @pre trackdir must not be INVALID_TRACKDIR
*/
static inline Trackdir ReverseTrackdir(Trackdir trackdir)
{
assert(trackdir != INVALID_TRACKDIR);
return (Trackdir)(trackdir ^ 8);
}
/**
* Returns the Track that a given Trackdir represents
*
* This function filters the Track which is used in the Trackdir value and
* returns it as a Track value.
*
* @param trackdir The trackdir value
* @return The Track which is used in the value
*/
static inline Track TrackdirToTrack(Trackdir trackdir)
{
return (Track)(trackdir & 0x7);
}
/**
* Returns a Trackdir for the given Track
*
* Since every Track corresponds to two Trackdirs, we choose the
* one which points between NE and S. Note that the actual
* implementation is quite futile, but this might change
* in the future.
*
* @param track The given Track
* @return The Trackdir from the given Track
*/
static inline Trackdir TrackToTrackdir(Track track)
{
return (Trackdir)track;
}
/**
* Returns a TrackdirBit mask from a given Track
*
* The TrackdirBit mask contains the two TrackdirBits that
* correspond with the given Track (one for each direction).
*
* @param track The track to get the TrackdirBits from
* @return The TrackdirBits which the selected tracks
*/
static inline TrackdirBits TrackToTrackdirBits(Track track)
{
Trackdir td = TrackToTrackdir(track);
return (TrackdirBits)(TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td)));
}
/**
* Discards all directional information from a TrackdirBits value
*
* Any Track which is present in either direction will be present in the result.
*
* @param bits The TrackdirBits to get the TrackBits from
* @return The TrackBits
*/
static inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
{
return (TrackBits)((bits | (bits >> 8)) & TRACK_BIT_MASK);
}
/**
* Converts TrackBits to TrackdirBits while allowing both directions.
*
* @param bits The TrackBits
* @return The TrackdirBits containing of bits in both directions.
*/
static inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
{
return (TrackdirBits)(bits * 0x101);
}
/**
* Returns the present-trackdir-information of a TrackStatus.
*
* @param ts The TrackStatus returned by GetTileTrackStatus()
* @return the present trackdirs
*/
static inline TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
{
return (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
}
/**
* Returns the present-track-information of a TrackStatus.
*
* @param ts The TrackStatus returned by GetTileTrackStatus()
* @return the present tracks
*/
static inline TrackBits TrackStatusToTrackBits(TrackStatus ts)
{
return TrackdirBitsToTrackBits(TrackStatusToTrackdirBits(ts));
}
/**
* Returns the red-signal-information of a TrackStatus.
*
* Note: The result may contain red signals for non-present tracks.
*
* @param ts The TrackStatus returned by GetTileTrackStatus()
* @return the The trackdirs that are blocked by red-signals
*/
static inline TrackdirBits TrackStatusToRedSignals(TrackStatus ts)
{
return (TrackdirBits)((ts >> 16) & TRACKDIR_BIT_MASK);
}
/**
* Builds a TrackStatus
*
* @param trackdirbits present trackdirs
* @param red_signals red signals
* @return the TrackStatus representing the given information
*/
static inline TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
{
return (TrackStatus)(trackdirbits | (red_signals << 16));
}
/**
* Maps a trackdir to the trackdir that you will end up on if you go straight
* ahead.
*
* This will be the same trackdir for diagonal trackdirs, but a
* different (alternating) one for straight trackdirs
*
* @param trackdir The given trackdir
* @return The next Trackdir value of the next tile.
*/
static inline Trackdir NextTrackdir(Trackdir trackdir)
{
extern const Trackdir _next_trackdir[TRACKDIR_END];
return _next_trackdir[trackdir];
}
/**
* Maps a track to all tracks that make 90 deg turns with it.
*
* For the diagonal directions these are the complement of the
* direction, for the straight directions these are the
* two vertical or horizontal tracks, depend on the given direction
*
* @param track The given track
* @return The TrackBits with the tracks marked which cross the given track by 90 deg.
*/
static inline TrackBits TrackCrossesTracks(Track track)
{
extern const TrackBits _track_crosses_tracks[TRACK_END];
return _track_crosses_tracks[track];
}
/**
* Maps a trackdir to the (4-way) direction the tile is exited when following
* that trackdir.
*
* For the diagonal directions these are the same directions. For
* the straight directions these are the directions from the imagined
* base-tile to the bordering tile which will be joined if the given
* straight direction is leaved from the base-tile.
*
* @param trackdir The given track direction
* @return The direction which points to the resulting tile if following the Trackdir
*/
static inline DiagDirection TrackdirToExitdir(Trackdir trackdir)
{
extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END];
return _trackdir_to_exitdir[trackdir];
}
/**
* Maps a track and an (4-way) dir to the trackdir that represents the track
* with the exit in the given direction.
*
* For the diagonal tracks the resulting track direction are clear for a given
* DiagDirection. It either matches the direction or it returns INVALID_TRACKDIR,
* as a TRACK_X cannot be applied with DIAG_SE.
* For the straight tracks the resulting track direction will be the
* direction which the DiagDirection is pointing. But this will be INVALID_TRACKDIR
* if the DiagDirection is pointing 'away' the track.
*
* @param track The track to applie an direction on
* @param diagdir The DiagDirection to applie on
* @return The resulting track direction or INVALID_TRACKDIR if not possible.
*/
static inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
{
extern const Trackdir _track_exitdir_to_trackdir[TRACK_END][DIAGDIR_END];
return _track_exitdir_to_trackdir[track][diagdir];
}
/**
* Maps a track and an (4-way) dir to the trackdir that represents the track
* with the entry in the given direction.
*
* For the diagonal tracks the return value is clear, its either the matching
* track direction or INVALID_TRACKDIR.
* For the straight tracks this returns the track direction which results if
* you follow the DiagDirection and then turn by 45 deg left or right on the
* next tile. The new direction on the new track will be the returning Trackdir
* value. If the parameters makes no sense like the track TRACK_UPPER and the
* diraction DIAGDIR_NE (target track cannot be reached) this function returns
* INVALID_TRACKDIR.
*
* @param track The target track
* @param diagdir The direction to "come from"
* @return the resulting Trackdir or INVALID_TRACKDIR if not possible.
*/
static inline Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir)
{
extern const Trackdir _track_enterdir_to_trackdir[TRACK_END][DIAGDIR_END];
return _track_enterdir_to_trackdir[track][diagdir];
}
/**
* Maps a track and a full (8-way) direction to the trackdir that represents
* the track running in the given direction.
*/
static inline Trackdir TrackDirectionToTrackdir(Track track, Direction dir)
{
extern const Trackdir _track_direction_to_trackdir[TRACK_END][DIR_END];
return _track_direction_to_trackdir[track][dir];
}
/**
* Maps a (4-way) direction to the diagonal track incidating with that diagdir
*
* @param diagdir The direction
* @return The resulting Track
*/
static inline Track DiagDirToDiagTrack(DiagDirection diagdir)
{
return (Track)(diagdir & 1);
}
/**
* Maps a (4-way) direction to the diagonal track bits incidating with that diagdir
*
* @param diagdir The direction
* @return The resulting TrackBits
*/
static inline TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
{
return TrackToTrackBits(DiagDirToDiagTrack(diagdir));
}
/**
* Maps a (4-way) direction to the diagonal trackdir that runs in that
* direction.
*
* @param diagdir The direction
* @return The resulting Trackdir direction
*/
static inline Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
{
extern const Trackdir _dir_to_diag_trackdir[DIAGDIR_END];
return _dir_to_diag_trackdir[diagdir];
}
/**
* Returns all trackdirs that can be reached when entering a tile from a given
* (diagonal) direction.
*
* This will obviously include 90 degree turns, since no information is available
* about the exact angle of entering
*
* @param diagdir The joining direction
* @return The TrackdirBits which can be used from the given direction
* @see DiagdirReachesTracks
*/
static inline TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
{
extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
return _exitdir_reaches_trackdirs[diagdir];
}
/**
* Returns all tracks that can be reached when entering a tile from a given
* (diagonal) direction.
*
* This will obviously include 90 degree turns, since no
* information is available about the exact angle of entering
*
* @param diagdir The joining irection
* @return The tracks which can be used
* @see DiagdirReachesTrackdirs
*/
static inline TrackBits DiagdirReachesTracks(DiagDirection diagdir) { return TrackdirBitsToTrackBits(DiagdirReachesTrackdirs(diagdir)); }
/**
* Maps a trackdir to the trackdirs that can be reached from it (ie, when
* entering the next tile.
*
* This will include 90 degree turns!
*
* @param trackdir The track direction which will be leaved
* @return The track directions which can be used from this direction (in the next tile)
*/
static inline TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir)
{
extern const TrackdirBits _exitdir_reaches_trackdirs[DIAGDIR_END];
return _exitdir_reaches_trackdirs[TrackdirToExitdir(trackdir)];
}
/* Note that there is no direct table for this function (there used to be),
* but it uses two simpeler tables to achieve the result */
/**
* Maps a trackdir to all trackdirs that make 90 deg turns with it.
*
* For the diagonal tracks this returns the track direction bits
* of the other axis in both directions, which cannot be joined by
* the given track direction.
* For the straight tracks this returns all possible 90 deg turns
* either on the current tile (which no train can joined) or on the
* bordering tiles.
*
* @param trackdir The track direction
* @return The TrackdirBits which are (more or less) 90 deg turns.
*/
static inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
{
extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END];
return _track_crosses_trackdirs[TrackdirToTrack(trackdir)];
}
/**
* Checks if a given Track is diagonal
*
* @param track The given track to check
* @return true if diagonal, else false
*/
static inline bool IsDiagonalTrack(Track track)
{
return (track == TRACK_X) || (track == TRACK_Y);
}
/**
* Checks if a given Trackdir is diagonal.
*
* @param trackdir The given trackdir
* @return true if the trackdir use a diagonal track
*/
static inline bool IsDiagonalTrackdir(Trackdir trackdir)
{
return IsDiagonalTrack(TrackdirToTrack(trackdir));
}
/**
* Checks if the given tracks overlap, ie form a crossing. Basically this
* means when there is more than one track on the tile, exept when there are
* two parallel tracks.
* @param bits The tracks present.
* @return Whether the tracks present overlap in any way.
*/
static inline bool TracksOverlap(TrackBits bits)
{
/* With no, or only one track, there is no overlap */
if (bits == TRACK_BIT_NONE || KillFirstBit(bits) == TRACK_BIT_NONE) return false;
/* We know that there are at least two tracks present. When there are more
* than 2 tracks, they will surely overlap. When there are two, they will
* always overlap unless they are lower & upper or right & left. */
return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT;
}
/**
* Check if a given track is contained within or overlaps some other tracks.
*
* @param tracks Tracks to be testet against
* @param track The track to test
* @return true if the track is already in the tracks or overlaps the tracks.
*/
static inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
{
if (HasBit(tracks, track)) return true;
return TracksOverlap(tracks | TrackToTrackBits(track));
}
/**
* Checks whether the trackdir means that we are reversing.
* @param dir the trackdir to check
* @return true if it is a reversing road trackdir
*/
static inline bool IsReversingRoadTrackdir(Trackdir dir)
{
return (dir & 0x07) >= 6;
}
/**
* Checks whether the given trackdir is a straight road
* @param dir the trackdir to check
* @return true if it is a straight road trackdir
*/
static inline bool IsStraightRoadTrackdir(Trackdir dir)
{
return (dir & 0x06) == 0;
}
/**
* Checks whether a trackdir on a specific slope is going uphill.
*
* Valid for rail and road tracks.
* Valid for tile-slopes (under foundation) and foundation-slopes (on foundation).
*
* @param slope The slope of the tile.
* @param dir The trackdir of interest.
* @return true iff the track goes upwards.
*/
static inline bool IsUphillTrackdir(Slope slope, Trackdir dir)
{
extern const TrackdirBits _uphill_trackdirs[];
return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir);
}
#endif /* TRACK_FUNC_H */
|