summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ai_old.c2
-rw-r--r--engine.c32
-rw-r--r--main_gui.c5
-rw-r--r--oldloader.c2
-rw-r--r--openttd.c5
-rw-r--r--player.h42
-rw-r--r--players.c25
-rw-r--r--table/engines.h11
-rw-r--r--train_gui.c2
-rw-r--r--vehicle.h2
10 files changed, 91 insertions, 37 deletions
diff --git a/ai_old.c b/ai_old.c
index f6cd06bed..70b4103c9 100644
--- a/ai_old.c
+++ b/ai_old.c
@@ -1075,7 +1075,7 @@ static void AiWantPassengerRoute(Player *p)
static void AiWantTrainRoute(Player *p)
{
uint16 r;
- p->ai.railtype_to_use = p->max_railtype - 1;
+ p->ai.railtype_to_use = GetBestRailtype(p);
r = (uint16)Random();
if (r > 0xD000) {
diff --git a/engine.c b/engine.c
index 45fbdb2f6..a17841dd8 100644
--- a/engine.c
+++ b/engine.c
@@ -12,8 +12,6 @@
#include "saveload.h"
#include "sprite.h"
-#define UPDATE_PLAYER_RAILTYPE(e,p) if ((byte)(e->railtype + 1) > p->max_railtype) p->max_railtype = e->railtype + 1;
-
enum {
ENGINE_AVAILABLE = 1,
ENGINE_INTRODUCING = 2,
@@ -755,9 +753,9 @@ void AcceptEnginePreview(Engine *e, PlayerID player)
{
Player *p = GetPlayer(player);
+ assert(e->railtype < RAILTYPE_END);
SETBIT(e->player_avail, player);
-
- UPDATE_PLAYER_RAILTYPE(e, p);
+ SETBIT(p->avail_railtypes, e->railtype);
e->preview_player = 0xFF;
InvalidateWindowClasses(WC_BUILD_VEHICLE);
@@ -897,8 +895,10 @@ static void NewVehicleAvailable(Engine *e)
// make maglev / monorail available
FOR_ALL_PLAYERS(p) {
- if (p->is_active)
- UPDATE_PLAYER_RAILTYPE(e,p);
+ if (p->is_active) {
+ assert(e->railtype < RAILTYPE_END);
+ SETBIT(p->avail_railtypes, e->railtype);
+ }
}
if ((byte)index < NUM_TRAIN_ENGINES) {
@@ -967,26 +967,6 @@ int32 CmdRenameEngine(int x, int y, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
-int GetPlayerMaxRailtype(int p)
-{
- Engine *e;
- int rt = 0;
- int i;
-
- for(e=_engines,i=0; i!=lengthof(_engines); e++,i++) {
- if (!HASBIT(e->player_avail, p))
- continue;
-
- if ((i >= 27 && i < 54) || (i >= 57 && i < 84) || (i >= 89 && i < 116))
- continue;
-
- if (rt < e->railtype)
- rt = e->railtype;
- }
-
- return rt + 1;
-}
-
static const SaveLoad _engine_desc[] = {
SLE_VAR(Engine,intro_date, SLE_UINT16),
diff --git a/main_gui.c b/main_gui.c
index 707eb46af..244cb2be0 100644
--- a/main_gui.c
+++ b/main_gui.c
@@ -327,8 +327,7 @@ static void MenuClickShowAir(int index)
static void MenuClickBuildRail(int index)
{
- Player *p = GetPlayer(_local_player);
- _last_built_railtype = min(index, p->max_railtype-1);
+ _last_built_railtype = index;
ShowBuildRailToolbar(_last_built_railtype, -1);
}
@@ -941,7 +940,7 @@ static void ToolbarBuildRailClick(Window *w)
{
Player *p = GetPlayer(_local_player);
Window *w2;
- w2 = PopupMainToolbMenu(w, 457, 19, STR_1015_RAILROAD_CONSTRUCTION, p->max_railtype);
+ w2 = PopupMainToolbMenu(w, 457, 19, STR_1015_RAILROAD_CONSTRUCTION, GetNumRailtypes(p));
WP(w2,menu_d).sel_index = _last_built_railtype;
}
diff --git a/oldloader.c b/oldloader.c
index 56ef7c51c..8dc1b1ae0 100644
--- a/oldloader.c
+++ b/oldloader.c
@@ -1020,7 +1020,7 @@ static const OldChunks player_chunk[] = {
OCL_SVAR( OC_UINT8, Player, block_preview ),
OCL_SVAR( OC_UINT8, Player, ai.tick ),
- OCL_SVAR( OC_UINT8, Player, max_railtype ),
+ OCL_SVAR( OC_UINT8, Player, avail_railtypes ),
OCL_SVAR( OC_TILE, Player, location_of_house ),
OCL_SVAR( OC_UINT8, Player, share_owners[0] ),
OCL_SVAR( OC_UINT8, Player, share_owners[1] ),
diff --git a/openttd.c b/openttd.c
index 8cef88613..85a65d800 100644
--- a/openttd.c
+++ b/openttd.c
@@ -1279,6 +1279,7 @@ bool AfterLoadGame(uint version)
{
Window *w;
ViewPort *vp;
+ Player *p;
// in version 2.1 of the savegame, town owner was unified.
if (version <= 0x200) {
@@ -1432,5 +1433,9 @@ bool AfterLoadGame(uint version)
} END_TILE_LOOP(tile, MapSizeX(), MapSizeY(), 0);
}
+ FOR_ALL_PLAYERS(p) {
+ p->avail_railtypes = GetPlayerRailtypes(p->index);
+ }
+
return true;
}
diff --git a/player.h b/player.h
index 9bad57a09..43af5b361 100644
--- a/player.h
+++ b/player.h
@@ -2,6 +2,8 @@
#define PLAYER_H
#include "aystar.h"
+#include "engine.h"
+#include "rail.h"
typedef struct PlayerEconomyEntry {
int32 income;
@@ -157,7 +159,7 @@ typedef struct Player {
byte player_color;
byte player_money_fraction;
- byte max_railtype;
+ byte avail_railtypes;
byte block_preview;
PlayerID index;
@@ -203,6 +205,44 @@ static inline Player* GetPlayer(uint i)
return &_players[i];
}
+/** Returns the number of rail types the player can build
+ * @param *p Player in question
+ */
+static inline int GetNumRailtypes(Player *p)
+{
+ int num = 0;
+ int i;
+
+ for (i = 0; i < (int)sizeof(p->avail_railtypes) * 8; i++)
+ if (HASBIT(p->avail_railtypes, i)) num++;
+
+ assert(num <= RAILTYPE_END);
+ return num;
+}
+
+byte GetPlayerRailtypes(int p);
+
+/** Finds out if a Player has a certain railtype available
+ */
+static inline bool HasRailtypeAvail(Player *p, RailType Railtype)
+{
+ return HASBIT(p->avail_railtypes, Railtype);
+}
+
+/** 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 byte GetBestRailtype(Player *p)
+{
+ if (HasRailtypeAvail(p, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV;
+ if (HasRailtypeAvail(p, RAILTYPE_MONO)) return RAILTYPE_MONO;
+ return RAILTYPE_RAIL;
+}
+
#define IS_HUMAN_PLAYER(p) (!GetPlayer((byte)(p))->is_ai)
#define IS_INTERACTIVE_PLAYER(p) (((byte)p) == _local_player)
diff --git a/players.c b/players.c
index 0ee406018..4478812e8 100644
--- a/players.c
+++ b/players.c
@@ -487,7 +487,7 @@ Player *DoStartupNewPlayer(bool is_ai)
p->ai.state = 5; /* AIS_WANT_NEW_ROUTE */
p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = 0xFF;
- p->max_railtype = GetPlayerMaxRailtype(index);
+ p->avail_railtypes = GetPlayerRailtypes(index);
p->inaugurated_year = _cur_year;
p->face = Random();
@@ -622,6 +622,27 @@ void DeletePlayerWindows(int pi)
DeleteWindowById(WC_BUY_COMPANY, pi);
}
+byte GetPlayerRailtypes(int p)
+{
+ Engine *e;
+ int rt = 0;
+ int i;
+
+ for(e = _engines, i = 0; i != lengthof(_engines); e++, i++) {
+ if (!HASBIT(e->player_avail, p))
+ continue;
+
+ /* Skip all wagons */
+ if ((i >= 27 && i < 54) || (i >= 57 && i < 84) || (i >= 89 && i < 116))
+ continue;
+
+ assert(e->railtype < RAILTYPE_END);
+ SETBIT(rt, e->railtype);
+ }
+
+ return rt;
+}
+
static void DeletePlayerStuff(int pi)
{
Player *p;
@@ -969,7 +990,7 @@ static const SaveLoad _player_desc[] = {
SLE_VAR(Player,player_color, SLE_UINT8),
SLE_VAR(Player,player_money_fraction,SLE_UINT8),
- SLE_VAR(Player,max_railtype, SLE_UINT8),
+ SLE_VAR(Player,avail_railtypes, SLE_UINT8),
SLE_VAR(Player,block_preview, SLE_UINT8),
SLE_VAR(Player,cargo_types, SLE_UINT16),
diff --git a/table/engines.h b/table/engines.h
index f329aea1f..23b0daf57 100644
--- a/table/engines.h
+++ b/table/engines.h
@@ -9,9 +9,18 @@
/** Writes the properties of a vehicle into the EngineInfo struct.
* @see EngineInfo
+ * @param a Introduction date
+ * @param e Rail Type of the vehicle
+ * @param f Bitmask of the climates
*/
-
#define MK(a,b,c,d,e,f) {a,b,c,d,((e)<<4)|(f)}
+/** Writes the properties of a train carriage into the EngineInfo struct.
+ * @see EngineInfo
+ * @param a Introduction date
+ * @param e Rail Type of the vehicle
+ * @param f Bitmask of the climates
+ * @note the 0x80 in parameter b sets the "is carriage bit"
+ */
#define MW(a,b,c,d,e,f) {a,b|0x80,c,d,((e)<<4)|(f)}
EngineInfo _engine_info[TOTAL_NUM_ENGINES] = {
diff --git a/train_gui.c b/train_gui.c
index 9a4c15cc9..2905c554d 100644
--- a/train_gui.c
+++ b/train_gui.c
@@ -323,7 +323,7 @@ static void ShowBuildTrainWindow(TileIndex tile)
WP(w,buildtrain_d).railtype = _m[tile].m3 & 0xF;
} else {
w->caption_color = _local_player;
- WP(w,buildtrain_d).railtype = GetPlayer(_local_player)->max_railtype - 1;
+ WP(w,buildtrain_d).railtype = GetBestRailtype(GetPlayer(_local_player));
}
}
diff --git a/vehicle.h b/vehicle.h
index 4460a890f..a68a234bd 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -435,7 +435,7 @@ static inline Vehicle *GetFirstVehicleFromSharedList(Vehicle *v)
}
/* Validate functions for rail building */
-static inline bool ValParamRailtype(uint32 rail) { return rail <= GetPlayer(_current_player)->max_railtype;}
+static inline bool ValParamRailtype(uint32 rail) { return HASBIT(GetPlayer(_current_player)->avail_railtypes, rail);}
// NOSAVE: Can be regenerated by inspecting the vehicles.
VARDEF VehicleID _vehicle_position_hash[0x1000];