diff --git a/ai.c b/ai.c index 5e3d9e2bdd..2a11329936 100644 --- a/ai.c +++ b/ai.c @@ -284,7 +284,7 @@ static void AiHandleReplaceTrain(Player *p) uint tile; // wait until the vehicle reaches the depot. - if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { + if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT); return; } @@ -312,7 +312,7 @@ static void AiHandleReplaceRoadVeh(Player *p) int veh; uint tile; - if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { + if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT); return; } @@ -3561,7 +3561,7 @@ static void AiStateSellVeh(Player *p) if (v->owner == _current_player) { if (v->type == VEH_Train) { - if (!IsTrainDepotTile(v->tile) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { + if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { if (v->current_order.type != OT_GOTO_DEPOT) DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_TRAIN_GOTO_DEPOT); goto going_to_depot; @@ -3571,7 +3571,7 @@ static void AiStateSellVeh(Player *p) DoCommandByTile(v->tile, v->index, 1, DC_EXEC, CMD_SELL_RAIL_WAGON); } else if (v->type == VEH_Road) { - if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { + if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { if (v->current_order.type != OT_GOTO_DEPOT) DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT); goto going_to_depot; diff --git a/ai_new.c b/ai_new.c index c3de5fedb2..3d28f7f9bc 100644 --- a/ai_new.c +++ b/ai_new.c @@ -1213,7 +1213,7 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) { // We are already sending him back if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) { - if (v->type == VEH_Road && IsRoadDepotTile(v->tile) && + if (v->type == VEH_Road && IsTileDepotType(v->tile, TRANSPORT_ROAD) && (v->vehstatus&VS_STOPPED)) { // We are at the depot, sell the vehicle DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH); diff --git a/ai_pathfinder.c b/ai_pathfinder.c index 1a4dcd6846..14d6487867 100644 --- a/ai_pathfinder.c +++ b/ai_pathfinder.c @@ -5,6 +5,7 @@ #include "tile.h" #include "command.h" #include "ai.h" +#include "depot.h" #define TEST_STATION_NO_DIR 0xFF @@ -35,7 +36,7 @@ static bool IsRoad(TileIndex tile) { return // MP_STREET, but not a road depot? - (IsTileType(tile, MP_STREET) && !(_map5[tile] & 0x20)) || + (IsTileType(tile, MP_STREET) && !(IsTileDepotType(tile, TRANSPORT_ROAD))) || (IsTileType(tile, MP_TUNNELBRIDGE) && ( // road tunnel? ((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) || diff --git a/depot.c b/depot.c index 0430162d26..f52bd25735 100644 --- a/depot.c +++ b/depot.c @@ -45,33 +45,6 @@ Depot *GetDepotByTile(uint tile) return NULL; } -/** - * Check if a tile is a road-depot - */ -bool IsRoadDepotTile(TileIndex tile) -{ - return IsTileType(tile, MP_STREET) && - (_map5[tile] & 0xF0) == 0x20; -} - -/** - * Check if a tile is a train-depot - */ -bool IsTrainDepotTile(TileIndex tile) -{ - return IsTileType(tile, MP_RAILWAY) && - (_map5[tile] & 0xFC) == 0xC0; -} - -/** - * Check if a tile is a ship-depot - */ -bool IsShipDepotTile(TileIndex tile) -{ - return IsTileType(tile, MP_WATER) && - (_map5[tile] & ~3) == 0x80; -} - /** * Allocate a new depot */ @@ -80,7 +53,7 @@ Depot *AllocateDepot(void) Depot *depot; FOR_ALL_DEPOTS(depot) { - if (depot->xy == 0) { + if (!IsValidDepot(depot)) { uint index = depot->index; memset(depot, 0, sizeof(Depot)); @@ -142,7 +115,7 @@ static void Save_DEPT(void) Depot *depot; FOR_ALL_DEPOTS(depot) { - if (depot->xy != 0) { + if (IsValidDepot(depot)) { SlSetArrayIndex(depot->index); SlObject(depot, _depot_desc); } diff --git a/depot.h b/depot.h index b2ae02068f..11f47401ab 100644 --- a/depot.h +++ b/depot.h @@ -2,6 +2,7 @@ #define DEPOT_H #include "pool.h" +#include "tile.h" struct Depot { TileIndex xy; @@ -40,12 +41,39 @@ VARDEF TileIndex _last_built_road_depot_tile; VARDEF TileIndex _last_built_aircraft_depot_tile; VARDEF TileIndex _last_built_ship_depot_tile; -bool IsTrainDepotTile(TileIndex tile); -bool IsRoadDepotTile(TileIndex tile); +/** + * Check if a depot really exists. + */ +static inline bool IsValidDepot(Depot* depot) +{ + return depot->xy != 0; /* XXX: Replace by INVALID_TILE someday */ +} + +/** + * Check if a tile is a depot of the given type. + */ +static inline bool IsTileDepotType(TileIndex tile, TransportType type) +{ + switch(type) + { + case TRANSPORT_RAIL: + return IsTileType(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0; + break; + case TRANSPORT_ROAD: + return IsTileType(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x20; + break; + case TRANSPORT_WATER: + return IsTileType(tile, MP_WATER) && (_map5[tile] & ~3) == 0x80; + break; + default: + assert(0); + return false; + } +} + Depot *GetDepotByTile(uint tile); void InitializeDepot(void); Depot *AllocateDepot(void); -bool IsShipDepotTile(TileIndex tile); void DoDeleteDepot(uint tile); #endif /* DEPOT_H */ diff --git a/industry.h b/industry.h index 7fac15f286..c7a2dd063e 100644 --- a/industry.h +++ b/industry.h @@ -31,6 +31,14 @@ struct Industry { extern MemoryPool _industry_pool; +/** + * Check if an Industry really exists. + */ +static inline bool IsValidIndustry(Industry* industry) +{ + return industry->xy != 0; /* XXX: Replace by INVALID_TILE someday */ +} + /** * Get the pointer to the industry with index 'index' */ diff --git a/map.h b/map.h index 55704a5552..f9cff89e2e 100644 --- a/map.h +++ b/map.h @@ -35,6 +35,14 @@ uint ScaleByMapSize(uint); // Scale relative to the number of tiles uint ScaleByMapSize1D(uint); // Scale relative to the circumference of the map typedef uint32 TileIndex; + +typedef enum { + OWNER_TOWN = 0xf, // a town owns the tile + OWNER_NONE = 0x10, // nobody owns the tile + OWNER_WATER = 0x11, // "water" owns the tile + OWNER_SPECTATOR = 0xff, // spectator in MP or in scenario editor +} Owner; + enum { INVALID_TILE = (uint32) -1 }; diff --git a/npf.c b/npf.c index 5a1696436f..965a0a9191 100644 --- a/npf.c +++ b/npf.c @@ -319,24 +319,7 @@ int32 NPFRailPathCost(AyStar* as, AyStarNode* current, OpenListNode* parent) { /* Will find any depot */ int32 NPFFindDepot(AyStar* as, OpenListNode *current) { TileIndex tile = current->path.node.tile; - bool isDepot; - switch(GetTileType(tile)) { - case MP_RAILWAY: - /* Check if this is a rail depot */ - isDepot = IsTrainDepotTile(tile); - break; - case MP_STREET: - /* Check if this is a road depot */ - isDepot = IsRoadDepotTile(tile); - break; - case MP_WATER: - isDepot = IsShipDepotTile(tile); - break; - default: - isDepot = false; - break; - } - if (isDepot) + if (IsTileDepotType(tile, as->user_data[NPF_TYPE])) return AYSTAR_FOUND_END_NODE; else return AYSTAR_DONE; @@ -397,11 +380,7 @@ void NPFFollowTrack(AyStar* aystar, OpenListNode* current) { flotr = FindLengthOfTunnel(src_tile, src_exitdir); dst_tile = flotr.tile; } else { - if ( - (type == TRANSPORT_ROAD && IsRoadStationTile(src_tile)) - || (type == TRANSPORT_ROAD && IsRoadDepotTile(src_tile)) - || (type == TRANSPORT_RAIL && IsTrainDepotTile(src_tile)) - ){ + if (IsTileDepotType(src_tile, type)){ /* This is a road station or a train or road depot. We can enter and exit * those from one side only. Trackdirs don't support that (yet), so we'll * do this here. */ @@ -429,19 +408,29 @@ void NPFFollowTrack(AyStar* aystar, OpenListNode* current) { } // TODO: check correct rail type (mono, maglev, etc) - // TODO: check tile owner + + /* Check the owner of the tile */ + if ( + IsTileType(dst_tile, MP_RAILWAY) /* Rail tile */ + || IsTileDepotType(dst_tile, TRANSPORT_ROAD) /* Road depot tile */ + || IsTileType(dst_tile, MP_STATION) /* Station tile */ + || IsTileDepotType(dst_tile, TRANSPORT_WATER) /* Water depot tile */ + ) /* TODO: Crossings, tunnels and bridges are "public" now */ + /* The above cases are "private" tiles, we need to check the owner */ + if (!IsTileOwner(dst_tile, aystar->user_data[NPF_OWNER])) + return; /* Determine available tracks */ - if (type == TRANSPORT_ROAD && (IsRoadStationTile(dst_tile) || IsRoadDepotTile(dst_tile))){ - byte exitdir; + if (type == TRANSPORT_ROAD && (IsRoadStationTile(dst_tile) || IsTileDepotType(dst_tile, TRANSPORT_ROAD))){ /* Road stations and depots return 0 on GTTS, so we have to do this by hand... */ - if (IsRoadStationTile(dst_tile)) - exitdir = GetRoadStationDir(dst_tile); - else /* Road depot */ - exitdir = _map5[dst_tile] & 3; /* Extract the direction from the map */ - ts = (1 << _dir_to_diag_trackdir[exitdir]) | - (1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]); - /* Find the trackdirs that are available for a station with this orientation. They are in both directions */ + byte exitdir; + if (IsRoadStationTile(dst_tile)) + exitdir = GetRoadStationDir(dst_tile); + else /* Road depot */ + /* Find the trackdirs that are available for a depot with this orientation. They are in both directions */ + exitdir = _map5[dst_tile] & 3; /* Extract the direction from the map */ + ts = (1 << _dir_to_diag_trackdir[exitdir]) + | (1 << _dir_to_diag_trackdir[_reverse_dir[exitdir]]); } else { ts = GetTileTrackStatus(dst_tile, type); } @@ -500,7 +489,7 @@ void NPFFollowTrack(AyStar* aystar, OpenListNode* current) { * multiple targets that are spread around, we should perform a breadth first * search by specifiying CalcZero as our heuristic. */ -NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type) { +NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, Owner owner) { int r; NPFFoundTargetData result; @@ -539,6 +528,7 @@ NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFF /* Initialize user_data */ _npf_aystar.user_data[NPF_TYPE] = type; + _npf_aystar.user_data[NPF_OWNER] = owner; /* GO! */ r = AyStarMain_Main(&_npf_aystar); @@ -556,7 +546,7 @@ NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFF return result; } -NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type) { +NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner) { AyStarNode start1; AyStarNode start2; @@ -565,10 +555,10 @@ NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1 start1.direction = trackdir1; start2.direction = trackdir2; - return NPFRouteInternal(&start1, &start2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type); + return NPFRouteInternal(&start1, &start2, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner); } -NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type) { +NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner) { AyStarNode start; assert(tile != 0); @@ -579,10 +569,10 @@ NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFin * return a not found then */ start.user_data[NPF_TRACKDIR_CHOICE] = 0xff; - return NPFRouteInternal(&start, NULL, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type); + return NPFRouteInternal(&start, NULL, target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, owner); } -NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type) { +NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner) { AyStarNode start; start.tile = tile; @@ -593,10 +583,10 @@ NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, Tr /* perform a breadth first search. Target is NULL, * since we are just looking for any depot...*/ - return NPFRouteInternal(&start, NULL, NULL, NPFFindDepot, NPFCalcZero, type); + return NPFRouteInternal(&start, NULL, NULL, NPFFindDepot, NPFCalcZero, type, owner); } -NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type) { +NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner) { /* Okay, what we're gonna do. First, we look at all depots, calculate * the manhatten distance to get to each depot. We then sort them by * distance. We start by trying to plan a route to the closest, then @@ -629,7 +619,10 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, Tran init_InsSort(&depots); /* Okay, let's find all depots that we can use first */ FOR_ALL_DEPOTS(depot) { - if (IsTileType(depot->xy, tiletype)) + /* Check if this is really a valid depot, it is of the needed type and + * owner */ + if (IsValidDepot(depot) && IsTileDepotType(depot->xy, tiletype) && IsTileOwner(depot->xy, owner)) + /* If so, let's add it to the queue, sorted by distance */ depots.push(&depots, depot, DistanceManhattan(tile, depot->xy)); } @@ -655,6 +648,7 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, Tran /* Initialize user_data */ _npf_aystar.user_data[NPF_TYPE] = type; + _npf_aystar.user_data[NPF_OWNER] = owner; /* Initialize Start Node */ start.tile = tile; @@ -663,11 +657,12 @@ NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, Tran /* Initialize Result */ _npf_aystar.user_path = &result; best_result.best_path_dist = (uint)-1; + best_result.best_bird_dist = (uint)-1; /* Just iterate the depots in order of increasing distance */ while ((current = depots.pop(&depots))) { /* Check to see if we already have a path shorter than this - * depot's manhattan distance. Hack: We call DistanceManhattan + * depot's manhattan distance. HACK: We call DistanceManhattan * again, we should probably modify the queue to give us that * value... */ if ( DistanceManhattan(tile, current->xy * NPF_TILE_LENGTH) > best_result.best_path_dist) diff --git a/npf.h b/npf.h index 0b3e17a0e6..1444cbe73a 100644 --- a/npf.h +++ b/npf.h @@ -15,7 +15,8 @@ typedef struct NPFFindStationOrTileData { /* Meant to be stored in AyStar.target } NPFFindStationOrTileData; enum { /* Indices into AyStar.userdata[] */ - NPF_TYPE = 0, /* Contains an TransportTypes value */ + NPF_TYPE = 0, /* Contains a TransportTypes value */ + NPF_OWNER, /* Contains an Owner value */ }; enum { /* Indices into AyStarNode.userdata[] */ @@ -30,7 +31,7 @@ enum { /* Flags for AyStarNode.userdata[NPF_NODE_FLAGS]*/ typedef struct NPFFoundTargetData { /* Meant to be stored in AyStar.userpath */ uint best_bird_dist; /* The best heuristic found. Is 0 if the target was found */ uint best_path_dist; /* The shortest path. Is (uint)-1 if no path is found */ - byte best_trackdir; /* The trackdir that leads to the shortes path/closest birds dist */ + byte best_trackdir; /* The trackdir that leads to the shortest path/closest birds dist */ AyStarNode node; /* The node within the target the search led us to */ } NPFFoundTargetData; @@ -39,20 +40,20 @@ typedef struct NPFFoundTargetData { /* Meant to be stored in AyStar.userpath */ /* Will search from the given tile and direction, for a route to the given * station for the given transport type. See the declaration of * NPFFoundTargetData above for the meaning of the result. */ -NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type); +NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, byte trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner); /* Will search as above, but with two start nodes, the second being the * reverse. Look at the NPF_NODE_REVERSE flag in the result node to see which * direction was taken */ -NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type); +NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, byte trackdir1, TileIndex tile2, byte trackdir2, NPFFindStationOrTileData* target, TransportType type, Owner owner); /* Will search a route to the closest depot. */ /* Search using breadth first. Good for little track choice and inaccurate * heuristic, such as railway/road */ -NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type); +NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, byte trackdir, TransportType type, Owner owner); /* Search by trying each depot in order of Manhattan Distance. Good for lots - * of choices and accurate heuristics, such as water */ -NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type); + * of choices and accurate heuristics, such as water. */ +NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, byte trackdir, TransportType type, Owner owner); void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v); diff --git a/order_gui.c b/order_gui.c index a7dce599d7..46be402783 100644 --- a/order_gui.c +++ b/order_gui.c @@ -194,7 +194,7 @@ static Order GetOrderCmdFromTile(Vehicle *v, uint tile) case MP_WATER: if (v->type != VEH_Ship) break; - if ( IsShipDepotTile(tile) && _map_owner[tile] == _local_player) { + if ( IsTileDepotType(tile, TRANSPORT_ROAD) && IsTileOwner(tile, _local_player)) { switch (_map5[tile]) { case 0x81: tile--; break; case 0x83: tile-= TILE_XY(0,1); break; diff --git a/rail_cmd.c b/rail_cmd.c index c4d8a2e378..845d6d8d08 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -2260,6 +2260,7 @@ static uint32 VehicleEnter_Track(Vehicle *v, uint tile, int x, int y) if ((v=v->next) != NULL) { v->vehstatus &= ~VS_HIDDEN; v->u.rail.track = _depot_track_mask[dir]; + assert(v->u.rail.track); } } } diff --git a/roadveh_cmd.c b/roadveh_cmd.c index 872d91a9ae..6dd84da5ae 100644 --- a/roadveh_cmd.c +++ b/roadveh_cmd.c @@ -116,12 +116,12 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 cost; Vehicle *v; UnitID unit_num; - uint tile = TILE_FROM_XY(x,y); + TileIndex tile = TILE_FROM_XY(x,y); Engine *e; if (!IsEngineBuildable(p1, VEH_Road)) return CMD_ERROR; - if (!IsRoadDepotTile((TileIndex)tile)) return CMD_ERROR; + if (!IsTileDepotType(tile, TRANSPORT_ROAD)) return CMD_ERROR; if (_map_owner[tile] != _current_player) return CMD_ERROR; @@ -243,7 +243,7 @@ int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - if (!IsRoadDepotTile(v->tile) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) + if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); if (flags & DC_EXEC) { @@ -297,7 +297,7 @@ static Depot *FindClosestRoadDepot(Vehicle *v) NPFFoundTargetData ftd; /* See where we are now */ byte trackdir = _dir_to_diag_trackdir[(v->direction>>1)&3]; - ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD); + ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_ROAD, v->owner); if (ftd.best_bird_dist == 0) return GetDepotByTile(ftd.node.tile); /* Target found */ else @@ -1104,7 +1104,7 @@ static int RoadFindPathToDest(Vehicle *v, uint tile, int enterdir) trackdir = _dir_to_diag_trackdir[enterdir]; //debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir); - ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD); + ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->owner); if (ftd.best_bird_dist != 0 || ftd.best_trackdir == 0xff) { /* Not found, just do something, or we are already there */ //TODO: maybe display error? diff --git a/roadveh_gui.c b/roadveh_gui.c index d5b5d28dab..f67365cf0f 100644 --- a/roadveh_gui.c +++ b/roadveh_gui.c @@ -822,7 +822,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) DrawVehicleProfitButton(v, x, y + 13); SetDParam(0, v->unitnumber); - if (IsRoadDepotTile(v->tile) && (v->vehstatus & VS_HIDDEN)) + if (IsTileDepotType(v->tile, TRANSPORT_ROAD) && (v->vehstatus & VS_HIDDEN)) str = STR_021F; else str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; @@ -881,7 +881,7 @@ static void PlayerRoadVehWndProc(Window *w, WindowEvent *e) tile = _last_built_road_depot_tile; do { - if (_map_owner[tile] == _local_player && IsRoadDepotTile(tile)) { + if (IsTileOwner(tile, _local_player) && IsTileDepotType(tile, TRANSPORT_ROAD)) { ShowRoadDepotWindow(tile); ShowBuildRoadVehWindow(tile); return; diff --git a/ship_cmd.c b/ship_cmd.c index 684d304711..537059ffd6 100644 --- a/ship_cmd.c +++ b/ship_cmd.c @@ -69,14 +69,12 @@ static Depot *FindClosestShipDepot(Vehicle *v) Depot *depot; Depot *best_depot = NULL; uint tile, dist, best_dist = (uint)-1; - byte owner = v->owner; uint tile2 = v->tile; if (_patches.new_pathfinding_all) { NPFFoundTargetData ftd; byte trackdir = _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.ship.state)][v->direction]; - /* XXX --- SLOW!!!! */ - ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER); + ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, v->owner); if (ftd.best_bird_dist == 0) best_depot = GetDepotByTile(ftd.node.tile); /* Found target */ else @@ -84,7 +82,7 @@ static Depot *FindClosestShipDepot(Vehicle *v) } else { FOR_ALL_DEPOTS(depot) { tile = depot->xy; - if (IsTileType(tile, MP_WATER) && _map_owner[tile] == owner) { + if (IsValidDepot(depot) && IsTileDepotType(tile, TRANSPORT_WATER) && IsTileOwner(tile, v->owner)) { dist = DistanceManhattan(tile, tile2); if (dist < best_dist) { best_dist = dist; @@ -598,7 +596,7 @@ static int ChooseShipTrack(Vehicle *v, uint tile, int enterdir, uint tracks) NPFFillWithOrderData(&fstd, v); - ftd = NPFRouteToStationOrTile(src_tile, _track_direction_to_trackdir[track][v->direction], &fstd, TRANSPORT_WATER); + ftd = NPFRouteToStationOrTile(src_tile, _track_direction_to_trackdir[track][v->direction], &fstd, TRANSPORT_WATER, v->owner); if (ftd.best_bird_dist == 0 && ftd.best_trackdir != 0xff) /* Found the target, and it is not our current tile */ @@ -876,12 +874,12 @@ int32 CmdBuildShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) int32 value; Vehicle *v; UnitID unit_num; - uint tile = TILE_FROM_XY(x,y); + TileIndex tile = TILE_FROM_XY(x,y); Engine *e; if (!IsEngineBuildable(p1, VEH_Ship)) return CMD_ERROR; - if (!IsShipDepotTile((TileIndex)tile)) return CMD_ERROR; + if (!IsTileDepotType(tile, TRANSPORT_WATER)) return CMD_ERROR; if (_map_owner[tile] != _current_player) return CMD_ERROR; @@ -964,7 +962,7 @@ int32 CmdSellShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); - if (!IsShipDepotTile(v->tile) || v->u.road.state != 0x80 || !(v->vehstatus&VS_STOPPED)) + if (!IsTileDepotType(v->tile, TRANSPORT_WATER) || v->u.road.state != 0x80 || !(v->vehstatus&VS_STOPPED)) return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); if (flags & DC_EXEC) { @@ -1088,7 +1086,7 @@ int32 CmdRefitShip(int x, int y, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; if (!( SkipStoppedInDepotCheck )) { - if (!IsShipDepotTile(v->tile) || + if (!IsTileDepotType(v->tile, TRANSPORT_WATER) || !(v->vehstatus&VS_STOPPED) || v->u.ship.state != 0x80) return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); diff --git a/ship_gui.c b/ship_gui.c index 2da8378f53..31d7081d9a 100644 --- a/ship_gui.c +++ b/ship_gui.c @@ -491,7 +491,7 @@ static void ShipViewWndProc(Window *w, WindowEvent *e) { if (ShipVehInfo(v->engine_type)->refittable && v->vehstatus&VS_STOPPED && v->u.ship.state == 0x80 && - IsShipDepotTile(v->tile)) + IsTileDepotType(v->tile, TRANSPORT_WATER)) disabled = 0; if (v->owner != _local_player) @@ -979,7 +979,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) DrawVehicleProfitButton(v, x, y + 13); SetDParam(0, v->unitnumber); - if (IsShipDepotTile(v->tile) && (v->vehstatus & VS_HIDDEN)) + if (IsTileDepotType(v->tile, TRANSPORT_WATER) && (v->vehstatus & VS_HIDDEN)) str = STR_021F; else str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; @@ -1040,7 +1040,7 @@ static void PlayerShipsWndProc(Window *w, WindowEvent *e) tile = _last_built_ship_depot_tile; do { - if (_map_owner[tile] == _local_player && IsShipDepotTile(tile)) { + if (_map_owner[tile] == _local_player && IsTileDepotType(tile, TRANSPORT_WATER)) { ShowShipDepotWindow(tile); ShowBuildShipWindow(tile); return; diff --git a/signs.h b/signs.h index 1d19206c54..dc8c657857 100644 --- a/signs.h +++ b/signs.h @@ -17,6 +17,14 @@ typedef struct SignStruct { extern MemoryPool _sign_pool; +/** + * Check if a Sign really exists. + */ +static inline bool IsValidSign(SignStruct* ss) +{ + return ss->str != 0; +} + /** * Get the pointer to the sign with index 'index' */ diff --git a/station.h b/station.h index 26d22b827d..4a4d721b19 100644 --- a/station.h +++ b/station.h @@ -272,6 +272,14 @@ static inline bool IsRoadStationTile(uint tile) { return IsTileType(tile, MP_STATION) && IS_BYTE_INSIDE(_map5[tile], 0x43, 0x4B); } +/** + * Check if a station really exists. + */ +static inline bool IsValidStation(Station* station) +{ + return station->xy != 0; /* XXX: Replace by INVALID_TILE someday */ +} + /* Get's the direction the station exit points towards. Ie, returns 0 for a * station with the exit NE. */ static inline byte GetRoadStationDir(uint tile) { diff --git a/tile.h b/tile.h index bd2917223e..bcb06d29d4 100644 --- a/tile.h +++ b/tile.h @@ -57,4 +57,14 @@ static inline bool IsTileType(TileIndex tile, TileType type) return GetTileType(tile) == type; } +static inline bool GetTileOwner(TileIndex tile) +{ + return _map_owner[tile]; +} + +static inline bool IsTileOwner(TileIndex tile, Owner owner) +{ + return GetTileOwner(tile) == owner; +} + #endif diff --git a/town.h b/town.h index c5c3b574ff..cf7eee16e4 100644 --- a/town.h +++ b/town.h @@ -133,6 +133,14 @@ VARDEF uint16 *_town_sort; extern MemoryPool _town_pool; +/** + * Check if a Town really exists. + */ +static inline bool IsValidTown(Town* town) +{ + return town->xy != 0; /* XXX: Replace by INVALID_TILE someday */ +} + /** * Get the pointer to the town with index 'index' */ diff --git a/train_cmd.c b/train_cmd.c index a26d37786f..3ab59828bd 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -538,11 +538,11 @@ int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2) Vehicle *v, *u; UnitID unit_num; Engine *e; - uint tile = TILE_FROM_XY(x,y); + TileIndex tile = TILE_FROM_XY(x,y); if (!IsEngineBuildable(p1, VEH_Train)) return CMD_ERROR; - if (!IsTrainDepotTile((TileIndex)tile)) return CMD_ERROR; + if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR; if (_map_owner[tile] != _current_player) return CMD_ERROR; @@ -641,7 +641,7 @@ int CheckTrainStoppedInDepot(Vehicle *v) TileIndex tile = v->tile; /* check if stopped in a depot */ - if (!IsTrainDepotTile(tile) || v->cur_speed != 0) { + if (!IsTileDepotType(tile, TRANSPORT_RAIL) || v->cur_speed != 0) { errmsg: _error_message = STR_881A_TRAINS_CAN_ONLY_BE_ALTERED; return -1; @@ -1128,7 +1128,7 @@ static void ReverseTrainDirection(Vehicle *v) int l = 0, r = -1; Vehicle *u; - if (IsTrainDepotTile(v->tile)) + if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); /* Check if we were approaching a rail/road-crossing */ @@ -1156,7 +1156,7 @@ static void ReverseTrainDirection(Vehicle *v) ReverseTrainSwapVeh(v, l++, r--); } while (l <= r); - if (IsTrainDepotTile(v->tile)) + if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) InvalidateWindow(WC_VEHICLE_DEPOT, v->tile); CLRBIT(v->u.rail.flags, VRF_REVERSING); @@ -1176,7 +1176,7 @@ int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2) _error_message = STR_EMPTY; -// if (v->u.rail.track & 0x80 || IsTrainDepotTile(v->tile)) +// if (v->u.rail.track & 0x80 || IsTileDepotType(v->tile, TRANSPORT_RAIL)) // return CMD_ERROR; if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) @@ -1300,7 +1300,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) tfdd.owner = v->owner; tfdd.best_length = (uint)-1; - if (IsTrainDepotTile(tile)){ + if (IsTileDepotType(tile, TRANSPORT_RAIL)){ tfdd.tile = tile; tfdd.best_length = 0; return tfdd; @@ -1311,7 +1311,7 @@ static TrainFindDepotData FindClosestTrainDepot(Vehicle *v) if (_patches.new_pathfinding_all) { NPFFoundTargetData ftd; byte trackdir = _track_direction_to_trackdir[FIND_FIRST_BIT(v->u.rail.track)][v->direction]; - ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_RAIL); + ftd = NPFRouteToDepotBreadthFirst(v->tile, trackdir, TRANSPORT_RAIL, v->owner); if (ftd.best_bird_dist == 0) { /* Found target */ tfdd.tile = ftd.node.tile; @@ -1442,7 +1442,7 @@ static void HandleLocomotiveSmokeCloud(Vehicle *v) switch (RailVehInfo(engtype)->engclass) { case 0: // steam smoke. - if ( (v->tick_counter&0xF) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile)) { + if ( (v->tick_counter&0xF) == 0 && !IsTileDepotType(v->tile, TRANSPORT_RAIL) && !IsTunnelTile(v->tile)) { CreateEffectVehicleRel(v, (_vehicle_smoke_pos[v->direction]), (_vehicle_smoke_pos[v->direction+8]), @@ -1453,14 +1453,14 @@ static void HandleLocomotiveSmokeCloud(Vehicle *v) case 1: // diesel smoke - if (u->cur_speed <= 40 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x1E00) { + if (u->cur_speed <= 40 && !IsTileDepotType(v->tile, TRANSPORT_RAIL) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x1E00) { CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_3); } break; case 2: // blue spark - if ( (v->tick_counter&0x3) == 0 && !IsTrainDepotTile(v->tile) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x5B0) { + if ( (v->tick_counter&0x3) == 0 && !IsTileDepotType(v->tile, TRANSPORT_RAIL) && !IsTunnelTile(v->tile) && (uint16)Random() <= 0x5B0) { CreateEffectVehicleRel(v, 0,0,10, EV_SMOKE_2); } break; @@ -1671,7 +1671,7 @@ static byte ChooseTrainTrack(Vehicle *v, uint tile, int enterdir, byte trackbits trackdir = _track_exitdir_to_trackdir[FIND_FIRST_BIT(v->u.rail.track)][enterdir]; assert(trackdir != 0xff); - ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL); + ftd = NPFRouteToStationOrTile(tile - TileOffsByDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner); if (ftd.best_bird_dist != 0 || ftd.best_trackdir == 0xff) { /* Not found, or we are already there. Just do something */ //TODO: maybe display error? @@ -1804,7 +1804,7 @@ static bool CheckReverseTrain(Vehicle *v) assert(trackdir != 0xff); assert(trackdir_rev != 0xff); - ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL); + ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, v->owner); if (ftd.best_bird_dist != 0) { /* We didn't find anything, just keep on going straight ahead */ reverse_best = false; @@ -2493,6 +2493,7 @@ static void TrainController(Vehicle *v) if (!(r&0x4)) { v->tile = gp.new_tile; v->u.rail.track = chosen_track; + assert(v->u.rail.track); } if (v->subtype == TS_Front_Engine) diff --git a/train_gui.c b/train_gui.c index 91db42a520..f3809421a5 100644 --- a/train_gui.c +++ b/train_gui.c @@ -1321,7 +1321,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) DrawVehicleProfitButton(v, x, y + 13); SetDParam(0, v->unitnumber); - if (IsTrainDepotTile(v->tile) && (v->vehstatus & VS_HIDDEN)) + if (IsTileDepotType(v->tile, TRANSPORT_RAIL) && (v->vehstatus & VS_HIDDEN)) str = STR_021F; else str = v->age > v->max_age - 366 ? STR_00E3 : STR_00E2; @@ -1382,7 +1382,7 @@ static void PlayerTrainsWndProc(Window *w, WindowEvent *e) tile = _last_built_train_depot_tile; do { - if (_map_owner[tile] == _local_player && IsTrainDepotTile(tile)) { + if (_map_owner[tile] == _local_player && IsTileDepotType(tile, TRANSPORT_RAIL)) { ShowTrainDepotWindow(tile); ShowBuildTrainWindow(tile); return; diff --git a/ttd.h b/ttd.h index 9e9127156e..1928e5099b 100644 --- a/ttd.h +++ b/ttd.h @@ -510,13 +510,6 @@ enum SpecialStrings { typedef void PlaceProc(uint tile); -enum MAP_OWNERS { - OWNER_TOWN = 0xf, // a town owns the tile - OWNER_NONE = 0x10, // nobody owns the tile - OWNER_WATER = 0x11, // "water" owns the tile - OWNER_SPECTATOR = 0xff, // spectator in MP or in scenario editor -}; - VARDEF bool _savegame_sort_dirty; VARDEF byte _savegame_sort_order; diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index 04903d3755..a42640deb4 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -1435,6 +1435,7 @@ static uint32 VehicleEnter_TunnelBridge(Vehicle *v, uint tile, int x, int y) /* We're at the tunnel exit ?? */ v->tile = tile; v->u.rail.track = _exit_tunnel_track[dir]; + assert(v->u.rail.track); v->vehstatus &= ~VS_HIDDEN; return 4; } diff --git a/vehicle.h b/vehicle.h index 689118bca9..15e9858896 100644 --- a/vehicle.h +++ b/vehicle.h @@ -371,6 +371,14 @@ static inline uint16 GetVehiclePoolSize(void) #define FOR_ALL_VEHICLES_FROM(v, start) for (v = GetVehicle(start); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) #define FOR_ALL_VEHICLES(v) FOR_ALL_VEHICLES_FROM(v, 0) +/** + * Check if a Vehicle really exists. + */ +static inline bool IsValidVehicle(Vehicle* v) +{ + return v->type != 0; +} + /** * Check if an index is a vehicle-index (so between 0 and max-vehicles) *