/** * Gets the other end of the aqueduct, if possible. * @param tile_from The begin tile for the aqueduct. * @param [out] tile_to The tile till where to show a selection for the aqueduct. * @return The other end of the aqueduct, or otherwise a tile in line with the aqueduct to cause the right error message. */ static TileIndex GetOtherAqueductEnd(TileIndex tile_from, TileIndex *tile_to = NULL) { int z; DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from, &z)); /* If the direction isn't right, just return the next tile so the command * complains about the wrong slope instead of the ends not matching up. * Make sure the coordinate is always a valid tile within the map, so we * don't go "off" the map. That would cause the wrong error message. */ if (!IsValidDiagDirection(dir)) return TILE_ADDXY(tile_from, TileX(tile_from) > 2 ? -1 : 1, 0); /* Direction the aqueduct is built to. */ TileIndexDiff offset = TileOffsByDiagDir(ReverseDiagDir(dir)); /* The maximum length of the aqueduct. */ int max_length = min(_settings_game.construction.max_bridge_length, DistanceFromEdgeDir(tile_from, ReverseDiagDir(dir)) - 1); TileIndex endtile = tile_from; for (int length = 0; IsValidTile(endtile) && TileX(endtile) != 0 && TileY(endtile) != 0; length++) { endtile = TILE_ADD(endtile, offset); if (length > max_length) break; if (GetTileMaxZ(endtile) > z) { if (tile_to != NULL) *tile_to = endtile; break; } } return endtile; }
/** returns the track to choose on the next tile, or -1 when it's better to * reverse. The tile given is the tile we are about to enter, enterdir is the * direction in which we are entering the tile */ static Track ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) { assert(IsValidDiagDirection(enterdir)); switch (_settings_game.pf.pathfinder_for_ships) { case VPF_OPF: return OPFShipChooseTrack(v, tile, enterdir, tracks); case VPF_NPF: return NPFShipChooseTrack(v, tile, enterdir, tracks); case VPF_YAPF: return YapfShipChooseTrack(v, tile, enterdir, tracks); default: NOT_REACHED(); } }
static void OPFShipFollowTrack(TileIndex tile, DiagDirection direction, TrackPathFinder *tpf) { assert(IsValidDiagDirection(direction)); /* initialize path finder variables */ tpf->rd.cur_length = 0; tpf->rd.depth = 0; tpf->rd.last_choosen_track = INVALID_TRACK; ShipTrackFollower(tile, tpf, 0); TPFModeShip(tpf, tile, direction); }
/** * Runs the pathfinder to choose a track to continue along. * * @param v Ship to navigate * @param tile Tile, the ship is about to enter * @param enterdir Direction of entering * @param tracks Available track choices on \a tile * @return Track to choose, or INVALID_TRACK when to reverse. */ static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) { assert(IsValidDiagDirection(enterdir)); bool path_found = true; Track track; switch (_settings_game.pf.pathfinder_for_ships) { case VPF_OPF: track = OPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break; case VPF_NPF: track = NPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break; case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found); break; default: NOT_REACHED(); } v->HandlePathfindingResult(path_found); return track; }
virtual void OnPlacePresize(Point pt, TileIndex tile_from) { TileIndex tile_to = tile_from; if (this->last_clicked_widget == WID_DT_BUILD_AQUEDUCT) { GetOtherAqueductEnd(tile_from, &tile_to); } else { DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile_from)); if (IsValidDiagDirection(dir)) { /* Locks and docks always select the tile "down" the slope. */ tile_to = TileAddByDiagDir(tile_from, ReverseDiagDir(dir)); /* Locks also select the tile "up" the slope. */ if (this->last_clicked_widget == WID_DT_LOCK) tile_from = TileAddByDiagDir(tile_from, dir); } } VpSetPresizeRange(tile_from, tile_to); }
/** * returns the track to choose on the next tile, or -1 when it's better to * reverse. The tile given is the tile we are about to enter, enterdir is the * direction in which we are entering the tile */ Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found) { assert(IsValidDiagDirection(enterdir)); TileIndex tile2 = TILE_ADD(tile, -TileOffsByDiagDir(enterdir)); Track track; /* Let's find out how far it would be if we would reverse first */ TrackBits b = TrackStatusToTrackBits(GetTileTrackStatus(tile2, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(ReverseDiagDir(enterdir)) & v->state; uint distr = UINT_MAX; // distance if we reversed if (b != 0) { distr = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track); if (distr != UINT_MAX) distr++; // penalty for reversing } /* And if we would not reverse? */ uint dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track); /* Due to the way this pathfinder works we cannot determine whether we're lost or not. */ path_found = true; if (dist <= distr) return track; return INVALID_TRACK; // We could better reverse }