Files
@ r13826:2077419a88c9
Branch filter:
Location: cpp/openttd-patchpack/source/src/pathfinder/opf/opf_ship.cpp
r13826:2077419a88c9
3.2 KiB
text/x-c
(svn r18365) -Cleanup: remove duplicate table
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /* $Id$ */
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file pathfind.cpp Implementation of the oldest supported pathfinder. */
#include "../../stdafx.h"
#include "../../debug.h"
#include "../../tunnelbridge_map.h"
#include "../../core/alloc_type.hpp"
#include "../../tunnelbridge.h"
#include "opf_ship.h"
struct RememberData {
uint16 cur_length;
byte depth;
Track last_choosen_track;
};
struct TrackPathFinder {
TPFEnumProc *enum_proc;
void *userdata;
RememberData rd;
TrackdirByte the_dir;
};
static void TPFModeShip(TrackPathFinder *tpf, TileIndex tile, DiagDirection direction)
{
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
/* wrong track type */
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) return;
DiagDirection dir = GetTunnelBridgeDirection(tile);
/* entering tunnel / bridge? */
if (dir == direction) {
TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
tpf->rd.cur_length += GetTunnelBridgeLength(tile, endtile) + 1;
tile = endtile;
} else {
/* leaving tunnel / bridge? */
if (ReverseDiagDir(dir) != direction) return;
}
}
/* This addition will sometimes overflow by a single tile.
* The use of TILE_MASK here makes sure that we still point at a valid
* tile, and then this tile will be in the sentinel row/col, so GetTileTrackStatus will fail. */
tile = TILE_MASK(tile + TileOffsByDiagDir(direction));
if (++tpf->rd.cur_length > 50)
return;
TrackBits bits = TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(direction);
if (bits == TRACK_BIT_NONE) return;
assert(TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY());
bool only_one_track = true;
do {
Track track = RemoveFirstTrack(&bits);
if (bits != TRACK_BIT_NONE) only_one_track = false;
RememberData rd = tpf->rd;
/* Change direction 4 times only */
if (!only_one_track && track != tpf->rd.last_choosen_track) {
if (++tpf->rd.depth > 4) {
tpf->rd = rd;
return;
}
tpf->rd.last_choosen_track = track;
}
tpf->the_dir = TrackEnterdirToTrackdir(track, direction);
if (!tpf->enum_proc(tile, tpf->userdata, tpf->the_dir, tpf->rd.cur_length)) {
TPFModeShip(tpf, tile, TrackdirToExitdir(tpf->the_dir));
}
tpf->rd = rd;
} while (bits != TRACK_BIT_NONE);
}
void OPFShipFollowTrack(TileIndex tile, DiagDirection direction, TPFEnumProc *enum_proc, void *data)
{
assert(IsValidDiagDirection(direction));
SmallStackSafeStackAlloc<TrackPathFinder, 1> tpf;
/* initialize path finder variables */
tpf->userdata = data;
tpf->enum_proc = enum_proc;
tpf->rd.cur_length = 0;
tpf->rd.depth = 0;
tpf->rd.last_choosen_track = INVALID_TRACK;
tpf->enum_proc(tile, data, INVALID_TRACKDIR, 0);
TPFModeShip(tpf, tile, direction);
}
|