# rail.cpp

Go to the documentation of this file.

    00001 /* $Id: rail.cpp 15718 2009-03-15 00:32:18Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "station_map.h"
    00007 #include "tunnelbridge_map.h"
    00008 #include "date_func.h"
    00009 #include "company_func.h"
    00010 #include "company_base.h"
    00011 #include "engine_base.h"
    00012 #include "settings_type.h"
    00013
    00014 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
    00015 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
    00016  * direction along with the trackdir */
    00017 extern const byte _signal_along_trackdir[TRACKDIR_END] = {
    00018   0x8, 0x8, 0x8, 0x2, 0x4, 0x1, 0, 0,
    00019   0x4, 0x4, 0x4, 0x1, 0x8, 0x2
    00020 };
    00021
    00022 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
    00023  * direction against the trackdir */
    00024 extern const byte _signal_against_trackdir[TRACKDIR_END] = {
    00025   0x4, 0x4, 0x4, 0x1, 0x8, 0x2, 0, 0,
    00026   0x8, 0x8, 0x8, 0x2, 0x4, 0x1
    00027 };
    00028
    00029 /* Maps a Track to the bits that store the status of the two signals that can
    00030  * be present on the given track */
    00031 extern const byte _signal_on_track[] = {
    00032   0xC, 0xC, 0xC, 0x3, 0xC, 0x3
    00033 };
    00034
    00035 /* Maps a diagonal direction to the all trackdirs that are connected to any
    00036  * track entering in this direction (including those making 90 degree turns)
    00037  */
    00038 extern const TrackdirBits _exitdir_reaches_trackdirs[] = {
    00039   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N,  // DIAGDIR_NE
    00040   TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_LEFT_S  | TRACKDIR_BIT_UPPER_E, // DIAGDIR_SE
    00041   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S, // DIAGDIR_SW
    00042   TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W  // DIAGDIR_NW
    00043 };
    00044
    00045 extern const Trackdir _next_trackdir[TRACKDIR_END] = {
    00046   TRACKDIR_X_NE,  TRACKDIR_Y_SE,  TRACKDIR_LOWER_E, TRACKDIR_UPPER_E, TRACKDIR_RIGHT_S, TRACKDIR_LEFT_S, INVALID_TRACKDIR, INVALID_TRACKDIR,
    00047   TRACKDIR_X_SW,  TRACKDIR_Y_NW,  TRACKDIR_LOWER_W, TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N
    00048 };
    00049
    00050 /* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
    00051 extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END] = {
    00052   TRACKDIR_BIT_Y_SE     | TRACKDIR_BIT_Y_NW,                                                   // TRACK_X
    00053   TRACKDIR_BIT_X_NE     | TRACKDIR_BIT_X_SW,                                                   // TRACK_Y
    00054   TRACKDIR_BIT_RIGHT_N  | TRACKDIR_BIT_RIGHT_S  | TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LEFT_S,  // TRACK_UPPER
    00055   TRACKDIR_BIT_RIGHT_N  | TRACKDIR_BIT_RIGHT_S  | TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LEFT_S,  // TRACK_LOWER
    00056   TRACKDIR_BIT_UPPER_W  | TRACKDIR_BIT_UPPER_E  | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_LOWER_E, // TRACK_LEFT
    00057   TRACKDIR_BIT_UPPER_W  | TRACKDIR_BIT_UPPER_E  | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_LOWER_E  // TRACK_RIGHT
    00058 };
    00059
    00060 /* Maps a track to all tracks that make 90 deg turns with it. */
    00061 extern const TrackBits _track_crosses_tracks[] = {
    00062   TRACK_BIT_Y,    // TRACK_X
    00063   TRACK_BIT_X,    // TRACK_Y
    00064   TRACK_BIT_VERT, // TRACK_UPPER
    00065   TRACK_BIT_VERT, // TRACK_LOWER
    00066   TRACK_BIT_HORZ, // TRACK_LEFT
    00067   TRACK_BIT_HORZ  // TRACK_RIGHT
    00068 };
    00069
    00070 /* Maps a trackdir to the (4-way) direction the tile is exited when following
    00071  * that trackdir */
    00072 extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END] = {
    00073   DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_NE,
    00074   DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE,
    00075 };
    00076
    00077 extern const Trackdir _track_exitdir_to_trackdir[][DIAGDIR_END] = {
    00078   {TRACKDIR_X_NE,     INVALID_TRACKDIR,  TRACKDIR_X_SW,     INVALID_TRACKDIR},
    00079   {INVALID_TRACKDIR,  TRACKDIR_Y_SE,     INVALID_TRACKDIR,  TRACKDIR_Y_NW},
    00080   {TRACKDIR_UPPER_E,  INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_UPPER_W},
    00081   {INVALID_TRACKDIR,  TRACKDIR_LOWER_E,  TRACKDIR_LOWER_W,  INVALID_TRACKDIR},
    00082   {INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_LEFT_S,   TRACKDIR_LEFT_N},
    00083   {TRACKDIR_RIGHT_N,  TRACKDIR_RIGHT_S,  INVALID_TRACKDIR,  INVALID_TRACKDIR}
    00084 };
    00085
    00086 extern const Trackdir _track_enterdir_to_trackdir[][DIAGDIR_END] = {
    00087   {TRACKDIR_X_NE,     INVALID_TRACKDIR,  TRACKDIR_X_SW,     INVALID_TRACKDIR},
    00088   {INVALID_TRACKDIR,  TRACKDIR_Y_SE,     INVALID_TRACKDIR,  TRACKDIR_Y_NW},
    00089   {INVALID_TRACKDIR,  TRACKDIR_UPPER_E,  TRACKDIR_UPPER_W,  INVALID_TRACKDIR},
    00090   {TRACKDIR_LOWER_E,  INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_LOWER_W},
    00091   {TRACKDIR_LEFT_N,   TRACKDIR_LEFT_S,   INVALID_TRACKDIR,  INVALID_TRACKDIR},
    00092   {INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_RIGHT_S,  TRACKDIR_RIGHT_N}
    00093 };
    00094
    00095 extern const Trackdir _track_direction_to_trackdir[][DIR_END] = {
    00096   {INVALID_TRACKDIR, TRACKDIR_X_NE,     INVALID_TRACKDIR, INVALID_TRACKDIR,  INVALID_TRACKDIR, TRACKDIR_X_SW,     INVALID_TRACKDIR, INVALID_TRACKDIR},
    00097   {INVALID_TRACKDIR, INVALID_TRACKDIR,  INVALID_TRACKDIR, TRACKDIR_Y_SE,     INVALID_TRACKDIR, INVALID_TRACKDIR,  INVALID_TRACKDIR, TRACKDIR_Y_NW},
    00098   {INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_UPPER_E, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_UPPER_W, INVALID_TRACKDIR},
    00099   {INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_LOWER_E, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_LOWER_W, INVALID_TRACKDIR},
    00100   {TRACKDIR_LEFT_N,  INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_LEFT_S,  INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR},
    00101   {TRACKDIR_RIGHT_N, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_RIGHT_S, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR}
    00102 };
    00103
    00104 extern const Trackdir _dir_to_diag_trackdir[] = {
    00105   TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW,
    00106 };
    00107
    00108 extern const TrackBits _corner_to_trackbits[] = {
    00109   TRACK_BIT_LEFT, TRACK_BIT_LOWER, TRACK_BIT_RIGHT, TRACK_BIT_UPPER,
    00110 };
    00111
    00112 extern const TrackdirBits _uphill_trackdirs[] = {
    00113   TRACKDIR_BIT_NONE                    ,
    00114   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW,
    00115   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE,
    00116   TRACKDIR_BIT_X_SW                    ,
    00117   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE,
    00118   TRACKDIR_BIT_NONE                    ,
    00119   TRACKDIR_BIT_Y_SE                    ,
    00120   TRACKDIR_BIT_NONE                    ,
    00121   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW,
    00122   TRACKDIR_BIT_Y_NW                    ,
    00123   TRACKDIR_BIT_NONE                    ,
    00124   TRACKDIR_BIT_NONE                    ,
    00125   TRACKDIR_BIT_X_NE                    ,
    00126   TRACKDIR_BIT_NONE                    ,
    00127   TRACKDIR_BIT_NONE                    ,
    00128   TRACKDIR_BIT_NONE                    ,
    00129   TRACKDIR_BIT_NONE                    ,
    00130   TRACKDIR_BIT_NONE                    ,
    00131   TRACKDIR_BIT_NONE                    ,
    00132   TRACKDIR_BIT_NONE                    ,
    00133   TRACKDIR_BIT_NONE                    ,
    00134   TRACKDIR_BIT_NONE                    ,
    00135   TRACKDIR_BIT_NONE                    ,
    00136   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE,
    00137   TRACKDIR_BIT_NONE                    ,
    00138   TRACKDIR_BIT_NONE                    ,
    00139   TRACKDIR_BIT_NONE                    ,
    00140   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW,
    00141   TRACKDIR_BIT_NONE                    ,
    00142   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW,
    00143   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE,
    00144 };
    00145
    00146 RailType GetTileRailType(TileIndex tile)
    00147 {
    00148   switch (GetTileType(tile)) {
    00149     case MP_RAILWAY:
    00150       return GetRailType(tile);
    00151
    00152     case MP_ROAD:
    00153       /* rail/road crossing */
    00154       if (IsLevelCrossing(tile)) return GetRailType(tile);
    00155       break;
    00156
    00157     case MP_STATION:
    00158       if (IsRailwayStationTile(tile)) return GetRailType(tile);
    00159       break;
    00160
    00161     case MP_TUNNELBRIDGE:
    00162       if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) return GetRailType(tile);
    00163       break;
    00164
    00165     default:
    00166       break;
    00167   }
    00168   return INVALID_RAILTYPE;
    00169 }
    00170
    00171 bool HasRailtypeAvail(const CompanyID company, const RailType railtype)
    00172 {
    00173   return HasBit(GetCompany(company)->avail_railtypes, railtype);
    00174 }
    00175
    00176 bool ValParamRailtype(const RailType rail)
    00177 {
    00178   return HasRailtypeAvail(_current_company, rail);
    00179 }
    00180
    00181 RailType GetBestRailtype(const CompanyID company)
    00182 {
    00183   if (HasRailtypeAvail(company, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV;
    00184   if (HasRailtypeAvail(company, RAILTYPE_MONO)) return RAILTYPE_MONO;
    00185   if (HasRailtypeAvail(company, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC;
    00186   return RAILTYPE_RAIL;
    00187 }
    00188
    00189 RailTypes GetCompanyRailtypes(CompanyID company)
    00190 {
    00191   RailTypes rt = RAILTYPES_NONE;
    00192
    00193   Engine *e;
    00194   FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
    00195     const EngineInfo *ei = &e->info;
    00196
    00197     if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
    00198         (HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) {
    00199       const RailVehicleInfo *rvi = &e->u.rail;
    00200
    00201       if (rvi->railveh_type != RAILVEH_WAGON) {
    00202         assert(rvi->railtype < RAILTYPE_END);
    00203         SetBit(rt, rvi->railtype);
    00204       }
    00205     }
    00206   }
    00207
    00208   return rt;
    00209 }
    00210
    00211 RailType GetRailTypeByLabel(RailTypeLabel label)
    00212 {
    00213   /* Loop through each rail type until the label is found */
    00214   for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
    00215     const RailtypeInfo *rti = GetRailTypeInfo(r);
    00216     if (rti->label == label) return r;
    00217   }
    00218
    00219   /* No matching label was found, so it is invalid */
    00220   return INVALID_RAILTYPE;
    00221 }