/** * Transform a given Point. * * The center point of the transformation is (0, 0). * For example, point (1, 2) rotated 90 degree left is (-2, 1). * * @param point The Point to transform. * @param transformation Transformation to perform. * @return The transformed Point. */ Point TransformPoint(Point point, DirTransformation transformation) { TileIndexDiffC diff_from_x = TileIndexDiffCByDiagDir(TransformDiagDir(DIAGDIR_SW, transformation)); TileIndexDiffC diff_from_y = TileIndexDiffCByDiagDir(TransformDiagDir(DIAGDIR_SE, transformation)); Point ret = { point.x * diff_from_x.x + point.y * diff_from_y.x, point.x * diff_from_x.y + point.y * diff_from_y.y }; return ret; }
/* Will just follow the results of GetTileTrackStatus concerning where we can * go and where not. Uses AyStar.user_data[NPF_TYPE] as the transport type and * an argument to GetTileTrackStatus. Will skip tunnels, meaning that the * entry and exit are neighbours. Will fill * AyStarNode.user_data[NPF_TRACKDIR_CHOICE] with an appropriate value, and * copy AyStarNode.user_data[NPF_NODE_FLAGS] from the parent */ static void NPFFollowTrack(AyStar *aystar, OpenListNode *current) { /* We leave src_tile on track src_trackdir in direction src_exitdir */ Trackdir src_trackdir = current->path.node.direction; TileIndex src_tile = current->path.node.tile; DiagDirection src_exitdir = TrackdirToExitdir(src_trackdir); /* Is src_tile valid, and can be used? * When choosing track on a junction src_tile is the tile neighboured to the junction wrt. exitdir. * But we must not check the validity of this move, as src_tile is totally unrelated to the move, if a roadvehicle reversed on a junction. */ bool ignore_src_tile = (current->path.parent == NULL && NPFGetFlag(¤t->path.node, NPF_FLAG_IGNORE_START_TILE)); /* Information about the vehicle: TransportType (road/rail/water) and SubType (compatible rail/road types) */ TransportType type = (TransportType)aystar->user_data[NPF_TYPE]; uint subtype = aystar->user_data[NPF_SUB_TYPE]; /* Initialize to 0, so we can jump out (return) somewhere an have no neighbours */ aystar->num_neighbours = 0; DEBUG(npf, 4, "Expanding: (%d, %d, %d) [%d]", TileX(src_tile), TileY(src_tile), src_trackdir, src_tile); /* We want to determine the tile we arrive, and which choices we have there */ TileIndex dst_tile; TrackdirBits trackdirbits; /* Find dest tile */ if (ignore_src_tile) { /* Do not perform any checks that involve src_tile */ dst_tile = src_tile + TileOffsByDiagDir(src_exitdir); trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); } else if (IsTileType(src_tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(src_tile) == src_exitdir) { /* We drive through the wormhole and arrive on the other side */ dst_tile = GetOtherTunnelBridgeEnd(src_tile); trackdirbits = TrackdirToTrackdirBits(src_trackdir); } else if (ForceReverse(src_tile, src_exitdir, type, subtype)) { /* We can only reverse on this tile */ dst_tile = src_tile; src_trackdir = ReverseTrackdir(src_trackdir); trackdirbits = TrackdirToTrackdirBits(src_trackdir); } else { /* We leave src_tile in src_exitdir and reach dst_tile */ dst_tile = AddTileIndexDiffCWrap(src_tile, TileIndexDiffCByDiagDir(src_exitdir)); if (dst_tile != INVALID_TILE && !CanEnterTile(dst_tile, src_exitdir, type, subtype, (RailTypes)aystar->user_data[NPF_RAILTYPES], (Owner)aystar->user_data[NPF_OWNER])) dst_tile = INVALID_TILE; if (dst_tile == INVALID_TILE) { /* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */ if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return; dst_tile = src_tile; src_trackdir = ReverseTrackdir(src_trackdir); } trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); if (trackdirbits == 0) { /* We cannot enter the next tile. Road vehicles can reverse, others reach dead end */ if (type != TRANSPORT_ROAD || HasBit(subtype, ROADTYPE_TRAM)) return; dst_tile = src_tile; src_trackdir = ReverseTrackdir(src_trackdir); trackdirbits = GetDriveableTrackdirBits(dst_tile, src_trackdir, type, subtype); } } if (NPFGetFlag(¤t->path.node, NPF_FLAG_IGNORE_RESERVED)) { /* Mask out any reserved tracks. */ TrackBits reserved = GetReservedTrackbits(dst_tile); trackdirbits &= ~TrackBitsToTrackdirBits(reserved); uint bits = TrackdirBitsToTrackBits(trackdirbits); int i; FOR_EACH_SET_BIT(i, bits) { if (TracksOverlap(reserved | TrackToTrackBits((Track)i))) trackdirbits &= ~TrackToTrackdirBits((Track)i); } }