示例#1
0
文件: npf.cpp 项目: andrew889/OpenTTD
/**
 * Returns the driveable Trackdirs on a tile.
 *
 * One-way-roads are taken into account. Signals are not tested.
 *
 * @param dst_tile The tile of interest.
 * @param src_trackdir The direction the vehicle is currently moving.
 * @param type The transporttype of the vehicle.
 * @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
 * @return The Trackdirs the vehicle can continue moving on.
 */
static TrackdirBits GetDriveableTrackdirBits(TileIndex dst_tile, Trackdir src_trackdir, TransportType type, uint subtype)
{
	TrackdirBits trackdirbits = TrackStatusToTrackdirBits(GetTileTrackStatus(dst_tile, type, subtype));

	if (trackdirbits == 0 && type == TRANSPORT_ROAD && HasBit(subtype, ROADTYPE_TRAM)) {
		/* GetTileTrackStatus() returns 0 for single tram bits.
		 * As we cannot change it there (easily) without breaking something, change it here */
		switch (GetSingleTramBit(dst_tile)) {
			case DIAGDIR_NE:
			case DIAGDIR_SW:
				trackdirbits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW;
				break;

			case DIAGDIR_NW:
			case DIAGDIR_SE:
				trackdirbits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE;
				break;

			default: break;
		}
	}

	DEBUG(npf, 4, "Next node: (%d, %d) [%d], possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), dst_tile, trackdirbits);

	/* Select only trackdirs we can reach from our current trackdir */
	trackdirbits &= TrackdirReachesTrackdirs(src_trackdir);

	/* Filter out trackdirs that would make 90 deg turns for trains */
	if (_settings_game.pf.forbid_90_deg && (type == TRANSPORT_RAIL || type == TRANSPORT_WATER)) trackdirbits &= ~TrackdirCrossesTrackdirs(src_trackdir);

	DEBUG(npf, 6, "After filtering: (%d, %d), possible trackdirs: 0x%X", TileX(dst_tile), TileY(dst_tile), trackdirbits);

	return trackdirbits;
}
示例#2
0
	/** main follower routine. Fills all members and return true on success.
	 *  Otherwise returns false if track can't be followed. */
	inline bool Follow(TileIndex old_tile, Trackdir old_td)
	{
		m_old_tile = old_tile;
		m_old_td = old_td;
		m_err = EC_NONE;
		assert(((TrackStatusToTrackdirBits(GetTileTrackStatus(m_old_tile, TT(), IsRoadTT() && m_veh != NULL ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0)) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
		       (IsTram() && GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR)); // Disable the assertion for single tram bits
		m_exitdir = TrackdirToExitdir(m_old_td);
		if (ForcedReverse()) return true;
		if (!CanExitOldTile()) return false;
		FollowTileExit();
		if (!QueryNewTileTrackStatus()) return TryReverse();
		if (!CanEnterNewTile()) return false;
		m_new_td_bits &= DiagdirReachesTrackdirs(m_exitdir);
		if (m_new_td_bits == TRACKDIR_BIT_NONE) {
			m_err = EC_NO_WAY;
			return false;
		}
		if (!Allow90degTurns()) {
			m_new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(m_old_td);
			if (m_new_td_bits == TRACKDIR_BIT_NONE) {
				m_err = EC_90DEG;
				return false;
			}
		}
		return true;
	}
示例#3
0
文件: npf.cpp 项目: andrew889/OpenTTD
/**
 * Tests if a tile can be entered or left only from one side.
 *
 * Depots, non-drive-through roadstops, and tiles with single trambits are tested.
 *
 * @param tile The tile of interest.
 * @param type The transporttype of the vehicle.
 * @param subtype For TRANSPORT_ROAD the compatible RoadTypes of the vehicle.
 * @return The single entry/exit-direction of the tile, or INVALID_DIAGDIR if there are more or less directions
 */
static DiagDirection GetTileSingleEntry(TileIndex tile, TransportType type, uint subtype)
{
	if (type != TRANSPORT_WATER && IsDepotTypeTile(tile, type)) return GetDepotDirection(tile, type);

	if (type == TRANSPORT_ROAD) {
		if (IsStandardRoadStopTile(tile)) return GetRoadStopDir(tile);
		if (HasBit(subtype, ROADTYPE_TRAM)) return GetSingleTramBit(tile);
	}

	return INVALID_DIAGDIR;
}
示例#4
0
	/**
	 * main follower routine. Fills all members and return true on success.
	 *  Otherwise returns false if track can't be followed.
	 */
	inline bool Follow(TileIndex old_tile, Trackdir old_td)
	{
		m_old_tile = old_tile;
		m_old_td = old_td;
		m_err = EC_NONE;
		assert(
			((TrackStatusToTrackdirBits(
				GetTileTrackStatus(m_old_tile, TT(), (IsRoadTT() && m_veh != NULL) ? RoadVehicle::From(m_veh)->compatible_roadtypes : 0)
			) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
			(IsTram() && GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR) // Disable the assertion for single tram bits
		);
		m_exitdir = TrackdirToExitdir(m_old_td);
		if (ForcedReverse()) return true;
		if (!CanExitOldTile()) return false;
		FollowTileExit();
		if (!QueryNewTileTrackStatus()) return TryReverse();
		m_new_td_bits &= DiagdirReachesTrackdirs(m_exitdir);
		if (m_new_td_bits == TRACKDIR_BIT_NONE || !CanEnterNewTile()) {
			/* In case we can't enter the next tile, but are
			 * a normal road vehicle, then we can actually
			 * try to reverse as this is the end of the road.
			 * Trams can only turn on the appropriate bits in
			 * which case reaching this would mean a dead end
			 * near a building and in that case there would
			 * a "false" QueryNewTileTrackStatus result and
			 * as such reversing is already tried. The fact
			 * that function failed can have to do with a
			 * missing road bit, or inability to connect the
			 * different bits due to slopes. */
			if (IsRoadTT() && !IsTram() && TryReverse()) return true;

			/* CanEnterNewTile already set a reason.
			 * Do NOT overwrite it (important for example for EC_RAIL_TYPE).
			 * Only set a reason if CanEnterNewTile was not called */
			if (m_new_td_bits == TRACKDIR_BIT_NONE) m_err = EC_NO_WAY;

			return false;
		}
		if (!Allow90degTurns()) {
			m_new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(m_old_td);
			if (m_new_td_bits == TRACKDIR_BIT_NONE) {
				m_err = EC_90DEG;
				return false;
			}
		}
		return true;
	}