train_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: train_cmd.cpp 14385 2008-09-22 19:57:31Z rubidium $ */
00002 
00005 #include "stdafx.h"
00006 #include "openttd.h"
00007 #include "bridge_map.h"
00008 #include "debug.h"
00009 #include "tile_cmd.h"
00010 #include "landscape.h"
00011 #include "gui.h"
00012 #include "station_map.h"
00013 #include "tunnel_map.h"
00014 #include "timetable.h"
00015 #include "articulated_vehicles.h"
00016 #include "command_func.h"
00017 #include "pathfind.h"
00018 #include "npf.h"
00019 #include "station.h"
00020 #include "news.h"
00021 #include "engine.h"
00022 #include "player_func.h"
00023 #include "player_base.h"
00024 #include "depot.h"
00025 #include "waypoint.h"
00026 #include "vehicle_gui.h"
00027 #include "train.h"
00028 #include "bridge.h"
00029 #include "newgrf_callbacks.h"
00030 #include "newgrf_engine.h"
00031 #include "newgrf_sound.h"
00032 #include "newgrf_text.h"
00033 #include "direction_func.h"
00034 #include "yapf/yapf.h"
00035 #include "cargotype.h"
00036 #include "group.h"
00037 #include "table/sprites.h"
00038 #include "tunnelbridge_map.h"
00039 #include "strings_func.h"
00040 #include "functions.h"
00041 #include "window_func.h"
00042 #include "date_func.h"
00043 #include "vehicle_func.h"
00044 #include "sound_func.h"
00045 #include "signal_func.h"
00046 #include "variables.h"
00047 #include "autoreplace_gui.h"
00048 #include "gfx_func.h"
00049 #include "settings_type.h"
00050 #include "network/network.h"
00051 
00052 #include "table/strings.h"
00053 #include "table/train_cmd.h"
00054 
00055 static bool TrainCheckIfLineEnds(Vehicle *v);
00056 static void TrainController(Vehicle *v, Vehicle *nomove, bool update_image);
00057 static TileIndex TrainApproachingCrossingTile(const Vehicle *v);
00058 
00059 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4,  8};
00060 static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
00061 
00062 
00070 static inline DiagDirection TrainExitDir(Direction direction, TrackBits track)
00071 {
00072   static const TrackBits state_dir_table[DIAGDIR_END] = { TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER };
00073 
00074   DiagDirection diagdir = DirToDiagDir(direction);
00075 
00076   /* Determine the diagonal direction in which we will exit this tile */
00077   if (!HasBit(direction, 0) && track != state_dir_table[diagdir]) {
00078     diagdir = ChangeDiagDir(diagdir, DIAGDIRDIFF_90LEFT);
00079   }
00080 
00081   return diagdir;
00082 }
00083 
00084 
00089 byte FreightWagonMult(CargoID cargo)
00090 {
00091   if (!GetCargo(cargo)->is_freight) return 1;
00092   return _patches.freight_trains;
00093 }
00094 
00095 
00100 void TrainPowerChanged(Vehicle* v)
00101 {
00102   uint32 total_power = 0;
00103   uint32 max_te = 0;
00104 
00105   for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00106     /* Power is not added for articulated parts */
00107     if (IsArticulatedPart(u)) continue;
00108 
00109     RailType railtype = GetRailType(u->tile);
00110     bool engine_has_power = HasPowerOnRail(u->u.rail.railtype, railtype);
00111     bool wagon_has_power  = HasPowerOnRail(v->u.rail.railtype, railtype);
00112 
00113     const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
00114 
00115     if (engine_has_power) {
00116       uint16 power = GetVehicleProperty(u, 0x0B, rvi_u->power);
00117       if (power != 0) {
00118         /* Halve power for multiheaded parts */
00119         if (IsMultiheaded(u)) power /= 2;
00120 
00121         total_power += power;
00122         /* Tractive effort in (tonnes * 1000 * 10 =) N */
00123         max_te += (u->u.rail.cached_veh_weight * 10000 * GetVehicleProperty(u, 0x1F, rvi_u->tractive_effort)) / 256;
00124       }
00125     }
00126 
00127     if (HasBit(u->u.rail.flags, VRF_POWEREDWAGON) && (wagon_has_power)) {
00128       total_power += RailVehInfo(u->u.rail.first_engine)->pow_wag_power;
00129     }
00130   }
00131 
00132   if (v->u.rail.cached_power != total_power || v->u.rail.cached_max_te != max_te) {
00133     /* If it has no power (no catenary), stop the train */
00134     if (total_power == 0) v->vehstatus |= VS_STOPPED;
00135 
00136     v->u.rail.cached_power = total_power;
00137     v->u.rail.cached_max_te = max_te;
00138     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
00139     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
00140   }
00141 }
00142 
00143 
00149 static void TrainCargoChanged(Vehicle* v)
00150 {
00151   uint32 weight = 0;
00152 
00153   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00154     uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo.Count() * FreightWagonMult(u->cargo_type) / 16;
00155 
00156     /* Vehicle weight is not added for articulated parts. */
00157     if (!IsArticulatedPart(u)) {
00158       /* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */
00159       vweight += GetVehicleProperty(u, 0x16, RailVehInfo(u->engine_type)->weight);
00160 
00161       /* powered wagons have extra weight added */
00162       if (HasBit(u->u.rail.flags, VRF_POWEREDWAGON))
00163         vweight += RailVehInfo(u->u.rail.first_engine)->pow_wag_weight;
00164     }
00165 
00166     /* consist weight is the sum of the weight of all vehicles in the consist */
00167     weight += vweight;
00168 
00169     /* store vehicle weight in cache */
00170     u->u.rail.cached_veh_weight = vweight;
00171   }
00172 
00173   /* store consist weight in cache */
00174   v->u.rail.cached_weight = weight;
00175 
00176   /* Now update train power (tractive effort is dependent on weight) */
00177   TrainPowerChanged(v);
00178 }
00179 
00180 
00185 static void RailVehicleLengthChanged(const Vehicle *u)
00186 {
00187   extern const GRFFile *_engine_grf[TOTAL_NUM_ENGINES];
00188   if (_engine_grf[u->engine_type] == NULL) return;
00189 
00190   uint32 grfid = _engine_grf[u->engine_type]->grfid;
00191   GRFConfig *grfconfig = GetGRFConfig(grfid);
00192   if (!HasBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH)) {
00193     SetBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH);
00194     SetDParamStr(0, grfconfig->name);
00195     SetDParam(1, u->engine_type);
00196     ShowErrorMessage(STR_NEWGRF_BROKEN_VEHICLE_LENGTH, STR_NEWGRF_BROKEN, 0, 0);
00197 
00198     /* debug output */
00199     char buffer[512];
00200 
00201     SetDParamStr(0, grfconfig->name);
00202     GetString(buffer, STR_NEWGRF_BROKEN, lastof(buffer));
00203     DEBUG(grf, 0, "%s", buffer + 3);
00204 
00205     SetDParam(1, u->engine_type);
00206     GetString(buffer, STR_NEWGRF_BROKEN_VEHICLE_LENGTH, lastof(buffer));
00207     DEBUG(grf, 0, "%s", buffer + 3);
00208 
00209     if (!_networking) _pause_game = -1;
00210   }
00211 }
00212 
00214 void CheckTrainsLengths()
00215 {
00216   const Vehicle *v;
00217 
00218   FOR_ALL_VEHICLES(v) {
00219     if (v->type == VEH_TRAIN && v->First() == v && !(v->vehstatus & VS_CRASHED)) {
00220       for (const Vehicle *u = v, *w = v->Next(); w != NULL; u = w, w = w->Next()) {
00221         if (u->u.rail.track != TRACK_BIT_DEPOT) {
00222           if ((w->u.rail.track != TRACK_BIT_DEPOT &&
00223               max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->u.rail.cached_veh_length) ||
00224               (w->u.rail.track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) {
00225             SetDParam(0, v->index);
00226             SetDParam(1, v->owner);
00227             ShowErrorMessage(INVALID_STRING_ID, STR_BROKEN_VEHICLE_LENGTH, 0, 0);
00228 
00229             if (!_networking) _pause_game = -1;
00230           }
00231         }
00232       }
00233     }
00234   }
00235 }
00236 
00244 void TrainConsistChanged(Vehicle *v, bool same_length)
00245 {
00246   uint16 max_speed = 0xFFFF;
00247 
00248   assert(v->type == VEH_TRAIN);
00249   assert(IsFrontEngine(v) || IsFreeWagon(v));
00250 
00251   const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
00252   EngineID first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE;
00253   v->u.rail.cached_total_length = 0;
00254   v->u.rail.compatible_railtypes = RAILTYPES_NONE;
00255 
00256   bool train_can_tilt = true;
00257 
00258   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00259     const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
00260 
00261     /* Check the v->first cache. */
00262     assert(u->First() == v);
00263 
00264     /* update the 'first engine' */
00265     u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine;
00266     u->u.rail.railtype = rvi_u->railtype;
00267 
00268     /* Set user defined data to its default value */
00269     u->u.rail.user_def_data = rvi_u->user_def_data;
00270   }
00271 
00272   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00273     /* Update user defined data (must be done before other properties) */
00274     u->u.rail.user_def_data = GetVehicleProperty(u, 0x25, u->u.rail.user_def_data);
00275   }
00276 
00277   for (Vehicle *u = v; u != NULL; u = u->Next()) {
00278     const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
00279 
00280     if (!HasBit(EngInfo(u->engine_type)->misc_flags, EF_RAIL_TILTS)) train_can_tilt = false;
00281 
00282     if (IsTrainEngine(u)) first_engine = u->engine_type;
00283 
00284     /* Cache wagon override sprite group. NULL is returned if there is none */
00285     u->u.rail.cached_override = GetWagonOverrideSpriteSet(u->engine_type, u->cargo_type, u->u.rail.first_engine);
00286 
00287     /* Reset color map */
00288     u->colormap = PAL_NONE;
00289 
00290     if (rvi_u->visual_effect != 0) {
00291       u->u.rail.cached_vis_effect = rvi_u->visual_effect;
00292     } else {
00293       if (IsTrainWagon(u) || IsArticulatedPart(u)) {
00294         /* Wagons and articulated parts have no effect by default */
00295         u->u.rail.cached_vis_effect = 0x40;
00296       } else if (rvi_u->engclass == 0) {
00297         /* Steam is offset by -4 units */
00298         u->u.rail.cached_vis_effect = 4;
00299       } else {
00300         /* Diesel fumes and sparks come from the centre */
00301         u->u.rail.cached_vis_effect = 8;
00302       }
00303     }
00304 
00305     if (!IsArticulatedPart(u)) {
00306       /* Check powered wagon / visual effect callback */
00307       if (HasBit(EngInfo(u->engine_type)->callbackmask, CBM_TRAIN_WAGON_POWER)) {
00308         uint16 callback = GetVehicleCallback(CBID_TRAIN_WAGON_POWER, 0, 0, u->engine_type, u);
00309 
00310         if (callback != CALLBACK_FAILED) u->u.rail.cached_vis_effect = GB(callback, 0, 8);
00311       }
00312 
00313       if (rvi_v->pow_wag_power != 0 && rvi_u->railveh_type == RAILVEH_WAGON &&
00314         UsesWagonOverride(u) && !HasBit(u->u.rail.cached_vis_effect, 7)) {
00315         /* wagon is powered */
00316         SetBit(u->u.rail.flags, VRF_POWEREDWAGON); // cache 'powered' status
00317       } else {
00318         ClrBit(u->u.rail.flags, VRF_POWEREDWAGON);
00319       }
00320 
00321       /* Do not count powered wagons for the compatible railtypes, as wagons always
00322          have railtype normal */
00323       if (rvi_u->power > 0) {
00324         v->u.rail.compatible_railtypes |= GetRailTypeInfo(u->u.rail.railtype)->powered_railtypes;
00325       }
00326 
00327       /* Some electric engines can be allowed to run on normal rail. It happens to all
00328        * existing electric engines when elrails are disabled and then re-enabled */
00329       if (HasBit(u->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
00330         u->u.rail.railtype = RAILTYPE_RAIL;
00331         u->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
00332       }
00333 
00334       /* max speed is the minimum of the speed limits of all vehicles in the consist */
00335       if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) && !UsesWagonOverride(u)) {
00336         uint16 speed = GetVehicleProperty(u, 0x09, rvi_u->max_speed);
00337         if (speed != 0) max_speed = min(speed, max_speed);
00338       }
00339     }
00340 
00341     if (u->cargo_type == rvi_u->cargo_type && u->cargo_subtype == 0) {
00342       /* Set cargo capacity if we've not been refitted */
00343       u->cargo_cap = GetVehicleProperty(u, 0x14, rvi_u->capacity);
00344     }
00345 
00346     /* check the vehicle length (callback) */
00347     uint16 veh_len = CALLBACK_FAILED;
00348     if (HasBit(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) {
00349       veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
00350     }
00351     if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
00352     veh_len = 8 - Clamp(veh_len, 0, u->Next() == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
00353 
00354     /* verify length hasn't changed */
00355     if (same_length && veh_len != u->u.rail.cached_veh_length) RailVehicleLengthChanged(u);
00356 
00357     /* update vehicle length? */
00358     if (!same_length) u->u.rail.cached_veh_length = veh_len;
00359 
00360     v->u.rail.cached_total_length += u->u.rail.cached_veh_length;
00361   }
00362 
00363   /* store consist weight/max speed in cache */
00364   v->u.rail.cached_max_speed = max_speed;
00365   v->u.rail.cached_tilt = train_can_tilt;
00366 
00367   /* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
00368   TrainCargoChanged(v);
00369 
00370   if (IsFrontEngine(v)) {
00371     UpdateTrainAcceleration(v);
00372     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
00373   }
00374 }
00375 
00376 enum AccelType {
00377   AM_ACCEL,
00378   AM_BRAKE
00379 };
00380 
00381 static bool TrainShouldStop(const Vehicle* v, TileIndex tile)
00382 {
00383   const Order* o = &v->current_order;
00384   StationID sid = GetStationIndex(tile);
00385 
00386   assert(v->type == VEH_TRAIN);
00387   /* When does a train drive through a station
00388    * first we deal with the "new nonstop handling" */
00389   if (_patches.new_nonstop && o->flags & OFB_NON_STOP && sid == o->dest) {
00390     return false;
00391   }
00392 
00393   if (v->last_station_visited == sid) return false;
00394 
00395   if (sid != o->dest && (o->flags & OFB_NON_STOP || _patches.new_nonstop)) {
00396     return false;
00397   }
00398 
00399   return true;
00400 }
00401 
00403 static int GetTrainAcceleration(Vehicle *v, bool mode)
00404 {
00405   static const int absolute_max_speed = 2000;
00406   int max_speed = absolute_max_speed;
00407   int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
00408   int curvecount[2] = {0, 0};
00409 
00410   /*first find the curve speed limit */
00411   int numcurve = 0;
00412   int sum = 0;
00413   int pos = 0;
00414   int lastpos = -1;
00415   for (const Vehicle *u = v; u->Next() != NULL; u = u->Next(), pos++) {
00416     Direction this_dir = u->direction;
00417     Direction next_dir = u->Next()->direction;
00418 
00419     DirDiff dirdiff = DirDifference(this_dir, next_dir);
00420     if (dirdiff == DIRDIFF_SAME) continue;
00421 
00422     if (dirdiff == DIRDIFF_45LEFT) curvecount[0]++;
00423     if (dirdiff == DIRDIFF_45RIGHT) curvecount[1]++;
00424     if (dirdiff == DIRDIFF_45LEFT || dirdiff == DIRDIFF_45RIGHT) {
00425       if (lastpos != -1) {
00426         numcurve++;
00427         sum += pos - lastpos;
00428         if (pos - lastpos == 1) {
00429           max_speed = 88;
00430         }
00431       }
00432       lastpos = pos;
00433     }
00434 
00435     /*if we have a 90 degree turn, fix the speed limit to 60 */
00436     if (dirdiff == DIRDIFF_90LEFT || dirdiff == DIRDIFF_90RIGHT) {
00437       max_speed = 61;
00438     }
00439   }
00440 
00441   if ((curvecount[0] != 0 || curvecount[1] != 0) && max_speed > 88) {
00442     int total = curvecount[0] + curvecount[1];
00443 
00444     if (curvecount[0] == 1 && curvecount[1] == 1) {
00445       max_speed = absolute_max_speed;
00446     } else if (total > 1) {
00447       if (numcurve > 0) sum /= numcurve;
00448       max_speed = 232 - (13 - Clamp(sum, 1, 12)) * (13 - Clamp(sum, 1, 12));
00449     }
00450   }
00451 
00452   if (max_speed != absolute_max_speed) {
00453     /* Apply the engine's rail type curve speed advantage, if it slowed by curves */
00454     const RailtypeInfo *rti = GetRailTypeInfo(v->u.rail.railtype);
00455     max_speed += (max_speed / 2) * rti->curve_speed;
00456 
00457     if (v->u.rail.cached_tilt) {
00458       /* Apply max_speed bonus of 20% for a tilting train */
00459       max_speed += max_speed / 5;
00460     }
00461   }
00462 
00463   if (IsTileType(v->tile, MP_STATION) && IsFrontEngine(v)) {
00464     if (TrainShouldStop(v, v->tile)) {
00465       int station_length = GetStationByTile(v->tile)->GetPlatformLength(v->tile, DirToDiagDir(v->direction));
00466 
00467       int st_max_speed = 120;
00468 
00469       int delta_v = v->cur_speed / (station_length + 1);
00470       if (v->max_speed > (v->cur_speed - delta_v)) {
00471         st_max_speed = v->cur_speed - (delta_v / 10);
00472       }
00473 
00474       st_max_speed = max(st_max_speed, 25 * station_length);
00475       max_speed = min(max_speed, st_max_speed);
00476     }
00477   }
00478 
00479   int mass = v->u.rail.cached_weight;
00480   int power = v->u.rail.cached_power * 746;
00481   max_speed = min(max_speed, v->u.rail.cached_max_speed);
00482 
00483   int num = 0; //number of vehicles, change this into the number of axles later
00484   int incl = 0;
00485   int drag_coeff = 20; //[1e-4]
00486   for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00487     num++;
00488     drag_coeff += 3;
00489 
00490     if (u->u.rail.track == TRACK_BIT_DEPOT) max_speed = min(max_speed, 61);
00491 
00492     if (HasBit(u->u.rail.flags, VRF_GOINGUP)) {
00493       incl += u->u.rail.cached_veh_weight * 60; //3% slope, quite a bit actually
00494     } else if (HasBit(u->u.rail.flags, VRF_GOINGDOWN)) {
00495       incl -= u->u.rail.cached_veh_weight * 60;
00496     }
00497   }
00498 
00499   v->max_speed = max_speed;
00500 
00501   const int area = 120;
00502   const int friction = 35; //[1e-3]
00503   int resistance;
00504   if (v->u.rail.railtype != RAILTYPE_MAGLEV) {
00505     resistance = 13 * mass / 10;
00506     resistance += 60 * num;
00507     resistance += friction * mass * speed / 1000;
00508     resistance += (area * drag_coeff * speed * speed) / 10000;
00509   } else {
00510     resistance = (area * (drag_coeff / 2) * speed * speed) / 10000;
00511   }
00512   resistance += incl;
00513   resistance *= 4; //[N]
00514 
00515   /* Due to the mph to m/s conversion below, at speeds below 3 mph the force is
00516    * actually double the train's power */
00517   const int max_te = v->u.rail.cached_max_te; // [N]
00518   int force;
00519   if (speed > 2) {
00520     switch (v->u.rail.railtype) {
00521       case RAILTYPE_RAIL:
00522       case RAILTYPE_ELECTRIC:
00523       case RAILTYPE_MONO:
00524         force = power / speed; //[N]
00525         force *= 22;
00526         force /= 10;
00527         if (mode == AM_ACCEL && force > max_te) force = max_te;
00528         break;
00529 
00530       default: NOT_REACHED();
00531       case RAILTYPE_MAGLEV:
00532         force = power / 25;
00533         break;
00534     }
00535   } else {
00536     /* "kickoff" acceleration */
00537     force = (mode == AM_ACCEL && v->u.rail.railtype != RAILTYPE_MAGLEV) ? min(max_te, power) : power;
00538     force = max(force, (mass * 8) + resistance);
00539   }
00540 
00541   if (force <= 0) force = 10000;
00542 
00543   if (v->u.rail.railtype != RAILTYPE_MAGLEV) force = min(force, mass * 10 * 200);
00544 
00545   if (mode == AM_ACCEL) {
00546     return (force - resistance) / (mass * 4);
00547   } else {
00548     return min((-force - resistance) / (mass * 4), -10000 / (mass * 4));
00549   }
00550 }
00551 
00552 void UpdateTrainAcceleration(Vehicle* v)
00553 {
00554   assert(IsFrontEngine(v));
00555 
00556   v->max_speed = v->u.rail.cached_max_speed;
00557 
00558   uint power = v->u.rail.cached_power;
00559   uint weight = v->u.rail.cached_weight;
00560   assert(weight != 0);
00561   v->acceleration = Clamp(power / weight * 4, 1, 255);
00562 }
00563 
00564 int Train::GetImage(Direction direction) const
00565 {
00566   int img = this->spritenum;
00567   int base;
00568 
00569   if (HasBit(this->u.rail.flags, VRF_REVERSE_DIRECTION)) direction = ReverseDir(direction);
00570 
00571   if (is_custom_sprite(img)) {
00572     base = GetCustomVehicleSprite(this, (Direction)(direction + 4 * IS_CUSTOM_SECONDHEAD_SPRITE(img)));
00573     if (base != 0) return base;
00574     img = _orig_rail_vehicle_info[this->engine_type].image_index;
00575   }
00576 
00577   base = _engine_sprite_base[img] + ((direction + _engine_sprite_add[img]) & _engine_sprite_and[img]);
00578 
00579   if (this->cargo.Count() >= this->cargo_cap / 2U) base += _wagon_full_adder[img];
00580   return base;
00581 }
00582 
00583 void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal)
00584 {
00585   const RailVehicleInfo *rvi = RailVehInfo(engine);
00586 
00587   int img = rvi->image_index;
00588   SpriteID image = 0;
00589 
00590   if (is_custom_sprite(img)) {
00591     image = GetCustomVehicleIcon(engine, DIR_W);
00592     if (image == 0) {
00593       img = _orig_rail_vehicle_info[engine].image_index;
00594     } else {
00595       y += _traininfo_vehicle_pitch;
00596     }
00597   }
00598   if (image == 0) {
00599     image = (6 & _engine_sprite_and[img]) + _engine_sprite_base[img];
00600   }
00601 
00602   if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
00603     DrawSprite(image, pal, x - 14, y);
00604     x += 15;
00605     image = 0;
00606     if (is_custom_sprite(img)) {
00607       image = GetCustomVehicleIcon(engine, DIR_E);
00608       if (image == 0) img = _orig_rail_vehicle_info[engine].image_index;
00609     }
00610     if (image == 0) {
00611       image =
00612         ((6 + _engine_sprite_add[img + 1]) & _engine_sprite_and[img + 1]) +
00613         _engine_sprite_base[img + 1];
00614     }
00615   }
00616   DrawSprite(image, pal, x, y);
00617 }
00618 
00619 static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags)
00620 {
00621   const RailVehicleInfo *rvi = RailVehInfo(engine);
00622   CommandCost value(EXPENSES_NEW_VEHICLES, (GetEngineProperty(engine, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8);
00623 
00624   uint num_vehicles = 1 + CountArticulatedParts(engine, false);
00625 
00626   if (!(flags & DC_QUERY_COST)) {
00627     /* Allow for the wagon and the articulated parts, plus one to "terminate" the list. */
00628     Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
00629     memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
00630 
00631     if (!Vehicle::AllocateList(vl, num_vehicles))
00632       return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
00633 
00634     if (flags & DC_EXEC) {
00635       Vehicle *v = vl[0];
00636       v->spritenum = rvi->image_index;
00637 
00638       Vehicle *u = NULL;
00639 
00640       Vehicle *w;
00641       FOR_ALL_VEHICLES(w) {
00642         if (w->type == VEH_TRAIN && w->tile == tile &&
00643             IsFreeWagon(w) && w->engine_type == engine &&
00644             !HASBITS(w->vehstatus, VS_CRASHED)) {          
00645           u = GetLastVehicleInChain(w);
00646           break;
00647         }
00648       }
00649 
00650       v = new (v) Train();
00651       v->engine_type = engine;
00652 
00653       DiagDirection dir = GetRailDepotDirection(tile);
00654 
00655       v->direction = DiagDirToDir(dir);
00656       v->tile = tile;
00657 
00658       int x = TileX(tile) * TILE_SIZE | _vehicle_initial_x_fract[dir];
00659       int y = TileY(tile) * TILE_SIZE | _vehicle_initial_y_fract[dir];
00660 
00661       v->x_pos = x;
00662       v->y_pos = y;
00663       v->z_pos = GetSlopeZ(x, y);
00664       v->owner = _current_player;
00665       v->u.rail.track = TRACK_BIT_DEPOT;
00666       v->vehstatus = VS_HIDDEN | VS_DEFPAL;
00667 
00668       v->subtype = 0;
00669       SetTrainWagon(v);
00670 
00671       if (u != NULL) {
00672         u->SetNext(v);
00673       } else {
00674         SetFreeWagon(v);
00675         InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
00676       }
00677 
00678       v->cargo_type = rvi->cargo_type;
00679       v->cargo_subtype = 0;
00680       v->cargo_cap = rvi->capacity;
00681       v->value = value.GetCost();
00682 //      v->day_counter = 0;
00683 
00684       v->u.rail.railtype = rvi->railtype;
00685 
00686       v->build_year = _cur_year;
00687       v->cur_image = 0xAC2;
00688       v->random_bits = VehicleRandomBits();
00689 
00690       v->group_id = DEFAULT_GROUP;
00691 
00692       AddArticulatedParts(vl, VEH_TRAIN);
00693 
00694       _new_vehicle_id = v->index;
00695 
00696       VehiclePositionChanged(v);
00697       TrainConsistChanged(v->First(), false);
00698       UpdateTrainGroupID(v->First());
00699 
00700       InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
00701       if (IsLocalPlayer()) {
00702         InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
00703       }
00704       GetPlayer(_current_player)->num_engines[engine]++;
00705     }
00706   }
00707 
00708   return value;
00709 }
00710 
00712 static void NormalizeTrainVehInDepot(const Vehicle* u)
00713 {
00714   const Vehicle* v;
00715 
00716   FOR_ALL_VEHICLES(v) {
00717     if (v->type == VEH_TRAIN && IsFreeWagon(v) &&
00718         v->tile == u->tile &&
00719         v->u.rail.track == TRACK_BIT_DEPOT) {
00720       if (CmdFailed(DoCommand(0, v->index | (u->index << 16), 1, DC_EXEC,
00721           CMD_MOVE_RAIL_VEHICLE)))
00722         break;
00723     }
00724   }
00725 }
00726 
00727 static CommandCost EstimateTrainCost(EngineID engine, const RailVehicleInfo* rvi)
00728 {
00729   return CommandCost(EXPENSES_NEW_VEHICLES, GetEngineProperty(engine, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5);
00730 }
00731 
00732 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building)
00733 {
00734   u = new (u) Train();
00735   u->direction = v->direction;
00736   u->owner = v->owner;
00737   u->tile = v->tile;
00738   u->x_pos = v->x_pos;
00739   u->y_pos = v->y_pos;
00740   u->z_pos = v->z_pos;
00741   u->u.rail.track = TRACK_BIT_DEPOT;
00742   u->vehstatus = v->vehstatus & ~VS_STOPPED;
00743   u->subtype = 0;
00744   SetMultiheaded(u);
00745   u->spritenum = v->spritenum + 1;
00746   u->cargo_type = v->cargo_type;
00747   u->cargo_subtype = v->cargo_subtype;
00748   u->cargo_cap = v->cargo_cap;
00749   u->u.rail.railtype = v->u.rail.railtype;
00750   if (building) v->SetNext(u);
00751   u->engine_type = v->engine_type;
00752   u->build_year = v->build_year;
00753   if (building) v->value >>= 1;
00754   u->value = v->value;
00755   u->cur_image = 0xAC2;
00756   u->random_bits = VehicleRandomBits();
00757   VehiclePositionChanged(u);
00758 }
00759 
00766 CommandCost CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
00767 {
00768   /* Check if the engine-type is valid (for the player) */
00769   if (!IsEngineBuildable(p1, VEH_TRAIN, _current_player)) return_cmd_error(STR_RAIL_VEHICLE_NOT_AVAILABLE);
00770 
00771   /* Check if the train is actually being built in a depot belonging
00772    * to the player. Doesn't matter if only the cost is queried */
00773   if (!(flags & DC_QUERY_COST)) {
00774     if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
00775     if (!IsTileOwner(tile, _current_player)) return CMD_ERROR;
00776   }
00777 
00778   const RailVehicleInfo *rvi = RailVehInfo(p1);
00779 
00780   /* Check if depot and new engine uses the same kind of tracks */
00781   /* We need to see if the engine got power on the tile to avoid eletric engines in non-electric depots */
00782   if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
00783 
00784   if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags);
00785 
00786   CommandCost value = EstimateTrainCost(p1, rvi);
00787 
00788   uint num_vehicles =
00789     (rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
00790     CountArticulatedParts(p1, false);
00791 
00792   if (!(flags & DC_QUERY_COST)) {
00793     /* Allow for the dual-heads and the articulated parts, plus one to "terminate" the list. */
00794     Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
00795     memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
00796 
00797     if (!Vehicle::AllocateList(vl, num_vehicles))
00798       return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
00799 
00800     Vehicle *v = vl[0];
00801 
00802     UnitID unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_TRAIN);
00803     if (unit_num > _patches.max_trains)
00804       return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
00805 
00806     if (flags & DC_EXEC) {
00807       DiagDirection dir = GetRailDepotDirection(tile);
00808       int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
00809       int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
00810 
00811       v = new (v) Train();
00812       v->unitnumber = unit_num;
00813       v->direction = DiagDirToDir(dir);
00814       v->tile = tile;
00815       v->owner = _current_player;
00816       v->x_pos = x;
00817       v->y_pos = y;
00818       v->z_pos = GetSlopeZ(x, y);
00819       v->running_ticks = 0;
00820       v->u.rail.track = TRACK_BIT_DEPOT;
00821       v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
00822       v->spritenum = rvi->image_index;
00823       v->cargo_type = rvi->cargo_type;
00824       v->cargo_subtype = 0;
00825       v->cargo_cap = rvi->capacity;
00826       v->max_speed = rvi->max_speed;
00827       v->value = value.GetCost();
00828       v->last_station_visited = INVALID_STATION;
00829       v->dest_tile = 0;
00830 
00831       v->engine_type = p1;
00832 
00833       const Engine *e = GetEngine(p1);
00834       v->reliability = e->reliability;
00835       v->reliability_spd_dec = e->reliability_spd_dec;
00836       v->max_age = e->lifelength * 366;
00837 
00838       v->name = NULL;
00839       v->u.rail.railtype = rvi->railtype;
00840       _new_vehicle_id = v->index;
00841 
00842       v->service_interval = _patches.servint_trains;
00843       v->date_of_last_service = _date;
00844       v->build_year = _cur_year;
00845       v->cur_image = 0xAC2;
00846       v->random_bits = VehicleRandomBits();
00847 
00848       v->vehicle_flags = 0;
00849       if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
00850 
00851       v->group_id = DEFAULT_GROUP;
00852 
00853       v->subtype = 0;
00854       SetFrontEngine(v);
00855       SetTrainEngine(v);
00856 
00857       VehiclePositionChanged(v);
00858 
00859       if (rvi->railveh_type == RAILVEH_MULTIHEAD) {
00860         SetMultiheaded(v);
00861         AddRearEngineToMultiheadedTrain(vl[0], vl[1], true);
00862         /* Now we need to link the front and rear engines together
00863          * other_multiheaded_part is the pointer that links to the other half of the engine
00864          * vl[0] is the front and vl[1] is the rear
00865          */
00866         vl[0]->u.rail.other_multiheaded_part = vl[1];
00867         vl[1]->u.rail.other_multiheaded_part = vl[0];
00868       } else {
00869         AddArticulatedParts(vl, VEH_TRAIN);
00870       }
00871 
00872       TrainConsistChanged(v, false);
00873       UpdateTrainGroupID(v);
00874 
00875       if (!HasBit(p2, 1) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
00876         NormalizeTrainVehInDepot(v);
00877       }
00878 
00879       InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
00880       RebuildVehicleLists();
00881       InvalidateWindow(WC_COMPANY, v->owner);
00882       if (IsLocalPlayer())
00883         InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window
00884 
00885       GetPlayer(_current_player)->num_engines[p1]++;
00886     }
00887   }
00888 
00889   return value;
00890 }
00891 
00892 
00893 /* Check if all the wagons of the given train are in a depot, returns the
00894  * number of cars (including loco) then. If not it returns -1 */
00895 int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped)
00896 {
00897   TileIndex tile = v->tile;
00898 
00899   /* check if stopped in a depot */
00900   if (!IsTileDepotType(tile, TRANSPORT_RAIL) || v->cur_speed != 0) return -1;
00901 
00902   int count = 0;
00903   for (; v != NULL; v = v->Next()) {
00904     /* This count is used by the depot code to determine the number of engines
00905      * in the consist. Exclude articulated parts so that autoreplacing to
00906      * engines with more articulated parts than before works correctly.
00907      *
00908      * Also skip counting rear ends of multiheaded engines */
00909     if (!IsArticulatedPart(v) && !IsRearDualheaded(v)) count++;
00910     if (v->u.rail.track != TRACK_BIT_DEPOT || v->tile != tile ||
00911         (IsFrontEngine(v) && needs_to_be_stopped && !(v->vehstatus & VS_STOPPED))) {
00912       return -1;
00913     }
00914   }
00915 
00916   return count;
00917 }
00918 
00919 /* Used to check if the train is inside the depot and verifying that the VS_STOPPED flag is set */
00920 int CheckTrainStoppedInDepot(const Vehicle *v)
00921 {
00922   return CheckTrainInDepot(v, true);
00923 }
00924 
00925 /* Used to check if the train is inside the depot, but not checking the VS_STOPPED flag */
00926 inline bool CheckTrainIsInsideDepot(const Vehicle *v)
00927 {
00928   return CheckTrainInDepot(v, false) > 0;
00929 }
00930 
00937 static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first)
00938 {
00939   /* unlinking the first vehicle of the chain? */
00940   if (v == first) {
00941     v = GetNextVehicle(v);
00942     if (v == NULL) return NULL;
00943 
00944     if (IsTrainWagon(v)) SetFreeWagon(v);
00945 
00946     return v;
00947   }
00948 
00949   Vehicle *u;
00950   for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {}
00951   GetLastEnginePart(u)->SetNext(GetNextVehicle(v));
00952   return first;
00953 }
00954 
00955 static Vehicle *FindGoodVehiclePos(const Vehicle *src)
00956 {
00957   Vehicle *dst;
00958   EngineID eng = src->engine_type;
00959   TileIndex tile = src->tile;
00960 
00961   FOR_ALL_VEHICLES(dst) {
00962     if (dst->type == VEH_TRAIN && IsFreeWagon(dst) && dst->tile == tile && !HASBITS(dst->vehstatus, VS_CRASHED)) {
00963       /* check so all vehicles in the line have the same engine. */
00964       Vehicle *v = dst;
00965 
00966       while (v->engine_type == eng) {
00967         v = v->Next();
00968         if (v == NULL) return dst;
00969       }
00970     }
00971   }
00972 
00973   return NULL;
00974 }
00975 
00976 /*
00977  * add a vehicle v behind vehicle dest
00978  * use this function since it sets flags as needed
00979  */
00980 static void AddWagonToConsist(Vehicle *v, Vehicle *dest)
00981 {
00982   UnlinkWagon(v, v->First());
00983   if (dest == NULL) return;
00984 
00985   Vehicle *next = dest->Next();
00986   v->SetNext(NULL);
00987   dest->SetNext(v);
00988   v->SetNext(next);
00989   ClearFreeWagon(v);
00990   ClearFrontEngine(v);
00991 }
00992 
00993 /*
00994  * move around on the train so rear engines are placed correctly according to the other engines
00995  * always call with the front engine
00996  */
00997 static void NormaliseTrainConsist(Vehicle *v)
00998 {
00999   if (IsFreeWagon(v)) return;
01000 
01001   assert(IsFrontEngine(v));
01002 
01003   for (; v != NULL; v = GetNextVehicle(v)) {
01004     if (!IsMultiheaded(v) || !IsTrainEngine(v)) continue;
01005 
01006     /* make sure that there are no free cars before next engine */
01007     Vehicle *u;
01008     for (u = v; u->Next() != NULL && !IsTrainEngine(u->Next()); u = u->Next()) {}
01009 
01010     if (u == v->u.rail.other_multiheaded_part) continue;
01011     AddWagonToConsist(v->u.rail.other_multiheaded_part, u);
01012   }
01013 }
01014 
01023 CommandCost CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
01024 {
01025   VehicleID s = GB(p1, 0, 16);
01026   VehicleID d = GB(p1, 16, 16);
01027 
01028   if (!IsValidVehicleID(s)) return CMD_ERROR;
01029 
01030   Vehicle *src = GetVehicle(s);
01031 
01032   if (src->type != VEH_TRAIN || !CheckOwnership(src->owner)) return CMD_ERROR;
01033 
01034   /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */
01035   if (HASBITS(src->vehstatus, VS_CRASHED)) return CMD_ERROR;
01036 
01037   /* if nothing is selected as destination, try and find a matching vehicle to drag to. */
01038   Vehicle *dst;
01039   if (d == INVALID_VEHICLE) {
01040     dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
01041   } else {
01042     if (!IsValidVehicleID(d)) return CMD_ERROR;
01043     dst = GetVehicle(d);
01044     if (dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR;
01045 
01046     /* Do not allow appending to crashed vehicles, too */
01047     if (HASBITS(dst->vehstatus, VS_CRASHED)) return CMD_ERROR;
01048   }
01049 
01050   /* if an articulated part is being handled, deal with its parent vehicle */
01051   while (IsArticulatedPart(src)) src = src->Previous();
01052   if (dst != NULL) {
01053     while (IsArticulatedPart(dst)) dst = dst->Previous();
01054   }
01055 
01056   /* don't move the same vehicle.. */
01057   if (src == dst) return CommandCost();
01058 
01059   /* locate the head of the two chains */
01060   Vehicle *src_head = src->First();
01061   Vehicle *dst_head;
01062   if (dst != NULL) {
01063     dst_head = dst->First();
01064     if (dst_head->tile != src_head->tile) return CMD_ERROR;
01065     /* Now deal with articulated part of destination wagon */
01066     dst = GetLastEnginePart(dst);
01067   } else {
01068     dst_head = NULL;
01069   }
01070 
01071   if (IsRearDualheaded(src)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
01072 
01073   /* when moving all wagons, we can't have the same src_head and dst_head */
01074   if (HasBit(p2, 0) && src_head == dst_head) return CommandCost();
01075 
01076   {
01077     int max_len = _patches.mammoth_trains ? 100 : 10;
01078 
01079     /* check if all vehicles in the source train are stopped inside a depot. */
01080     int src_len = CheckTrainStoppedInDepot(src_head);
01081     if (src_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
01082 
01083     /* check the destination row if the source and destination aren't the same. */
01084     if (src_head != dst_head) {
01085       int dst_len = 0;
01086 
01087       if (dst_head != NULL) {
01088         /* check if all vehicles in the dest train are stopped. */
01089         dst_len = CheckTrainStoppedInDepot(dst_head);
01090         if (dst_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
01091       }
01092 
01093       /* We are moving between rows, so only count the wagons from the source
01094        * row that are being moved. */
01095       if (HasBit(p2, 0)) {
01096         const Vehicle *u;
01097         for (u = src_head; u != src && u != NULL; u = GetNextVehicle(u))
01098           src_len--;
01099       } else {
01100         /* If moving only one vehicle, just count that. */
01101         src_len = 1;
01102       }
01103 
01104       if (src_len + dst_len > max_len) {
01105         /* Abort if we're adding too many wagons to a train. */
01106         if (dst_head != NULL && IsFrontEngine(dst_head)) return_cmd_error(STR_8819_TRAIN_TOO_LONG);
01107         /* Abort if we're making a train on a new row. */
01108         if (dst_head == NULL && IsTrainEngine(src)) return_cmd_error(STR_8819_TRAIN_TOO_LONG);
01109       }
01110     } else {
01111       /* Abort if we're creating a new train on an existing row. */
01112       if (src_len > max_len && src == src_head && IsTrainEngine(GetNextVehicle(src_head)))
01113         return_cmd_error(STR_8819_TRAIN_TOO_LONG);
01114     }
01115   }
01116 
01117   /* moving a loco to a new line?, then we need to assign a unitnumber. */
01118   if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) {
01119     UnitID unit_num = GetFreeUnitNumber(VEH_TRAIN);
01120     if (unit_num > _patches.max_trains)
01121       return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
01122 
01123     if (flags & DC_EXEC) src->unitnumber = unit_num;
01124   }
01125 
01126   /* When we move the front vehicle, the second vehicle might need a unitnumber */
01127   if (!HasBit(p2, 0) && (IsFreeWagon(src) || IsFrontEngine(src)) && (flags & DC_AUTOREPLACE) == 0) {
01128     Vehicle *second = GetNextUnit(src);
01129     if (second != NULL && IsTrainEngine(second) && GetFreeUnitNumber(VEH_TRAIN) > _patches.max_trains) {
01130       return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
01131     }
01132   }
01133 
01134   /*
01135    * Check whether the vehicles in the source chain are in the destination
01136    * chain. This can easily be done by checking whether the first vehicle
01137    * of the source chain is in the destination chain as the Next/Previous
01138    * pointers always make a doubly linked list of it where the assumption
01139    * v->Next()->Previous() == v holds (assuming v->Next() != NULL).
01140    */
01141   bool src_in_dst = false;
01142   for (Vehicle *v = dst_head; !src_in_dst && v != NULL; v = v->Next()) src_in_dst = v == src;
01143 
01144   /*
01145    * If the source chain is in the destination chain then the user is
01146    * only reordering the vehicles, thus not attaching a new vehicle.
01147    * Therefor the 'allow wagon attach' callback does not need to be
01148    * called. If it would be called strange things would happen because
01149    * one 'attaches' an already 'attached' vehicle causing more trouble
01150    * than it actually solves (infinite loops and such).
01151    */
01152   if (dst_head != NULL && !src_in_dst) {
01153     /*
01154      * When performing the 'allow wagon attach' callback, we have to check
01155      * that for each and every wagon, not only the first one. This means
01156      * that we have to test one wagon, attach it to the train and then test
01157      * the next wagon till we have reached the end. We have to restore it
01158      * to the state it was before we 'tried' attaching the train when the
01159      * attaching fails or succeeds because we are not 'only' doing this
01160      * in the DC_EXEC state.
01161      */
01162     Vehicle *dst_tail = dst_head;
01163     while (dst_tail->Next() != NULL) dst_tail = dst_tail->Next();
01164 
01165     Vehicle *orig_tail = dst_tail;
01166     Vehicle *next_to_attach = src;
01167     Vehicle *src_previous = src->Previous();
01168 
01169     while (next_to_attach != NULL) {
01170       /* Back up and clear the first_engine data to avoid using wagon override group */
01171       EngineID first_engine = next_to_attach->u.rail.first_engine;
01172       next_to_attach->u.rail.first_engine = INVALID_ENGINE;
01173 
01174       uint16 callback = GetVehicleCallbackParent(CBID_TRAIN_ALLOW_WAGON_ATTACH, 0, 0, dst_head->engine_type, next_to_attach, dst_head);
01175 
01176       /* Restore original first_engine data */
01177       next_to_attach->u.rail.first_engine = first_engine;
01178 
01179       if (callback != CALLBACK_FAILED) {
01180         StringID error = STR_NULL;
01181 
01182         if (callback == 0xFD) error = STR_INCOMPATIBLE_RAIL_TYPES;
01183         if (callback < 0xFD) error = GetGRFStringID(GetEngineGRFID(dst_head->engine_type), 0xD000 + callback);
01184 
01185         if (error != STR_NULL) {
01186           /*
01187            * The attaching is not allowed. In this case 'next_to_attach'
01188            * can contain some vehicles of the 'source' and the destination
01189            * train can have some too. We 'just' add the to-be added wagons
01190            * to the chain and then split it where it was previously
01191            * separated, i.e. the tail of the original destination train.
01192            * Furthermore the 'previous' link of the original source vehicle needs
01193            * to be restored, otherwise the train goes missing in the depot.
01194            */
01195           dst_tail->SetNext(next_to_attach);
01196           orig_tail->SetNext(NULL);
01197           if (src_previous != NULL) src_previous->SetNext(src);
01198 
01199           return_cmd_error(error);
01200         }
01201       }
01202 
01203       /* Only check further wagons if told to move the chain */
01204       if (!HasBit(p2, 0)) break;
01205 
01206       /*
01207        * Adding a next wagon to the chain so we can test the other wagons.
01208        * First 'take' the first wagon from 'next_to_attach' and move it
01209        * to the next wagon. Then add that to the tail of the destination
01210        * train and update the tail with the new vehicle.
01211        */
01212       Vehicle *to_add = next_to_attach;
01213       next_to_attach = next_to_attach->Next();
01214 
01215       to_add->SetNext(NULL);
01216       dst_tail->SetNext(to_add);
01217       dst_tail = dst_tail->Next();
01218     }
01219 
01220     /*
01221      * When we reach this the attaching is allowed. It also means that the
01222      * chain of vehicles to attach is empty, so we do not need to merge that.
01223      * This means only the splitting needs to be done.
01224      * Furthermore the 'previous' link of the original source vehicle needs
01225      * to be restored, otherwise the train goes missing in the depot.
01226      */
01227     orig_tail->SetNext(NULL);
01228     if (src_previous != NULL) src_previous->SetNext(src);
01229   }
01230 
01231   /* do it? */
01232   if (flags & DC_EXEC) {
01233     /* If we move the front Engine and if the second vehicle is not an engine
01234        add the whole vehicle to the DEFAULT_GROUP */
01235     if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) {
01236       Vehicle *v = GetNextVehicle(src);
01237 
01238       if (v != NULL && IsTrainEngine(v)) {
01239         v->group_id   = src->group_id;
01240         src->group_id = DEFAULT_GROUP;
01241       }
01242     }
01243 
01244     if (HasBit(p2, 0)) {
01245       /* unlink ALL wagons */
01246       if (src != src_head) {
01247         Vehicle *v = src_head;
01248         while (GetNextVehicle(v) != src) v = GetNextVehicle(v);
01249         GetLastEnginePart(v)->SetNext(NULL);
01250       } else {
01251         InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile); // We removed a line
01252         src_head = NULL;
01253       }
01254     } else {
01255       /* if moving within the same chain, dont use dst_head as it may get invalidated */
01256       if (src_head == dst_head) dst_head = NULL;
01257       /* unlink single wagon from linked list */
01258       src_head = UnlinkWagon(src, src_head);
01259       GetLastEnginePart(src)->SetNext(NULL);
01260     }
01261 
01262     if (dst == NULL) {
01263       /* We make a new line in the depot, so we know already that we invalidate the window data */
01264       InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
01265 
01266       /* move the train to an empty line. for locomotives, we set the type to TS_Front. for wagons, 4. */
01267       if (IsTrainEngine(src)) {
01268         if (!IsFrontEngine(src)) {
01269           /* setting the type to 0 also involves setting up the orders field. */
01270           SetFrontEngine(src);
01271           assert(src->orders == NULL);
01272           src->num_orders = 0;
01273 
01274           // Decrease the engines number of the src engine_type
01275           if (!IsDefaultGroupID(src->group_id) && IsValidGroupID(src->group_id)) {
01276             GetGroup(src->group_id)->num_engines[src->engine_type]--;
01277           }
01278 
01279           // If we move an engine to a new line affect it to the DEFAULT_GROUP
01280           src->group_id = DEFAULT_GROUP;
01281         }
01282       } else {
01283         SetFreeWagon(src);
01284       }
01285       dst_head = src;
01286     } else {
01287       if (IsFrontEngine(src)) {
01288         /* the vehicle was previously a loco. need to free the order list and delete vehicle windows etc. */
01289         DeleteWindowById(WC_VEHICLE_VIEW, src->index);
01290         DeleteVehicleOrders(src);
01291         RemoveVehicleFromGroup(src);
01292       }
01293 
01294       if (IsFrontEngine(src) || IsFreeWagon(src)) {
01295         InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
01296         ClearFrontEngine(src);
01297         ClearFreeWagon(src);
01298         src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
01299       }
01300 
01301       /* link in the wagon(s) in the chain. */
01302       {
01303         Vehicle *v;
01304 
01305         for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v)) {}
01306         GetLastEnginePart(v)->SetNext(dst->Next());
01307       }
01308       dst->SetNext(src);
01309     }
01310 
01311     if (src->u.rail.other_multiheaded_part != NULL) {
01312       if (src->u.rail.other_multiheaded_part == src_head) {
01313         src_head = src_head->Next();
01314       }
01315       AddWagonToConsist(src->u.rail.other_multiheaded_part, src);
01316     }
01317 
01318     /* If there is an engine behind first_engine we moved away, it should become new first_engine
01319      * To do this, CmdMoveRailVehicle must be called once more
01320      * we can't loop forever here because next time we reach this line we will have a front engine */
01321     if (src_head != NULL && !IsFrontEngine(src_head) && IsTrainEngine(src_head)) {
01322       /* As in CmdMoveRailVehicle src_head->group_id will be equal to DEFAULT_GROUP
01323        * we need to save the group and reaffect it to src_head */
01324       const GroupID tmp_g = src_head->group_id;
01325       CmdMoveRailVehicle(0, flags, src_head->index | (INVALID_VEHICLE << 16), 1);
01326       SetTrainGroupID(src_head, tmp_g);
01327       src_head = NULL; // don't do anything more to this train since the new call will do it
01328     }
01329 
01330     if (src_head != NULL) {
01331       NormaliseTrainConsist(src_head);
01332       TrainConsistChanged(src_head, false);
01333       UpdateTrainGroupID(src_head);
01334       if (IsFrontEngine(src_head)) {
01335         /* Update the refit button and window */
01336         InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
01337         InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, VVW_WIDGET_REFIT_VEH);
01338       }
01339       /* Update the depot window */
01340       InvalidateWindow(WC_VEHICLE_DEPOT, src_head->tile);
01341     }
01342 
01343     if (dst_head != NULL) {
01344       NormaliseTrainConsist(dst_head);
01345       TrainConsistChanged(dst_head, false);
01346       UpdateTrainGroupID(dst_head);
01347       if (IsFrontEngine(dst_head)) {
01348         /* Update the refit button and window */
01349         InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, VVW_WIDGET_REFIT_VEH);
01350         InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index);
01351       }
01352       /* Update the depot window */
01353       InvalidateWindow(WC_VEHICLE_DEPOT, dst_head->tile);
01354     }
01355 
01356     RebuildVehicleLists();
01357   }
01358 
01359   return CommandCost();
01360 }
01361 
01368 CommandCost CmdStartStopTrain(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
01369 {
01370   if (!IsValidVehicleID(p1)) return CMD_ERROR;
01371 
01372   Vehicle *v = GetVehicle(p1);
01373 
01374   if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
01375 
01376   /* Check if this train can be started/stopped. The callback will fail or
01377    * return 0xFF if it can. */
01378   uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v);
01379   if (callback != CALLBACK_FAILED && GB(callback, 0, 8) != 0xFF) {
01380     StringID error = GetGRFStringID(GetEngineGRFID(v->engine_type), 0xD000 + callback);
01381     return_cmd_error(error);
01382   }
01383 
01384   if (v->vehstatus & VS_STOPPED && v->u.rail.cached_power == 0) return_cmd_error(STR_TRAIN_START_NO_CATENARY);
01385 
01386   if (flags & DC_EXEC) {
01387     if (v->vehstatus & VS_STOPPED && v->u.rail.track == TRACK_BIT_DEPOT) {
01388       DeleteVehicleNews(p1, STR_8814_TRAIN_IS_WAITING_IN_DEPOT);
01389     }
01390 
01391     v->vehstatus ^= VS_STOPPED;
01392     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
01393     InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
01394   }
01395   return CommandCost();
01396 }
01397 
01409 CommandCost CmdSellRailWagon(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
01410 {
01411   /* Check if we deleted a vehicle window */
01412   Window *w = NULL;
01413 
01414   if (!IsValidVehicleID(p1) || p2 > 2) return CMD_ERROR;
01415 
01416   Vehicle *v = GetVehicle(p1);
01417 
01418   if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
01419 
01420   if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
01421 
01422   while (IsArticulatedPart(v)) v = v->Previous();
01423   Vehicle *first = v->First();
01424 
01425   /* make sure the vehicle is stopped in the depot */
01426   if (CheckTrainStoppedInDepot(first) < 0) {
01427     return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
01428   }
01429 
01430   if (IsRearDualheaded(v)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
01431 
01432   if (flags & DC_EXEC) {
01433     if (v == first && IsFrontEngine(first)) {
01434       w = FindWindowById(WC_VEHICLE_VIEW, first->index);
01435       if (w != NULL) DeleteWindow(w);
01436     }
01437     InvalidateWindow(WC_VEHICLE_DEPOT, first->tile);
01438     RebuildVehicleLists();
01439   }
01440 
01441   CommandCost cost(EXPENSES_NEW_VEHICLES);
01442   switch (p2) {
01443     case 0: case 2: { /* Delete given wagon */
01444       bool switch_engine = false;    // update second wagon to engine?
01445       byte ori_subtype = v->subtype; // backup subtype of deleted wagon in case DeleteVehicle() changes
01446 
01447       /* 1. Delete the engine, if it is dualheaded also delete the matching
01448        * rear engine of the loco (from the point of deletion onwards) */
01449       Vehicle *rear = (IsMultiheaded(v) &&
01450         IsTrainEngine(v)) ? v->u.rail.other_multiheaded_part : NULL;
01451 
01452       if (rear != NULL) {
01453         cost.AddCost(-rear->value);
01454         if (flags & DC_EXEC) {
01455           UnlinkWagon(rear, first);
01456           DeleteDepotHighlightOfVehicle(rear);
01457           delete rear;
01458         }
01459       }
01460 
01461       /* 2. We are selling the first engine, some special action might be required
01462        * here, so take attention */
01463       if ((flags & DC_EXEC) && v == first) {
01464         Vehicle *new_f = GetNextVehicle(first);
01465 
01466         /* 2.2 If there are wagons present after the deleted front engine, check
01467          * if the second wagon (which will be first) is an engine. If it is one,
01468          * promote it as a new train, retaining the unitnumber, orders */
01469         if (new_f != NULL && IsTrainEngine(new_f)) {
01470           switch_engine = true;
01471           /* Copy important data from the front engine */
01472           new_f->unitnumber      = first->unitnumber;
01473           new_f->current_order   = first->current_order;
01474           new_f->cur_order_index = first->cur_order_index;
01475           new_f->orders          = first->orders;
01476           new_f->num_orders      = first->num_orders;
01477           new_f->group_id        = first->group_id;
01478 
01479           if (first->prev_shared != NULL) {
01480             first->prev_shared->next_shared = new_f;
01481             new_f->prev_shared = first->prev_shared;
01482           }
01483 
01484           if (first->next_shared != NULL) {
01485             first->next_shared->prev_shared = new_f;
01486             new_f->next_shared = first->next_shared;
01487           }
01488 
01489           /*
01490            * Remove all order information from the front train, to
01491            * prevent the order and the shared order list to be
01492            * destroyed by Destroy/DeleteVehicle.
01493            */
01494           first->orders      = NULL;
01495           first->prev_shared = NULL;
01496           first->next_shared = NULL;
01497           first->group_id    = DEFAULT_GROUP;
01498 
01499           /* If we deleted a window then open a new one for the 'new' train */
01500           if (IsLocalPlayer() && w != NULL) ShowVehicleViewWindow(new_f);
01501         }
01502       }
01503 
01504       /* 3. Delete the requested wagon */
01505       cost.AddCost(-v->value);
01506       if (flags & DC_EXEC) {
01507         first = UnlinkWagon(v, first);
01508         DeleteDepotHighlightOfVehicle(v);
01509         delete v;
01510 
01511         /* 4 If the second wagon was an engine, update it to front_engine
01512           * which UnlinkWagon() has changed to TS_Free_Car */
01513         if (switch_engine) SetFrontEngine(first);
01514 
01515         /* 5. If the train still exists, update its acceleration, window, etc. */
01516         if (first != NULL) {
01517           NormaliseTrainConsist(first);
01518           TrainConsistChanged(first, false);
01519           UpdateTrainGroupID(first);
01520           if (IsFrontEngine(first)) InvalidateWindow(WC_VEHICLE_REFIT, first->index);
01521         }
01522 
01523 
01524         /* (6.) Borked AI. If it sells an engine it expects all wagons lined
01525          * up on a new line to be added to the newly built loco. Replace it is.
01526          * Totally braindead cause building a new engine adds all loco-less
01527          * engines to its train anyways */
01528         if (p2 == 2 && HasBit(ori_subtype, TS_FRONT)) {
01529           Vehicle *tmp;
01530           for (v = first; v != NULL; v = tmp) {
01531             tmp = GetNextVehicle(v);
01532             DoCommand(v->tile, v->index | INVALID_VEHICLE << 16, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
01533           }
01534         }
01535       }
01536     } break;
01537     case 1: { /* Delete wagon and all wagons after it given certain criteria */
01538       /* Start deleting every vehicle after the selected one
01539        * If we encounter a matching rear-engine to a front-engine
01540        * earlier in the chain (before deletion), leave it alone */
01541       Vehicle *tmp;
01542       for (; v != NULL; v = tmp) {
01543         tmp = GetNextVehicle(v);
01544 
01545         if (IsMultiheaded(v)) {
01546           if (IsTrainEngine(v)) {
01547             /* We got a front engine of a multiheaded set. Now we will sell the rear end too */
01548             Vehicle *rear = v->u.rail.other_multiheaded_part;
01549 
01550             if (rear != NULL) {
01551               cost.AddCost(-rear->value);
01552 
01553               /* If this is a multiheaded vehicle with nothing
01554                * between the parts, tmp will be pointing to the
01555                * rear part, which is unlinked from the train and
01556                * deleted here. However, because tmp has already
01557                * been set it needs to be updated now so that the
01558                * loop never sees the rear part. */
01559               if (tmp == rear) tmp = GetNextVehicle(tmp);
01560 
01561               if (flags & DC_EXEC) {
01562                 first = UnlinkWagon(rear, first);
01563                 DeleteDepotHighlightOfVehicle(rear);
01564                 delete rear;
01565               }
01566             }
01567           } else if (v->u.rail.other_multiheaded_part != NULL) {
01568             /* The front to this engine is earlier in this train. Do nothing */
01569             continue;
01570           }
01571         }
01572 
01573         cost.AddCost(-v->value);
01574         if (flags & DC_EXEC) {
01575           first = UnlinkWagon(v, first);
01576           DeleteDepotHighlightOfVehicle(v);
01577           delete v;
01578         }
01579       }
01580 
01581       /* 3. If it is still a valid train after selling, update its acceleration and cached values */
01582       if (flags & DC_EXEC && first != NULL) {
01583         NormaliseTrainConsist(first);
01584         TrainConsistChanged(first, false);
01585         UpdateTrainGroupID(first);
01586         InvalidateWindow(WC_VEHICLE_REFIT, first->index);
01587       }
01588     } break;
01589   }
01590   return cost;
01591 }
01592 
01593 void Train::UpdateDeltaXY(Direction direction)
01594 {
01595 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
01596   static const uint32 _delta_xy_table[8] = {
01597     MKIT(3, 3, -1, -1),
01598     MKIT(3, 7, -1, -3),
01599     MKIT(3, 3, -1, -1),
01600     MKIT(7, 3, -3, -1),
01601     MKIT(3, 3, -1, -1),
01602     MKIT(3, 7, -1, -3),
01603     MKIT(3, 3, -1, -1),
01604     MKIT(7, 3, -3, -1),
01605   };
01606 #undef MKIT
01607 
01608   uint32 x = _delta_xy_table[direction];
01609   this->x_offs        = GB(x,  0, 8);
01610   this->y_offs        = GB(x,  8, 8);
01611   this->sprite_width  = GB(x, 16, 8);
01612   this->sprite_height = GB(x, 24, 8);
01613   this->z_height      = 6;
01614 }
01615 
01616 static void UpdateVarsAfterSwap(Vehicle *v)
01617 {
01618   v->UpdateDeltaXY(v->direction);
01619   v->cur_image = v->GetImage(v->direction);
01620   BeginVehicleMove(v);
01621   VehiclePositionChanged(v);
01622   EndVehicleMove(v);
01623 }
01624 
01625 static inline void SetLastSpeed(Vehicle* v, int spd)
01626 {
01627   int old = v->u.rail.last_speed;
01628   if (spd != old) {
01629     v->u.rail.last_speed = spd;
01630     if (_patches.vehicle_speed || (old == 0) != (spd == 0))
01631       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
01632   }
01633 }
01634 
01635 static void SwapTrainFlags(byte *swap_flag1, byte *swap_flag2)
01636 {
01637   byte flag1 = *swap_flag1;
01638   byte flag2 = *swap_flag2;
01639 
01640   /* Clear the flags */
01641   ClrBit(*swap_flag1, VRF_GOINGUP);
01642   ClrBit(*swap_flag1, VRF_GOINGDOWN);
01643   ClrBit(*swap_flag2, VRF_GOINGUP);
01644   ClrBit(*swap_flag2, VRF_GOINGDOWN);
01645 
01646   /* Reverse the rail-flags (if needed) */
01647   if (HasBit(flag1, VRF_GOINGUP)) {
01648     SetBit(*swap_flag2, VRF_GOINGDOWN);
01649   } else if (HasBit(flag1, VRF_GOINGDOWN)) {
01650     SetBit(*swap_flag2, VRF_GOINGUP);
01651   }
01652   if (HasBit(flag2, VRF_GOINGUP)) {
01653     SetBit(*swap_flag1, VRF_GOINGDOWN);
01654   } else if (HasBit(flag2, VRF_GOINGDOWN)) {
01655     SetBit(*swap_flag1, VRF_GOINGUP);
01656   }
01657 }
01658 
01659 static void ReverseTrainSwapVeh(Vehicle *v, int l, int r)
01660 {
01661   Vehicle *a, *b;
01662 
01663   /* locate vehicles to swap */
01664   for (a = v; l != 0; l--) a = a->Next();
01665   for (b = v; r != 0; r--) b = b->Next();
01666 
01667   if (a != b) {
01668     /* swap the hidden bits */
01669     {
01670       uint16 tmp = (a->vehstatus & ~VS_HIDDEN) | (b->vehstatus&VS_HIDDEN);
01671       b->vehstatus = (b->vehstatus & ~VS_HIDDEN) | (a->vehstatus&VS_HIDDEN);
01672       a->vehstatus = tmp;
01673     }
01674 
01675     Swap(a->u.rail.track, b->u.rail.track);
01676     Swap(a->direction,    b->direction);
01677 
01678     /* toggle direction */
01679     if (a->u.rail.track != TRACK_BIT_DEPOT) a->direction = ReverseDir(a->direction);
01680     if (b->u.rail.track != TRACK_BIT_DEPOT) b->direction = ReverseDir(b->direction);
01681 
01682     Swap(a->x_pos, b->x_pos);
01683     Swap(a->y_pos, b->y_pos);
01684     Swap(a->tile,  b->tile);
01685     Swap(a->z_pos, b->z_pos);
01686 
01687     SwapTrainFlags(&a->u.rail.flags, &b->u.rail.flags);
01688 
01689     /* update other vars */
01690     UpdateVarsAfterSwap(a);
01691     UpdateVarsAfterSwap(b);
01692 
01693     /* call the proper EnterTile function unless we are in a wormhole */
01694     if (a->u.rail.track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
01695     if (b->u.rail.track != TRACK_BIT_WORMHOLE) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
01696   } else {
01697     if (a->u.rail.track != TRACK_BIT_DEPOT) a->direction = ReverseDir(a->direction);
01698     UpdateVarsAfterSwap(a);
01699 
01700     if (a->u.rail.track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
01701   }
01702 
01703   /* Update train's power incase tiles were different rail type */
01704   TrainPowerChanged(v);
01705 }
01706 
01707 
01713 static void *TrainOnTileEnum(Vehicle *v, void *)
01714 {
01715   return (v->type == VEH_TRAIN) ? v : NULL;
01716 }
01717 
01718 
01725 static void *TrainApproachingCrossingEnum(Vehicle *v, void *data)
01726 {
01727   /* not a train || not front engine || crashed */
01728   if (v->type != VEH_TRAIN || !IsFrontEngine(v) || v->vehstatus & VS_CRASHED) return NULL;
01729 
01730   TileIndex tile = *(TileIndex*)data;
01731 
01732   if (TrainApproachingCrossingTile(v) != tile) return NULL;
01733 
01734   return v;
01735 }
01736 
01737 
01744 static bool TrainApproachingCrossing(TileIndex tile)
01745 {
01746   assert(IsLevelCrossingTile(tile));
01747 
01748   DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
01749   TileIndex tile_from = tile + TileOffsByDiagDir(dir);
01750 
01751   if (HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum)) return true;
01752 
01753   dir = ReverseDiagDir(dir);
01754   tile_from = tile + TileOffsByDiagDir(dir);
01755 
01756   return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum);
01757 }
01758 
01759 
01766 void UpdateLevelCrossing(TileIndex tile, bool sound)
01767 {
01768   assert(IsLevelCrossingTile(tile));
01769 
01770   /* train on crossing || train approaching crossing || reserved */
01771   bool new_state = HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile);
01772 
01773   if (new_state != IsCrossingBarred(tile)) {
01774     if (new_state && sound) {
01775       SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
01776     }
01777     SetCrossingBarred(tile, new_state);
01778     MarkTileDirtyByTile(tile);
01779   }
01780 }
01781 
01782 
01788 static inline void MaybeBarCrossingWithSound(TileIndex tile)
01789 {
01790   if (!IsCrossingBarred(tile)) {
01791     BarCrossing(tile);
01792     SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile);
01793     MarkTileDirtyByTile(tile);
01794   }
01795 }
01796 
01797 
01803 static void AdvanceWagonsBeforeSwap(Vehicle *v)
01804 {
01805   Vehicle *base = v;
01806   Vehicle *first = base;                    // first vehicle to move
01807   Vehicle *last = GetLastVehicleInChain(v); // last vehicle to move
01808   uint length = CountVehiclesInChain(v);
01809 
01810   while (length > 2) {
01811     last = last->Previous();
01812     first = first->Next();
01813 
01814     int differential = base->u.rail.cached_veh_length - last->u.rail.cached_veh_length;
01815 
01816     /* do not update images now
01817      * negative differential will be handled in AdvanceWagonsAfterSwap() */
01818     for (int i = 0; i < differential; i++) TrainController(first, last->Next(), false);
01819 
01820     base = first; // == base->Next()
01821     length -= 2;
01822   }
01823 }
01824 
01825 
01831 static void AdvanceWagonsAfterSwap(Vehicle *v)
01832 {
01833   /* first of all, fix the situation when the train was entering a depot */
01834   Vehicle *dep = v; // last vehicle in front of just left depot
01835   while (dep->Next() != NULL && (dep->u.rail.track == TRACK_BIT_DEPOT || dep->Next()->u.rail.track != TRACK_BIT_DEPOT)) {
01836     dep = dep->Next(); // find first vehicle outside of a depot, with next vehicle inside a depot
01837   }
01838 
01839   Vehicle *leave = dep->Next(); // first vehicle in a depot we are leaving now
01840 
01841   if (leave != NULL) {
01842     /* 'pull' next wagon out of the depot, so we won't miss it (it could stay in depot forever) */
01843     int d = TicksToLeaveDepot(dep);
01844 
01845     if (d <= 0) {
01846       leave->vehstatus &= ~VS_HIDDEN; // move it out of the depot
01847       leave->u.rail.track = AxisToTrackBits(DiagDirToAxis(GetRailDepotDirection(leave->tile)));
01848       for (int i = 0; i >= d; i--) TrainController(leave, NULL, false); // maybe move it, and maybe let another wagon leave
01849     }
01850   } else {
01851     dep = NULL; // no vehicle in a depot, so no vehicle leaving a depot
01852   }
01853 
01854   Vehicle *base = v;
01855   Vehicle *first = base;                    // first vehicle to move
01856   Vehicle *last = GetLastVehicleInChain(v); // last vehicle to move
01857   uint length = CountVehiclesInChain(v);
01858 
01859   /* we have to make sure all wagons that leave a depot because of train reversing are moved coorectly
01860    * they have already correct spacing, so we have to make sure they are moved how they should */
01861   bool nomove = (dep == NULL); // if there is no vehicle leaving a depot, limit the number of wagons moved immediatelly
01862 
01863   while (length > 2) {
01864     /* we reached vehicle (originally) in front of a depot, stop now
01865      * (we would move wagons that are alredy moved with new wagon length) */
01866     if (base == dep) break;
01867 
01868     /* the last wagon was that one leaving a depot, so do not move it anymore */
01869     if (last == dep) nomove = true;
01870 
01871     last = last->Previous();
01872     first = first->Next();
01873 
01874     int differential = last->u.rail.cached_veh_length - base->u.rail.cached_veh_length;
01875 
01876     /* do not update images now */
01877     for (int i = 0; i < differential; i++) TrainController(first, (nomove ? last->Next() : NULL), false);
01878 
01879     base = first; // == base->Next()
01880     length -= 2;
01881   }
01882 }
01883 
01884 
01885 static void ReverseTrainDirection(Vehicle *v)
01886 {
01887   if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) {
01888     InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
01889   }
01890 
01891   /* Check if we were approaching a rail/road-crossing */
01892   TileIndex crossing = TrainApproachingCrossingTile(v);
01893 
01894   /* count number of vehicles */
01895   int r = 0;  
01896   for (const Vehicle *u = v; (u = u->Next()) != NULL;) { r++; }
01897 
01898   AdvanceWagonsBeforeSwap(v);
01899 
01900   /* swap start<>end, start+1<>end-1, ... */
01901   int l = 0;
01902   do {
01903     ReverseTrainSwapVeh(v, l++, r--);
01904   } while (l <= r);
01905 
01906   AdvanceWagonsAfterSwap(v);
01907 
01908   if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) {
01909     InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
01910   }
01911 
01912   /* set reversed flag on all parts */
01913   for (Vehicle *u = v; u != NULL; u = u->Next()) ToggleBit(u->u.rail.flags, VRF_TOGGLE_REVERSE);
01914 
01915   ClrBit(v->u.rail.flags, VRF_REVERSING);
01916 
01917   /* recalculate cached data */
01918   TrainConsistChanged(v, true);
01919 
01920   /* update all images */
01921   for (Vehicle *u = v; u != NULL; u = u->Next()) u->cur_image = u->GetImage(u->direction);
01922 
01923   /* update crossing we were approaching */
01924   if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
01925 
01926   /* maybe we are approaching crossing now, after reversal */
01927   crossing = TrainApproachingCrossingTile(v);
01928   if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing);
01929 }
01930 
01937 CommandCost CmdReverseTrainDirection(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
01938 {
01939   if (!IsValidVehicleID(p1)) return CMD_ERROR;
01940 
01941   Vehicle *v = GetVehicle(p1);
01942 
01943   if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
01944 
01945   if (p2) {
01946     /* turn a single unit around */
01947 
01948     if (IsMultiheaded(v) || HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) {
01949       return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT);
01950     }
01951 
01952     Vehicle *front = v->First();
01953     /* make sure the vehicle is stopped in the depot */
01954     if (CheckTrainStoppedInDepot(front) < 0) {
01955       return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
01956     }
01957 
01958     if (flags & DC_EXEC) {
01959       ToggleBit(v->u.rail.flags, VRF_REVERSE_DIRECTION);
01960       InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
01961       InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
01962     }
01963   } else {
01964     /* turn the whole train around */
01965     if (v->vehstatus & VS_CRASHED || v->breakdown_ctr != 0) return CMD_ERROR;
01966 
01967     if (flags & DC_EXEC) {
01968       if (_patches.realistic_acceleration && v->cur_speed != 0) {
01969         ToggleBit(v->u.rail.flags, VRF_REVERSING);
01970       } else {
01971         v->cur_speed = 0;
01972         SetLastSpeed(v, 0);
01973         HideFillingPercent(&v->fill_percent_te_id);
01974         ReverseTrainDirection(v);
01975       }
01976     }
01977   }
01978   return CommandCost();
01979 }
01980 
01987 CommandCost CmdForceTrainProceed(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
01988 {
01989   if (!IsValidVehicleID(p1)) return CMD_ERROR;
01990 
01991   Vehicle *v = GetVehicle(p1);
01992 
01993   if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
01994 
01995   if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
01996 
01997   return CommandCost();
01998 }
01999 
02010 CommandCost CmdRefitRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
02011 {
02012   CargoID new_cid = GB(p2, 0, 8);
02013   byte new_subtype = GB(p2, 8, 8);
02014   bool only_this = HasBit(p2, 16);
02015 
02016   if (!IsValidVehicleID(p1)) return CMD_ERROR;
02017 
02018   Vehicle *v = GetVehicle(p1);
02019 
02020   if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
02021   if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
02022   if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_CAN_T_REFIT_DESTROYED_VEHICLE);
02023 
02024   /* Check cargo */
02025   if (new_cid >= NUM_CARGO) return CMD_ERROR;
02026 
02027   CommandCost cost(EXPENSES_TRAIN_RUN);
02028   uint num = 0;
02029 
02030   do {
02031     /* XXX: We also refit all the attached wagons en-masse if they
02032      * can be refitted. This is how TTDPatch does it.  TODO: Have
02033      * some nice [Refit] button near each wagon. --pasky */
02034     if (!CanRefitTo(v->engine_type, new_cid)) continue;
02035 
02036     if (v->cargo_cap != 0) {
02037       uint16 amount = CALLBACK_FAILED;
02038 
02039       if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) {
02040         /* Back up the vehicle's cargo type */
02041         CargoID temp_cid = v->cargo_type;
02042         byte temp_subtype = v->cargo_subtype;
02043         v->cargo_type = new_cid;
02044         v->cargo_subtype = new_subtype;
02045         /* Check the refit capacity callback */
02046         amount = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v);
02047         /* Restore the original cargo type */
02048         v->cargo_type = temp_cid;
02049         v->cargo_subtype = temp_subtype;
02050       }
02051 
02052       if (amount == CALLBACK_FAILED) { // callback failed or not used, use default
02053         const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
02054         CargoID old_cid = rvi->cargo_type;
02055         /* normally, the capacity depends on the cargo type, a rail vehicle can
02056          * carry twice as much mail/goods as normal cargo, and four times as
02057          * many passengers
02058          */
02059         amount = rvi->capacity;
02060         switch (old_cid) {
02061           case CT_PASSENGERS: break;
02062           case CT_MAIL:
02063           case CT_GOODS: amount *= 2; break;
02064           default:       amount *= 4; break;
02065         }
02066         switch (new_cid) {
02067           case CT_PASSENGERS: break;
02068           case CT_MAIL:
02069           case CT_GOODS: amount /= 2; break;
02070           default:       amount /= 4; break;
02071         }
02072       }
02073 
02074       if (amount != 0) {
02075         if (new_cid != v->cargo_type) {
02076           cost.AddCost(GetRefitCost(v->engine_type));
02077         }
02078 
02079         num += amount;
02080         if (flags & DC_EXEC) {
02081           v->cargo.Truncate((v->cargo_type == new_cid) ? amount : 0);
02082           v->cargo_type = new_cid;
02083           v->cargo_cap = amount;
02084           v->cargo_subtype = new_subtype;
02085           InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
02086           InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
02087           RebuildVehicleLists();
02088         }
02089       }
02090     }
02091   } while ((v = v->Next()) != NULL && !only_this);
02092 
02093   _returned_refit_capacity = num;
02094 
02095   /* Update the train's cached variables */
02096   if (flags & DC_EXEC) TrainConsistChanged(GetVehicle(p1)->First(), false);
02097 
02098   return cost;
02099 }
02100 
02101 struct TrainFindDepotData {
02102   uint best_length;
02103   TileIndex tile;
02104   PlayerID owner;
02109   bool reverse;
02110 };
02111 
02112 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
02113 {
02114   if (IsTileType(tile, MP_RAILWAY) &&
02115       IsTileOwner(tile, tfdd->owner) &&
02116       IsRailDepot(tile)) {
02117     /* approximate number of tiles by dividing by DIAG_FACTOR */
02118     tfdd->best_length = length / DIAG_FACTOR;
02119     tfdd->tile = tile;
02120     return true;
02121   }
02122 
02123   return false;
02124 }
02125 
02128 static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
02129 {
02130   assert(!(v->vehstatus & VS_CRASHED));
02131 
02132   TrainFindDepotData tfdd;
02133   tfdd.owner = v->owner;
02134   tfdd.best_length = UINT_MAX;
02135   tfdd.reverse = false;
02136 
02137   TileIndex tile = v->tile;
02138   if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
02139     tfdd.tile = tile;
02140     tfdd.best_length = 0;
02141     return tfdd;
02142   }
02143 
02144   switch (_patches.pathfinder_for_trains) {
02145     case VPF_YAPF: { /* YAPF */
02146       bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
02147       tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
02148     } break;
02149 
02150     case VPF_NPF: { /* NPF */
02151       Vehicle* last = GetLastVehicleInChain(v);
02152       Trackdir trackdir = GetVehicleTrackdir(v);
02153       Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
02154 
02155       assert(trackdir != INVALID_TRACKDIR);
02156       NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
02157       if (ftd.best_bird_dist == 0) {
02158         /* Found target */
02159         tfdd.tile = ftd.node.tile;
02160         /* Our caller expects a number of tiles, so we just approximate that
02161         * number by this. It might not be completely what we want, but it will
02162         * work for now :-) We can possibly change this when the old pathfinder
02163         * is removed. */
02164         tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
02165         if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
02166       }
02167     } break;
02168 
02169     default:
02170     case VPF_NTP: { /* NTP */
02171       /* search in the forward direction first. */
02172       DiagDirection i = TrainExitDir(v->direction, v->u.rail.track);
02173       NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
02174       if (tfdd.best_length == UINT_MAX){
02175         tfdd.reverse = true;
02176         /* search in backwards direction */
02177         i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track);
02178         NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
02179       }
02180     } break;
02181   }
02182 
02183   return tfdd;
02184 }
02185 
02194 CommandCost CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
02195 {
02196   if (p2 & DEPOT_MASS_SEND) {
02197     /* Mass goto depot requested */
02198     if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
02199     return SendAllVehiclesToDepot(VEH_TRAIN, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
02200   }
02201 
02202   if (!IsValidVehicleID(p1)) return CMD_ERROR;
02203 
02204   Vehicle *v = GetVehicle(p1);
02205 
02206   if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
02207 
02208   if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
02209 
02210   if (v->current_order.type == OT_GOTO_DEPOT) {
02211     if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OF_HALT_IN_DEPOT)) {
02212       /* We called with a different DEPOT_SERVICE setting.
02213        * Now we change the setting to apply the new one and let the vehicle head for the same depot.
02214        * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
02215       if (flags & DC_EXEC) {
02216         ClrBit(v->current_order.flags, OF_PART_OF_ORDERS);
02217         ToggleBit(v->current_order.flags, OF_HALT_IN_DEPOT);
02218         InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
02219       }
02220       return CommandCost();
02221     }
02222 
02223     if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
02224     if (flags & DC_EXEC) {
02225       if (HasBit(v->current_order.flags, OF_PART_OF_ORDERS)) {
02226         v->cur_order_index++;
02227       }
02228 
02229       v->current_order.type = OT_DUMMY;
02230       v->current_order.flags = 0;
02231       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
02232     }
02233     return CommandCost();
02234   }
02235 
02236   /* check if at a standstill (not stopped only) in a depot
02237    * the check is down here to make it possible to alter stop/service for trains entering the depot */
02238   if (IsTileDepotType(v->tile, TRANSPORT_RAIL) && v->cur_speed == 0) return CMD_ERROR;
02239 
02240   TrainFindDepotData tfdd = FindClosestTrainDepot(v, 0);
02241   if (tfdd.best_length == (uint)-1) return_cmd_error(STR_883A_UNABLE_TO_FIND_ROUTE_TO);
02242 
02243   if (flags & DC_EXEC) {
02244     if (v->current_order.type == OT_LOADING) v->LeaveStation();
02245 
02246     v->dest_tile = tfdd.tile;
02247     v->current_order.type = OT_GOTO_DEPOT;
02248     v->current_order.flags = OFB_NON_STOP;
02249     if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OF_HALT_IN_DEPOT);
02250     v->current_order.dest = GetDepotByTile(tfdd.tile)->index;
02251     v->current_order.refit_cargo = CT_INVALID;
02252     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
02253     /* If there is no depot in front, reverse automatically */
02254     if (tfdd.reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
02255   }
02256 
02257   return CommandCost();
02258 }
02259 
02260 
02261 void OnTick_Train()
02262 {
02263   _age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1);
02264 }
02265 
02266 static const int8 _vehicle_smoke_pos[8] = {
02267   1, 1, 1, 0, -1, -1, -1, 0
02268 };
02269 
02270 static void HandleLocomotiveSmokeCloud(const Vehicle* v)
02271 {
02272   bool sound = false;
02273 
02274   if (v->vehstatus & VS_TRAIN_SLOWING || v->load_unload_time_rem != 0 || v->cur_speed < 2)
02275     return;
02276 
02277   const Vehicle* u = v;
02278 
02279   do {
02280     const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
02281     int effect_offset = GB(v->u.rail.cached_vis_effect, 0, 4) - 8;
02282     byte effect_type = GB(v->u.rail.cached_vis_effect, 4, 2);
02283     bool disable_effect = HasBit(v->u.rail.cached_vis_effect, 6);
02284 
02285     /* no smoke? */
02286     if ((rvi->railveh_type == RAILVEH_WAGON && effect_type == 0) ||
02287         disable_effect ||
02288         v->vehstatus & VS_HIDDEN) {
02289       continue;
02290     }
02291 
02292     /* No smoke in depots or tunnels */
02293     if (IsTileDepotType(v->tile, TRANSPORT_RAIL) || IsTunnelTile(v->tile)) continue;
02294 
02295     /* No sparks for electric vehicles on nonelectrified tracks */
02296     if (!HasPowerOnRail(v->u.rail.railtype, GetTileRailType(v->tile))) continue;
02297 
02298     if (effect_type == 0) {
02299       /* Use default effect type for engine class. */
02300       effect_type = rvi->engclass;
02301     } else {
02302       effect_type--;
02303     }
02304 
02305     int x = _vehicle_smoke_pos[v->direction] * effect_offset;
02306     int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset;
02307 
02308     if (HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
02309       x = -x;
02310       y = -y;
02311     }
02312 
02313     switch (effect_type) {
02314     case 0:
02315       /* steam smoke. */
02316       if (GB(v->tick_counter, 0, 4) == 0) {
02317         CreateEffectVehicleRel(v, x, y, 10, EV_STEAM_SMOKE);
02318         sound = true;
02319       }
02320       break;
02321 
02322     case 1:
02323       /* diesel smoke */
02324       if (u->cur_speed <= 40 && Chance16(15, 128)) {
02325         CreateEffectVehicleRel(v, 0, 0, 10, EV_DIESEL_SMOKE);
02326         sound = true;
02327       }
02328       break;
02329 
02330     case 2:
02331       /* blue spark */
02332       if (GB(v->tick_counter, 0, 2) == 0 && Chance16(1, 45)) {
02333         CreateEffectVehicleRel(v, 0, 0, 10, EV_ELECTRIC_SPARK);
02334         sound = true;
02335       }
02336       break;
02337     }
02338   } while ((v = v->Next()) != NULL);
02339 
02340   if (sound) PlayVehicleSound(u, VSE_TRAIN_EFFECT);
02341 }
02342 
02343 void Train::PlayLeaveStationSound() const
02344 {
02345   static const SoundFx sfx[] = {
02346     SND_04_TRAIN,
02347     SND_0A_TRAIN_HORN,
02348     SND_0A_TRAIN_HORN,
02349     SND_47_MAGLEV_2,
02350     SND_41_MAGLEV
02351   };
02352 
02353   if (PlayVehicleSound(this, VSE_START)) return;
02354 
02355   EngineID engtype = this->engine_type;
02356   SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
02357 }
02358 
02359 static bool CheckTrainStayInDepot(Vehicle *v)
02360 {
02361   /* bail out if not all wagons are in the same depot or not in a depot at all */
02362   for (const Vehicle *u = v; u != NULL; u = u->Next()) {
02363     if (u->u.rail.track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
02364   }
02365 
02366   /* if the train got no power, then keep it in the depot */
02367   if (v->u.rail.cached_power == 0) {
02368     v->vehstatus |= VS_STOPPED;
02369     InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
02370     return true;
02371   }
02372 
02373   if (v->u.rail.force_proceed == 0) {
02374     if (++v->load_unload_time_rem < 37) {
02375       InvalidateWindowClasses(WC_TRAINS_LIST);
02376       return true;
02377     }
02378 
02379     v->load_unload_time_rem = 0;
02380 
02381     if (UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner)) {
02382       InvalidateWindowClasses(WC_TRAINS_LIST);
02383       return true;
02384     }
02385   }
02386 
02387   VehicleServiceInDepot(v);
02388   InvalidateWindowClasses(WC_TRAINS_LIST);
02389   v->PlayLeaveStationSound();
02390 
02391   v->u.rail.track = TRACK_BIT_X;
02392   if (v->direction & 2) v->u.rail.track = TRACK_BIT_Y;
02393 
02394   v->vehstatus &= ~VS_HIDDEN;
02395   v->cur_speed = 0;
02396 
02397   v->UpdateDeltaXY(v->direction);
02398   v->cur_image = v->GetImage(v->direction);
02399   VehiclePositionChanged(v);
02400   UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
02401   UpdateTrainAcceleration(v);
02402   InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
02403 
02404   return false;
02405 }
02406 
02407 /* Check for station tiles */
02408 struct TrainTrackFollowerData {
02409   TileIndex dest_coords;
02410   StationID station_index; // station index we're heading for
02411   uint best_bird_dist;
02412   uint best_track_dist;
02413   TrackdirByte best_track;
02414 };
02415 
02416 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
02417 {
02418   /* heading for nowhere? */
02419   if (ttfd->dest_coords == 0) return false;
02420 
02421   /* did we reach the final station? */
02422   if ((ttfd->station_index == INVALID_STATION && tile == ttfd->dest_coords) || (
02423         IsTileType(tile, MP_STATION) &&
02424         IsRailwayStation(tile) &&
02425         GetStationIndex(tile) == ttfd->station_index
02426       )) {
02427     /* We do not check for dest_coords if we have a station_index,
02428      * because in that case the dest_coords are just an
02429      * approximation of where the station is */
02430 
02431     /* found station */
02432     ttfd->best_track = track;
02433     ttfd->best_bird_dist = 0;
02434     return true;
02435   } else {
02436     /* didn't find station, keep track of the best path so far. */
02437     uint dist = DistanceManhattan(tile, ttfd->dest_coords);
02438     if (dist < ttfd->best_bird_dist) {
02439       ttfd->best_bird_dist = dist;
02440       ttfd->best_track = track;
02441     }
02442     return false;
02443   }
02444 }
02445 
02446 static void FillWithStationData(TrainTrackFollowerData* fd, const Vehicle* v)
02447 {
02448   fd->dest_coords = v->dest_tile;
02449   if (v->current_order.type == OT_GOTO_STATION) {
02450     fd->station_index = v->current_order.dest;
02451   } else {
02452     fd->station_index = INVALID_STATION;
02453   }
02454 }
02455 
02456 static const byte _initial_tile_subcoord[6][4][3] = {
02457 {{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0,  0, 0 }},
02458 {{  0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }},
02459 {{  0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0,  0, 0 }},
02460 {{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }},
02461 {{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0,  0, 0 }},
02462 {{  0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }},
02463 };
02464 
02465 static const uint32 _reachable_tracks[4] = {
02466   0x10091009,
02467   0x00160016,
02468   0x05200520,
02469   0x2A002A00,
02470 };
02471 
02472 static const byte _search_directions[6][4] = {
02473   { 0, 9, 2, 9 }, 
02474   { 9, 1, 9, 3 }, 
02475   { 9, 0, 3, 9 }, 
02476   { 1, 9, 9, 2 }, 
02477   { 3, 2, 9, 9 }, 
02478   { 9, 9, 1, 0 }, 
02479 };
02480 
02481 static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0};
02482 
02483 /* choose a track */
02484 static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
02485 {
02486   Track best_track;
02487   /* pathfinders are able to tell that route was only 'guessed' */
02488   bool path_not_found = false;
02489 
02490 #ifdef PF_BENCHMARK
02491   TIC()
02492 #endif
02493 
02494   assert((tracks & ~TRACK_BIT_MASK) == 0);
02495 
02496   /* quick return in case only one possible track is available */
02497   if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks);
02498 
02499   switch (_patches.pathfinder_for_trains) {
02500     case VPF_YAPF: { /* YAPF */
02501       Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
02502       if (trackdir != INVALID_TRACKDIR) {
02503         best_track = TrackdirToTrack(trackdir);
02504       } else {
02505         best_track = FindFirstTrack(tracks);
02506       }
02507     } break;
02508 
02509     case VPF_NPF: { /* NPF */
02510       void *perf = NpfBeginInterval();
02511 
02512       NPFFindStationOrTileData fstd;
02513       NPFFillWithOrderData(&fstd, v);
02514       /* The enterdir for the new tile, is the exitdir for the old tile */
02515       Trackdir trackdir = GetVehicleTrackdir(v);
02516       assert(trackdir != INVALID_TRACKDIR);
02517 
02518       NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
02519 
02520       if (ftd.best_trackdir == INVALID_TRACKDIR) {
02521         /* We are already at our target. Just do something
02522          * @todo maybe display error?
02523          * @todo: go straight ahead if possible? */
02524         best_track = FindFirstTrack(tracks);
02525       } else {
02526         /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
02527          * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
02528          * we did not find our target, but ftd.best_trackdir contains the direction leading
02529          * to the tile closest to our target. */
02530         if (ftd.best_bird_dist != 0) path_not_found = true;
02531         /* Discard enterdir information, making it a normal track */
02532         best_track = TrackdirToTrack(ftd.best_trackdir);
02533       }
02534 
02535       int time = NpfEndInterval(perf);
02536       DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
02537     } break;
02538 
02539     default:
02540     case VPF_NTP: { /* NTP */
02541       void *perf = NpfBeginInterval();
02542 
02543       TrainTrackFollowerData fd;
02544       FillWithStationData(&fd, v);
02545 
02546       /* New train pathfinding */
02547       fd.best_bird_dist = UINT_MAX;
02548       fd.best_track_dist = UINT_MAX;
02549       fd.best_track = INVALID_TRACKDIR;
02550 
02551       NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
02552         v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
02553 
02554       /* check whether the path was found or only 'guessed' */
02555       if (fd.best_bird_dist != 0) path_not_found = true;
02556 
02557       if (fd.best_track == INVALID_TRACKDIR) {
02558         /* blaha */
02559         best_track = FindFirstTrack(tracks);
02560       } else {
02561         best_track = TrackdirToTrack(fd.best_track);
02562       }
02563 
02564       int time = NpfEndInterval(perf);
02565       DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
02566     } break;
02567   }
02568 
02569   /* handle "path not found" state */
02570   if (path_not_found) {
02571     /* PF didn't find the route */
02572     if (!HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
02573       /* it is first time the problem occurred, set the "path not found" flag */
02574       SetBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
02575       /* and notify user about the event */
02576       if (_patches.lost_train_warn && v->owner == _local_player) {
02577         SetDParam(0, v->unitnumber);
02578         AddNewsItem(
02579           STR_TRAIN_IS_LOST,
02580           NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
02581           v->index,
02582           0);
02583       }
02584     }
02585   } else {
02586     /* route found, is the train marked with "path not found" flag? */
02587     if (HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
02588       /* clear the flag as the PF's problem was solved */
02589       ClrBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
02590       /* can we also delete the "News" item somehow? */
02591     }
02592   }
02593 
02594 #ifdef PF_BENCHMARK
02595   TOC("PF time = ", 1)
02596 #endif
02597 
02598   return best_track;
02599 }
02600 
02601 
02602 static bool CheckReverseTrain(Vehicle *v)
02603 {
02604   if (_opt.diff.line_reverse_mode != 0 ||
02605       v->u.rail.track == TRACK_BIT_DEPOT || v->u.rail.track == TRACK_BIT_WORMHOLE ||
02606       !(v->direction & 1))
02607     return false;
02608 
02609   TrainTrackFollowerData fd;
02610   FillWithStationData(&fd, v);
02611 
02612   uint reverse_best = 0;
02613 
02614   assert(v->u.rail.track);
02615 
02616   int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)];
02617 
02618   switch (_patches.pathfinder_for_trains) {
02619     case VPF_YAPF: { /* YAPF */
02620       reverse_best = YapfCheckReverseTrain(v);
02621     } break;
02622 
02623     case VPF_NPF: { /* NPF */
02624       NPFFindStationOrTileData fstd;
02625       NPFFoundTargetData ftd;
02626       Vehicle* last = GetLastVehicleInChain(v);
02627 
02628       NPFFillWithOrderData(&fstd, v);
02629 
02630       Trackdir trackdir = GetVehicleTrackdir(v);
02631       Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
02632       assert(trackdir != INVALID_TRACKDIR);
02633       assert(trackdir_rev != INVALID_TRACKDIR);
02634 
02635       ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
02636       if (ftd.best_bird_dist != 0) {
02637         /* We didn't find anything, just keep on going straight ahead */
02638         reverse_best = false;
02639       } else {
02640         if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) {
02641           reverse_best = true;
02642         } else {
02643           reverse_best = false;
02644         }
02645       }
02646     } break;
02647 
02648     default:
02649     case VPF_NTP: { /* NTP */
02650       int best_track = -1;
02651       uint reverse = 0;
02652       uint best_bird_dist  = 0;
02653       uint best_track_dist = 0;
02654 
02655       for (;;) {
02656         fd.best_bird_dist = UINT_MAX;
02657         fd.best_track_dist = UINT_MAX;
02658 
02659         NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
02660 
02661         if (best_track != -1) {
02662           if (best_bird_dist != 0) {
02663             if (fd.best_bird_dist != 0) {
02664               /* neither reached the destination, pick the one with the smallest bird dist */
02665               if (fd.best_bird_dist > best_bird_dist) goto bad;
02666               if (fd.best_bird_dist < best_bird_dist) goto good;
02667             } else {
02668               /* we found the destination for the first time */
02669               goto good;
02670             }
02671           } else {
02672             if (fd.best_bird_dist != 0) {
02673               /* didn't find destination, but we've found the destination previously */
02674               goto bad;
02675             } else {
02676               /* both old & new reached the destination, compare track length */
02677               if (fd.best_track_dist > best_track_dist) goto bad;
02678               if (fd.best_track_dist < best_track_dist) goto good;
02679             }
02680           }
02681 
02682           /* if we reach this position, there's two paths of equal value so far.
02683            * pick one randomly. */
02684           int r = GB(Random(), 0, 8);
02685           if (_pick_track_table[i] == (v->direction & 3)) r += 80;
02686           if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
02687           if (r <= 127) goto bad;
02688         }
02689 good:;
02690         best_track = i;
02691         best_bird_dist = fd.best_bird_dist;
02692         best_track_dist = fd.best_track_dist;
02693         reverse_best = reverse;
02694 bad:;
02695         if (reverse != 0) break;
02696         reverse = 2;
02697       }
02698     } break;
02699   }
02700 
02701   return reverse_best != 0;
02702 }
02703 
02704 static bool ProcessTrainOrder(Vehicle *v)
02705 {
02706   switch (v->current_order.type) {
02707     case OT_GOTO_DEPOT:
02708       if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return false;
02709       if ((v->current_order.flags & OFB_SERVICE_IF_NEEDED) &&
02710           !v->NeedsServicing()) {
02711         UpdateVehicleTimetable(v, true);
02712         v->cur_order_index++;
02713       }
02714       break;
02715 
02716     case OT_LOADING:
02717     case OT_LEAVESTATION:
02718       return false;
02719 
02720     default: break;
02721   }
02722 
02730   bool may_reverse = v->current_order.type == OT_NOTHING;
02731 
02732   /* check if we've reached the waypoint? */
02733   if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
02734     UpdateVehicleTimetable(v, true);
02735     v->cur_order_index++;
02736   }
02737 
02738   /* check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
02739   if (_patches.new_nonstop &&
02740       v->current_order.flags & OFB_NON_STOP &&
02741       IsTileType(v->tile, MP_STATION) &&
02742       v->current_order.dest == GetStationIndex(v->tile)) {
02743     UpdateVehicleTimetable(v, true);
02744     v->cur_order_index++;
02745   }
02746 
02747   /* Get the current order */
02748   if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
02749 
02750   const Order *order = GetVehicleOrder(v, v->cur_order_index);
02751 
02752   /* If no order, do nothing. */
02753   if (order == NULL) {
02754     v->current_order.Free();
02755     v->dest_tile = 0;
02756     return false;
02757   }
02758 
02759   /* If it is unchanged, keep it. */
02760   if (order->type  == v->current_order.type &&
02761       order->flags == v->current_order.flags &&
02762       order->dest  == v->current_order.dest)
02763     return false;
02764 
02765   /* Otherwise set it, and determine the destination tile. */
02766   v->current_order = *order;
02767 
02768   v->dest_tile = 0;
02769 
02770   InvalidateVehicleOrder(v);
02771 
02772   switch (order->type) {
02773     case OT_GOTO_STATION:
02774       if (order->dest == v->last_station_visited)
02775         v->last_station_visited = INVALID_STATION;
02776       v->dest_tile = GetStation(order->dest)->xy;
02777       break;
02778 
02779     case OT_GOTO_DEPOT:
02780       v->dest_tile = GetDepot(order->dest)->xy;
02781       break;
02782 
02783     case OT_GOTO_WAYPOINT:
02784       v->dest_tile = GetWaypoint(order->dest)->xy;
02785       break;
02786 
02787     default:
02788       return false;
02789   }
02790 
02791   return may_reverse && CheckReverseTrain(v);
02792 }
02793 
02794 void Train::MarkDirty()
02795 {
02796   Vehicle *v = this;
02797   do {
02798     v->cur_image = v->GetImage(v->direction);
02799     MarkSingleVehicleDirty(v);
02800   } while ((v = v->Next()) != NULL);
02801 
02802   /* need to update acceleration and cached values since the goods on the train changed. */
02803   TrainCargoChanged(this);
02804   UpdateTrainAcceleration(this);
02805 }
02806 
02807 static int UpdateTrainSpeed(Vehicle *v)
02808 {
02809   uint accel;
02810 
02811   if (v->vehstatus & VS_STOPPED || HasBit(v->u.rail.flags, VRF_REVERSING)) {
02812     if (_patches.realistic_acceleration) {
02813       accel = GetTrainAcceleration(v, AM_BRAKE) * 2;
02814     } else {
02815       accel = v->acceleration * -2;
02816     }
02817   } else {
02818     if (_patches.realistic_acceleration) {
02819       accel = GetTrainAcceleration(v, AM_ACCEL);
02820     } else {
02821       accel = v->acceleration;
02822     }
02823   }
02824 
02825   uint spd = v->subspeed + accel * 2;
02826   v->subspeed = (byte)spd;
02827   {
02828     int tempmax = v->max_speed;
02829     if (v->cur_speed > v->max_speed)
02830       tempmax = v->cur_speed - (v->cur_speed / 10) - 1;
02831     v->cur_speed = spd = Clamp(v->cur_speed + ((int)spd >> 8), 0, tempmax);
02832   }
02833 
02834   if (!(v->direction & 1)) spd = spd * 3 >> 2;
02835 
02836   spd += v->progress;
02837   v->progress = (byte)spd;
02838   return (spd >> 8);
02839 }
02840 
02841 static void TrainEnterStation(Vehicle *v, StationID station)
02842 {
02843   v->last_station_visited = station;
02844 
02845   /* check if a train ever visited this station before */
02846   Station *st = GetStation(station);
02847   if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
02848     st->had_vehicle_of_type |= HVOT_TRAIN;
02849     SetDParam(0, st->index);
02850     uint32 flags = v->owner == _local_player ?
02851       NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) :
02852       NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ARRIVAL_OTHER,  0);
02853     AddNewsItem(
02854       STR_8801_CITIZENS_CELEBRATE_FIRST,
02855       flags,
02856       v->index,
02857       0
02858     );
02859   }
02860 
02861   v->BeginLoading();
02862   v->current_order.dest = 0;
02863 }
02864 
02865 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
02866 {
02867   byte old_z = v->z_pos;
02868   v->z_pos = GetSlopeZ(v->x_pos, v->y_pos);
02869 
02870   if (new_tile) {
02871     ClrBit(v->u.rail.flags, VRF_GOINGUP);
02872     ClrBit(v->u.rail.flags, VRF_GOINGDOWN);
02873 
02874     if (v->u.rail.track == TRACK_BIT_X || v->u.rail.track == TRACK_BIT_Y) {
02875       /* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped.
02876        * To check whether the current tile is sloped, and in which
02877        * direction it is sloped, we get the 'z' at the center of
02878        * the tile (middle_z) and the edge of the tile (old_z),
02879        * which we then can compare. */
02880       static const int HALF_TILE_SIZE = TILE_SIZE / 2;
02881       static const int INV_TILE_SIZE_MASK = ~(TILE_SIZE - 1);
02882 
02883       byte middle_z = GetSlopeZ((v->x_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE, (v->y_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE);
02884 
02885       /* For some reason tunnel tiles are always given as sloped :(
02886        * But they are not sloped... */
02887       if (middle_z != v->z_pos && !IsTunnelTile(TileVirtXY(v->x_pos, v->y_pos))) {
02888         SetBit(v->u.rail.flags, (middle_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
02889       }
02890     }
02891   }
02892 
02893   VehiclePositionChanged(v);
02894   EndVehicleMove(v);
02895   return old_z;
02896 }
02897 
02898 static const Direction _new_vehicle_direction_table[11] = {
02899   DIR_N , DIR_NW, DIR_W , INVALID_DIR,
02900   DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
02901   DIR_E , DIR_SE, DIR_S
02902 };
02903 
02904 static inline Direction GetNewVehicleDirectionByTile(TileIndex new_tile, TileIndex old_tile)
02905 {
02906   uint offs = (TileY(new_tile) - TileY(old_tile) + 1) * 4 +
02907               TileX(new_tile) - TileX(old_tile) + 1;
02908   assert(offs < 11);
02909   return _new_vehicle_direction_table[offs];
02910 }
02911 
02912 static inline int GetDirectionToVehicle(const Vehicle *v, int x, int y)
02913 {
02914   byte offs;
02915 
02916   x -= v->x_pos;
02917   if (x >= 0) {
02918     offs = (x > 2) ? 0 : 1;
02919   } else {
02920     offs = (x < -2) ? 2 : 1;
02921   }
02922 
02923   y -= v->y_pos;
02924   if (y >= 0) {
02925     offs += ((y > 2) ? 0 : 1) * 4;
02926   } else {
02927     offs += ((y < -2) ? 2 : 1) * 4;
02928   }
02929 
02930   assert(offs < 11);
02931   return _new_vehicle_direction_table[offs];
02932 }
02933 
02934 /* Check if the vehicle is compatible with the specified tile */
02935 static inline bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
02936 {
02937   return
02938     IsTileOwner(tile, v->owner) && (
02939       !IsFrontEngine(v) ||
02940       HasBit(v->u.rail.compatible_railtypes, GetRailType(tile))
02941     );
02942 }
02943 
02944 struct RailtypeSlowdownParams {
02945   byte small_turn, large_turn;
02946   byte z_up; // fraction to remove when moving up
02947   byte z_down; // fraction to remove when moving down
02948 };
02949 
02950 static const RailtypeSlowdownParams _railtype_slowdown[] = {
02951   // normal accel
02952   {256 / 4, 256 / 2, 256 / 4, 2}, 
02953   {256 / 4, 256 / 2, 256 / 4, 2}, 
02954   {256 / 4, 256 / 2, 256 / 4, 2}, 
02955   {0,       256 / 2, 256 / 4, 2}, 
02956 };
02957 
02959 static inline void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
02960 {
02961   if (_patches.realistic_acceleration) return;
02962 
02963   DirDiff diff = DirDifference(v->direction, new_dir);
02964   if (diff == DIRDIFF_SAME) return;
02965 
02966   const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
02967   v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
02968 }
02969 
02971 static inline void AffectSpeedByZChange(Vehicle *v, byte old_z)
02972 {
02973   if (old_z == v->z_pos || _patches.realistic_acceleration) return;
02974 
02975   const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
02976 
02977   if (old_z < v->z_pos) {
02978     v->cur_speed -= (v->cur_speed * rsp->z_up >> 8);
02979   } else {
02980     uint16 spd = v->cur_speed + rsp->z_down;
02981     if (spd <= v->max_speed) v->cur_speed = spd;
02982   }
02983 }
02984 
02985 static const DiagDirection _otherside_signal_directions[] = {
02986   DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE, INVALID_DIAGDIR, INVALID_DIAGDIR,
02987   DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE
02988 };
02989 
02990 static void TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
02991 {
02992   if (IsTileType(tile, MP_RAILWAY) &&
02993       GetRailTileType(tile) == RAIL_TILE_SIGNALS) {
02994     uint i = FindFirstBit2x64(GetTrackBits(tile) * 0x101 & _reachable_tracks[dir]);
02995     UpdateSignalsOnSegment(tile, _otherside_signal_directions[i], GetTileOwner(tile));
02996   }
02997 }
02998 
02999 
03000 static void SetVehicleCrashed(Vehicle *v)
03001 {
03002   if (v->u.rail.crash_anim_pos != 0) return;
03003 
03004   /* we may need to update crossing we were approaching */
03005   TileIndex crossing = TrainApproachingCrossingTile(v);
03006 
03007   v->u.rail.crash_anim_pos++;
03008 
03009   InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
03010   InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
03011 
03012   if (v->u.rail.track == TRACK_BIT_DEPOT) {
03013     InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
03014   }
03015 
03016   RebuildVehicleLists();
03017 
03018   BEGIN_ENUM_WAGONS(v)
03019     v->vehstatus |= VS_CRASHED;
03020     MarkSingleVehicleDirty(v);
03021   END_ENUM_WAGONS(v)
03022 
03023   /* must be updated after the train has been marked crashed */
03024   if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
03025 }
03026 
03027 static uint CountPassengersInTrain(const Vehicle* v)
03028 {
03029   uint num = 0;
03030   BEGIN_ENUM_WAGONS(v)
03031     if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo.Count();
03032   END_ENUM_WAGONS(v)
03033   return num;
03034 }
03035 
03036 struct TrainCollideChecker {
03037   Vehicle *v;
03038   uint num;
03039 };
03040 
03041 static void *FindTrainCollideEnum(Vehicle *v, void *data)
03042 {
03043   TrainCollideChecker* tcc = (TrainCollideChecker*)data;
03044 
03045   if (v->type != VEH_TRAIN) return NULL;
03046 
03047   /* get first vehicle now to make most usual checks faster */
03048   Vehicle *coll = v->First();
03049 
03050   /* can't collide with own wagons && can't crash in depot && the same height level */
03051   if (coll != tcc->v && v->u.rail.track != TRACK_BIT_DEPOT && abs(v->z_pos - tcc->v->z_pos) < 6) {
03052     int x_diff = v->x_pos - tcc->v->x_pos;
03053     int y_diff = v->y_pos - tcc->v->y_pos;
03054 
03055     /* needed to disable possible crash of competitor train in station by building diagonal track at its end */
03056     if (x_diff * x_diff + y_diff * y_diff > 25) return NULL;
03057 
03058     if (!(tcc->v->vehstatus & VS_CRASHED)) {
03059       /* two drivers + passengers killed in train tcc->v (if it was not crashed already) */
03060       tcc->num += 2 + CountPassengersInTrain(tcc->v);
03061       SetVehicleCrashed(tcc->v);
03062     }
03063 
03064     if (!(coll->vehstatus & VS_CRASHED)) {
03065       /* two drivers + passengers killed in train coll (if it was not crashed already) */
03066       tcc->num += 2 + CountPassengersInTrain(coll);
03067       SetVehicleCrashed(coll);
03068     }
03069   }
03070 
03071   return NULL;
03072 }
03073 
03080 static void CheckTrainCollision(Vehicle *v)
03081 {
03082   /* can't collide in depot */
03083   if (v->u.rail.track == TRACK_BIT_DEPOT) return;
03084 
03085   assert(v->u.rail.track == TRACK_BIT_WORMHOLE || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
03086 
03087   TrainCollideChecker tcc;
03088   tcc.v = v;
03089   tcc.num = 0;
03090 
03091   /* find colliding vehicles */
03092   if (v->u.rail.track == TRACK_BIT_WORMHOLE) {
03093     FindVehicleOnPos(v->tile, &tcc, FindTrainCollideEnum);
03094     FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum);
03095   } else {
03096     FindVehicleOnPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
03097   }
03098 
03099   /* any dead -> no crash */
03100   if (tcc.num == 0) return;
03101 
03102   SetDParam(0, tcc.num);
03103   AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
03104     NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
03105     v->index,
03106     0
03107   );
03108 
03109   ModifyStationRatingAround(v->tile, v->owner, -160, 30);
03110   SndPlayVehicleFx(SND_13_BIG_CRASH, v);
03111 }
03112 
03113 static void *CheckVehicleAtSignal(Vehicle *v, void *data)
03114 {
03115   DiagDirection exitdir = *(DiagDirection *)data;
03116 
03117   /* front engine of a train, not inside wormhole or depot, not crashed */
03118   if (v->type == VEH_TRAIN && IsFrontEngine(v) && (v->u.rail.track & TRACK_BIT_MASK) != 0 && !(v->vehstatus & VS_CRASHED)) {
03119     if (v->cur_speed <= 5 && TrainExitDir(v->direction, v->u.rail.track) == exitdir) return v;
03120   }
03121 
03122   return NULL;
03123 }
03124 
03125 static void TrainController(Vehicle *v, Vehicle *nomove, bool update_image)
03126 {
03127   Vehicle *prev;
03128 
03129   /* For every vehicle after and including the given vehicle */
03130   for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) {
03131     DiagDirection enterdir = DIAGDIR_BEGIN;
03132     bool update_signals_crossing = false; // will we update signals or crossing state?
03133     BeginVehicleMove(v);
03134 
03135     GetNewVehiclePosResult gp = GetNewVehiclePos(v);
03136     if (v->u.rail.track != TRACK_BIT_WORMHOLE) {
03137       /* Not inside tunnel */
03138       if (gp.old_tile == gp.new_tile) {
03139         /* Staying in the old tile */
03140         if (v->u.rail.track == TRACK_BIT_DEPOT) {
03141           /* Inside depot */
03142           gp.x = v->x_pos;
03143           gp.y = v->y_pos;
03144         } else {
03145           /* Not inside depot */
03146 
03147           if (IsFrontEngine(v) && !TrainCheckIfLineEnds(v)) return;
03148 
03149           uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
03150           if (HasBit(r, VETS_CANNOT_ENTER)) {
03151             goto invalid_rail;
03152           }
03153           if (HasBit(r, VETS_ENTERED_STATION)) {
03154             TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
03155             return;
03156           }
03157 
03158           if (v->current_order.type == OT_LEAVESTATION) {
03159             v->current_order.Free();
03160             InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
03161           }
03162         }
03163       } else {
03164         /* A new tile is about to be entered. */
03165 
03166         /* Determine what direction we're entering the new tile from */
03167         Direction dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile);
03168         enterdir = DirToDiagDir(dir);
03169         assert(IsValidDiagDirection(enterdir));
03170 
03171         /* Get the status of the tracks in the new tile and mask
03172          * away the bits that aren't reachable. */
03173         TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir)) & _reachable_tracks[enterdir];
03174         TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
03175         TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts));
03176 
03177         TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
03178         if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) {
03179           /* We allow wagons to make 90 deg turns, because forbid_90_deg
03180            * can be switched on halfway a turn */
03181           bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
03182         }
03183 
03184         if (bits == TRACK_BIT_NONE) goto invalid_rail;
03185 
03186         /* Check if the new tile contrains tracks that are compatible
03187          * with the current train, if not, bail out. */
03188         if (!CheckCompatibleRail(v, gp.new_tile)) goto invalid_rail;
03189 
03190         TrackBits chosen_track;
03191         if (prev == NULL) {
03192           /* Currently the locomotive is active. Determine which one of the
03193            * available tracks to choose */
03194           chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits));
03195           assert(chosen_track & bits);
03196 
03197           /* Check if it's a red signal and that force proceed is not clicked. */
03198           if (red_signals & chosen_track && v->u.rail.force_proceed == 0) {
03199             /* In front of a red signal */
03200             Trackdir i = FindFirstTrackdir(trackdirbits);
03201 
03202             if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
03203               v->cur_speed = 0;
03204               v->subspeed = 0;
03205               v->progress = 255 - 100;
03206               if (++v->load_unload_time_rem < _patches.wait_oneway_signal * 20) return;
03207             } else if (HasSignalOnTrackdir(gp.new_tile, i)) {
03208               v->cur_speed = 0;
03209               v->subspeed = 0;
03210               v->progress = 255 - 10;
03211               if (++v->load_unload_time_rem < _patches.wait_twoway_signal * 73) {
03212                 DiagDirection exitdir = TrackdirToExitdir(i);
03213                 TileIndex o_tile = TileAddByDiagDir(gp.new_tile, exitdir);
03214 
03215                 exitdir = ReverseDiagDir(exitdir);
03216 
03217                 /* check if a train is waiting on the other side */
03218                 if (!HasVehicleOnPos(o_tile, &exitdir, &CheckVehicleAtSignal)) return;
03219               }
03220             }
03221             goto reverse_train_direction;
03222           }
03223         } else {
03224           static const TrackBits _matching_tracks[8] = {
03225               TRACK_BIT_LEFT  | TRACK_BIT_RIGHT, TRACK_BIT_X,
03226               TRACK_BIT_UPPER | TRACK_BIT_LOWER, TRACK_BIT_Y,
03227               TRACK_BIT_LEFT  | TRACK_BIT_RIGHT, TRACK_BIT_X,
03228               TRACK_BIT_UPPER | TRACK_BIT_LOWER, TRACK_BIT_Y
03229           };
03230 
03231           /* The wagon is active, simply follow the prev vehicle. */
03232           chosen_track = (TrackBits)(byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits);
03233         }
03234 
03235         /* Make sure chosen track is a valid track */
03236         assert(
03237             chosen_track == TRACK_BIT_X     || chosen_track == TRACK_BIT_Y ||
03238             chosen_track == TRACK_BIT_UPPER || chosen_track == TRACK_BIT_LOWER ||
03239             chosen_track == TRACK_BIT_LEFT  || chosen_track == TRACK_BIT_RIGHT);
03240 
03241         /* Update XY to reflect the entrance to the new tile, and select the direction to use */
03242         const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir];
03243         gp.x = (gp.x & ~0xF) | b[0];
03244         gp.y = (gp.y & ~0xF) | b[1];
03245         Direction chosen_dir = (Direction)b[2];
03246 
03247         /* Call the landscape function and tell it that the vehicle entered the tile */
03248         uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
03249         if (HasBit(r, VETS_CANNOT_ENTER)) {
03250           goto invalid_rail;
03251         }
03252 
03253         if (IsFrontEngine(v)) v->load_unload_time_rem = 0;
03254 
03255         if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
03256           v->tile = gp.new_tile;
03257 
03258           if (GetTileRailType(gp.new_tile) != GetTileRailType(gp.old_tile)) {
03259             TrainPowerChanged(v->First());
03260           }
03261 
03262           v->u.rail.track = chosen_track;
03263           assert(v->u.rail.track);
03264         }
03265 
03266         /* We need to update signal status, but after the vehicle position hash
03267          * has been updated by AfterSetTrainPos() */
03268         update_signals_crossing = true;
03269 
03270         if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
03271 
03272         v->direction = chosen_dir;
03273       }
03274     } else {
03275       /* In a tunnel or on a bridge
03276        * - for tunnels, only the part when the vehicle is not visible (part of enter/exit tile too)
03277        * - for bridges, only the middle part - without the bridge heads */
03278       if (!(v->vehstatus & VS_HIDDEN)) {
03279         v->cur_speed =
03280           min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed);
03281       }
03282 
03283       if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
03284         v->x_pos = gp.x;
03285         v->y_pos = gp.y;
03286         VehiclePositionChanged(v);
03287         if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
03288         continue;
03289       }
03290     }
03291 
03292     /* update image of train, as well as delta XY */
03293     v->UpdateDeltaXY(v->direction);
03294     if (update_image) v->cur_image = v->GetImage(v->direction);
03295 
03296     v->x_pos = gp.x;
03297     v->y_pos = gp.y;
03298 
03299     /* update the Z position of the vehicle */
03300     byte old_z = AfterSetTrainPos(v, (gp.new_tile != gp.old_tile));
03301 
03302     if (prev == NULL) {
03303       /* This is the first vehicle in the train */
03304       AffectSpeedByZChange(v, old_z);
03305     }
03306 
03307     if (update_signals_crossing) {
03308       if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir);
03309 
03310       /* Signals can only change when the first
03311        * (above) or the last vehicle moves. */
03312       if (v->Next() == NULL) {
03313         TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
03314         if (IsLevelCrossingTile(gp.old_tile)) UpdateLevelCrossing(gp.old_tile);
03315       }
03316     }
03317   }
03318   return;
03319 
03320 invalid_rail:
03321   /* We've reached end of line?? */
03322   if (prev != NULL) error("!Disconnecting train");
03323 
03324 reverse_train_direction:
03325   v->load_unload_time_rem = 0;
03326   v->cur_speed = 0;
03327   v->subspeed = 0;
03328   ReverseTrainDirection(v);
03329 }
03330 
03338 static void DeleteLastWagon(Vehicle *v)
03339 {
03340   Vehicle *first = v->First();
03341 
03342   /* Go to the last wagon and delete the link pointing there
03343    * *u is then the one-before-last wagon, and *v the last
03344    * one which will physicially be removed */
03345   Vehicle *u = v;
03346   for (; v->Next() != NULL; v = v->Next()) u = v;
03347   u->SetNext(NULL);
03348 
03349   if (first == v) {
03350     /* Removing front vehicle (the last to go) */
03351     DeleteWindowById(WC_VEHICLE_VIEW, v->index);
03352     InvalidateWindow(WC_COMPANY, v->owner);
03353   } else {
03354     /* Recalculate cached train properties */
03355     TrainConsistChanged(first, false);
03356     /* Update the depot window if the first vehicle is in depot -
03357      * if v == first, then it is updated in PreDestructor() */
03358     if (first->u.rail.track == TRACK_BIT_DEPOT) {
03359       InvalidateWindow(WC_VEHICLE_DEPOT, first->tile);
03360     }
03361   }
03362 
03363   RebuildVehicleLists();
03364 
03365   MarkSingleVehicleDirty(v);
03366 
03367   /* 'v' shouldn't be accessed after it has been deleted */
03368   TrackBits track = v->u.rail.track;
03369   TileIndex tile = v->tile;
03370   Owner owner = v->owner;
03371 
03372   delete v;
03373   v = NULL; // make sure nobody will won't try to read 'v' anymore
03374 
03375   /* check if the wagon was on a road/rail-crossing */
03376   if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
03377 
03378   /* Update signals */
03379   if (IsTileType(tile, MP_TUNNELBRIDGE) || IsTileDepotType(tile, TRANSPORT_RAIL)) {
03380     UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, owner);
03381   } else {
03382     SetSignalsOnBothDir(tile, (Track)(FIND_FIRST_BIT(track)), owner);
03383   }
03384 }
03385 
03386 static void ChangeTrainDirRandomly(Vehicle *v)
03387 {
03388   static const DirDiff delta[] = {
03389     DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
03390   };
03391 
03392   do {
03393     /* We don't need to twist around vehicles if they're not visible */
03394     if (!(v->vehstatus & VS_HIDDEN)) {
03395       v->direction = ChangeDir(v->direction, delta[GB(Random(), 0, 2)]);
03396       BeginVehicleMove(v);
03397       v->UpdateDeltaXY(v->direction);
03398       v->cur_image = v->GetImage(v->direction);
03399       /* Refrain from updating the z position of the vehicle when on
03400          a bridge, because AfterSetTrainPos will put the vehicle under
03401          the bridge in that case */
03402       if (v->u.rail.track != TRACK_BIT_WORMHOLE) AfterSetTrainPos(v, false);
03403     }
03404   } while ((v = v->Next()) != NULL);
03405 }
03406 
03407 static void HandleCrashedTrain(Vehicle *v)
03408 {
03409   int state = ++v->u.rail.crash_anim_pos;
03410 
03411   if (state == 4 && !(v->vehstatus & VS_HIDDEN)) {
03412     CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
03413   }
03414 
03415   uint32 r;
03416   if (state <= 200 && Chance16R(1, 7, r)) {
03417     int index = (r * 10 >> 16);
03418 
03419     Vehicle *u = v;
03420     do {
03421       if (--index < 0) {
03422         r = Random();
03423 
03424         CreateEffectVehicleRel(u,
03425           GB(r,  8, 3) + 2,
03426           GB(r, 16, 3) + 2,
03427           GB(r,  0, 3) + 5,
03428           EV_EXPLOSION_SMALL);
03429         break;
03430       }
03431     } while ((u = u->Next()) != NULL);
03432   }
03433 
03434   if (state <= 240 && !(v->tick_counter & 3)) ChangeTrainDirRandomly(v);
03435 
03436   if (state >= 4440 && !(v->tick_counter&0x1F)) {
03437     DeleteLastWagon(v);
03438     InvalidateWindow(WC_REPLACE_VEHICLE, (v->group_id << 16) | VEH_TRAIN);
03439   }
03440 }
03441 
03442 static void HandleBrokenTrain(Vehicle *v)
03443 {
03444   if (v->breakdown_ctr != 1) {
03445     v->breakdown_ctr = 1;
03446     v->cur_speed = 0;
03447 
03448     if (v->breakdowns_since_last_service != 255)
03449       v->breakdowns_since_last_service++;
03450 
03451     InvalidateWindow(WC_VEHICLE_VIEW, v->index);
03452     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
03453 
03454     if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
03455       SndPlayVehicleFx((_opt.landscape != LT_TOYLAND) ?
03456         SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v);
03457     }
03458 
03459     if (!(v->vehstatus & VS_HIDDEN)) {
03460       Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
03461       if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2;
03462     }
03463   }
03464 
03465   if (!(v->tick_counter & 3)) {
03466     if (!--v->breakdown_delay) {
03467       v->breakdown_ctr = 0;
03468       InvalidateWindow(WC_VEHICLE_VIEW, v->index);
03469     }
03470   }
03471 }
03472 
03474 static const uint16 _breakdown_speeds[16] = {
03475   225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
03476 };
03477 
03478 
03486 static bool TrainApproachingLineEnd(Vehicle *v, bool signal)
03487 {
03488   /* Calc position within the current tile */
03489   uint x = v->x_pos & 0xF;
03490   uint y = v->y_pos & 0xF;
03491 
03492   /* for diagonal directions, 'x' will be 0..15 -
03493    * for other directions, it will be 1, 3, 5, ..., 15 */
03494   switch (v->direction) {
03495     case DIR_N : x = ~x + ~y + 25; break;
03496     case DIR_NW: x = y;            /* FALLTHROUGH */
03497     case DIR_NE: x = ~x + 16;      break;
03498     case DIR_E : x = ~x + y + 9;   break;
03499     case DIR_SE: x = y;            break;
03500     case DIR_S : x = x + y - 7;    break;
03501     case DIR_W : x = ~y + x + 9;   break;
03502     default: break;
03503   }
03504 
03505   /* do not reverse when approaching red signal */
03506   if (!signal && x + 4 >= TILE_SIZE) {
03507     /* we are too near the tile end, reverse now */
03508     v->cur_speed = 0;
03509     ReverseTrainDirection(v);
03510     return false;
03511   }
03512 
03513   /* slow down */
03514   v->vehstatus |= VS_TRAIN_SLOWING;
03515   uint16 break_speed = _breakdown_speeds[x & 0xF];
03516   if (break_speed < v->cur_speed) v->cur_speed = break_speed;
03517 
03518   return true;
03519 }
03520 
03521 
03527 static bool TrainCanLeaveTile(const Vehicle *v)
03528 {
03529   /* Exit if inside a tunnel/bridge or a depot */
03530   if (v->u.rail.track == TRACK_BIT_WORMHOLE || v->u.rail.track == TRACK_BIT_DEPOT) return false;
03531 
03532   TileIndex tile = v->tile;
03533 
03534   /* entering a tunnel/bridge? */
03535   if (IsTileType(tile, MP_TUNNELBRIDGE)) {
03536     DiagDirection dir = GetTunnelBridgeDirection(tile);
03537     if (DiagDirToDir(dir) == v->direction) return false;
03538   }
03539 
03540   /* entering a depot? */
03541   if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
03542     DiagDirection dir = ReverseDiagDir(GetRailDepotDirection(tile));
03543     if (DiagDirToDir(dir) == v->direction) return false;
03544   }
03545 
03546   return true;
03547 }
03548 
03549 
03557 static TileIndex TrainApproachingCrossingTile(const Vehicle *v)
03558 {
03559   assert(IsFrontEngine(v));
03560   assert(!(v->vehstatus & VS_CRASHED));
03561 
03562   if (!TrainCanLeaveTile(v)) return INVALID_TILE;
03563 
03564   DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
03565   TileIndex tile = v->tile + TileOffsByDiagDir(dir);
03566 
03567   /* not a crossing || wrong axis || unusable rail (wrong type or owner) */
03568   if (!IsLevelCrossingTile(tile) || DiagDirToAxis(dir) == GetCrossingRoadAxis(tile) ||
03569       !CheckCompatibleRail(v, tile)) {
03570     return INVALID_TILE;
03571   }
03572 
03573   return tile;
03574 }
03575 
03576 
03583 static bool TrainCheckIfLineEnds(Vehicle *v)
03584 {
03585   /* First, handle broken down train */
03586 
03587   int t = v->breakdown_ctr;
03588   if (t > 1) {
03589     v->vehstatus |= VS_TRAIN_SLOWING;
03590 
03591     uint16 break_speed = _breakdown_speeds[GB(~t, 4, 4)];
03592     if (break_speed < v->cur_speed) v->cur_speed = break_speed;
03593   } else {
03594     v->vehstatus &= ~VS_TRAIN_SLOWING;
03595   }
03596 
03597   if (!TrainCanLeaveTile(v)) return true;
03598 
03599   /* Determine the non-diagonal direction in which we will exit this tile */
03600   DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
03601   /* Calculate next tile */
03602   TileIndex tile = v->tile + TileOffsByDiagDir(dir);
03603 
03604   /* Determine the track status on the next tile */
03605 ; TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0, ReverseDiagDir(dir)) & _reachable_tracks[dir];
03606   TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
03607   TrackdirBits red_signals = TrackStatusToRedSignals(ts);
03608 
03609   /* We are sure the train is not entering a depot, it is detected above */
03610 
03611   /* mask unreachable track bits if we are forbidden to do 90deg turns */
03612   TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
03613   if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) {
03614     bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
03615   }
03616 
03617   /* no suitable trackbits at all || unusable rail (wrong type or owner) */
03618   if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(v, tile)) {
03619     return TrainApproachingLineEnd(v, false);
03620   }
03621 
03622   /* approaching red signal */
03623   if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(v, true);
03624 
03625   /* approaching a rail/road crossing? then make it red */
03626   if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile);
03627 
03628   return true;
03629 }
03630 
03631 
03632 static void TrainLocoHandler(Vehicle *v, bool mode)
03633 {
03634   /* train has crashed? */
03635   if (v->vehstatus & VS_CRASHED) {
03636     if (!mode) HandleCrashedTrain(v);
03637     return;
03638   }
03639 
03640   if (v->u.rail.force_proceed != 0) v->u.rail.force_proceed--;
03641 
03642   /* train is broken down? */
03643   if (v->breakdown_ctr != 0) {
03644     if (v->breakdown_ctr <= 2) {
03645       HandleBrokenTrain(v);
03646       return;
03647     }
03648     if (v->current_order.type != OT_LOADING) v->breakdown_ctr--;
03649   }
03650 
03651   if (HasBit(v->u.rail.flags, VRF_REVERSING) && v->cur_speed == 0) {
03652     ReverseTrainDirection(v);
03653   }
03654 
03655   /* exit if train is stopped */
03656   if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) return;
03657 
03658   if (ProcessTrainOrder(v)) {
03659     v->load_unload_time_rem = 0;
03660     v->cur_speed = 0;
03661     v->subspeed = 0;
03662     ReverseTrainDirection(v);
03663     return;
03664   }
03665 
03666   v->HandleLoading(mode);
03667 
03668   if (v->current_order.type == OT_LOADING) return;
03669 
03670   if (CheckTrainStayInDepot(v)) return;
03671 
03672   if (!mode) HandleLocomotiveSmokeCloud(v);
03673 
03674   int j = UpdateTrainSpeed(v);
03675 
03676   /* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */
03677   if (v->cur_speed == 0 && v->u.rail.last_speed == 0 && v->vehstatus & VS_STOPPED) {
03678     InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
03679   }
03680 
03681   if (j == 0) {
03682     /* if the vehicle has speed 0, update the last_speed field. */
03683     if (v->cur_speed != 0) return;
03684   } else {
03685     TrainCheckIfLineEnds(v);
03686 
03687     do {
03688       TrainController(v, NULL, true);
03689       CheckTrainCollision(v);
03690       if (v->cur_speed <= 0x100)
03691         break;
03692     } while (--j != 0);
03693   }
03694 
03695   SetLastSpeed(v, v->cur_speed);
03696 }
03697 
03698 
03699 
03700 Money Train::GetRunningCost() const
03701 {
03702   Money cost = 0;
03703   const Vehicle *v = this;
03704 
03705   do {
03706     const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
03707 
03708     byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost);
03709     if (cost_factor == 0) continue;
03710 
03711     /* Halve running cost for multiheaded parts */
03712     if (IsMultiheaded(v)) cost_factor /= 2;
03713 
03714     cost += cost_factor * GetPriceByIndex(rvi->running_cost_class);
03715   } while ((v = GetNextVehicle(v)) != NULL);
03716 
03717   return cost;
03718 }
03719 
03720 
03721 void Train::Tick()
03722 {
03723   if (_age_cargo_skip_counter == 0) this->cargo.AgeCargo();
03724 
03725   this->tick_counter++;
03726 
03727   if (IsFrontEngine(this)) {
03728     if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
03729     this->current_order_time++;
03730 
03731     TrainLocoHandler(this, false);
03732 
03733     /* make sure vehicle wasn't deleted. */
03734     if (this->type == VEH_TRAIN && IsFrontEngine(this))
03735       TrainLocoHandler(this, true);
03736   } else if (IsFreeWagon(this) && HASBITS(this->vehstatus, VS_CRASHED)) {
03737     /* Delete flooded standalone wagon chain */
03738     if (++this->u.rail.crash_anim_pos >= 4400) DeleteVehicleChain(this);
03739   }
03740 }
03741 
03742 #define MAX_ACCEPTABLE_DEPOT_DIST 16
03743 
03744 static void CheckIfTrainNeedsService(Vehicle *v)
03745 {
03746   if (_patches.servint_trains == 0 || !v->NeedsAutomaticServicing()) return;
03747   if (v->IsInDepot()) {
03748     VehicleServiceInDepot(v);
03749     return;
03750   }
03751 
03752   TrainFindDepotData tfdd = FindClosestTrainDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
03753   /* Only go to the depot if it is not too far out of our way. */
03754   if (tfdd.best_length == (uint)-1 || tfdd.best_length > MAX_ACCEPTABLE_DEPOT_DIST) {
03755     if (v->current_order.type == OT_GOTO_DEPOT) {
03756       /* If we were already heading for a depot but it has
03757        * suddenly moved farther away, we continue our normal
03758        * schedule? */
03759       v->current_order.type = OT_DUMMY;
03760       v->current_order.flags = 0;
03761       InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
03762     }
03763     return;
03764   }
03765 
03766   const Depot* depot = GetDepotByTile(tfdd.tile);
03767 
03768   if (v->current_order.type == OT_GOTO_DEPOT &&
03769       v->current_order.dest != depot->index &&
03770       !Chance16(3, 16)) {
03771     return;
03772   }
03773 
03774   v->current_order.type = OT_GOTO_DEPOT;
03775   v->current_order.flags = OFB_NON_STOP;
03776   v->current_order.dest = depot->index;
03777   v->dest_tile = tfdd.tile;
03778   InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
03779 }
03780 
03781 void Train::OnNewDay()
03782 {
03783   if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
03784 
03785   if (IsFrontEngine(this)) {
03786     CheckVehicleBreakdown(this);
03787     AgeVehicle(this);
03788 
03789     CheckIfTrainNeedsService(this);
03790 
03791     CheckOrders(this);
03792 
03793     /* update destination */
03794     if (this->current_order.type == OT_GOTO_STATION) {
03795       TileIndex tile = GetStation(this->current_order.dest)->train_tile;
03796       if (tile != 0) this->dest_tile = tile;
03797     }
03798 
03799     if (this->running_ticks != 0) {
03800       /* running costs */
03801       CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() * this->running_ticks / (364 * DAY_TICKS));
03802 
03803       this->profit_this_year -= cost.GetCost();
03804       this->running_ticks = 0;
03805 
03806       SubtractMoneyFromPlayerFract(this->owner, cost);
03807 
03808       InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
03809       InvalidateWindowClasses(WC_TRAINS_LIST);
03810     }
03811   } else if (IsTrainEngine(this)) {
03812     /* Also age engines that aren't front engines */
03813     AgeVehicle(this);
03814   }
03815 }
03816 
03817 void TrainsYearlyLoop()
03818 {
03819   Vehicle *v;
03820 
03821   FOR_ALL_VEHICLES(v) {
03822     if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
03823       /* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
03824       if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) {
03825         SetDParam(1, v->GetDisplayProfitThisYear());
03826         SetDParam(0, v->unitnumber);
03827         AddNewsItem(
03828           STR_TRAIN_IS_UNPROFITABLE,
03829           NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
03830           v->index,
03831           0);
03832       }
03833 
03834       v->profit_last_year = v->profit_this_year;
03835       v->profit_this_year = 0;
03836       InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
03837     }
03838   }
03839 }
03840 
03841 
03842 void InitializeTrains()
03843 {
03844   _age_cargo_skip_counter = 1;
03845 }
03846 
03847 /*
03848  * Link front and rear multiheaded engines to each other
03849  * This is done when loading a savegame
03850  */
03851 void ConnectMultiheadedTrains()
03852 {
03853   Vehicle *v;
03854 
03855   FOR_ALL_VEHICLES(v) {
03856     if (v->type == VEH_TRAIN) {
03857       v->u.rail.other_multiheaded_part = NULL;
03858     }
03859   }
03860 
03861   FOR_ALL_VEHICLES(v) {
03862     if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
03863       /* Two ways to associate multiheaded parts to each other:
03864        * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
03865        * bracket-matching:    Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
03866        *
03867        * Note: Old savegames might contain chains which do not comply with these rules, e.g.
03868        *   - the front and read parts have invalid orders
03869        *   - different engine types might be combined
03870        *   - there might be different amounts of front and rear parts.
03871        *
03872        * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
03873        *   This is why two matching strategies are needed.
03874        */
03875 
03876       bool sequential_matching = IsFrontEngine(v);
03877 
03878       Vehicle *u = v;
03879       BEGIN_ENUM_WAGONS(u) {
03880         if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
03881 
03882         if (IsMultiheaded(u)) {
03883           if (!IsTrainEngine(u)) {
03884             /* we got a rear car without a front car. We will convert it to a front one */
03885             SetTrainEngine(u);
03886             u->spritenum--;
03887           }
03888 
03889           /* Find a matching back part */
03890           EngineID eid = u->engine_type;
03891           Vehicle *w;
03892           if (sequential_matching) {
03893             for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
03894               if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
03895 
03896               /* we found a car to partner with this engine. Now we will make sure it face the right way */
03897               if (IsTrainEngine(w)) {
03898                 ClearTrainEngine(w);
03899                 w->spritenum++;
03900               }
03901               break;
03902             }
03903           } else {
03904             uint stack_pos = 0;
03905             for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
03906               if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
03907 
03908               if (IsTrainEngine(w)) {
03909                 stack_pos++;
03910               } else {
03911                 if (stack_pos == 0) break;
03912                 stack_pos--;
03913               }
03914             }
03915           }
03916 
03917           if (w != NULL) {
03918             w->u.rail.other_multiheaded_part = u;
03919             u->u.rail.other_multiheaded_part = w;
03920           } else {
03921             /* we got a front car and no rear cars. We will fake this one for forget that it should have been multiheaded */
03922             ClearMultiheaded(u);
03923           }
03924         }
03925       } END_ENUM_WAGONS(u)
03926     }
03927   }
03928 }
03929 
03934 void ConvertOldMultiheadToNew()
03935 {
03936   Vehicle *v;
03937   FOR_ALL_VEHICLES(v) {
03938     if (v->type == VEH_TRAIN) {
03939       SetBit(v->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop
03940     }
03941   }
03942 
03943   FOR_ALL_VEHICLES(v) {
03944     if (v->type == VEH_TRAIN) {
03945       if (HasBit(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
03946         Vehicle *u = v;
03947 
03948         BEGIN_ENUM_WAGONS(u) {
03949           const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
03950 
03951           ClrBit(u->subtype, 7);
03952           switch (u->subtype) {
03953             case 0: /* TS_Front_Engine */
03954               if (rvi->railveh_type == RAILVEH_MULTIHEAD) SetMultiheaded(u);
03955               SetFrontEngine(u);
03956               SetTrainEngine(u);
03957               break;
03958 
03959             case 1: /* TS_Artic_Part */
03960               u->subtype = 0;
03961               SetArticulatedPart(u);
03962               break;
03963 
03964             case 2: /* TS_Not_First */
03965               u->subtype = 0;
03966               if (rvi->railveh_type == RAILVEH_WAGON) {
03967                 // normal wagon
03968                 SetTrainWagon(u);
03969                 break;
03970               }
03971               if (rvi->railveh_type == RAILVEH_MULTIHEAD && rvi->image_index == u->spritenum - 1) {
03972                 // rear end of a multiheaded engine
03973                 SetMultiheaded(u);
03974                 break;
03975               }
03976               if (rvi->railveh_type == RAILVEH_MULTIHEAD) SetMultiheaded(u);
03977               SetTrainEngine(u);
03978               break;
03979 
03980             case 4: /* TS_Free_Car */
03981               u->subtype = 0;
03982               SetTrainWagon(u);
03983               SetFreeWagon(u);
03984               break;
03985             default: NOT_REACHED(); break;
03986           }
03987         } END_ENUM_WAGONS(u)
03988       }
03989     }
03990   }
03991 }

Generated on Mon Sep 22 20:34:19 2008 for openttd by  doxygen 1.5.6