tron@2186: /* $Id$ */ tron@2186: truelight@0: #ifndef PLAYER_H truelight@0: #define PLAYER_H truelight@0: matthijs@5216: #include "oldpool.h" truelight@84: #include "aystar.h" celestar@2147: #include "rail.h" peter1138@2573: #include "engine.h" peter1138@4603: #include "livery.h" truelight@84: truelight@0: typedef struct PlayerEconomyEntry { truelight@0: int32 income; truelight@0: int32 expenses; truelight@0: int32 delivered_cargo; rubidium@4344: int32 performance_history; // player score (scale 0-1000) truelight@200: int64 company_value; truelight@0: } PlayerEconomyEntry; truelight@0: truelight@0: typedef struct AiBuildRec { truelight@0: TileIndex spec_tile; truelight@0: TileIndex use_tile; truelight@0: byte rand_rng; truelight@0: byte cur_building_rule; truelight@0: byte unk6; truelight@0: byte unk7; truelight@0: byte buildcmd_a; truelight@0: byte buildcmd_b; truelight@0: byte direction; Darkvater@3344: CargoID cargo; truelight@0: } AiBuildRec; truelight@0: truelight@0: typedef struct PlayerAI { truelight@0: byte state; rubidium@4344: byte tick; // Used to determine how often to move pasky@1576: uint32 state_counter; // Can hold tile index! truelight@0: uint16 timeout_counter; truelight@0: truelight@0: byte state_mode; truelight@0: byte banned_tile_count; truelight@0: byte railtype_to_use; truelight@0: Darkvater@3344: CargoID cargo_type; truelight@0: byte num_wagons; truelight@0: byte build_kind; truelight@0: byte num_build_rec; truelight@0: byte num_loco_to_build; truelight@0: byte num_want_fullload; truelight@0: truelight@0: byte route_type_mask; truelight@0: truelight@0: TileIndex start_tile_a; truelight@0: TileIndex cur_tile_a; truelight@0: byte cur_dir_a; truelight@0: byte start_dir_a; truelight@145: truelight@0: TileIndex start_tile_b; truelight@0: TileIndex cur_tile_b; truelight@0: byte cur_dir_b; truelight@0: byte start_dir_b; truelight@0: truelight@0: Vehicle *cur_veh; /* only used by some states */ truelight@145: truelight@0: AiBuildRec src, dst, mid1, mid2; truelight@145: truelight@0: VehicleID wagon_list[9]; truelight@0: byte order_list_blocks[20]; truelight@145: truelight@0: TileIndex banned_tiles[16]; truelight@0: byte banned_val[16]; truelight@0: } PlayerAI; truelight@0: truelight@84: typedef struct Ai_PathFinderInfo { truelight@84: TileIndex start_tile_tl; // tl = top-left truelight@84: TileIndex start_tile_br; // br = bottom-right rubidium@4344: TileIndex end_tile_tl; // tl = top-left rubidium@4344: TileIndex end_tile_br; // br = bottom-right rubidium@4344: byte start_direction; // 0 to 3 or AI_PATHFINDER_NO_DIRECTION rubidium@4344: byte end_direction; // 0 to 3 or AI_PATHFINDER_NO_DIRECTION truelight@84: truelight@84: TileIndex route[500]; rubidium@4344: byte route_extra[500]; // Some extra information about the route like bridge/tunnel truelight@84: int route_length; rubidium@4344: int position; // Current position in the build-path, needed to build the path truelight@145: rubidium@4344: bool rail_or_road; // true = rail, false = road truelight@84: } Ai_PathFinderInfo; truelight@84: truelight@145: // The amount of memory reserved for the AI-special-vehicles truelight@145: #define AI_MAX_SPECIAL_VEHICLES 100 truelight@145: truelight@145: typedef struct Ai_SpecialVehicle { truelight@145: VehicleID veh_id; truelight@145: uint32 flag; truelight@145: } Ai_SpecialVehicle; truelight@145: truelight@84: typedef struct PlayerAiNew { truelight@84: uint8 state; truelight@84: uint tick; truelight@84: uint idle; truelight@145: rubidium@4344: int temp; // A value used in more than one function, but it just temporary rubidium@4344: // The use is pretty simple: with this we can 'think' about stuff rubidium@4344: // in more than one tick, and more than one AI. A static will not rubidium@4344: // do, because they are not saved. This way, the AI is almost human ;) rubidium@4344: int counter; // For the same reason as temp, we have counter. It can count how rubidium@4344: // long we are trying something, and just abort if it takes too long truelight@145: truelight@84: // Pathfinder stuff truelight@84: Ai_PathFinderInfo path_info; truelight@84: AyStar *pathfinder; truelight@145: truelight@84: // Route stuff truelight@145: Darkvater@3344: CargoID cargo; truelight@84: byte tbt; // train/bus/truck 0/1/2 AI_TRAIN/AI_BUS/AI_TRUCK truelight@84: int new_cost; truelight@145: truelight@84: byte action; truelight@145: truelight@990: int last_id; // here is stored the last id of the searched city/industry rubidium@4289: Date last_vehiclecheck_date; // Used in CheckVehicle truelight@145: Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; // Some vehicles have some special flags truelight@145: truelight@84: TileIndex from_tile; truelight@84: TileIndex to_tile; truelight@145: truelight@84: byte from_direction; truelight@84: byte to_direction; truelight@145: truelight@84: bool from_deliver; // True if this is the station that GIVES cargo truelight@84: bool to_deliver; truelight@145: truelight@84: TileIndex depot_tile; truelight@84: byte depot_direction; truelight@145: rubidium@4344: byte amount_veh; // How many vehicles we are going to build in this route rubidium@4344: byte cur_veh; // How many vehicles did we bought? rubidium@4344: VehicleID veh_id; // Used when bought a vehicle truelight@84: VehicleID veh_main_id; // The ID of the first vehicle, for shared copy truelight@145: rubidium@4344: int from_ic; // ic = industry/city. This is the ID of them rubidium@4344: byte from_type; // AI_NO_TYPE/AI_CITY/AI_INDUSTRY truelight@84: int to_ic; truelight@84: byte to_type; truelight@145: truelight@84: } PlayerAiNew; truelight@84: truelight@84: truelight@84: truelight@0: typedef struct Player { truelight@0: uint32 name_2; truelight@0: uint16 name_1; truelight@0: truelight@0: uint16 president_name_1; truelight@0: uint32 president_name_2; truelight@0: truelight@0: uint32 face; truelight@0: truelight@0: int32 player_money; truelight@0: int32 current_loan; truelight@0: int64 money64; // internal 64-bit version of the money. the 32-bit field will be clamped to plus minus 2 billion truelight@0: truelight@0: byte player_color; peter1138@4603: Livery livery[LS_END]; truelight@0: byte player_money_fraction; celestar@2147: byte avail_railtypes; truelight@0: byte block_preview; Darkvater@1786: PlayerID index; truelight@0: truelight@0: uint16 cargo_types; /* which cargo types were transported the last year */ truelight@0: truelight@0: TileIndex location_of_house; truelight@0: TileIndex last_build_coordinate; truelight@145: Darkvater@2436: PlayerID share_owners[4]; truelight@145: rubidium@4326: Year inaugurated_year; truelight@0: byte num_valid_stat_ent; truelight@145: truelight@0: byte quarters_of_bankrupcy; truelight@0: byte bankrupt_asked; // which players were asked about buying it? truelight@0: int16 bankrupt_timeout; truelight@0: int32 bankrupt_value; truelight@0: truelight@0: bool is_active; Darkvater@3345: bool is_ai; truelight@0: PlayerAI ai; truelight@84: PlayerAiNew ainew; truelight@145: truelight@0: int64 yearly_expenses[3][13]; truelight@0: PlayerEconomyEntry cur_economy; truelight@0: PlayerEconomyEntry old_economy[24]; peter1138@2848: EngineRenewList engine_renew_list; // Defined later bjarni@2293: bool engine_renew; bjarni@2617: bool renew_keep_length; bjarni@2293: int16 engine_renew_months; bjarni@2293: uint32 engine_renew_money; bjarni@4574: uint16 num_engines[TOTAL_NUM_ENGINES]; // caches the number of engines of each type the player owns (no need to save this) truelight@0: } Player; truelight@0: tron@4428: uint16 GetDrawStringPlayerColor(PlayerID player); tron@4428: Darkvater@2436: void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player); Darkvater@4849: void GetNameOfOwner(Owner owner, TileIndex tile); tron@2475: int64 CalculateCompanyValue(const Player* p); tron@2475: void InvalidatePlayerWindows(const Player* p); truelight@0: void UpdatePlayerMoney32(Player *p); rubidium@5564: void SetLocalPlayer(PlayerID new_player); tron@2952: #define FOR_ALL_PLAYERS(p) for (p = _players; p != endof(_players); p++) truelight@0: Darkvater@2425: VARDEF PlayerID _local_player; Darkvater@2425: VARDEF PlayerID _current_player; tron@2154: Darkvater@4848: /* Player identifiers All players below MAX_PLAYERS are playable Darkvater@4848: * players, above, they are special, computer controlled players */ Darkvater@4861: enum Players { Darkvater@4878: PLAYER_INACTIVE_CLIENT = 253, Darkvater@4861: PLAYER_NEW_COMPANY = 254, ///< Command 'player' in Multiplayer to create a new company Darkvater@4848: PLAYER_SPECTATOR = 255, ///< Spectator in Multiplayer or the player in the scenario editor Darkvater@4848: MAX_PLAYERS = 8, Darkvater@4848: }; Darkvater@4848: truelight@0: VARDEF Player _players[MAX_PLAYERS]; tron@2154: // NOSAVE: can be determined from player structs tron@2154: VARDEF byte _player_colors[MAX_PLAYERS]; truelight@0: Darkvater@4824: static inline byte ActivePlayerCount(void) Darkvater@4824: { Darkvater@4824: const Player *p; Darkvater@4824: byte count = 0; Darkvater@4824: Darkvater@4824: FOR_ALL_PLAYERS(p) { Darkvater@4824: if (p->is_active) count++; Darkvater@4824: } Darkvater@4824: Darkvater@4824: return count; Darkvater@4824: } Darkvater@2944: Darkvater@2436: static inline Player* GetPlayer(PlayerID i) tron@1767: { Darkvater@2425: assert(i < lengthof(_players)); Darkvater@2425: return &_players[i]; Darkvater@2425: } Darkvater@2425: Darkvater@2425: static inline bool IsLocalPlayer(void) Darkvater@2425: { Darkvater@2425: return _local_player == _current_player; tron@1767: } tron@1767: Darkvater@4850: static inline bool IsValidPlayer(PlayerID pi) Darkvater@4850: { Darkvater@4850: return pi < MAX_PLAYERS; Darkvater@4850: } Darkvater@4850: tron@2544: byte GetPlayerRailtypes(PlayerID p); celestar@2147: rubidium@4549: /** Finds out if a Player has a certain railtype available */ Darkvater@2436: static inline bool HasRailtypeAvail(const Player *p, RailType Railtype) celestar@2147: { celestar@2147: return HASBIT(p->avail_railtypes, Railtype); celestar@2147: } celestar@2147: Darkvater@4845: static inline bool IsHumanPlayer(PlayerID pi) Darkvater@4845: { Darkvater@4845: return !GetPlayer(pi)->is_ai; Darkvater@4845: } Darkvater@4845: Darkvater@4845: static inline bool IsInteractivePlayer(PlayerID pi) Darkvater@4845: { Darkvater@4845: return pi == _local_player; Darkvater@4845: } Darkvater@4845: tron@2154: /* Validate functions for rail building */ tron@2154: static inline bool ValParamRailtype(uint32 rail) { return HASBIT(GetPlayer(_current_player)->avail_railtypes, rail);} tron@2154: celestar@2147: /** Returns the "best" railtype a player can build. tron@4077: * As the AI doesn't know what the BEST one is, we have our own priority list tron@4077: * here. When adding new railtypes, modify this function tron@4077: * @param p the player "in action" tron@4077: * @return The "best" railtype a player has available tron@4077: */ tron@2520: static inline RailType GetBestRailtype(const Player* p) celestar@2147: { celestar@2147: if (HasRailtypeAvail(p, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV; celestar@2147: if (HasRailtypeAvail(p, RAILTYPE_MONO)) return RAILTYPE_MONO; celestar@3355: if (HasRailtypeAvail(p, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC; celestar@2147: return RAILTYPE_RAIL; celestar@2147: } celestar@2147: darkvater@983: typedef struct HighScore { darkvater@983: char company[100]; Darkvater@2613: StringID title; // NO_SAVE, has troubles with changing string-numbers. Darkvater@2613: uint16 score; // do NOT change type, will break hs.dat darkvater@983: } HighScore; darkvater@983: darkvater@998: VARDEF HighScore _highscore_table[5][5]; // 4 difficulty-settings (+ network); top 5 darkvater@983: void SaveToHighScore(void); darkvater@983: void LoadFromHighScore(void); darkvater@998: int8 SaveHighScoreValue(const Player *p); darkvater@998: int8 SaveHighScoreValueNetwork(void); darkvater@983: peter1138@2848: /* Engine Replacement Functions */ peter1138@2848: peter1138@2848: /** peter1138@2848: * Remove all engine replacement settings for the given player. peter1138@2848: * @param p Player. peter1138@2848: */ peter1138@2848: static inline void RemoveAllEngineReplacementForPlayer(Player *p) { RemoveAllEngineReplacement(&p->engine_renew_list); } peter1138@2848: peter1138@2848: /** peter1138@2848: * Retrieve the engine replacement for the given player and original engine type. peter1138@2848: * @param p Player. peter1138@2848: * @param engine Engine type. peter1138@2848: * @return The engine type to replace with, or INVALID_ENGINE if no peter1138@2848: * replacement is in the list. peter1138@2848: */ peter1138@2848: static inline EngineID EngineReplacementForPlayer(const Player *p, EngineID engine) { return EngineReplacement(p->engine_renew_list, engine); } peter1138@2848: peter1138@2848: /** peter1138@2848: * Check if a player has a replacement set up for the given engine. peter1138@2848: * @param p Player. peter1138@2848: * @param engine Engine type to be replaced. peter1138@2848: * @return true if a replacement was set up, false otherwise. peter1138@2848: */ peter1138@2848: static inline bool EngineHasReplacementForPlayer(const Player *p, EngineID engine) { return EngineReplacementForPlayer(p, engine) != INVALID_ENGINE; } peter1138@2848: peter1138@2848: /** peter1138@2848: * Add an engine replacement for the player. peter1138@2848: * @param p Player. peter1138@2848: * @param old_engine The original engine type. peter1138@2848: * @param new_engine The replacement engine type. peter1138@2848: * @param flags The calling command flags. peter1138@2848: * @return 0 on success, CMD_ERROR on failure. peter1138@2848: */ peter1138@2848: static inline int32 AddEngineReplacementForPlayer(Player *p, EngineID old_engine, EngineID new_engine, uint32 flags) { return AddEngineReplacement(&p->engine_renew_list, old_engine, new_engine, flags); } peter1138@2848: peter1138@2848: /** peter1138@2848: * Remove an engine replacement for the player. peter1138@2848: * @param p Player. peter1138@2848: * @param engine The original engine type. peter1138@2848: * @param flags The calling command flags. peter1138@2848: * @return 0 on success, CMD_ERROR on failure. peter1138@2848: */ peter1138@2848: static inline int32 RemoveEngineReplacementForPlayer(Player *p, EngineID engine, uint32 flags) {return RemoveEngineReplacement(&p->engine_renew_list, engine, flags); } peter1138@2697: peter1138@4603: /** peter1138@4603: * Reset the livery schemes to the player's primary colour. peter1138@4603: * This is used on loading games without livery information and on new player start up. peter1138@4603: * @param p Player to reset. peter1138@4603: */ peter1138@4603: void ResetPlayerLivery(Player *p); peter1138@4603: truelight@0: #endif /* PLAYER_H */