1 /* $Id$ */ |
|
2 |
|
3 /** @file player.h */ |
|
4 |
|
5 #ifndef PLAYER_H |
|
6 #define PLAYER_H |
|
7 |
|
8 #include "oldpool.h" |
|
9 #include "aystar.h" |
|
10 #include "rail.h" |
|
11 #include "road.h" |
|
12 #include "engine.h" |
|
13 #include "livery.h" |
|
14 #include "genworld.h" |
|
15 #include "gfx.h" |
|
16 |
|
17 struct PlayerEconomyEntry { |
|
18 Money income; |
|
19 Money expenses; |
|
20 int32 delivered_cargo; |
|
21 int32 performance_history; ///< player score (scale 0-1000) |
|
22 Money company_value; |
|
23 }; |
|
24 |
|
25 struct AiBuildRec { |
|
26 TileIndex spec_tile; |
|
27 TileIndex use_tile; |
|
28 byte rand_rng; |
|
29 byte cur_building_rule; |
|
30 byte unk6; |
|
31 byte unk7; |
|
32 byte buildcmd_a; |
|
33 byte buildcmd_b; |
|
34 byte direction; |
|
35 CargoID cargo; |
|
36 }; |
|
37 |
|
38 struct PlayerAI { |
|
39 byte state; |
|
40 byte tick; ///< Used to determine how often to move |
|
41 uint32 state_counter; ///< Can hold tile index! |
|
42 uint16 timeout_counter; |
|
43 |
|
44 byte state_mode; |
|
45 byte banned_tile_count; |
|
46 RailTypeByte railtype_to_use; |
|
47 |
|
48 CargoID cargo_type; |
|
49 byte num_wagons; |
|
50 byte build_kind; |
|
51 byte num_build_rec; |
|
52 byte num_loco_to_build; |
|
53 byte num_want_fullload; |
|
54 |
|
55 byte route_type_mask; |
|
56 |
|
57 TileIndex start_tile_a; |
|
58 TileIndex cur_tile_a; |
|
59 DiagDirectionByte cur_dir_a; |
|
60 DiagDirectionByte start_dir_a; |
|
61 |
|
62 TileIndex start_tile_b; |
|
63 TileIndex cur_tile_b; |
|
64 DiagDirectionByte cur_dir_b; |
|
65 DiagDirectionByte start_dir_b; |
|
66 |
|
67 Vehicle *cur_veh; ///< only used by some states |
|
68 |
|
69 AiBuildRec src, dst, mid1, mid2; |
|
70 |
|
71 VehicleID wagon_list[9]; |
|
72 byte order_list_blocks[20]; |
|
73 |
|
74 TileIndex banned_tiles[16]; |
|
75 byte banned_val[16]; |
|
76 }; |
|
77 |
|
78 struct Ai_PathFinderInfo { |
|
79 TileIndex start_tile_tl; ///< tl = top-left |
|
80 TileIndex start_tile_br; ///< br = bottom-right |
|
81 TileIndex end_tile_tl; ///< tl = top-left |
|
82 TileIndex end_tile_br; ///< br = bottom-right |
|
83 DiagDirection start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION |
|
84 DiagDirection end_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION |
|
85 |
|
86 TileIndex route[500]; |
|
87 byte route_extra[500]; ///< Some extra information about the route like bridge/tunnel |
|
88 int route_length; |
|
89 int position; ///< Current position in the build-path, needed to build the path |
|
90 |
|
91 bool rail_or_road; ///< true = rail, false = road |
|
92 }; |
|
93 |
|
94 /* The amount of memory reserved for the AI-special-vehicles */ |
|
95 #define AI_MAX_SPECIAL_VEHICLES 100 |
|
96 |
|
97 struct Ai_SpecialVehicle { |
|
98 VehicleID veh_id; |
|
99 uint32 flag; |
|
100 }; |
|
101 |
|
102 struct PlayerAiNew { |
|
103 uint8 state; |
|
104 uint tick; |
|
105 uint idle; |
|
106 |
|
107 int temp; ///< A value used in more than one function, but it just temporary |
|
108 ///< The use is pretty simple: with this we can 'think' about stuff |
|
109 ///< in more than one tick, and more than one AI. A static will not |
|
110 ///< do, because they are not saved. This way, the AI is almost human ;) |
|
111 int counter; ///< For the same reason as temp, we have counter. It can count how |
|
112 ///< long we are trying something, and just abort if it takes too long |
|
113 |
|
114 /* Pathfinder stuff */ |
|
115 Ai_PathFinderInfo path_info; |
|
116 AyStar *pathfinder; |
|
117 |
|
118 /* Route stuff */ |
|
119 |
|
120 CargoID cargo; |
|
121 byte tbt; ///< train/bus/truck 0/1/2 AI_TRAIN/AI_BUS/AI_TRUCK |
|
122 Money new_cost; |
|
123 |
|
124 byte action; |
|
125 |
|
126 int last_id; ///< here is stored the last id of the searched city/industry |
|
127 Date last_vehiclecheck_date; // Used in CheckVehicle |
|
128 Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; ///< Some vehicles have some special flags |
|
129 |
|
130 TileIndex from_tile; |
|
131 TileIndex to_tile; |
|
132 |
|
133 DiagDirectionByte from_direction; |
|
134 DiagDirectionByte to_direction; |
|
135 |
|
136 bool from_deliver; ///< True if this is the station that GIVES cargo |
|
137 bool to_deliver; |
|
138 |
|
139 TileIndex depot_tile; |
|
140 DiagDirectionByte depot_direction; |
|
141 |
|
142 byte amount_veh; ///< How many vehicles we are going to build in this route |
|
143 byte cur_veh; ///< How many vehicles did we bought? |
|
144 VehicleID veh_id; ///< Used when bought a vehicle |
|
145 VehicleID veh_main_id; ///< The ID of the first vehicle, for shared copy |
|
146 |
|
147 int from_ic; ///< ic = industry/city. This is the ID of them |
|
148 byte from_type; ///< AI_NO_TYPE/AI_CITY/AI_INDUSTRY |
|
149 int to_ic; |
|
150 byte to_type; |
|
151 |
|
152 }; |
|
153 |
|
154 |
|
155 /* The "steps" in loan size, in British Pounds! */ |
|
156 enum { |
|
157 LOAN_INTERVAL = 10000, |
|
158 LOAN_INTERVAL_OLD_AI = 50000, |
|
159 }; |
|
160 |
|
161 struct Player { |
|
162 uint32 name_2; |
|
163 uint16 name_1; |
|
164 |
|
165 uint16 president_name_1; |
|
166 uint32 president_name_2; |
|
167 |
|
168 PlayerFace face; |
|
169 |
|
170 Money player_money; |
|
171 Money current_loan; |
|
172 |
|
173 byte player_color; |
|
174 Livery livery[LS_END]; |
|
175 byte player_money_fraction; |
|
176 byte avail_railtypes; |
|
177 byte avail_roadtypes; |
|
178 byte block_preview; |
|
179 PlayerByte index; |
|
180 |
|
181 uint16 cargo_types; ///< which cargo types were transported the last year |
|
182 |
|
183 TileIndex location_of_house; |
|
184 TileIndex last_build_coordinate; |
|
185 |
|
186 PlayerByte share_owners[4]; |
|
187 |
|
188 Year inaugurated_year; |
|
189 byte num_valid_stat_ent; |
|
190 |
|
191 byte quarters_of_bankrupcy; |
|
192 byte bankrupt_asked; ///< which players were asked about buying it? |
|
193 int16 bankrupt_timeout; |
|
194 Money bankrupt_value; |
|
195 |
|
196 bool is_active; |
|
197 bool is_ai; |
|
198 PlayerAI ai; |
|
199 PlayerAiNew ainew; |
|
200 |
|
201 Money yearly_expenses[3][13]; |
|
202 PlayerEconomyEntry cur_economy; |
|
203 PlayerEconomyEntry old_economy[24]; |
|
204 EngineRenewList engine_renew_list; ///< Defined later |
|
205 bool engine_renew; |
|
206 bool renew_keep_length; |
|
207 int16 engine_renew_months; |
|
208 uint32 engine_renew_money; |
|
209 uint16 num_engines[TOTAL_NUM_ENGINES]; ///< caches the number of engines of each type the player owns (no need to save this) |
|
210 }; |
|
211 |
|
212 uint16 GetDrawStringPlayerColor(PlayerID player); |
|
213 |
|
214 void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player); |
|
215 void GetNameOfOwner(Owner owner, TileIndex tile); |
|
216 Money CalculateCompanyValue(const Player *p); |
|
217 void InvalidatePlayerWindows(const Player *p); |
|
218 void SetLocalPlayer(PlayerID new_player); |
|
219 #define FOR_ALL_PLAYERS(p) for (p = _players; p != endof(_players); p++) |
|
220 |
|
221 VARDEF PlayerByte _local_player; |
|
222 VARDEF PlayerByte _current_player; |
|
223 |
|
224 VARDEF Player _players[MAX_PLAYERS]; |
|
225 /* NOSAVE: can be determined from player structs */ |
|
226 VARDEF byte _player_colors[MAX_PLAYERS]; |
|
227 |
|
228 static inline byte ActivePlayerCount() |
|
229 { |
|
230 const Player *p; |
|
231 byte count = 0; |
|
232 |
|
233 FOR_ALL_PLAYERS(p) { |
|
234 if (p->is_active) count++; |
|
235 } |
|
236 |
|
237 return count; |
|
238 } |
|
239 |
|
240 static inline Player *GetPlayer(PlayerID i) |
|
241 { |
|
242 assert(IsInsideBS(i, PLAYER_FIRST, lengthof(_players))); |
|
243 return &_players[i]; |
|
244 } |
|
245 |
|
246 static inline bool IsLocalPlayer() |
|
247 { |
|
248 return _local_player == _current_player; |
|
249 } |
|
250 |
|
251 static inline bool IsValidPlayer(PlayerID pi) |
|
252 { |
|
253 return IsInsideBS(pi, PLAYER_FIRST, MAX_PLAYERS); |
|
254 } |
|
255 |
|
256 byte GetPlayerRailtypes(PlayerID p); |
|
257 byte GetPlayerRoadtypes(PlayerID p); |
|
258 |
|
259 /** Finds out if a Player has a certain railtype available |
|
260 * @param p Player in question |
|
261 * @param Railtype requested RailType |
|
262 * @return true if player has requested RailType available |
|
263 */ |
|
264 static inline bool HasRailtypeAvail(const Player *p, const RailType Railtype) |
|
265 { |
|
266 return HasBit(p->avail_railtypes, Railtype); |
|
267 } |
|
268 |
|
269 /** Finds out, whether given player has all given RoadTypes available |
|
270 * @param PlayerID ID of player |
|
271 * @param rts RoadTypes to test |
|
272 * @return true if player has all requested RoadTypes available |
|
273 */ |
|
274 static inline bool HasRoadTypesAvail(const PlayerID p, const RoadTypes rts) |
|
275 { |
|
276 RoadTypes avail_roadtypes; |
|
277 |
|
278 if (p == OWNER_TOWN || _game_mode == GM_EDITOR || IsGeneratingWorld()) { |
|
279 avail_roadtypes = ROADTYPES_ROAD; |
|
280 } else { |
|
281 if (!IsValidPlayer(p)) return false; |
|
282 avail_roadtypes = (RoadTypes)GetPlayer(p)->avail_roadtypes | ROADTYPES_ROAD; // road is available for always for everybody |
|
283 } |
|
284 return (rts & ~avail_roadtypes) == 0; |
|
285 } |
|
286 |
|
287 static inline bool IsHumanPlayer(PlayerID pi) |
|
288 { |
|
289 return !GetPlayer(pi)->is_ai; |
|
290 } |
|
291 |
|
292 static inline bool IsInteractivePlayer(PlayerID pi) |
|
293 { |
|
294 return pi == _local_player; |
|
295 } |
|
296 |
|
297 void DrawPlayerIcon(PlayerID p, int x, int y); |
|
298 |
|
299 /* Validate functions for rail building */ |
|
300 static inline bool ValParamRailtype(const uint32 rail) { return HasBit(GetPlayer(_current_player)->avail_railtypes, rail);} |
|
301 |
|
302 /* Validate functions for road building */ |
|
303 static inline bool ValParamRoadType(const RoadType rt) { return HasRoadTypesAvail(_current_player, RoadTypeToRoadTypes(rt));} |
|
304 |
|
305 /** Returns the "best" railtype a player can build. |
|
306 * As the AI doesn't know what the BEST one is, we have our own priority list |
|
307 * here. When adding new railtypes, modify this function |
|
308 * @param p the player "in action" |
|
309 * @return The "best" railtype a player has available |
|
310 */ |
|
311 static inline RailType GetBestRailtype(const Player *p) |
|
312 { |
|
313 if (HasRailtypeAvail(p, RAILTYPE_MAGLEV)) return RAILTYPE_MAGLEV; |
|
314 if (HasRailtypeAvail(p, RAILTYPE_MONO)) return RAILTYPE_MONO; |
|
315 if (HasRailtypeAvail(p, RAILTYPE_ELECTRIC)) return RAILTYPE_ELECTRIC; |
|
316 return RAILTYPE_RAIL; |
|
317 } |
|
318 |
|
319 struct HighScore { |
|
320 char company[100]; |
|
321 StringID title; ///< NO_SAVE, has troubles with changing string-numbers. |
|
322 uint16 score; ///< do NOT change type, will break hs.dat |
|
323 }; |
|
324 |
|
325 VARDEF HighScore _highscore_table[5][5]; // 4 difficulty-settings (+ network); top 5 |
|
326 void SaveToHighScore(); |
|
327 void LoadFromHighScore(); |
|
328 int8 SaveHighScoreValue(const Player *p); |
|
329 int8 SaveHighScoreValueNetwork(); |
|
330 |
|
331 /* Engine Replacement Functions */ |
|
332 |
|
333 /** |
|
334 * Remove all engine replacement settings for the given player. |
|
335 * @param p Player. |
|
336 */ |
|
337 static inline void RemoveAllEngineReplacementForPlayer(Player *p) { RemoveAllEngineReplacement(&p->engine_renew_list); } |
|
338 |
|
339 /** |
|
340 * Retrieve the engine replacement for the given player and original engine type. |
|
341 * @param p Player. |
|
342 * @param engine Engine type. |
|
343 * @return The engine type to replace with, or INVALID_ENGINE if no |
|
344 * replacement is in the list. |
|
345 */ |
|
346 static inline EngineID EngineReplacementForPlayer(const Player *p, EngineID engine, GroupID group) { return EngineReplacement(p->engine_renew_list, engine, group); } |
|
347 |
|
348 /** |
|
349 * Check if a player has a replacement set up for the given engine. |
|
350 * @param p Player. |
|
351 * @param engine Engine type to be replaced. |
|
352 * @return true if a replacement was set up, false otherwise. |
|
353 */ |
|
354 static inline bool EngineHasReplacementForPlayer(const Player *p, EngineID engine, GroupID group) { return EngineReplacementForPlayer(p, engine, group) != INVALID_ENGINE; } |
|
355 |
|
356 /** |
|
357 * Add an engine replacement for the player. |
|
358 * @param p Player. |
|
359 * @param old_engine The original engine type. |
|
360 * @param new_engine The replacement engine type. |
|
361 * @param flags The calling command flags. |
|
362 * @return 0 on success, CMD_ERROR on failure. |
|
363 */ |
|
364 static inline CommandCost 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); } |
|
365 |
|
366 /** |
|
367 * Remove an engine replacement for the player. |
|
368 * @param p Player. |
|
369 * @param engine The original engine type. |
|
370 * @param flags The calling command flags. |
|
371 * @return 0 on success, CMD_ERROR on failure. |
|
372 */ |
|
373 static inline CommandCost RemoveEngineReplacementForPlayer(Player *p, EngineID engine, GroupID group, uint32 flags) {return RemoveEngineReplacement(&p->engine_renew_list, engine, group, flags); } |
|
374 |
|
375 /** |
|
376 * Reset the livery schemes to the player's primary colour. |
|
377 * This is used on loading games without livery information and on new player start up. |
|
378 * @param p Player to reset. |
|
379 */ |
|
380 void ResetPlayerLivery(Player *p); |
|
381 |
|
382 #endif /* PLAYER_H */ |
|