changeset 8236:d1191295967a draft

(svn r11800) -Codechange: move some functions to a more logical location + some type safety.
author rubidium <rubidium@openttd.org>
date Wed, 09 Jan 2008 21:05:03 +0000
parents b06bb17fc4c7
children eafa6364d947
files src/ai/default/default.cpp src/ai/default/default.h src/elrail.cpp src/gfxinit.cpp src/newgrf.cpp src/newgrf_engine.cpp src/npf.cpp src/npf.h src/pathfind.cpp src/pathfind.h src/player.h src/player_face.h src/players.cpp src/rail.cpp src/rail.h src/rail_cmd.cpp src/rail_gui.cpp src/rail_type.h src/road.cpp src/road_func.h src/road_type.h src/roadveh_cmd.cpp src/ship_cmd.cpp src/station_cmd.cpp src/table/railtypes.h src/terraform_gui.cpp src/train_cmd.cpp src/tunnelbridge_cmd.cpp src/vehicle_base.h src/yapf/yapf_destrail.hpp
diffstat 30 files changed, 220 insertions(+), 151 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/default/default.cpp
+++ b/src/ai/default/default.cpp
@@ -1103,7 +1103,7 @@
 {
 	uint16 r = GB(Random(), 0, 16);
 
-	_players_ai[p->index].railtype_to_use = GetBestRailtype(p);
+	_players_ai[p->index].railtype_to_use = GetBestRailtype(p->index);
 
 	if (r > 0xD000) {
 		AiWantLongIndustryRoute(p);
@@ -4034,4 +4034,4 @@
 	for (int i = 0; i != pai->num_build_rec; i++) {
 		SlObject(&pai->src + i, _player_ai_build_rec_desc);
 	}
-}
\ No newline at end of file
+}
--- a/src/ai/default/default.h
+++ b/src/ai/default/default.h
@@ -3,6 +3,8 @@
 #ifndef DEFAULT_H
 #define DEFAULT_H
 
+#include "../../direction_type.h"
+
 void AiDoGameLoop(Player*);
 void SaveLoad_AI(PlayerID id);
 
--- a/src/elrail.cpp
+++ b/src/elrail.cpp
@@ -496,7 +496,7 @@
 			if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
 				/* this railroad vehicle is now compatible only with elrail,
 				*  so add there also normal rail compatibility */
-				v->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
+				v->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
 				v->u.rail.railtype = RAILTYPE_RAIL;
 				SetBit(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
 			}
--- a/src/gfxinit.cpp
+++ b/src/gfxinit.cpp
@@ -16,6 +16,7 @@
 #include "fontcache.h"
 #include "gfx_func.h"
 #include "core/alloc_func.hpp"
+#include "core/bitmath_func.hpp"
 #include <string.h>
 
 struct MD5File {
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -46,6 +46,7 @@
 #include "vehicle_func.h"
 #include "sound_func.h"
 #include "string_func.h"
+#include "road_func.h"
 
 /* TTDPatch extended GRF format codec
  * (c) Petr Baudis 2004 (GPL'd)
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -21,6 +21,7 @@
 #include "date_func.h"
 #include "vehicle_func.h"
 #include "core/random_func.hpp"
+#include "direction_func.h"
 
 
 int _traininfo_vehicle_pitch = 0;
--- a/src/npf.cpp
+++ b/src/npf.cpp
@@ -668,7 +668,7 @@
  * multiple targets that are spread around, we should perform a breadth first
  * search by specifiying CalcZero as our heuristic.
  */
-static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
+static NPFFoundTargetData NPFRouteInternal(AyStarNode* start1, AyStarNode* start2, NPFFindStationOrTileData* target, AyStar_EndNodeCheck target_proc, AyStar_CalculateH heuristic_proc, TransportType type, uint sub_type, Owner owner, RailTypes railtypes, uint reverse_penalty)
 {
 	int r;
 	NPFFoundTargetData result;
@@ -727,7 +727,7 @@
 	return result;
 }
 
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
 {
 	AyStarNode start1;
 	AyStarNode start2;
@@ -744,12 +744,12 @@
 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), target, NPFFindStationOrTile, NPFCalcStationOrTileHeuristic, type, sub_type, owner, railtypes, 0);
 }
 
-NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
 {
 	return NPFRouteToStationOrTileTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, target, type, sub_type, owner, railtypes);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes, uint reverse_penalty)
+NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypes railtypes, uint reverse_penalty)
 {
 	AyStarNode start1;
 	AyStarNode start2;
@@ -768,12 +768,12 @@
 	return NPFRouteInternal(&start1, (IsValidTile(tile2) ? &start2 : NULL), NULL, NPFFindDepot, NPFCalcZero, type, sub_type, owner, railtypes, reverse_penalty);
 }
 
-NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
 {
 	return NPFRouteToDepotBreadthFirstTwoWay(tile, trackdir, INVALID_TILE, INVALID_TRACKDIR, type, sub_type, owner, railtypes, 0);
 }
 
-NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
 {
 	/* 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
--- a/src/npf.h
+++ b/src/npf.h
@@ -10,6 +10,7 @@
 #include "vehicle_type.h"
 #include "tile_type.h"
 #include "track_type.h"
+#include "core/bitmath_func.hpp"
 
 /* mowing grass */
 enum {
@@ -77,28 +78,28 @@
 /* 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, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes);
 
 /* Will search as above, but with two start nodes, the second being the
  * reverse. Look at the NPF_FLAG_REVERSE flag in the result node to see which
  * direction was taken (NPFGetBit(result.node, NPF_FLAG_REVERSE)) */
-NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToStationOrTileTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes);
 
 /* 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, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToDepotBreadthFirst(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes);
 /* Same as above but with two start nodes, the second being the reverse. Call
  * NPFGetBit(result.node, NPF_FLAG_REVERSE) to see from which node the path
  * orginated. All pathfs from the second node will have the given
  * reverse_penalty applied (NPF_TILE_LENGTH is the equivalent of one full
  * tile).
  */
-NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes, uint reverse_penalty);
+NPFFoundTargetData NPFRouteToDepotBreadthFirstTwoWay(TileIndex tile1, Trackdir trackdir1, TileIndex tile2, Trackdir trackdir2, TransportType type, uint sub_type, Owner owner, RailTypes railtypes, uint reverse_penalty);
 /* 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, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes);
+NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, TransportType type, uint sub_type, Owner owner, RailTypes railtypes);
 
 void NPFFillWithOrderData(NPFFindStationOrTileData* fstd, Vehicle* v);
 
--- a/src/pathfind.cpp
+++ b/src/pathfind.cpp
@@ -442,7 +442,7 @@
 	TileIndex dest;
 
 	TransportType tracktype;
-	RailTypeMask railtypes;
+	RailTypes railtypes;
 	uint maxlength;
 
 	HashLink *new_link;
@@ -938,7 +938,7 @@
 
 
 /** new pathfinder for trains. better and faster. */
-void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypeMask railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data)
+void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypes railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data)
 {
 	NewTrackPathFinder tpf;
 
--- a/src/pathfind.h
+++ b/src/pathfind.h
@@ -76,6 +76,6 @@
 };
 FindLengthOfTunnelResult FindLengthOfTunnel(TileIndex tile, DiagDirection direction);
 
-void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypeMask railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data);
+void NewTrainPathfind(TileIndex tile, TileIndex dest, RailTypes railtypes, DiagDirection direction, NTPEnumProc* enum_proc, void* data);
 
 #endif /* PATHFIND_H */
--- a/src/player.h
+++ b/src/player.h
@@ -5,11 +5,11 @@
 #ifndef PLAYER_H
 #define PLAYER_H
 
-#include "road_func.h"
+#include "road_type.h"
+#include "rail_type.h"
 #include "date_type.h"
 #include "engine.h"
 #include "livery.h"
-#include "genworld.h"
 #include "autoreplace_type.h"
 
 struct PlayerEconomyEntry {
@@ -41,8 +41,8 @@
 	byte player_color;
 	Livery livery[LS_END];
 	byte player_money_fraction;
-	byte avail_railtypes;
-	byte avail_roadtypes;
+	RailTypes avail_railtypes;
+	RoadTypes avail_roadtypes;
 	byte block_preview;
 	PlayerByte index;
 
@@ -119,37 +119,6 @@
 	return IsInsideBS(pi, PLAYER_FIRST, MAX_PLAYERS);
 }
 
-byte GetPlayerRailtypes(PlayerID p);
-byte GetPlayerRoadtypes(PlayerID p);
-
-/** Finds out if a Player has a certain railtype available
- * @param p Player in question
- * @param Railtype requested RailType
- * @return true if player has requested RailType available
- */
-static inline bool HasRailtypeAvail(const Player *p, const RailType Railtype)
-{
-	return HasBit(p->avail_railtypes, Railtype);
-}
-
-/** Finds out, whether given player has all given RoadTypes available
- * @param PlayerID ID of player
- * @param rts RoadTypes to test
- * @return true if player has all requested RoadTypes available
- */
-static inline bool HasRoadTypesAvail(const PlayerID p, const RoadTypes rts)
-{
-	RoadTypes avail_roadtypes;
-
-	if (p == OWNER_TOWN || _game_mode == GM_EDITOR || IsGeneratingWorld()) {
-		avail_roadtypes = ROADTYPES_ROAD;
-	} else {
-		if (!IsValidPlayer(p)) return false;
-		avail_roadtypes = (RoadTypes)GetPlayer(p)->avail_roadtypes | ROADTYPES_ROAD; // road is available for always for everybody
-	}
-	return (rts & ~avail_roadtypes) == 0;
-}
-
 static inline bool IsHumanPlayer(PlayerID pi)
 {
 	return !GetPlayer(pi)->is_ai;
@@ -162,26 +131,6 @@
 
 void DrawPlayerIcon(PlayerID p, int x, int y);
 
-/* Validate functions for rail building */
-static inline bool ValParamRailtype(const uint32 rail) { return HasBit(GetPlayer(_current_player)->avail_railtypes, rail);}
-
-/* Validate functions for road building */
-static inline bool ValParamRoadType(const RoadType rt) { return HasRoadTypesAvail(_current_player, RoadTypeToRoadTypes(rt));}
-
-/** Returns the "best" railtype a player can build.
- * As the AI doesn't know what the BEST one is, we have our own priority list
- * here. When adding new railtypes, modify this function
- * @param p the player "in action"
- * @return The "best" railtype a player has available
- */
-static inline RailType GetBestRailtype(const Player *p)
-{
-	if (HasRailtypeAvail(p, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV;
-	if (HasRailtypeAvail(p, RAILTYPE_MONO)) return RAILTYPE_MONO;
-	if (HasRailtypeAvail(p, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC;
-	return RAILTYPE_RAIL;
-}
-
 struct HighScore {
 	char company[100];
 	StringID title; ///< NO_SAVE, has troubles with changing string-numbers.
--- a/src/player_face.h
+++ b/src/player_face.h
@@ -6,6 +6,7 @@
 #define PLAYER_FACE_H
 
 #include "core/random_func.hpp"
+#include "core/bitmath_func.hpp"
 
 /** The gender/race combinations that we have faces for */
 enum GenderEthnicity {
--- a/src/players.cpp
+++ b/src/players.cpp
@@ -32,6 +32,8 @@
 #include "string_func.h"
 #include "ai/default/default.h"
 #include "ai/trolly/trolly.h"
+#include "road_func.h"
+#include "rail.h"
 
 /**
  * Sets the local player and updates the patch settings that are set on a
@@ -590,47 +592,6 @@
 	}
 }
 
-byte GetPlayerRailtypes(PlayerID p)
-{
-	byte rt = 0;
-	EngineID i;
-
-	for (i = 0; i != TOTAL_NUM_ENGINES; i++) {
-		const Engine* e = GetEngine(i);
-		const EngineInfo *ei = EngInfo(i);
-
-		if (e->type == VEH_TRAIN && HasBit(ei->climates, _opt.landscape) &&
-				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
-			const RailVehicleInfo *rvi = RailVehInfo(i);
-
-			if (rvi->railveh_type != RAILVEH_WAGON) {
-				assert(rvi->railtype < RAILTYPE_END);
-				SetBit(rt, rvi->railtype);
-			}
-		}
-	}
-
-	return rt;
-}
-
-byte GetPlayerRoadtypes(PlayerID p)
-{
-	byte rt = 0;
-	EngineID i;
-
-	for (i = 0; i != TOTAL_NUM_ENGINES; i++) {
-		const Engine* e = GetEngine(i);
-		const EngineInfo *ei = EngInfo(i);
-
-		if (e->type == VEH_ROAD && HasBit(ei->climates, _opt.landscape) &&
-				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
-			SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
-		}
-	}
-
-	return rt;
-}
-
 static void DeletePlayerStuff(PlayerID pi)
 {
 	Player *p;
--- a/src/rail.cpp
+++ b/src/rail.cpp
@@ -9,6 +9,8 @@
 #include "station_map.h"
 #include "tunnel_map.h"
 #include "tunnelbridge_map.h"
+#include "settings_type.h"
+#include "date_func.h"
 
 
 /* XXX: Below 3 tables store duplicate data. Maybe remove some? */
@@ -140,3 +142,43 @@
 	}
 	return INVALID_RAILTYPE;
 }
+
+bool HasRailtypeAvail(const PlayerID p, const RailType railtype)
+{
+	return HasBit(GetPlayer(p)->avail_railtypes, railtype);
+}
+
+bool ValParamRailtype(const RailType rail)
+{
+	return HasRailtypeAvail(_current_player, rail);
+}
+
+RailType GetBestRailtype(const PlayerID p)
+{
+	if (HasRailtypeAvail(p, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV;
+	if (HasRailtypeAvail(p, RAILTYPE_MONO)) return RAILTYPE_MONO;
+	if (HasRailtypeAvail(p, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC;
+	return RAILTYPE_RAIL;
+}
+
+RailTypes GetPlayerRailtypes(PlayerID p)
+{
+	RailTypes rt = RAILTYPES_NONE;
+
+	for (EngineID i = 0; i != TOTAL_NUM_ENGINES; i++) {
+		const Engine* e = GetEngine(i);
+		const EngineInfo *ei = EngInfo(i);
+
+		if (e->type == VEH_TRAIN && HasBit(ei->climates, _opt.landscape) &&
+				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
+			const RailVehicleInfo *rvi = RailVehInfo(i);
+
+			if (rvi->railveh_type != RAILVEH_WAGON) {
+				assert(rvi->railtype < RAILTYPE_END);
+				SetBit(rt, rvi->railtype);
+			}
+		}
+	}
+
+	return rt;
+}
--- a/src/rail.h
+++ b/src/rail.h
@@ -64,10 +64,10 @@
 	SpriteID snow_offset;
 
 	/** bitmask to the OTHER railtypes on which an engine of THIS railtype generates power */
-	RailTypeMask powered_railtypes;
+	RailTypes powered_railtypes;
 
 	/** bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel */
-	RailTypeMask compatible_railtypes;
+	RailTypes compatible_railtypes;
 
 	/**
 	 * Offset between the current railtype and normal rail. This means that:<p>
@@ -201,4 +201,35 @@
 
 int32 SettingsDisableElrail(int32 p1); ///< _patches.disable_elrail callback
 
+/**
+ * Finds out if a Player has a certain railtype available
+ * @param p Player in question
+ * @param railtype requested RailType
+ * @return true if player has requested RailType available
+ */
+bool HasRailtypeAvail(const PlayerID p, const RailType railtype);
+
+/**
+ * Validate functions for rail building.
+ * @param rail the railtype to check.
+ * @return true if the current player may build the rail.
+ */
+bool ValParamRailtype(const RailType rail);
+
+/**
+ * Returns the "best" railtype a player can build.
+ * As the AI doesn't know what the BEST one is, we have our own priority list
+ * here. When adding new railtypes, modify this function
+ * @param p the player "in action"
+ * @return The "best" railtype a player has available
+ */
+RailType GetBestRailtype(const PlayerID p);
+
+/**
+ * Get the rail types the given player can build.
+ * @param p the player to get the rail types for.
+ * @return the rail types.
+ */
+RailTypes GetPlayerRailtypes(const PlayerID p);
+
 #endif /* RAIL_H */
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -303,15 +303,13 @@
 CommandCost CmdBuildSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	Slope tileh;
-	RailType railtype;
-	Track track;
+	RailType railtype = (RailType)p1;
+	Track track = (Track)p2;
 	TrackBits trackbit;
 	CommandCost cost(EXPENSES_CONSTRUCTION);
 	CommandCost ret;
 
-	if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR;
-	railtype = (RailType)p1;
-	track = (Track)p2;
+	if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
 
 	tileh = GetTileSlope(tile, NULL);
 	trackbit = TrackToTrackBits(track);
@@ -703,7 +701,7 @@
 	Slope tileh;
 
 	/* check railtype and valid direction for depot (0 through 3), 4 in total */
-	if (!ValParamRailtype(p1)) return CMD_ERROR;
+	if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
 
 	tileh = GetTileSlope(tile, NULL);
 
@@ -1150,12 +1148,11 @@
 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	CommandCost cost(EXPENSES_CONSTRUCTION);
-
-	if (!ValParamRailtype(p2)) return CMD_ERROR;
+	RailType totype = (RailType)p2;
+
+	if (!ValParamRailtype(totype)) return CMD_ERROR;
 	if (p1 >= MapSize()) return CMD_ERROR;
 
-	RailType totype = (RailType)p2;
-
 	uint ex = TileX(tile);
 	uint ey = TileY(tile);
 	uint sx = TileX(p1);
--- a/src/rail_gui.cpp
+++ b/src/rail_gui.cpp
@@ -1540,11 +1540,11 @@
 		switch (rt) {
 			case RAILTYPE_END + 0:
 				rt = RAILTYPE_RAIL;
-				while (rt < RAILTYPE_END && !HasRailtypeAvail(GetPlayer(_local_player), rt)) rt++;
+				while (rt < RAILTYPE_END && !HasRailtypeAvail(_local_player, rt)) rt++;
 				break;
 
 			case RAILTYPE_END + 1:
-				rt = GetBestRailtype(GetPlayer(_local_player));
+				rt = GetBestRailtype(_local_player);
 				break;
 
 			default:
--- a/src/rail_type.h
+++ b/src/rail_type.h
@@ -20,12 +20,27 @@
 	INVALID_RAILTYPE  = 0xFF        ///< Flag for invalid railtype
 };
 
-typedef byte RailTypeMask;
-
 /** Allow incrementing of Track variables */
 DECLARE_POSTFIX_INCREMENT(RailType);
 /** Define basic enum properties */
 template <> struct EnumPropsT<RailType> : MakeEnumPropsT<RailType, byte, RAILTYPE_BEGIN, RAILTYPE_END, INVALID_RAILTYPE> {};
 typedef TinyEnumT<RailType> RailTypeByte;
 
+/**
+ * The different roadtypes we support, but then a bitmask of them
+ */
+enum RailTypes {
+	RAILTYPES_NONE     = 0,                      ///< No rail types
+	RAILTYPES_RAIL     = 1 << RAILTYPE_RAIL,     ///< Non-electrified rails
+	RAILTYPES_ELECTRIC = 1 << RAILTYPE_ELECTRIC, ///< Electrified rails
+	RAILTYPES_MONO     = 1 << RAILTYPE_MONO,     ///< Monorail!
+	RAILTYPES_MAGLEV   = 1 << RAILTYPE_MAGLEV,   ///< Ever fast maglev
+	RAILTYPES_ALL      = RAILTYPES_RAIL | RAILTYPES_ELECTRIC | RAILTYPES_MONO | RAILTYPES_MAGLEV, ///< All of them
+	RAILTYPES_END,                               ///< Used for iterations?
+	INVALID_RAILTYPES  = 0xFF                    ///< Invalid railtypes
+};
+DECLARE_ENUM_AS_BIT_SET(RailTypes);
+template <> struct EnumPropsT<RailTypes> : MakeEnumPropsT<RailTypes, byte, RAILTYPES_NONE, RAILTYPES_END, INVALID_RAILTYPES> {};
+typedef TinyEnumT<RailTypes> RailTypesByte;
+
 #endif /* RAIL_TYPE_H */
--- a/src/road.cpp
+++ b/src/road.cpp
@@ -6,6 +6,11 @@
 #include "road_map.h"
 #include "road_internal.h"
 #include "water_map.h"
+#include "genworld.h"
+#include "player.h"
+#include "engine.h"
+#include "settings_type.h"
+#include "date_func.h"
 
 bool IsPossibleCrossing(const TileIndex tile, Axis ax)
 {
@@ -67,3 +72,38 @@
 
 	return org_rb;
 }
+
+bool HasRoadTypesAvail(const PlayerID p, const RoadTypes rts)
+{
+	RoadTypes avail_roadtypes;
+
+	if (p == OWNER_TOWN || _game_mode == GM_EDITOR || IsGeneratingWorld()) {
+		avail_roadtypes = ROADTYPES_ROAD;
+	} else {
+		if (!IsValidPlayer(p)) return false;
+		avail_roadtypes = (RoadTypes)GetPlayer(p)->avail_roadtypes | ROADTYPES_ROAD; // road is available for always for everybody
+	}
+	return (rts & ~avail_roadtypes) == 0;
+}
+
+bool ValParamRoadType(const RoadType rt)
+{
+	return HasRoadTypesAvail(_current_player, RoadTypeToRoadTypes(rt));
+}
+
+RoadTypes GetPlayerRoadtypes(PlayerID p)
+{
+	RoadTypes rt = ROADTYPES_NONE;
+
+	for (EngineID i = 0; i != TOTAL_NUM_ENGINES; i++) {
+		const Engine* e = GetEngine(i);
+		const EngineInfo *ei = EngInfo(i);
+
+		if (e->type == VEH_ROAD && HasBit(ei->climates, _opt.landscape) &&
+				(HasBit(e->player_avail, p) || _date >= e->intro_date + 365)) {
+			SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
+		}
+	}
+
+	return rt;
+}
--- a/src/road_func.h
+++ b/src/road_func.h
@@ -113,4 +113,26 @@
 	return (RoadBits)(ROAD_NW << (3 ^ d));
 }
 
+/**
+ * Finds out, whether given player has all given RoadTypes available
+ * @param PlayerID ID of player
+ * @param rts RoadTypes to test
+ * @return true if player has all requested RoadTypes available
+ */
+bool HasRoadTypesAvail(const PlayerID p, const RoadTypes rts);
+
+/**
+ * Validate functions for rail building.
+ * @param rt road type to check.
+ * @return true if the current player may build the road.
+ */
+bool ValParamRoadType(const RoadType rt);
+
+/**
+ * Get the road types the given player can build.
+ * @param p the player to get the roadtypes for.
+ * @return the road types.
+ */
+RoadTypes GetPlayerRoadtypes(const PlayerID p);
+
 #endif /* ROAD_FUNC_H */
--- a/src/road_type.h
+++ b/src/road_type.h
@@ -34,8 +34,12 @@
 	ROADTYPES_ROADHWAY = ROADTYPES_ROAD | ROADTYPES_HWAY,                   ///< Road + highway (or whatever substitute)
 	ROADTYPES_TRAMHWAY = ROADTYPES_TRAM | ROADTYPES_HWAY,                   ///< Trams + highway (or whatever substitute)
 	ROADTYPES_ALL      = ROADTYPES_ROAD | ROADTYPES_TRAM | ROADTYPES_HWAY,  ///< Road + trams + highway (or whatever substitute)
+	ROADTYPES_END,                                                          ///< Used for iterations?
+	INVALID_ROADTYPES  = 0xFF                                               ///< Invalid roadtypes
 };
 DECLARE_ENUM_AS_BIT_SET(RoadTypes);
+template <> struct EnumPropsT<RoadTypes> : MakeEnumPropsT<RoadTypes, byte, ROADTYPES_NONE, ROADTYPES_END, INVALID_ROADTYPES> {};
+typedef TinyEnumT<RoadTypes> RoadTypesByte;
 
 
 /**
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -422,7 +422,7 @@
 		/* See where we are now */
 		Trackdir trackdir = GetVehicleTrackdir(v);
 
-		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, v->tile, ReverseTrackdir(trackdir), TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE, 0);
+		ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, v->tile, ReverseTrackdir(trackdir), TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0);
 		if (ftd.best_bird_dist == 0) {
 			return GetDepotByTile(ftd.node.tile); /* Target found */
 		} else {
@@ -1126,7 +1126,7 @@
 	return false;
 }
 
-static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypeMask railtypes)
+static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, uint sub_type, Owner owner, RailTypes railtypes)
 {
 
 	void* perf = NpfBeginInterval();
@@ -1228,7 +1228,7 @@
 		trackdir = DiagdirToDiagTrackdir(enterdir);
 		//debug("Finding path. Enterdir: %d, Trackdir: %d", enterdir, trackdir);
 
-		ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE);
+		ftd = PerfNPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES);
 		if (ftd.best_trackdir == INVALID_TRACKDIR) {
 			/* We are already at our target. Just do something
 			 * @todo: maybe display error?
@@ -1310,7 +1310,7 @@
 		fstd.dest_coords = tile;
 		fstd.station_index = INVALID_STATION; // indicates that the destination is a tile, not a station
 
-		dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPE).best_path_dist;
+		dist = NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES).best_path_dist;
 		/* change units from NPF_TILE_LENGTH to # of tiles */
 		if (dist != UINT_MAX)
 			dist = (dist + NPF_TILE_LENGTH - 1) / NPF_TILE_LENGTH;
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -121,7 +121,7 @@
 	if (_patches.new_pathfinding_all) {
 		NPFFoundTargetData ftd;
 		Trackdir trackdir = GetVehicleTrackdir(v);
-		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPE);
+		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES);
 		if (ftd.best_bird_dist == 0) {
 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
 		} else {
@@ -508,7 +508,7 @@
 	return best_bird_dist;
 }
 
-static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes)
+static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypes railtypes)
 {
 
 	void* perf = NpfBeginInterval();
@@ -537,7 +537,7 @@
 
 		NPFFillWithOrderData(&fstd, v);
 
-		ftd = PerfNPFRouteToStationOrTile(src_tile, trackdir, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
+		ftd = PerfNPFRouteToStationOrTile(src_tile, trackdir, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPES);
 
 		if (ftd.best_trackdir != 0xff) {
 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -905,7 +905,7 @@
 
 	/* Does the authority allow this? */
 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile_org)) return CMD_ERROR;
-	if (!ValParamRailtype(p2 & 0xF)) return CMD_ERROR;
+	if (!ValParamRailtype((RailType)(p2 & 0xF))) return CMD_ERROR;
 
 	/* unpack parameters */
 	Axis axis = Extract<Axis, 0>(p1);
--- a/src/table/railtypes.h
+++ b/src/table/railtypes.h
@@ -44,10 +44,10 @@
 		SPR_RAIL_SNOW_OFFSET,
 
 		/* Powered railtypes */
-		1 << RAILTYPE_RAIL | 1 << RAILTYPE_ELECTRIC,
+		RAILTYPES_RAIL | RAILTYPES_ELECTRIC,
 
 		/* Compatible railtypes */
-		1 << RAILTYPE_RAIL | 1 << RAILTYPE_ELECTRIC,
+		RAILTYPES_RAIL | RAILTYPES_ELECTRIC,
 
 		/* main offset */
 		0,
@@ -100,10 +100,10 @@
 		SPR_RAIL_SNOW_OFFSET,
 
 		/* Powered railtypes */
-		1 << RAILTYPE_ELECTRIC,
+		RAILTYPES_ELECTRIC,
 
 		/* Compatible railtypes */
-		1 << RAILTYPE_ELECTRIC | 1 << RAILTYPE_RAIL,
+		RAILTYPES_ELECTRIC | RAILTYPES_RAIL,
 
 		/* main offset */
 		0,
@@ -152,10 +152,10 @@
 		SPR_MONO_SNOW_OFFSET,
 
 		/* Powered railtypes */
-		1 << RAILTYPE_MONO,
+		RAILTYPES_MONO,
 
 		/* Compatible Railtypes */
-		1 << RAILTYPE_MONO,
+		RAILTYPES_MONO,
 
 		/* main offset */
 		82,
@@ -204,10 +204,10 @@
 		SPR_MGLV_SNOW_OFFSET,
 
 		/* Powered railtypes */
-		1 << RAILTYPE_MAGLEV,
+		RAILTYPES_MAGLEV,
 
 		/* Compatible Railtypes */
-		1 << RAILTYPE_MAGLEV,
+		RAILTYPES_MAGLEV,
 
 		/* main offset */
 		164,
--- a/src/terraform_gui.cpp
+++ b/src/terraform_gui.cpp
@@ -21,6 +21,7 @@
 #include "station.h"
 #include "unmovable_map.h"
 #include "textbuf_gui.h"
+#include "genworld.h"
 
 void CcTerraform(bool success, TileIndex tile, uint32 p1, uint32 p2)
 {
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -165,7 +165,7 @@
 	const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
 	EngineID first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE;
 	v->u.rail.cached_total_length = 0;
-	v->u.rail.compatible_railtypes = 0;
+	v->u.rail.compatible_railtypes = RAILTYPES_NONE;
 
 	bool train_can_tilt = true;
 
@@ -230,7 +230,7 @@
 			 * existing electric engines when elrails are disabled and then re-enabled */
 			if (HasBit(u->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
 				u->u.rail.railtype = RAILTYPE_RAIL;
-				u->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
+				u->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
 			}
 
 			/* max speed is the minimum of the speed limits of all vehicles in the consist */
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -214,7 +214,7 @@
 		roadtypes = (RoadTypes)GB(p2, 8, 3);
 		if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_player, roadtypes)) return CMD_ERROR;
 	} else {
-		if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR;
+		if (!ValParamRailtype((RailType)GB(p2, 8, 8))) return CMD_ERROR;
 		railtype = (RailType)GB(p2, 8, 8);
 		roadtypes = ROADTYPES_NONE;
 	}
@@ -462,7 +462,7 @@
 
 	_build_tunnel_endtile = 0;
 	if (!HasBit(p1, 9)) {
-		if (!ValParamRailtype(p1)) return CMD_ERROR;
+		if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
 	} else {
 		const RoadTypes rts = (RoadTypes)GB(p1, 0, 3);
 		if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR;
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -106,7 +106,7 @@
 	TrackBitsByte track;
 	byte force_proceed;
 	RailTypeByte railtype;
-	RailTypeMask compatible_railtypes;
+	RailTypes compatible_railtypes;
 
 	byte flags;
 
--- a/src/yapf/yapf_destrail.hpp
+++ b/src/yapf/yapf_destrail.hpp
@@ -8,7 +8,7 @@
 class CYapfDestinationRailBase
 {
 protected:
-	RailTypeMask m_compatible_railtypes;
+	RailTypes m_compatible_railtypes;
 
 public:
 	void SetDestination(Vehicle* v)