inline int SwitchCost(TileIndex tile1, TileIndex tile2, DiagDirection exitdir) { if (IsPlainRailTile(tile1) && IsPlainRailTile(tile2)) { bool t1 = KillFirstBit(GetTrackBits(tile1) & DiagdirReachesTracks(ReverseDiagDir(exitdir))) != TRACK_BIT_NONE; bool t2 = KillFirstBit(GetTrackBits(tile2) & DiagdirReachesTracks(exitdir)) != TRACK_BIT_NONE; if (t1 && t2) return Yapf().PfGetSettings().rail_doubleslip_penalty; } return 0; }
void CopyPastePlaceRailWaypoint(GenericTileIndex tile, StationID sid, Axis axis, RailType rt, StationGfx gfx, StationClassID stat_class, byte stat_type, int specindex, bool adjacent) { if (IsMainMapTile(tile)) { TileIndex t = AsMainMapTile(tile); /* check if required track is already there, try to build one if not */ if (!IsTileOwner(t, _current_company) || (!IsRailWaypointTile(tile) && !IsPlainRailTile(tile)) || GetRailType(t) != rt || (IsTileType(t, MP_STATION) ? GetRailStationAxis(tile) != axis : !HasBit(GetTrackBits(t), AxisToTrack(axis)))) { CopyPastePlaceTracks(tile, rt, AxisToTrackBits(axis)); if (_current_pasting->last_result.Failed()) return; } /* build the waypoint */ _station_cmd_specindex_to_paste = specindex; uint32 p1 = 0; SB(p1, 0, 4, rt); SB(p1, 4, 1, axis); SB(p1, 8, 8, 1); // width SB(p1, 16, 8, 1); // height SB(p1, 24, 1, adjacent); uint32 p2 = 0; SB(p2, 0, 8, stat_class); SB(p2, 8, 8, stat_type); SB(p2, 16, 16, sid); _current_pasting->DoCommand(t, p1, p2, CMD_BUILD_RAIL_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT)); } else { MakeRailWaypoint(tile, OWNER_NONE, sid, axis, gfx & ~1, rt); assert(IsInsideMM(specindex, 0, MAX_UVALUE(byte) + 1)); SetCustomStationSpecIndex(tile, (byte)specindex); _clipboard_stations_builder.AddRailPart(sid, stat_class, stat_type, (byte)specindex); } }
/** * Return if the tile is a valid tile for a crossing. * * @param tile the curent tile * @param ax the axis of the road over the rail * @return true if it is a valid tile */ static bool IsPossibleCrossing(const TileIndex tile, Axis ax) { return (IsTileType(tile, MP_RAILWAY) && GetRailTileType(tile) == RAIL_TILE_NORMAL && GetTrackBits(tile) == (ax == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X) && GetFoundationSlope(tile) == SLOPE_FLAT); }
/** * Get the axis for a new waypoint. This means that if it is a valid * tile to build a waypoint on it returns a valid Axis, otherwise an * invalid one. * @param tile the tile to look at. * @return the axis for the to-be-build waypoint. */ Axis GetAxisForNewWaypoint(TileIndex tile) { /* The axis for rail waypoints is easy. */ if (IsRailWaypointTile(tile)) return GetRailStationAxis(tile); /* Non-plain rail type, no valid axis for waypoints. */ if (!IsTileType(tile, MP_RAILWAY) || GetRailTileType(tile) != RAIL_TILE_NORMAL) return INVALID_AXIS; switch (GetTrackBits(tile)) { case TRACK_BIT_X: return AXIS_X; case TRACK_BIT_Y: return AXIS_Y; default: return INVALID_AXIS; } }
/** * Search signal block * * @param owner owner whose signals we are updating * @return SigFlags */ static SigFlags ExploreSegment(Owner owner) { SigFlags flags = SF_NONE; TileIndex tile; DiagDirection enterdir; while (_tbdset.Get(&tile, &enterdir)) { TileIndex oldtile = tile; // tile we are leaving DiagDirection exitdir = enterdir == INVALID_DIAGDIR ? INVALID_DIAGDIR : ReverseDiagDir(enterdir); // expected new exit direction (for straight line) switch (GetTileType(tile)) { case MP_RAILWAY: { if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing) if (IsRailDepot(tile)) { if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; exitdir = GetRailDepotDirection(tile); tile += TileOffsByDiagDir(exitdir); enterdir = ReverseDiagDir(exitdir); break; } else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; continue; } else { continue; } } TrackBits tracks = GetTrackBits(tile); // trackbits of tile TrackBits tracks_masked = (TrackBits)(tracks & _enterdir_to_trackbits[enterdir]); // only incidating trackbits if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one incidating track, no need to check tracks = tracks_masked; /* If no train detected yet, and there is not no train -> there is a train -> set the flag */ if (!(flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags |= SF_TRAIN; } else { if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; } if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir SignalType sig = GetSignalType(tile, track); Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101) & _enterdir_to_trackdirbits[enterdir]); Trackdir reversedir = ReverseTrackdir(trackdir); /* add (tile, reversetrackdir) to 'to-be-updated' set when there is * ANY conventional signal in REVERSE direction * (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */ if (HasSignalOnTrackdir(tile, reversedir)) { if (IsPbsSignal(sig)) { flags |= SF_PBS; } else if (!_tbuset.Add(tile, reversedir)) { return flags | SF_FULL; } } if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags |= SF_PBS; /* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */ if (!(flags & SF_GREEN2) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit if (flags & SF_EXIT) flags |= SF_EXIT2; // found two (or more) exits flags |= SF_EXIT; // found at least one exit - allow for compiler optimizations if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit if (flags & SF_GREEN) flags |= SF_GREEN2; flags |= SF_GREEN; } } continue; } } for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { // test all possible exit directions if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any track incidating? TileIndex newtile = tile + TileOffsByDiagDir(dir); // new tile to check DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SF_FULL; } } continue; // continue the while() loop } case MP_STATION: if (!HasStationRail(tile)) continue; if (GetTileOwner(tile) != owner) continue; if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; tile += TileOffsByDiagDir(exitdir); break; case MP_ROAD: if (!IsLevelCrossing(tile)) continue; if (GetTileOwner(tile) != owner) continue; if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; tile += TileOffsByDiagDir(exitdir); break; case MP_TUNNELBRIDGE: { if (GetTileOwner(tile) != owner) continue; if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue; DiagDirection dir = GetTunnelBridgeDirection(tile); if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; enterdir = dir; exitdir = ReverseDiagDir(dir); tile += TileOffsByDiagDir(exitdir); // just skip to next tile } else { // NOT incoming from the wormhole! if (ReverseDiagDir(enterdir) != dir) continue; if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN; tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile enterdir = INVALID_DIAGDIR; exitdir = INVALID_DIAGDIR; } } break; default: continue; // continue the while() loop } if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) return flags | SF_FULL; } return flags; }