# rail.cpp

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "station_map.h"
    00014 #include "tunnelbridge_map.h"
    00015 #include "date_func.h"
    00016 #include "company_func.h"
    00017 #include "company_base.h"
    00018 #include "engine_base.h"
    00019
    00020 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
    00021 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
    00022  * direction along with the trackdir */
    00023 extern const byte _signal_along_trackdir[TRACKDIR_END] = {
    00024   0x8, 0x8, 0x8, 0x2, 0x4, 0x1, 0, 0,
    00025   0x4, 0x4, 0x4, 0x1, 0x8, 0x2
    00026 };
    00027
    00028 /* Maps a trackdir to the bit that stores its status in the map arrays, in the
    00029  * direction against the trackdir */
    00030 extern const byte _signal_against_trackdir[TRACKDIR_END] = {
    00031   0x4, 0x4, 0x4, 0x1, 0x8, 0x2, 0, 0,
    00032   0x8, 0x8, 0x8, 0x2, 0x4, 0x1
    00033 };
    00034
    00035 /* Maps a Track to the bits that store the status of the two signals that can
    00036  * be present on the given track */
    00037 extern const byte _signal_on_track[] = {
    00038   0xC, 0xC, 0xC, 0x3, 0xC, 0x3
    00039 };
    00040
    00041 /* Maps a diagonal direction to the all trackdirs that are connected to any
    00042  * track entering in this direction (including those making 90 degree turns)
    00043  */
    00044 extern const TrackdirBits _exitdir_reaches_trackdirs[] = {
    00045   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N,  // DIAGDIR_NE
    00046   TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_LEFT_S  | TRACKDIR_BIT_UPPER_E, // DIAGDIR_SE
    00047   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S, // DIAGDIR_SW
    00048   TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W  // DIAGDIR_NW
    00049 };
    00050
    00051 extern const Trackdir _next_trackdir[TRACKDIR_END] = {
    00052   TRACKDIR_X_NE,  TRACKDIR_Y_SE,  TRACKDIR_LOWER_E, TRACKDIR_UPPER_E, TRACKDIR_RIGHT_S, TRACKDIR_LEFT_S, INVALID_TRACKDIR, INVALID_TRACKDIR,
    00053   TRACKDIR_X_SW,  TRACKDIR_Y_NW,  TRACKDIR_LOWER_W, TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N
    00054 };
    00055
    00056 /* Maps a trackdir to all trackdirs that make 90 deg turns with it. */
    00057 extern const TrackdirBits _track_crosses_trackdirs[TRACKDIR_END] = {
    00058   TRACKDIR_BIT_Y_SE     | TRACKDIR_BIT_Y_NW,                                                   // TRACK_X
    00059   TRACKDIR_BIT_X_NE     | TRACKDIR_BIT_X_SW,                                                   // TRACK_Y
    00060   TRACKDIR_BIT_RIGHT_N  | TRACKDIR_BIT_RIGHT_S  | TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LEFT_S,  // TRACK_UPPER
    00061   TRACKDIR_BIT_RIGHT_N  | TRACKDIR_BIT_RIGHT_S  | TRACKDIR_BIT_LEFT_N  | TRACKDIR_BIT_LEFT_S,  // TRACK_LOWER
    00062   TRACKDIR_BIT_UPPER_W  | TRACKDIR_BIT_UPPER_E  | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_LOWER_E, // TRACK_LEFT
    00063   TRACKDIR_BIT_UPPER_W  | TRACKDIR_BIT_UPPER_E  | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_LOWER_E  // TRACK_RIGHT
    00064 };
    00065
    00066 /* Maps a track to all tracks that make 90 deg turns with it. */
    00067 extern const TrackBits _track_crosses_tracks[] = {
    00068   TRACK_BIT_Y,    // TRACK_X
    00069   TRACK_BIT_X,    // TRACK_Y
    00070   TRACK_BIT_VERT, // TRACK_UPPER
    00071   TRACK_BIT_VERT, // TRACK_LOWER
    00072   TRACK_BIT_HORZ, // TRACK_LEFT
    00073   TRACK_BIT_HORZ  // TRACK_RIGHT
    00074 };
    00075
    00076 /* Maps a trackdir to the (4-way) direction the tile is exited when following
    00077  * that trackdir */
    00078 extern const DiagDirection _trackdir_to_exitdir[TRACKDIR_END] = {
    00079   DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_NE,
    00080   DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE,
    00081 };
    00082
    00083 extern const Trackdir _track_exitdir_to_trackdir[][DIAGDIR_END] = {
    00084   {TRACKDIR_X_NE,     INVALID_TRACKDIR,  TRACKDIR_X_SW,     INVALID_TRACKDIR},
    00085   {INVALID_TRACKDIR,  TRACKDIR_Y_SE,     INVALID_TRACKDIR,  TRACKDIR_Y_NW},
    00086   {TRACKDIR_UPPER_E,  INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_UPPER_W},
    00087   {INVALID_TRACKDIR,  TRACKDIR_LOWER_E,  TRACKDIR_LOWER_W,  INVALID_TRACKDIR},
    00088   {INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_LEFT_S,   TRACKDIR_LEFT_N},
    00089   {TRACKDIR_RIGHT_N,  TRACKDIR_RIGHT_S,  INVALID_TRACKDIR,  INVALID_TRACKDIR}
    00090 };
    00091
    00092 extern const Trackdir _track_enterdir_to_trackdir[][DIAGDIR_END] = {
    00093   {TRACKDIR_X_NE,     INVALID_TRACKDIR,  TRACKDIR_X_SW,     INVALID_TRACKDIR},
    00094   {INVALID_TRACKDIR,  TRACKDIR_Y_SE,     INVALID_TRACKDIR,  TRACKDIR_Y_NW},
    00095   {INVALID_TRACKDIR,  TRACKDIR_UPPER_E,  TRACKDIR_UPPER_W,  INVALID_TRACKDIR},
    00096   {TRACKDIR_LOWER_E,  INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_LOWER_W},
    00097   {TRACKDIR_LEFT_N,   TRACKDIR_LEFT_S,   INVALID_TRACKDIR,  INVALID_TRACKDIR},
    00098   {INVALID_TRACKDIR,  INVALID_TRACKDIR,  TRACKDIR_RIGHT_S,  TRACKDIR_RIGHT_N}
    00099 };
    00100
    00101 extern const Trackdir _track_direction_to_trackdir[][DIR_END] = {
    00102   {INVALID_TRACKDIR, TRACKDIR_X_NE,     INVALID_TRACKDIR, INVALID_TRACKDIR,  INVALID_TRACKDIR, TRACKDIR_X_SW,     INVALID_TRACKDIR, INVALID_TRACKDIR},
    00103   {INVALID_TRACKDIR, INVALID_TRACKDIR,  INVALID_TRACKDIR, TRACKDIR_Y_SE,     INVALID_TRACKDIR, INVALID_TRACKDIR,  INVALID_TRACKDIR, TRACKDIR_Y_NW},
    00104   {INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_UPPER_E, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_UPPER_W, INVALID_TRACKDIR},
    00105   {INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_LOWER_E, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_LOWER_W, INVALID_TRACKDIR},
    00106   {TRACKDIR_LEFT_N,  INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_LEFT_S,  INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR},
    00107   {TRACKDIR_RIGHT_N, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR,  TRACKDIR_RIGHT_S, INVALID_TRACKDIR,  INVALID_TRACKDIR, INVALID_TRACKDIR}
    00108 };
    00109
    00110 extern const Trackdir _dir_to_diag_trackdir[] = {
    00111   TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW,
    00112 };
    00113
    00114 extern const TrackBits _corner_to_trackbits[] = {
    00115   TRACK_BIT_LEFT, TRACK_BIT_LOWER, TRACK_BIT_RIGHT, TRACK_BIT_UPPER,
    00116 };
    00117
    00118 extern const TrackdirBits _uphill_trackdirs[] = {
    00119   TRACKDIR_BIT_NONE                    ,
    00120   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW,
    00121   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE,
    00122   TRACKDIR_BIT_X_SW                    ,
    00123   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE,
    00124   TRACKDIR_BIT_NONE                    ,
    00125   TRACKDIR_BIT_Y_SE                    ,
    00126   TRACKDIR_BIT_NONE                    ,
    00127   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW,
    00128   TRACKDIR_BIT_Y_NW                    ,
    00129   TRACKDIR_BIT_NONE                    ,
    00130   TRACKDIR_BIT_NONE                    ,
    00131   TRACKDIR_BIT_X_NE                    ,
    00132   TRACKDIR_BIT_NONE                    ,
    00133   TRACKDIR_BIT_NONE                    ,
    00134   TRACKDIR_BIT_NONE                    ,
    00135   TRACKDIR_BIT_NONE                    ,
    00136   TRACKDIR_BIT_NONE                    ,
    00137   TRACKDIR_BIT_NONE                    ,
    00138   TRACKDIR_BIT_NONE                    ,
    00139   TRACKDIR_BIT_NONE                    ,
    00140   TRACKDIR_BIT_NONE                    ,
    00141   TRACKDIR_BIT_NONE                    ,
    00142   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE,
    00143   TRACKDIR_BIT_NONE                    ,
    00144   TRACKDIR_BIT_NONE                    ,
    00145   TRACKDIR_BIT_NONE                    ,
    00146   TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW,
    00147   TRACKDIR_BIT_NONE                    ,
    00148   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW,
    00149   TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE,
    00150 };
    00151
    00155 RailType GetTileRailType(TileIndex tile)
    00156 {
    00157   switch (GetTileType(tile)) {
    00158     case MP_RAILWAY:
    00159       return GetRailType(tile);
    00160
    00161     case MP_ROAD:
    00162       /* rail/road crossing */
    00163       if (IsLevelCrossing(tile)) return GetRailType(tile);
    00164       break;
    00165
    00166     case MP_STATION:
    00167       if (HasStationRail(tile)) return GetRailType(tile);
    00168       break;
    00169
    00170     case MP_TUNNELBRIDGE:
    00171       if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) return GetRailType(tile);
    00172       break;
    00173
    00174     default:
    00175       break;
    00176   }
    00177   return INVALID_RAILTYPE;
    00178 }
    00179
    00186 bool HasRailtypeAvail(const CompanyID company, const RailType railtype)
    00187 {
    00188   return HasBit(Company::Get(company)->avail_railtypes, railtype);
    00189 }
    00190
    00196 bool ValParamRailtype(const RailType rail)
    00197 {
    00198   return rail < RAILTYPE_END && HasRailtypeAvail(_current_company, rail);
    00199 }
    00200
    00208 RailType GetBestRailtype(const CompanyID company)
    00209 {
    00210   if (HasRailtypeAvail(company, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV;
    00211   if (HasRailtypeAvail(company, RAILTYPE_MONO)) return RAILTYPE_MONO;
    00212   if (HasRailtypeAvail(company, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC;
    00213   return RAILTYPE_RAIL;
    00214 }
    00215
    00223 RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date)
    00224 {
    00225   RailTypes rts = current;
    00226
    00227   for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
    00228     const RailtypeInfo *rti = GetRailTypeInfo(rt);
    00229     /* Unused rail type. */
    00230     if (rti->label == 0) continue;
    00231
    00232     /* Not date introduced. */
    00233     if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
    00234
    00235     /* Not yet introduced at this date. */
    00236     if (rti->introduction_date > date) continue;
    00237
    00238     /* Have we introduced all required railtypes? */
    00239     RailTypes required = rti->introduction_required_railtypes;
    00240     if ((rts & required) != required) continue;
    00241
    00242     rts |= rti->introduces_railtypes;
    00243   }
    00244
    00245   /* When we added railtypes we need to run this method again; the added
    00246    * railtypes might enable more rail types to become introduced. */
    00247   return rts == current ? rts : AddDateIntroducedRailTypes(rts, date);
    00248 }
    00249
    00255 RailTypes GetCompanyRailtypes(CompanyID company)
    00256 {
    00257   RailTypes rts = RAILTYPES_NONE;
    00258
    00259   Engine *e;
    00260   FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
    00261     const EngineInfo *ei = &e->info;
    00262
    00263     if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
    00264         (HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) {
    00265       const RailVehicleInfo *rvi = &e->u.rail;
    00266
    00267       if (rvi->railveh_type != RAILVEH_WAGON) {
    00268         assert(rvi->railtype < RAILTYPE_END);
    00269         rts |= GetRailTypeInfo(rvi->railtype)->introduces_railtypes;
    00270       }
    00271     }
    00272   }
    00273
    00274   return AddDateIntroducedRailTypes(rts, _date);
    00275 }
    00276
    00283 RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels)
    00284 {
    00285   /* Loop through each rail type until the label is found */
    00286   for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
    00287     const RailtypeInfo *rti = GetRailTypeInfo(r);
    00288     if (rti->label == label) return r;
    00289   }
    00290
    00291   if (allow_alternate_labels) {
    00292     /* Test if any rail type defines the label as an alternate. */
    00293     for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) {
    00294       const RailtypeInfo *rti = GetRailTypeInfo(r);
    00295       if (rti->alternate_labels.Contains(label)) return r;
    00296     }
    00297   }
    00298
    00299   /* No matching label was found, so it is invalid */
    00300   return INVALID_RAILTYPE;
    00301 }