tron@2186: /* $Id$ */ tron@2186: belugas@6352: /** @file player.h */ belugas@6352: 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: rubidium@6248: struct PlayerEconomyEntry { truelight@0: int32 income; truelight@0: int32 expenses; truelight@0: int32 delivered_cargo; belugas@6352: int32 performance_history; ///< player score (scale 0-1000) truelight@200: int64 company_value; rubidium@6248: }; truelight@0: rubidium@6248: 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; rubidium@6248: }; truelight@0: rubidium@6248: struct PlayerAI { truelight@0: byte state; belugas@6352: byte tick; ///< Used to determine how often to move belugas@6352: 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; rubidium@5587: RailTypeByte 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: belugas@6352: 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]; rubidium@6248: }; truelight@0: rubidium@6248: struct Ai_PathFinderInfo { belugas@6352: TileIndex start_tile_tl; ///< tl = top-left belugas@6352: TileIndex start_tile_br; ///< br = bottom-right belugas@6352: TileIndex end_tile_tl; ///< tl = top-left belugas@6352: TileIndex end_tile_br; ///< br = bottom-right belugas@6352: byte start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION belugas@6352: byte end_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION truelight@84: truelight@84: TileIndex route[500]; belugas@6352: byte route_extra[500]; ///< Some extra information about the route like bridge/tunnel truelight@84: int route_length; belugas@6352: int position; ///< Current position in the build-path, needed to build the path truelight@145: belugas@6352: bool rail_or_road; ///< true = rail, false = road rubidium@6248: }; truelight@84: belugas@6352: /* The amount of memory reserved for the AI-special-vehicles */ truelight@145: #define AI_MAX_SPECIAL_VEHICLES 100 truelight@145: rubidium@6248: struct Ai_SpecialVehicle { truelight@145: VehicleID veh_id; truelight@145: uint32 flag; rubidium@6248: }; truelight@145: rubidium@6248: struct PlayerAiNew { truelight@84: uint8 state; truelight@84: uint tick; truelight@84: uint idle; truelight@145: belugas@6352: int temp; ///< A value used in more than one function, but it just temporary belugas@6352: ///< The use is pretty simple: with this we can 'think' about stuff belugas@6352: ///< in more than one tick, and more than one AI. A static will not belugas@6352: ///< do, because they are not saved. This way, the AI is almost human ;) belugas@6352: int counter; ///< For the same reason as temp, we have counter. It can count how belugas@6352: ///< long we are trying something, and just abort if it takes too long truelight@145: belugas@6352: /* Pathfinder stuff */ truelight@84: Ai_PathFinderInfo path_info; truelight@84: AyStar *pathfinder; truelight@145: belugas@6352: /* Route stuff */ truelight@145: Darkvater@3344: CargoID cargo; belugas@6352: 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: belugas@6352: int last_id; ///< here is stored the last id of the searched city/industry rubidium@4289: Date last_vehiclecheck_date; // Used in CheckVehicle belugas@6352: 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: belugas@6352: bool from_deliver; ///< True if this is the station that GIVES cargo truelight@84: bool to_deliver; truelight@145: truelight@84: TileIndex depot_tile; rubidium@5587: DiagDirectionByte depot_direction; truelight@145: belugas@6352: byte amount_veh; ///< How many vehicles we are going to build in this route belugas@6352: byte cur_veh; ///< How many vehicles did we bought? belugas@6352: VehicleID veh_id; ///< Used when bought a vehicle belugas@6352: VehicleID veh_main_id; ///< The ID of the first vehicle, for shared copy truelight@145: belugas@6352: int from_ic; ///< ic = industry/city. This is the ID of them belugas@6352: byte from_type; ///< AI_NO_TYPE/AI_CITY/AI_INDUSTRY truelight@84: int to_ic; truelight@84: byte to_type; truelight@145: rubidium@6248: }; truelight@84: truelight@84: rubidium@6909: /* The "steps" in loan size, in British Pounds! */ rubidium@6909: enum { rubidium@6909: LOAN_INTERVAL = 10000, rubidium@6909: LOAN_INTERVAL_OLD_AI = 50000, rubidium@6909: }; rubidium@6909: rubidium@6190: typedef uint32 PlayerFace; truelight@84: rubidium@6248: 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: rubidium@6190: PlayerFace face; truelight@0: truelight@0: int32 player_money; truelight@0: int32 current_loan; belugas@6352: 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; rubidium@6685: byte avail_roadtypes; truelight@0: byte block_preview; rubidium@5587: PlayerByte index; truelight@0: belugas@6352: 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: rubidium@5587: PlayerByte 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; belugas@6352: 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]; belugas@6352: 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; belugas@6352: uint16 num_engines[TOTAL_NUM_ENGINES]; ///< caches the number of engines of each type the player owns (no need to save this) rubidium@6248: }; 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@5376: 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: truelight@0: VARDEF Player _players[MAX_PLAYERS]; belugas@6352: /* NOSAVE: can be determined from player structs */ tron@2154: VARDEF byte _player_colors[MAX_PLAYERS]; truelight@0: rubidium@6247: static inline byte ActivePlayerCount() 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: { KUDr@5729: assert(IS_INSIDE_1D(i, PLAYER_FIRST, lengthof(_players))); Darkvater@2425: return &_players[i]; Darkvater@2425: } Darkvater@2425: rubidium@6247: static inline bool IsLocalPlayer() Darkvater@2425: { Darkvater@2425: return _local_player == _current_player; tron@1767: } tron@1767: Darkvater@4850: static inline bool IsValidPlayer(PlayerID pi) Darkvater@4850: { KUDr@5729: return IS_INSIDE_1D(pi, PLAYER_FIRST, MAX_PLAYERS); Darkvater@4850: } Darkvater@4850: tron@2544: byte GetPlayerRailtypes(PlayerID p); rubidium@6685: byte GetPlayerRoadtypes(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: maedhros@5750: void DrawPlayerIcon(PlayerID p, int x, int y); maedhros@5750: 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: rubidium@6248: struct HighScore { darkvater@983: char company[100]; belugas@6352: StringID title; ///< NO_SAVE, has troubles with changing string-numbers. belugas@6352: uint16 score; ///< do NOT change type, will break hs.dat rubidium@6248: }; darkvater@983: darkvater@998: VARDEF HighScore _highscore_table[5][5]; // 4 difficulty-settings (+ network); top 5 rubidium@6247: void SaveToHighScore(); rubidium@6247: void LoadFromHighScore(); darkvater@998: int8 SaveHighScoreValue(const Player *p); rubidium@6247: int8 SaveHighScoreValueNetwork(); 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: */ rubidium@6643: static inline EngineID EngineReplacementForPlayer(const Player *p, EngineID engine, GroupID group) { return EngineReplacement(p->engine_renew_list, engine, group); } 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: */ rubidium@6643: static inline bool EngineHasReplacementForPlayer(const Player *p, EngineID engine, GroupID group) { return EngineReplacementForPlayer(p, engine, group) != 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: */ rubidium@6643: static inline int32 AddEngineReplacementForPlayer(Player *p, EngineID old_engine, EngineID new_engine, GroupID group, uint32 flags) { return AddEngineReplacement(&p->engine_renew_list, old_engine, new_engine, group, 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: */ rubidium@6643: static inline int32 RemoveEngineReplacementForPlayer(Player *p, EngineID engine, GroupID group, uint32 flags) {return RemoveEngineReplacement(&p->engine_renew_list, engine, group, 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 */