41 #include "../../player_base.h" |
41 #include "../../player_base.h" |
42 #include "../../player_func.h" |
42 #include "../../player_func.h" |
43 |
43 |
44 #include "table/strings.h" |
44 #include "table/strings.h" |
45 |
45 |
46 PlayerAiNew _players_ainew[MAX_PLAYERS]; |
46 CompanyAiNew _companies_ainew[MAX_COMPANIES]; |
47 |
47 |
48 // This function is called after StartUp. It is the init of an AI |
48 // This function is called after StartUp. It is the init of an AI |
49 static void AiNew_State_FirstTime(Player *p) |
49 static void AiNew_State_FirstTime(Company *c) |
50 { |
50 { |
51 // This assert is used to protect those function from misuse |
51 // This assert is used to protect those function from misuse |
52 // You have quickly a small mistake in the state-array |
52 // You have quickly a small mistake in the state-array |
53 // With that, everything would go wrong. Finding that, is almost impossible |
53 // With that, everything would go wrong. Finding that, is almost impossible |
54 // With this assert, that problem can never happen. |
54 // With this assert, that problem can never happen. |
55 assert(_players_ainew[p->index].state == AI_STATE_FIRST_TIME); |
55 assert(_companies_ainew[c->index].state == AI_STATE_FIRST_TIME); |
56 // We first have to init some things |
56 // We first have to init some things |
57 |
57 |
58 if (_current_player == 1) ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_IN_PROGRESS, 0, 0); |
58 if (_current_company == 1) ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_IN_PROGRESS, 0, 0); |
59 |
59 |
60 // The PathFinder (AyStar) |
60 // The PathFinder (AyStar) |
61 // TODO: Maybe when an AI goes bankrupt, this is de-init |
61 // TODO: Maybe when an AI goes bankrupt, this is de-init |
62 // or when coming from a savegame.. should be checked out! |
62 // or when coming from a savegame.. should be checked out! |
63 _players_ainew[p->index].path_info.start_tile_tl = 0; |
63 _companies_ainew[c->index].path_info.start_tile_tl = 0; |
64 _players_ainew[p->index].path_info.start_tile_br = 0; |
64 _companies_ainew[c->index].path_info.start_tile_br = 0; |
65 _players_ainew[p->index].path_info.end_tile_tl = 0; |
65 _companies_ainew[c->index].path_info.end_tile_tl = 0; |
66 _players_ainew[p->index].path_info.end_tile_br = 0; |
66 _companies_ainew[c->index].path_info.end_tile_br = 0; |
67 _players_ainew[p->index].pathfinder = new_AyStar_AiPathFinder(12, &_players_ainew[p->index].path_info); |
67 _companies_ainew[c->index].pathfinder = new_AyStar_AiPathFinder(12, &_companies_ainew[c->index].path_info); |
68 |
68 |
69 _players_ainew[p->index].idle = 0; |
69 _companies_ainew[c->index].idle = 0; |
70 _players_ainew[p->index].last_vehiclecheck_date = _date; |
70 _companies_ainew[c->index].last_vehiclecheck_date = _date; |
71 |
71 |
72 // We ALWAYS start with a bus route.. just some basic money ;) |
72 // We ALWAYS start with a bus route.. just some basic money ;) |
73 _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE; |
73 _companies_ainew[c->index].action = AI_ACTION_BUS_ROUTE; |
74 |
74 |
75 // Let's popup the news, and after that, start building.. |
75 // Let's popup the news, and after that, start building.. |
76 _players_ainew[p->index].state = AI_STATE_WAKE_UP; |
76 _companies_ainew[c->index].state = AI_STATE_WAKE_UP; |
77 } |
77 } |
78 |
78 |
79 |
79 |
80 // This function just waste some time |
80 // This function just waste some time |
81 // It keeps it more real. The AI can build on such tempo no normal user |
81 // It keeps it more real. The AI can build on such tempo no normal user |
82 // can ever keep up with that. The competitor_speed already delays a bit |
82 // can ever keep up with that. The competitor_speed already delays a bit |
83 // but after the AI finished a track it really needs to go to sleep. |
83 // but after the AI finished a track it really needs to go to sleep. |
84 // |
84 // |
85 // Let's say, we sleep between one and three days if the AI is put on Very Fast. |
85 // Let's say, we sleep between one and three days if the AI is put on Very Fast. |
86 // This means that on Very Slow it will be between 16 and 48 days.. slow enough? |
86 // This means that on Very Slow it will be between 16 and 48 days.. slow enough? |
87 static void AiNew_State_Nothing(Player *p) |
87 static void AiNew_State_Nothing(Company *c) |
88 { |
88 { |
89 assert(_players_ainew[p->index].state == AI_STATE_NOTHING); |
89 assert(_companies_ainew[c->index].state == AI_STATE_NOTHING); |
90 // If we are done idling, start over again |
90 // If we are done idling, start over again |
91 if (_players_ainew[p->index].idle == 0) _players_ainew[p->index].idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS; |
91 if (_companies_ainew[c->index].idle == 0) _companies_ainew[c->index].idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS; |
92 if (--_players_ainew[p->index].idle == 0) { |
92 if (--_companies_ainew[c->index].idle == 0) { |
93 // We are done idling.. what you say? Let's do something! |
93 // We are done idling.. what you say? Let's do something! |
94 // I mean.. the next tick ;) |
94 // I mean.. the next tick ;) |
95 _players_ainew[p->index].state = AI_STATE_WAKE_UP; |
95 _companies_ainew[c->index].state = AI_STATE_WAKE_UP; |
96 } |
96 } |
97 } |
97 } |
98 |
98 |
99 |
99 |
100 // This function picks out a task we are going to do. |
100 // This function picks out a task we are going to do. |
101 // Currently supported: |
101 // Currently supported: |
102 // - Make new route |
102 // - Make new route |
103 // - Check route |
103 // - Check route |
104 // - Build HQ |
104 // - Build HQ |
105 static void AiNew_State_WakeUp(Player *p) |
105 static void AiNew_State_WakeUp(Company *c) |
106 { |
106 { |
107 int c; |
107 assert(_companies_ainew[c->index].state == AI_STATE_WAKE_UP); |
108 assert(_players_ainew[p->index].state == AI_STATE_WAKE_UP); |
|
109 // First, check if we have a HQ |
108 // First, check if we have a HQ |
110 if (p->location_of_HQ == 0) { |
109 if (c->location_of_HQ == 0) { |
111 // We have no HQ yet, build one on a random place |
110 // We have no HQ yet, build one on a random place |
112 // Random till we found a place for it! |
111 // Random till we found a place for it! |
113 // TODO: this should not be on a random place.. |
112 // TODO: this should not be on a random place.. |
114 AiNew_Build_CompanyHQ(p, AI_Random() % MapSize()); |
113 AiNew_Build_CompanyHQ(c, AI_Random() % MapSize()); |
115 // Enough for now, but we want to come back here the next time |
114 // Enough for now, but we want to come back here the next time |
116 // so we do not change any status |
115 // so we do not change any status |
117 return; |
116 return; |
118 } |
117 } |
119 |
118 |
120 Money money = p->player_money - AI_MINIMUM_MONEY; |
119 Money money = c->money - AI_MINIMUM_MONEY; |
121 |
120 |
122 // Let's pick an action! |
121 // Let's pick an action! |
123 if (_players_ainew[p->index].action == AI_ACTION_NONE) { |
122 if (_companies_ainew[c->index].action == AI_ACTION_NONE) { |
124 c = AI_Random() & 0xFF; |
123 int r = AI_Random() & 0xFF; |
125 if (p->current_loan > 0 && |
124 if (c->current_loan > 0 && |
126 p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN && |
125 c->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN && |
127 c < 10) { |
126 r < 10) { |
128 _players_ainew[p->index].action = AI_ACTION_REPAY_LOAN; |
127 _companies_ainew[c->index].action = AI_ACTION_REPAY_LOAN; |
129 } else if (_players_ainew[p->index].last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) { |
128 } else if (_companies_ainew[c->index].last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) { |
130 // Check all vehicles once in a while |
129 // Check all vehicles once in a while |
131 _players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES; |
130 _companies_ainew[c->index].action = AI_ACTION_CHECK_ALL_VEHICLES; |
132 _players_ainew[p->index].last_vehiclecheck_date = _date; |
131 _companies_ainew[c->index].last_vehiclecheck_date = _date; |
133 } else if (c < 100 && !_settings_game.ai.ai_disable_veh_roadveh) { |
132 } else if (r < 100 && !_settings_game.ai.ai_disable_veh_roadveh) { |
134 // Do we have any spots for road-vehicles left open? |
133 // Do we have any spots for road-vehicles left open? |
135 if (GetFreeUnitNumber(VEH_ROAD) <= _settings_game.vehicle.max_roadveh) { |
134 if (GetFreeUnitNumber(VEH_ROAD) <= _settings_game.vehicle.max_roadveh) { |
136 if (c < 85) { |
135 if (r < 85) { |
137 _players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE; |
136 _companies_ainew[c->index].action = AI_ACTION_TRUCK_ROUTE; |
138 } else { |
137 } else { |
139 _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE; |
138 _companies_ainew[c->index].action = AI_ACTION_BUS_ROUTE; |
140 } |
139 } |
141 } |
140 } |
142 #if 0 |
141 #if 0 |
143 } else if (c < 200 && !_settings_game.ai.ai_disable_veh_train) { |
142 } else if (r < 200 && !_settings_game.ai.ai_disable_veh_train) { |
144 if (GetFreeUnitNumber(VEH_TRAIN) <= _settings_game.vehicle.max_trains) { |
143 if (GetFreeUnitNumber(VEH_TRAIN) <= _settings_game.vehicle.max_trains) { |
145 _players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE; |
144 _companies_ainew[c->index].action = AI_ACTION_TRAIN_ROUTE; |
146 } |
145 } |
147 #endif |
146 #endif |
148 } |
147 } |
149 |
148 |
150 _players_ainew[p->index].counter = 0; |
149 _companies_ainew[c->index].counter = 0; |
151 } |
150 } |
152 |
151 |
153 if (_players_ainew[p->index].counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) { |
152 if (_companies_ainew[c->index].counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) { |
154 _players_ainew[p->index].action = AI_ACTION_NONE; |
153 _companies_ainew[c->index].action = AI_ACTION_NONE; |
155 return; |
154 return; |
156 } |
155 } |
157 |
156 |
158 if (_settings_game.ai.ai_disable_veh_roadveh && ( |
157 if (_settings_game.ai.ai_disable_veh_roadveh && ( |
159 _players_ainew[p->index].action == AI_ACTION_BUS_ROUTE || |
158 _companies_ainew[c->index].action == AI_ACTION_BUS_ROUTE || |
160 _players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE |
159 _companies_ainew[c->index].action == AI_ACTION_TRUCK_ROUTE |
161 )) { |
160 )) { |
162 _players_ainew[p->index].action = AI_ACTION_NONE; |
161 _companies_ainew[c->index].action = AI_ACTION_NONE; |
163 return; |
162 return; |
164 } |
163 } |
165 |
164 |
166 if (_players_ainew[p->index].action == AI_ACTION_REPAY_LOAN && |
165 if (_companies_ainew[c->index].action == AI_ACTION_REPAY_LOAN && |
167 money > AI_MINIMUM_LOAN_REPAY_MONEY) { |
166 money > AI_MINIMUM_LOAN_REPAY_MONEY) { |
168 // We start repaying some money.. |
167 // We start repaying some money.. |
169 _players_ainew[p->index].state = AI_STATE_REPAY_MONEY; |
168 _companies_ainew[c->index].state = AI_STATE_REPAY_MONEY; |
170 return; |
169 return; |
171 } |
170 } |
172 |
171 |
173 if (_players_ainew[p->index].action == AI_ACTION_CHECK_ALL_VEHICLES) { |
172 if (_companies_ainew[c->index].action == AI_ACTION_CHECK_ALL_VEHICLES) { |
174 _players_ainew[p->index].state = AI_STATE_CHECK_ALL_VEHICLES; |
173 _companies_ainew[c->index].state = AI_STATE_CHECK_ALL_VEHICLES; |
175 return; |
174 return; |
176 } |
175 } |
177 |
176 |
178 // It is useless to start finding a route if we don't have enough money |
177 // It is useless to start finding a route if we don't have enough money |
179 // to build the route anyway.. |
178 // to build the route anyway.. |
180 if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE && |
179 if (_companies_ainew[c->index].action == AI_ACTION_BUS_ROUTE && |
181 money > AI_MINIMUM_BUS_ROUTE_MONEY) { |
180 money > AI_MINIMUM_BUS_ROUTE_MONEY) { |
182 if (GetFreeUnitNumber(VEH_ROAD) > _settings_game.vehicle.max_roadveh) { |
181 if (GetFreeUnitNumber(VEH_ROAD) > _settings_game.vehicle.max_roadveh) { |
183 _players_ainew[p->index].action = AI_ACTION_NONE; |
182 _companies_ainew[c->index].action = AI_ACTION_NONE; |
184 return; |
183 return; |
185 } |
184 } |
186 _players_ainew[p->index].cargo = AI_NEED_CARGO; |
185 _companies_ainew[c->index].cargo = AI_NEED_CARGO; |
187 _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE; |
186 _companies_ainew[c->index].state = AI_STATE_LOCATE_ROUTE; |
188 _players_ainew[p->index].tbt = AI_BUS; // Bus-route |
187 _companies_ainew[c->index].tbt = AI_BUS; // Bus-route |
189 return; |
188 return; |
190 } |
189 } |
191 if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE && |
190 if (_companies_ainew[c->index].action == AI_ACTION_TRUCK_ROUTE && |
192 money > AI_MINIMUM_TRUCK_ROUTE_MONEY) { |
191 money > AI_MINIMUM_TRUCK_ROUTE_MONEY) { |
193 if (GetFreeUnitNumber(VEH_ROAD) > _settings_game.vehicle.max_roadveh) { |
192 if (GetFreeUnitNumber(VEH_ROAD) > _settings_game.vehicle.max_roadveh) { |
194 _players_ainew[p->index].action = AI_ACTION_NONE; |
193 _companies_ainew[c->index].action = AI_ACTION_NONE; |
195 return; |
194 return; |
196 } |
195 } |
197 _players_ainew[p->index].cargo = AI_NEED_CARGO; |
196 _companies_ainew[c->index].cargo = AI_NEED_CARGO; |
198 _players_ainew[p->index].last_id = 0; |
197 _companies_ainew[c->index].last_id = 0; |
199 _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE; |
198 _companies_ainew[c->index].state = AI_STATE_LOCATE_ROUTE; |
200 _players_ainew[p->index].tbt = AI_TRUCK; |
199 _companies_ainew[c->index].tbt = AI_TRUCK; |
201 return; |
200 return; |
202 } |
201 } |
203 |
202 |
204 _players_ainew[p->index].state = AI_STATE_NOTHING; |
203 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
205 } |
204 } |
206 |
205 |
207 |
206 |
208 static void AiNew_State_ActionDone(Player *p) |
207 static void AiNew_State_ActionDone(Company *c) |
209 { |
208 { |
210 _players_ainew[p->index].action = AI_ACTION_NONE; |
209 _companies_ainew[c->index].action = AI_ACTION_NONE; |
211 _players_ainew[p->index].state = AI_STATE_NOTHING; |
210 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
212 } |
211 } |
213 |
212 |
214 |
213 |
215 // Check if a city or industry is good enough to start a route there |
214 // Check if a city or industry is good enough to start a route there |
216 static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) |
215 static bool AiNew_Check_City_or_Industry(Company *c, int ic, byte type) |
217 { |
216 { |
218 if (type == AI_CITY) { |
217 if (type == AI_CITY) { |
219 const Town* t = GetTown(ic); |
218 const Town* t = GetTown(ic); |
220 const Station* st; |
219 const Station* st; |
221 uint count = 0; |
220 uint count = 0; |
336 return true; |
335 return true; |
337 } |
336 } |
338 |
337 |
339 |
338 |
340 // This functions tries to locate a good route |
339 // This functions tries to locate a good route |
341 static void AiNew_State_LocateRoute(Player *p) |
340 static void AiNew_State_LocateRoute(Company *c) |
342 { |
341 { |
343 assert(_players_ainew[p->index].state == AI_STATE_LOCATE_ROUTE); |
342 assert(_companies_ainew[c->index].state == AI_STATE_LOCATE_ROUTE); |
344 // For now, we only support PASSENGERS, CITY and BUSSES |
343 // For now, we only support PASSENGERS, CITY and BUSSES |
345 |
344 |
346 // We don't have a route yet |
345 // We don't have a route yet |
347 if (_players_ainew[p->index].cargo == AI_NEED_CARGO) { |
346 if (_companies_ainew[c->index].cargo == AI_NEED_CARGO) { |
348 _players_ainew[p->index].new_cost = 0; // No cost yet |
347 _companies_ainew[c->index].new_cost = 0; // No cost yet |
349 _players_ainew[p->index].temp = -1; |
348 _companies_ainew[c->index].temp = -1; |
350 // Reset the counter |
349 // Reset the counter |
351 _players_ainew[p->index].counter = 0; |
350 _companies_ainew[c->index].counter = 0; |
352 |
351 |
353 _players_ainew[p->index].from_ic = -1; |
352 _companies_ainew[c->index].from_ic = -1; |
354 _players_ainew[p->index].to_ic = -1; |
353 _companies_ainew[c->index].to_ic = -1; |
355 if (_players_ainew[p->index].tbt == AI_BUS) { |
354 if (_companies_ainew[c->index].tbt == AI_BUS) { |
356 // For now we only have a passenger route |
355 // For now we only have a passenger route |
357 _players_ainew[p->index].cargo = CT_PASSENGERS; |
356 _companies_ainew[c->index].cargo = CT_PASSENGERS; |
358 |
357 |
359 // Find a route to cities |
358 // Find a route to cities |
360 _players_ainew[p->index].from_type = AI_CITY; |
359 _companies_ainew[c->index].from_type = AI_CITY; |
361 _players_ainew[p->index].to_type = AI_CITY; |
360 _companies_ainew[c->index].to_type = AI_CITY; |
362 } else if (_players_ainew[p->index].tbt == AI_TRUCK) { |
361 } else if (_companies_ainew[c->index].tbt == AI_TRUCK) { |
363 _players_ainew[p->index].cargo = AI_NO_CARGO; |
362 _companies_ainew[c->index].cargo = AI_NO_CARGO; |
364 |
363 |
365 _players_ainew[p->index].from_type = AI_INDUSTRY; |
364 _companies_ainew[c->index].from_type = AI_INDUSTRY; |
366 _players_ainew[p->index].to_type = AI_INDUSTRY; |
365 _companies_ainew[c->index].to_type = AI_INDUSTRY; |
367 } |
366 } |
368 |
367 |
369 // Now we are doing initing, we wait one tick |
368 // Now we are doing initing, we wait one tick |
370 return; |
369 return; |
371 } |
370 } |
372 |
371 |
373 // Increase the counter and abort if it is taking too long! |
372 // Increase the counter and abort if it is taking too long! |
374 _players_ainew[p->index].counter++; |
373 _companies_ainew[c->index].counter++; |
375 if (_players_ainew[p->index].counter > AI_LOCATE_ROUTE_MAX_COUNTER) { |
374 if (_companies_ainew[c->index].counter > AI_LOCATE_ROUTE_MAX_COUNTER) { |
376 // Switch back to doing nothing! |
375 // Switch back to doing nothing! |
377 _players_ainew[p->index].state = AI_STATE_NOTHING; |
376 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
378 return; |
377 return; |
379 } |
378 } |
380 |
379 |
381 // We are going to locate a city from where we are going to connect |
380 // We are going to locate a city from where we are going to connect |
382 if (_players_ainew[p->index].from_ic == -1) { |
381 if (_companies_ainew[c->index].from_ic == -1) { |
383 if (_players_ainew[p->index].temp == -1) { |
382 if (_companies_ainew[c->index].temp == -1) { |
384 // First, we pick a random spot to search from |
383 // First, we pick a random spot to search from |
385 if (_players_ainew[p->index].from_type == AI_CITY) { |
384 if (_companies_ainew[c->index].from_type == AI_CITY) { |
386 _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1); |
385 _companies_ainew[c->index].temp = AI_RandomRange(GetMaxTownIndex() + 1); |
387 } else { |
386 } else { |
388 _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1); |
387 _companies_ainew[c->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1); |
389 } |
388 } |
390 } |
389 } |
391 |
390 |
392 if (!AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].from_type)) { |
391 if (!AiNew_Check_City_or_Industry(c, _companies_ainew[c->index].temp, _companies_ainew[c->index].from_type)) { |
393 // It was not a valid city |
392 // It was not a valid city |
394 // increase the temp with one, and return. We will come back later here |
393 // increase the temp with one, and return. We will come back later here |
395 // to try again |
394 // to try again |
396 _players_ainew[p->index].temp++; |
395 _companies_ainew[c->index].temp++; |
397 if (_players_ainew[p->index].from_type == AI_CITY) { |
396 if (_companies_ainew[c->index].from_type == AI_CITY) { |
398 if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0; |
397 if (_companies_ainew[c->index].temp > GetMaxTownIndex()) _companies_ainew[c->index].temp = 0; |
399 } else { |
398 } else { |
400 if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0; |
399 if (_companies_ainew[c->index].temp > GetMaxIndustryIndex()) _companies_ainew[c->index].temp = 0; |
401 } |
400 } |
402 |
401 |
403 // Don't do an attempt if we are trying the same id as the last time... |
402 // Don't do an attempt if we are trying the same id as the last time... |
404 if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return; |
403 if (_companies_ainew[c->index].last_id == _companies_ainew[c->index].temp) return; |
405 _players_ainew[p->index].last_id = _players_ainew[p->index].temp; |
404 _companies_ainew[c->index].last_id = _companies_ainew[c->index].temp; |
406 |
405 |
407 return; |
406 return; |
408 } |
407 } |
409 |
408 |
410 // We found a good city/industry, save the data of it |
409 // We found a good city/industry, save the data of it |
411 _players_ainew[p->index].from_ic = _players_ainew[p->index].temp; |
410 _companies_ainew[c->index].from_ic = _companies_ainew[c->index].temp; |
412 |
411 |
413 // Start the next tick with finding a to-city |
412 // Start the next tick with finding a to-city |
414 _players_ainew[p->index].temp = -1; |
413 _companies_ainew[c->index].temp = -1; |
415 return; |
414 return; |
416 } |
415 } |
417 |
416 |
418 // Find a to-city |
417 // Find a to-city |
419 if (_players_ainew[p->index].temp == -1) { |
418 if (_companies_ainew[c->index].temp == -1) { |
420 // First, we pick a random spot to search to |
419 // First, we pick a random spot to search to |
421 if (_players_ainew[p->index].to_type == AI_CITY) { |
420 if (_companies_ainew[c->index].to_type == AI_CITY) { |
422 _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1); |
421 _companies_ainew[c->index].temp = AI_RandomRange(GetMaxTownIndex() + 1); |
423 } else { |
422 } else { |
424 _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1); |
423 _companies_ainew[c->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1); |
425 } |
424 } |
426 } |
425 } |
427 |
426 |
428 // The same city is not allowed |
427 // The same city is not allowed |
429 // Also check if the city is valid |
428 // Also check if the city is valid |
430 if (_players_ainew[p->index].temp != _players_ainew[p->index].from_ic && AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].to_type)) { |
429 if (_companies_ainew[c->index].temp != _companies_ainew[c->index].from_ic && AiNew_Check_City_or_Industry(c, _companies_ainew[c->index].temp, _companies_ainew[c->index].to_type)) { |
431 // Maybe it is valid.. |
430 // Maybe it is valid.. |
432 |
431 |
433 /* We need to know if they are not to far apart from eachother.. |
432 /* We need to know if they are not to far apart from eachother.. |
434 * We do that by checking how much cargo we have to move and how long the |
433 * We do that by checking how much cargo we have to move and how long the |
435 * route is. |
434 * route is. |
436 */ |
435 */ |
437 |
436 |
438 if (_players_ainew[p->index].from_type == AI_CITY && _players_ainew[p->index].tbt == AI_BUS) { |
437 if (_companies_ainew[c->index].from_type == AI_CITY && _companies_ainew[c->index].tbt == AI_BUS) { |
439 const Town* town_from = GetTown(_players_ainew[p->index].from_ic); |
438 const Town* town_from = GetTown(_companies_ainew[c->index].from_ic); |
440 const Town* town_temp = GetTown(_players_ainew[p->index].temp); |
439 const Town* town_temp = GetTown(_companies_ainew[c->index].temp); |
441 uint distance = DistanceManhattan(town_from->xy, town_temp->xy); |
440 uint distance = DistanceManhattan(town_from->xy, town_temp->xy); |
442 int max_cargo; |
441 int max_cargo; |
443 |
442 |
444 max_cargo = town_from->max_pass + town_temp->max_pass; |
443 max_cargo = town_from->max_pass + town_temp->max_pass; |
445 max_cargo -= town_from->act_pass + town_temp->act_pass; |
444 max_cargo -= town_from->act_pass + town_temp->act_pass; |
446 |
445 |
447 // max_cargo is now the amount of cargo we can move between the two cities |
446 // max_cargo is now the amount of cargo we can move between the two cities |
448 // If it is more than the distance, we allow it |
447 // If it is more than the distance, we allow it |
449 if (distance <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) { |
448 if (distance <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) { |
450 // We found a good city/industry, save the data of it |
449 // We found a good city/industry, save the data of it |
451 _players_ainew[p->index].to_ic = _players_ainew[p->index].temp; |
450 _companies_ainew[c->index].to_ic = _companies_ainew[c->index].temp; |
452 _players_ainew[p->index].state = AI_STATE_FIND_STATION; |
451 _companies_ainew[c->index].state = AI_STATE_FIND_STATION; |
453 |
452 |
454 DEBUG(ai, 1, "[LocateRoute] found bus-route of %d tiles long (from %d to %d)", |
453 DEBUG(ai, 1, "[LocateRoute] found bus-route of %d tiles long (from %d to %d)", |
455 distance, |
454 distance, |
456 _players_ainew[p->index].from_ic, |
455 _companies_ainew[c->index].from_ic, |
457 _players_ainew[p->index].temp |
456 _companies_ainew[c->index].temp |
458 ); |
457 ); |
459 |
458 |
460 _players_ainew[p->index].from_tile = 0; |
459 _companies_ainew[c->index].from_tile = 0; |
461 _players_ainew[p->index].to_tile = 0; |
460 _companies_ainew[c->index].to_tile = 0; |
462 |
461 |
463 return; |
462 return; |
464 } |
463 } |
465 } else if (_players_ainew[p->index].tbt == AI_TRUCK) { |
464 } else if (_companies_ainew[c->index].tbt == AI_TRUCK) { |
466 const Industry* ind_from = GetIndustry(_players_ainew[p->index].from_ic); |
465 const Industry* ind_from = GetIndustry(_companies_ainew[c->index].from_ic); |
467 const Industry* ind_temp = GetIndustry(_players_ainew[p->index].temp); |
466 const Industry* ind_temp = GetIndustry(_companies_ainew[c->index].temp); |
468 bool found = false; |
467 bool found = false; |
469 int max_cargo = 0; |
468 int max_cargo = 0; |
470 uint i; |
469 uint i; |
471 |
470 |
472 // TODO: in max_cargo, also check other cargo (beside [0]) |
471 // TODO: in max_cargo, also check other cargo (beside [0]) |
503 // Check the length against the amount of goods |
502 // Check the length against the amount of goods |
504 uint distance = DistanceManhattan(ind_from->xy, ind_temp->xy); |
503 uint distance = DistanceManhattan(ind_from->xy, ind_temp->xy); |
505 |
504 |
506 if (distance > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE && |
505 if (distance > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE && |
507 distance <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) { |
506 distance <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) { |
508 _players_ainew[p->index].to_ic = _players_ainew[p->index].temp; |
507 _companies_ainew[c->index].to_ic = _companies_ainew[c->index].temp; |
509 if (_players_ainew[p->index].from_deliver) { |
508 if (_companies_ainew[c->index].from_deliver) { |
510 _players_ainew[p->index].cargo = ind_from->produced_cargo[0]; |
509 _companies_ainew[c->index].cargo = ind_from->produced_cargo[0]; |
511 } else { |
510 } else { |
512 _players_ainew[p->index].cargo = ind_temp->produced_cargo[0]; |
511 _companies_ainew[c->index].cargo = ind_temp->produced_cargo[0]; |
513 } |
512 } |
514 _players_ainew[p->index].state = AI_STATE_FIND_STATION; |
513 _companies_ainew[c->index].state = AI_STATE_FIND_STATION; |
515 |
514 |
516 DEBUG(ai, 1, "[LocateRoute] found truck-route of %d tiles long (from %d to %d)", |
515 DEBUG(ai, 1, "[LocateRoute] found truck-route of %d tiles long (from %d to %d)", |
517 distance, |
516 distance, |
518 _players_ainew[p->index].from_ic, |
517 _companies_ainew[c->index].from_ic, |
519 _players_ainew[p->index].temp |
518 _companies_ainew[c->index].temp |
520 ); |
519 ); |
521 |
520 |
522 _players_ainew[p->index].from_tile = 0; |
521 _companies_ainew[c->index].from_tile = 0; |
523 _players_ainew[p->index].to_tile = 0; |
522 _companies_ainew[c->index].to_tile = 0; |
524 |
523 |
525 return; |
524 return; |
526 } |
525 } |
527 } |
526 } |
528 } |
527 } |
529 } |
528 } |
530 |
529 |
531 // It was not a valid city |
530 // It was not a valid city |
532 // increase the temp with one, and return. We will come back later here |
531 // increase the temp with one, and return. We will come back later here |
533 // to try again |
532 // to try again |
534 _players_ainew[p->index].temp++; |
533 _companies_ainew[c->index].temp++; |
535 if (_players_ainew[p->index].to_type == AI_CITY) { |
534 if (_companies_ainew[c->index].to_type == AI_CITY) { |
536 if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0; |
535 if (_companies_ainew[c->index].temp > GetMaxTownIndex()) _companies_ainew[c->index].temp = 0; |
537 } else { |
536 } else { |
538 if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0; |
537 if (_companies_ainew[c->index].temp > GetMaxIndustryIndex()) _companies_ainew[c->index].temp = 0; |
539 } |
538 } |
540 |
539 |
541 // Don't do an attempt if we are trying the same id as the last time... |
540 // Don't do an attempt if we are trying the same id as the last time... |
542 if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return; |
541 if (_companies_ainew[c->index].last_id == _companies_ainew[c->index].temp) return; |
543 _players_ainew[p->index].last_id = _players_ainew[p->index].temp; |
542 _companies_ainew[c->index].last_id = _companies_ainew[c->index].temp; |
544 } |
543 } |
545 |
544 |
546 |
545 |
547 // Check if there are not more than a certain amount of vehicles pointed to a certain |
546 // Check if there are not more than a certain amount of vehicles pointed to a certain |
548 // station. This to prevent 10 busses going to one station, which gives... problems ;) |
547 // station. This to prevent 10 busses going to one station, which gives... problems ;) |
549 static bool AiNew_CheckVehicleStation(Player *p, Station *st) |
548 static bool AiNew_CheckVehicleStation(Company *c, Station *st) |
550 { |
549 { |
551 int count = 0; |
550 int count = 0; |
552 Vehicle *v; |
551 Vehicle *v; |
553 |
552 |
554 // Also check if we don't have already a lot of busses to this city... |
553 // Also check if we don't have already a lot of busses to this city... |
555 FOR_ALL_VEHICLES(v) { |
554 FOR_ALL_VEHICLES(v) { |
556 if (v->owner == _current_player) { |
555 if (v->owner == _current_company) { |
557 const Order *order; |
556 const Order *order; |
558 |
557 |
559 FOR_VEHICLE_ORDERS(v, order) { |
558 FOR_VEHICLE_ORDERS(v, order) { |
560 if (order->IsType(OT_GOTO_STATION) && GetStation(order->GetDestination()) == st) { |
559 if (order->IsType(OT_GOTO_STATION) && GetStation(order->GetDestination()) == st) { |
561 // This vehicle has this city in its list |
560 // This vehicle has this city in its list |
568 if (count > AI_CHECK_MAX_VEHICLE_PER_STATION) return false; |
567 if (count > AI_CHECK_MAX_VEHICLE_PER_STATION) return false; |
569 return true; |
568 return true; |
570 } |
569 } |
571 |
570 |
572 // This function finds a good spot for a station |
571 // This function finds a good spot for a station |
573 static void AiNew_State_FindStation(Player *p) |
572 static void AiNew_State_FindStation(Company *c) |
574 { |
573 { |
575 TileIndex tile; |
574 TileIndex tile; |
576 Station *st; |
575 Station *st; |
577 int count = 0; |
576 int count = 0; |
578 EngineID i; |
577 EngineID i; |
579 TileIndex new_tile = 0; |
578 TileIndex new_tile = 0; |
580 DiagDirection direction = DIAGDIR_NE; |
579 DiagDirection direction = DIAGDIR_NE; |
581 Town *town = NULL; |
580 Town *town = NULL; |
582 assert(_players_ainew[p->index].state == AI_STATE_FIND_STATION); |
581 assert(_companies_ainew[c->index].state == AI_STATE_FIND_STATION); |
583 |
582 |
584 if (_players_ainew[p->index].from_tile == 0) { |
583 if (_companies_ainew[c->index].from_tile == 0) { |
585 // First we scan for a station in the from-city |
584 // First we scan for a station in the from-city |
586 if (_players_ainew[p->index].from_type == AI_CITY) { |
585 if (_companies_ainew[c->index].from_type == AI_CITY) { |
587 town = GetTown(_players_ainew[p->index].from_ic); |
586 town = GetTown(_companies_ainew[c->index].from_ic); |
588 tile = town->xy; |
587 tile = town->xy; |
589 } else { |
588 } else { |
590 tile = GetIndustry(_players_ainew[p->index].from_ic)->xy; |
589 tile = GetIndustry(_companies_ainew[c->index].from_ic)->xy; |
591 } |
590 } |
592 } else if (_players_ainew[p->index].to_tile == 0) { |
591 } else if (_companies_ainew[c->index].to_tile == 0) { |
593 // Second we scan for a station in the to-city |
592 // Second we scan for a station in the to-city |
594 if (_players_ainew[p->index].to_type == AI_CITY) { |
593 if (_companies_ainew[c->index].to_type == AI_CITY) { |
595 town = GetTown(_players_ainew[p->index].to_ic); |
594 town = GetTown(_companies_ainew[c->index].to_ic); |
596 tile = town->xy; |
595 tile = town->xy; |
597 } else { |
596 } else { |
598 tile = GetIndustry(_players_ainew[p->index].to_ic)->xy; |
597 tile = GetIndustry(_companies_ainew[c->index].to_ic)->xy; |
599 } |
598 } |
600 } else { |
599 } else { |
601 // Unsupported request |
600 // Unsupported request |
602 // Go to FIND_PATH |
601 // Go to FIND_PATH |
603 _players_ainew[p->index].temp = -1; |
602 _companies_ainew[c->index].temp = -1; |
604 _players_ainew[p->index].state = AI_STATE_FIND_PATH; |
603 _companies_ainew[c->index].state = AI_STATE_FIND_PATH; |
605 return; |
604 return; |
606 } |
605 } |
607 |
606 |
608 // First, we are going to look at the stations that already exist inside the city |
607 // First, we are going to look at the stations that already exist inside the city |
609 // If there is enough cargo left in the station, we take that station |
608 // If there is enough cargo left in the station, we take that station |
610 // If that is not possible, and there are more than 2 stations in the city, abort |
609 // If that is not possible, and there are more than 2 stations in the city, abort |
611 i = AiNew_PickVehicle(p); |
610 i = AiNew_PickVehicle(c); |
612 // Euhmz, this should not happen _EVER_ |
611 // Euhmz, this should not happen _EVER_ |
613 // Quit finding a route... |
612 // Quit finding a route... |
614 if (i == INVALID_ENGINE) { |
613 if (i == INVALID_ENGINE) { |
615 _players_ainew[p->index].state = AI_STATE_NOTHING; |
614 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
616 return; |
615 return; |
617 } |
616 } |
618 |
617 |
619 FOR_ALL_STATIONS(st) { |
618 FOR_ALL_STATIONS(st) { |
620 if (st->owner == _current_player) { |
619 if (st->owner == _current_company) { |
621 if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) { |
620 if (_companies_ainew[c->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) { |
622 if (st->town == town) { |
621 if (st->town == town) { |
623 // Check how much cargo there is left in the station |
622 // Check how much cargo there is left in the station |
624 if ((int)st->goods[_players_ainew[p->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) { |
623 if ((int)st->goods[_companies_ainew[c->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) { |
625 if (AiNew_CheckVehicleStation(p, st)) { |
624 if (AiNew_CheckVehicleStation(c, st)) { |
626 // We did found a station that was good enough! |
625 // We did found a station that was good enough! |
627 new_tile = st->xy; |
626 new_tile = st->xy; |
628 direction = GetRoadStopDir(st->xy); |
627 direction = GetRoadStopDir(st->xy); |
629 break; |
628 break; |
630 } |
629 } |
691 best = found_best[x]; |
690 best = found_best[x]; |
692 } |
691 } |
693 } |
692 } |
694 |
693 |
695 // See how much it is going to cost us... |
694 // See how much it is going to cost us... |
696 r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST); |
695 r = AiNew_Build_Station(c, _companies_ainew[c->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST); |
697 _players_ainew[p->index].new_cost += r.GetCost(); |
696 _companies_ainew[c->index].new_cost += r.GetCost(); |
698 |
697 |
699 direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION; |
698 direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION; |
700 } else if (new_tile == 0 && _players_ainew[p->index].tbt == AI_TRUCK) { |
699 } else if (new_tile == 0 && _companies_ainew[c->index].tbt == AI_TRUCK) { |
701 // Truck station locater works differently.. a station can be on any place |
700 // Truck station locater works differently.. a station can be on any place |
702 // as long as it is in range. So we give back code AI_STATION_RANGE |
701 // as long as it is in range. So we give back code AI_STATION_RANGE |
703 // so the pathfinder routine can work it out! |
702 // so the pathfinder routine can work it out! |
704 new_tile = AI_STATION_RANGE; |
703 new_tile = AI_STATION_RANGE; |
705 direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION; |
704 direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION; |
706 } |
705 } |
707 |
706 |
708 if (_players_ainew[p->index].from_tile == 0) { |
707 if (_companies_ainew[c->index].from_tile == 0) { |
709 _players_ainew[p->index].from_tile = new_tile; |
708 _companies_ainew[c->index].from_tile = new_tile; |
710 _players_ainew[p->index].from_direction = direction; |
709 _companies_ainew[c->index].from_direction = direction; |
711 // Now we found thisone, go in for to_tile |
710 // Now we found thisone, go in for to_tile |
712 return; |
711 return; |
713 } else if (_players_ainew[p->index].to_tile == 0) { |
712 } else if (_companies_ainew[c->index].to_tile == 0) { |
714 _players_ainew[p->index].to_tile = new_tile; |
713 _companies_ainew[c->index].to_tile = new_tile; |
715 _players_ainew[p->index].to_direction = direction; |
714 _companies_ainew[c->index].to_direction = direction; |
716 // K, done placing stations! |
715 // K, done placing stations! |
717 _players_ainew[p->index].temp = -1; |
716 _companies_ainew[c->index].temp = -1; |
718 _players_ainew[p->index].state = AI_STATE_FIND_PATH; |
717 _companies_ainew[c->index].state = AI_STATE_FIND_PATH; |
719 return; |
718 return; |
720 } |
719 } |
721 } |
720 } |
722 |
721 |
723 |
722 |
724 // We try to find a path between 2 points |
723 // We try to find a path between 2 points |
725 static void AiNew_State_FindPath(Player *p) |
724 static void AiNew_State_FindPath(Company *c) |
726 { |
725 { |
727 int r; |
726 int r; |
728 assert(_players_ainew[p->index].state == AI_STATE_FIND_PATH); |
727 assert(_companies_ainew[c->index].state == AI_STATE_FIND_PATH); |
729 |
728 |
730 // First time, init some data |
729 // First time, init some data |
731 if (_players_ainew[p->index].temp == -1) { |
730 if (_companies_ainew[c->index].temp == -1) { |
732 // Init path_info |
731 // Init path_info |
733 if (_players_ainew[p->index].from_tile == AI_STATION_RANGE) { |
732 if (_companies_ainew[c->index].from_tile == AI_STATION_RANGE) { |
734 const Industry* i = GetIndustry(_players_ainew[p->index].from_ic); |
733 const Industry* i = GetIndustry(_companies_ainew[c->index].from_ic); |
735 |
734 |
736 // For truck routes we take a range around the industry |
735 // For truck routes we take a range around the industry |
737 _players_ainew[p->index].path_info.start_tile_tl = i->xy - TileDiffXY(1, 1); |
736 _companies_ainew[c->index].path_info.start_tile_tl = i->xy - TileDiffXY(1, 1); |
738 _players_ainew[p->index].path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1); |
737 _companies_ainew[c->index].path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1); |
739 _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction; |
738 _companies_ainew[c->index].path_info.start_direction = _companies_ainew[c->index].from_direction; |
740 } else { |
739 } else { |
741 _players_ainew[p->index].path_info.start_tile_tl = _players_ainew[p->index].from_tile; |
740 _companies_ainew[c->index].path_info.start_tile_tl = _companies_ainew[c->index].from_tile; |
742 _players_ainew[p->index].path_info.start_tile_br = _players_ainew[p->index].from_tile; |
741 _companies_ainew[c->index].path_info.start_tile_br = _companies_ainew[c->index].from_tile; |
743 _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction; |
742 _companies_ainew[c->index].path_info.start_direction = _companies_ainew[c->index].from_direction; |
744 } |
743 } |
745 |
744 |
746 if (_players_ainew[p->index].to_tile == AI_STATION_RANGE) { |
745 if (_companies_ainew[c->index].to_tile == AI_STATION_RANGE) { |
747 const Industry* i = GetIndustry(_players_ainew[p->index].to_ic); |
746 const Industry* i = GetIndustry(_companies_ainew[c->index].to_ic); |
748 |
747 |
749 _players_ainew[p->index].path_info.end_tile_tl = i->xy - TileDiffXY(1, 1); |
748 _companies_ainew[c->index].path_info.end_tile_tl = i->xy - TileDiffXY(1, 1); |
750 _players_ainew[p->index].path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1); |
749 _companies_ainew[c->index].path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1); |
751 _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction; |
750 _companies_ainew[c->index].path_info.end_direction = _companies_ainew[c->index].to_direction; |
752 } else { |
751 } else { |
753 _players_ainew[p->index].path_info.end_tile_tl = _players_ainew[p->index].to_tile; |
752 _companies_ainew[c->index].path_info.end_tile_tl = _companies_ainew[c->index].to_tile; |
754 _players_ainew[p->index].path_info.end_tile_br = _players_ainew[p->index].to_tile; |
753 _companies_ainew[c->index].path_info.end_tile_br = _companies_ainew[c->index].to_tile; |
755 _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction; |
754 _companies_ainew[c->index].path_info.end_direction = _companies_ainew[c->index].to_direction; |
756 } |
755 } |
757 |
756 |
758 _players_ainew[p->index].path_info.rail_or_road = (_players_ainew[p->index].tbt == AI_TRAIN); |
757 _companies_ainew[c->index].path_info.rail_or_road = (_companies_ainew[c->index].tbt == AI_TRAIN); |
759 |
758 |
760 // First, clean the pathfinder with our new begin and endpoints |
759 // First, clean the pathfinder with our new begin and endpoints |
761 clean_AyStar_AiPathFinder(_players_ainew[p->index].pathfinder, &_players_ainew[p->index].path_info); |
760 clean_AyStar_AiPathFinder(_companies_ainew[c->index].pathfinder, &_companies_ainew[c->index].path_info); |
762 |
761 |
763 _players_ainew[p->index].temp = 0; |
762 _companies_ainew[c->index].temp = 0; |
764 } |
763 } |
765 |
764 |
766 // Start the pathfinder |
765 // Start the pathfinder |
767 r = _players_ainew[p->index].pathfinder->main(_players_ainew[p->index].pathfinder); |
766 r = _companies_ainew[c->index].pathfinder->main(_companies_ainew[c->index].pathfinder); |
768 switch (r) { |
767 switch (r) { |
769 case AYSTAR_NO_PATH: |
768 case AYSTAR_NO_PATH: |
770 DEBUG(ai, 1, "No route found by pathfinder"); |
769 DEBUG(ai, 1, "No route found by pathfinder"); |
771 // Start all over again |
770 // Start all over again |
772 _players_ainew[p->index].state = AI_STATE_NOTHING; |
771 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
773 break; |
772 break; |
774 |
773 |
775 case AYSTAR_FOUND_END_NODE: // We found the end-point |
774 case AYSTAR_FOUND_END_NODE: // We found the end-point |
776 _players_ainew[p->index].temp = -1; |
775 _companies_ainew[c->index].temp = -1; |
777 _players_ainew[p->index].state = AI_STATE_FIND_DEPOT; |
776 _companies_ainew[c->index].state = AI_STATE_FIND_DEPOT; |
778 break; |
777 break; |
779 |
778 |
780 // In any other case, we are still busy finding the route |
779 // In any other case, we are still busy finding the route |
781 default: break; |
780 default: break; |
782 } |
781 } |
783 } |
782 } |
784 |
783 |
785 |
784 |
786 // This function tries to locate a good place for a depot! |
785 // This function tries to locate a good place for a depot! |
787 static void AiNew_State_FindDepot(Player *p) |
786 static void AiNew_State_FindDepot(Company *c) |
788 { |
787 { |
789 // To place the depot, we walk through the route, and if we find a lovely spot (MP_CLEAR, MP_TREES), we place it there.. |
788 // To place the depot, we walk through the route, and if we find a lovely spot (MP_CLEAR, MP_TREES), we place it there.. |
790 // Simple, easy, works! |
789 // Simple, easy, works! |
791 // To make the depot stand in the middle of the route, we start from the center.. |
790 // To make the depot stand in the middle of the route, we start from the center.. |
792 // But first we walk through the route see if we can find a depot that is ours |
791 // But first we walk through the route see if we can find a depot that is ours |
793 // this keeps things nice ;) |
792 // this keeps things nice ;) |
794 int g, i; |
793 int g, i; |
795 CommandCost r; |
794 CommandCost r; |
796 DiagDirection j; |
795 DiagDirection j; |
797 TileIndex tile; |
796 TileIndex tile; |
798 assert(_players_ainew[p->index].state == AI_STATE_FIND_DEPOT); |
797 assert(_companies_ainew[c->index].state == AI_STATE_FIND_DEPOT); |
799 |
798 |
800 _players_ainew[p->index].depot_tile = 0; |
799 _companies_ainew[c->index].depot_tile = 0; |
801 |
800 |
802 for (i = 2; i < _players_ainew[p->index].path_info.route_length - 2; i++) { |
801 for (i = 2; i < _companies_ainew[c->index].path_info.route_length - 2; i++) { |
803 tile = _players_ainew[p->index].path_info.route[i]; |
802 tile = _companies_ainew[c->index].path_info.route[i]; |
804 for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) { |
803 for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) { |
805 TileIndex t = tile + TileOffsByDiagDir(j); |
804 TileIndex t = tile + TileOffsByDiagDir(j); |
806 |
805 |
807 if (IsRoadDepotTile(t) && |
806 if (IsRoadDepotTile(t) && |
808 IsTileOwner(t, _current_player) && |
807 IsTileOwner(t, _current_company) && |
809 GetRoadDepotDirection(t) == ReverseDiagDir(j)) { |
808 GetRoadDepotDirection(t) == ReverseDiagDir(j)) { |
810 _players_ainew[p->index].depot_tile = t; |
809 _companies_ainew[c->index].depot_tile = t; |
811 _players_ainew[p->index].depot_direction = ReverseDiagDir(j); |
810 _companies_ainew[c->index].depot_direction = ReverseDiagDir(j); |
812 _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE; |
811 _companies_ainew[c->index].state = AI_STATE_VERIFY_ROUTE; |
813 return; |
812 return; |
814 } |
813 } |
815 } |
814 } |
816 } |
815 } |
817 |
816 |
818 // This routine let depot finding start in the middle, and work his way to the stations |
817 // This routine let depot finding start in the middle, and work his way to the stations |
819 // It makes depot placing nicer :) |
818 // It makes depot placing nicer :) |
820 i = _players_ainew[p->index].path_info.route_length / 2; |
819 i = _companies_ainew[c->index].path_info.route_length / 2; |
821 g = 1; |
820 g = 1; |
822 while (i > 1 && i < _players_ainew[p->index].path_info.route_length - 2) { |
821 while (i > 1 && i < _companies_ainew[c->index].path_info.route_length - 2) { |
823 i += g; |
822 i += g; |
824 g *= -1; |
823 g *= -1; |
825 (g < 0 ? g-- : g++); |
824 (g < 0 ? g-- : g++); |
826 |
825 |
827 if (_players_ainew[p->index].path_info.route_extra[i] != 0 || _players_ainew[p->index].path_info.route_extra[i + 1] != 0) { |
826 if (_companies_ainew[c->index].path_info.route_extra[i] != 0 || _companies_ainew[c->index].path_info.route_extra[i + 1] != 0) { |
828 // Bridge or tunnel.. we can't place a depot there |
827 // Bridge or tunnel.. we can't place a depot there |
829 continue; |
828 continue; |
830 } |
829 } |
831 |
830 |
832 tile = _players_ainew[p->index].path_info.route[i]; |
831 tile = _companies_ainew[c->index].path_info.route[i]; |
833 |
832 |
834 for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) { |
833 for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) { |
835 TileIndex t = tile + TileOffsByDiagDir(j); |
834 TileIndex t = tile + TileOffsByDiagDir(j); |
836 |
835 |
837 // It may not be placed on the road/rail itself |
836 // It may not be placed on the road/rail itself |
838 // And because it is not build yet, we can't see it on the tile.. |
837 // And because it is not build yet, we can't see it on the tile.. |
839 // So check the surrounding tiles :) |
838 // So check the surrounding tiles :) |
840 if (t == _players_ainew[p->index].path_info.route[i - 1] || |
839 if (t == _companies_ainew[c->index].path_info.route[i - 1] || |
841 t == _players_ainew[p->index].path_info.route[i + 1]) { |
840 t == _companies_ainew[c->index].path_info.route[i + 1]) { |
842 continue; |
841 continue; |
843 } |
842 } |
844 // Not around a bridge? |
843 // Not around a bridge? |
845 if (_players_ainew[p->index].path_info.route_extra[i] != 0) continue; |
844 if (_companies_ainew[c->index].path_info.route_extra[i] != 0) continue; |
846 if (IsTileType(tile, MP_TUNNELBRIDGE)) continue; |
845 if (IsTileType(tile, MP_TUNNELBRIDGE)) continue; |
847 // Is the terrain clear? |
846 // Is the terrain clear? |
848 if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) { |
847 if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) { |
849 // If the current tile is on a slope then we do not allow this |
848 // If the current tile is on a slope then we do not allow this |
850 if (GetTileSlope(tile, NULL) != SLOPE_FLAT) continue; |
849 if (GetTileSlope(tile, NULL) != SLOPE_FLAT) continue; |
851 // Check if everything went okay.. |
850 // Check if everything went okay.. |
852 r = AiNew_Build_Depot(p, t, ReverseDiagDir(j), 0); |
851 r = AiNew_Build_Depot(c, t, ReverseDiagDir(j), 0); |
853 if (CmdFailed(r)) continue; |
852 if (CmdFailed(r)) continue; |
854 // Found a spot! |
853 // Found a spot! |
855 _players_ainew[p->index].new_cost += r.GetCost(); |
854 _companies_ainew[c->index].new_cost += r.GetCost(); |
856 _players_ainew[p->index].depot_tile = t; |
855 _companies_ainew[c->index].depot_tile = t; |
857 _players_ainew[p->index].depot_direction = ReverseDiagDir(j); // Reverse direction |
856 _companies_ainew[c->index].depot_direction = ReverseDiagDir(j); // Reverse direction |
858 _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE; |
857 _companies_ainew[c->index].state = AI_STATE_VERIFY_ROUTE; |
859 return; |
858 return; |
860 } |
859 } |
861 } |
860 } |
862 } |
861 } |
863 |
862 |
864 // Failed to find a depot? |
863 // Failed to find a depot? |
865 _players_ainew[p->index].state = AI_STATE_NOTHING; |
864 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
866 } |
865 } |
867 |
866 |
868 |
867 |
869 // This function calculates how many vehicles there are needed on this |
868 // This function calculates how many vehicles there are needed on this |
870 // traject. |
869 // traject. |
871 // It works pretty simple: get the length, see how much we move around |
870 // It works pretty simple: get the length, see how much we move around |
872 // and hussle that, and you know how many vehicles there are needed. |
871 // and hussle that, and you know how many vehicles there are needed. |
873 // It returns the cost for the vehicles |
872 // It returns the cost for the vehicles |
874 static int AiNew_HowManyVehicles(Player *p) |
873 static int AiNew_HowManyVehicles(Company *c) |
875 { |
874 { |
876 if (_players_ainew[p->index].tbt == AI_BUS) { |
875 if (_companies_ainew[c->index].tbt == AI_BUS) { |
877 // For bus-routes we look at the time before we are back in the station |
876 // For bus-routes we look at the time before we are back in the station |
878 EngineID i; |
877 EngineID i; |
879 int length, tiles_a_day; |
878 int length, tiles_a_day; |
880 int amount; |
879 int amount; |
881 i = AiNew_PickVehicle(p); |
880 i = AiNew_PickVehicle(c); |
882 if (i == INVALID_ENGINE) return 0; |
881 if (i == INVALID_ENGINE) return 0; |
883 // Passenger run.. how long is the route? |
882 // Passenger run.. how long is the route? |
884 length = _players_ainew[p->index].path_info.route_length; |
883 length = _companies_ainew[c->index].path_info.route_length; |
885 // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done! |
884 // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done! |
886 tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16; |
885 tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16; |
887 if (tiles_a_day == 0) tiles_a_day = 1; |
886 if (tiles_a_day == 0) tiles_a_day = 1; |
888 // We want a vehicle in a station once a month at least, so, calculate it! |
887 // We want a vehicle in a station once a month at least, so, calculate it! |
889 // (the * 2 is because we have 2 stations ;)) |
888 // (the * 2 is because we have 2 stations ;)) |
890 amount = length * 2 * 2 / tiles_a_day / 30; |
889 amount = length * 2 * 2 / tiles_a_day / 30; |
891 if (amount == 0) amount = 1; |
890 if (amount == 0) amount = 1; |
892 return amount; |
891 return amount; |
893 } else if (_players_ainew[p->index].tbt == AI_TRUCK) { |
892 } else if (_companies_ainew[c->index].tbt == AI_TRUCK) { |
894 // For truck-routes we look at the cargo |
893 // For truck-routes we look at the cargo |
895 EngineID i; |
894 EngineID i; |
896 int length, amount, tiles_a_day; |
895 int length, amount, tiles_a_day; |
897 int max_cargo; |
896 int max_cargo; |
898 i = AiNew_PickVehicle(p); |
897 i = AiNew_PickVehicle(c); |
899 if (i == INVALID_ENGINE) return 0; |
898 if (i == INVALID_ENGINE) return 0; |
900 // Passenger run.. how long is the route? |
899 // Passenger run.. how long is the route? |
901 length = _players_ainew[p->index].path_info.route_length; |
900 length = _companies_ainew[c->index].path_info.route_length; |
902 // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done! |
901 // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done! |
903 tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16; |
902 tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16; |
904 if (tiles_a_day == 0) tiles_a_day = 1; |
903 if (tiles_a_day == 0) tiles_a_day = 1; |
905 if (_players_ainew[p->index].from_deliver) { |
904 if (_companies_ainew[c->index].from_deliver) { |
906 max_cargo = GetIndustry(_players_ainew[p->index].from_ic)->last_month_production[0]; |
905 max_cargo = GetIndustry(_companies_ainew[c->index].from_ic)->last_month_production[0]; |
907 } else { |
906 } else { |
908 max_cargo = GetIndustry(_players_ainew[p->index].to_ic)->last_month_production[0]; |
907 max_cargo = GetIndustry(_companies_ainew[c->index].to_ic)->last_month_production[0]; |
909 } |
908 } |
910 |
909 |
911 // This is because moving 60% is more than we can dream of! |
910 // This is because moving 60% is more than we can dream of! |
912 max_cargo *= 6; |
911 max_cargo *= 6; |
913 max_cargo /= 10; |
912 max_cargo /= 10; |
926 |
925 |
927 // This function checks: |
926 // This function checks: |
928 // - If the route went okay |
927 // - If the route went okay |
929 // - Calculates the amount of money needed to build the route |
928 // - Calculates the amount of money needed to build the route |
930 // - Calculates how much vehicles needed for the route |
929 // - Calculates how much vehicles needed for the route |
931 static void AiNew_State_VerifyRoute(Player *p) |
930 static void AiNew_State_VerifyRoute(Company *c) |
932 { |
931 { |
933 int res, i; |
932 int res, i; |
934 assert(_players_ainew[p->index].state == AI_STATE_VERIFY_ROUTE); |
933 assert(_companies_ainew[c->index].state == AI_STATE_VERIFY_ROUTE); |
935 |
934 |
936 // Let's calculate the cost of the path.. |
935 // Let's calculate the cost of the path.. |
937 // new_cost already contains the cost of the stations |
936 // new_cost already contains the cost of the stations |
938 _players_ainew[p->index].path_info.position = -1; |
937 _companies_ainew[c->index].path_info.position = -1; |
939 |
938 |
940 do { |
939 do { |
941 _players_ainew[p->index].path_info.position++; |
940 _companies_ainew[c->index].path_info.position++; |
942 _players_ainew[p->index].new_cost += AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_QUERY_COST).GetCost(); |
941 _companies_ainew[c->index].new_cost += AiNew_Build_RoutePart(c, &_companies_ainew[c->index].path_info, DC_QUERY_COST).GetCost(); |
943 } while (_players_ainew[p->index].path_info.position != -2); |
942 } while (_companies_ainew[c->index].path_info.position != -2); |
944 |
943 |
945 // Now we know the price of build station + path. Now check how many vehicles |
944 // Now we know the price of build station + path. Now check how many vehicles |
946 // we need and what the price for that will be |
945 // we need and what the price for that will be |
947 res = AiNew_HowManyVehicles(p); |
946 res = AiNew_HowManyVehicles(c); |
948 // If res == 0, no vehicle was found, or an other problem did occour |
947 // If res == 0, no vehicle was found, or an other problem did occour |
949 if (res == 0) { |
948 if (res == 0) { |
950 _players_ainew[p->index].state = AI_STATE_NOTHING; |
949 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
951 return; |
950 return; |
952 } |
951 } |
953 _players_ainew[p->index].amount_veh = res; |
952 _companies_ainew[c->index].amount_veh = res; |
954 _players_ainew[p->index].cur_veh = 0; |
953 _companies_ainew[c->index].cur_veh = 0; |
955 |
954 |
956 // Check how much it it going to cost us.. |
955 // Check how much it it going to cost us.. |
957 for (i = 0; i < res; i++) { |
956 for (i = 0; i < res; i++) { |
958 _players_ainew[p->index].new_cost += AiNew_Build_Vehicle(p, 0, DC_QUERY_COST).GetCost(); |
957 _companies_ainew[c->index].new_cost += AiNew_Build_Vehicle(c, 0, DC_QUERY_COST).GetCost(); |
959 } |
958 } |
960 |
959 |
961 // Now we know how much the route is going to cost us |
960 // Now we know how much the route is going to cost us |
962 // Check if we have enough money for it! |
961 // Check if we have enough money for it! |
963 if (_players_ainew[p->index].new_cost > p->player_money - AI_MINIMUM_MONEY) { |
962 if (_companies_ainew[c->index].new_cost > c->money - AI_MINIMUM_MONEY) { |
964 // Too bad.. |
963 // Too bad.. |
965 DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)_players_ainew[p->index].new_cost); |
964 DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)_companies_ainew[c->index].new_cost); |
966 _players_ainew[p->index].state = AI_STATE_NOTHING; |
965 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
967 return; |
966 return; |
968 } |
967 } |
969 |
968 |
970 // Now we can build the route, check the direction of the stations! |
969 // Now we can build the route, check the direction of the stations! |
971 if (_players_ainew[p->index].from_direction == AI_PATHFINDER_NO_DIRECTION) { |
970 if (_companies_ainew[c->index].from_direction == AI_PATHFINDER_NO_DIRECTION) { |
972 _players_ainew[p->index].from_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1], _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 2]); |
971 _companies_ainew[c->index].from_direction = AiNew_GetDirection(_companies_ainew[c->index].path_info.route[_companies_ainew[c->index].path_info.route_length - 1], _companies_ainew[c->index].path_info.route[_companies_ainew[c->index].path_info.route_length - 2]); |
973 } |
972 } |
974 if (_players_ainew[p->index].to_direction == AI_PATHFINDER_NO_DIRECTION) { |
973 if (_companies_ainew[c->index].to_direction == AI_PATHFINDER_NO_DIRECTION) { |
975 _players_ainew[p->index].to_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[0], _players_ainew[p->index].path_info.route[1]); |
974 _companies_ainew[c->index].to_direction = AiNew_GetDirection(_companies_ainew[c->index].path_info.route[0], _companies_ainew[c->index].path_info.route[1]); |
976 } |
975 } |
977 if (_players_ainew[p->index].from_tile == AI_STATION_RANGE) |
976 if (_companies_ainew[c->index].from_tile == AI_STATION_RANGE) |
978 _players_ainew[p->index].from_tile = _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1]; |
977 _companies_ainew[c->index].from_tile = _companies_ainew[c->index].path_info.route[_companies_ainew[c->index].path_info.route_length - 1]; |
979 if (_players_ainew[p->index].to_tile == AI_STATION_RANGE) |
978 if (_companies_ainew[c->index].to_tile == AI_STATION_RANGE) |
980 _players_ainew[p->index].to_tile = _players_ainew[p->index].path_info.route[0]; |
979 _companies_ainew[c->index].to_tile = _companies_ainew[c->index].path_info.route[0]; |
981 |
980 |
982 _players_ainew[p->index].state = AI_STATE_BUILD_STATION; |
981 _companies_ainew[c->index].state = AI_STATE_BUILD_STATION; |
983 _players_ainew[p->index].temp = 0; |
982 _companies_ainew[c->index].temp = 0; |
984 |
983 |
985 DEBUG(ai, 1, "The route is set and buildable, building 0x%X to 0x%X...", _players_ainew[p->index].from_tile, _players_ainew[p->index].to_tile); |
984 DEBUG(ai, 1, "The route is set and buildable, building 0x%X to 0x%X...", _companies_ainew[c->index].from_tile, _companies_ainew[c->index].to_tile); |
986 } |
985 } |
987 |
986 |
988 |
987 |
989 // Build the stations |
988 // Build the stations |
990 static void AiNew_State_BuildStation(Player *p) |
989 static void AiNew_State_BuildStation(Company *c) |
991 { |
990 { |
992 CommandCost res; |
991 CommandCost res; |
993 assert(_players_ainew[p->index].state == AI_STATE_BUILD_STATION); |
992 assert(_companies_ainew[c->index].state == AI_STATE_BUILD_STATION); |
994 if (_players_ainew[p->index].temp == 0) { |
993 if (_companies_ainew[c->index].temp == 0) { |
995 if (!IsTileType(_players_ainew[p->index].from_tile, MP_STATION)) |
994 if (!IsTileType(_companies_ainew[c->index].from_tile, MP_STATION)) |
996 res = AiNew_Build_Station(p, _players_ainew[p->index].tbt, _players_ainew[p->index].from_tile, 0, 0, _players_ainew[p->index].from_direction, DC_EXEC); |
995 res = AiNew_Build_Station(c, _companies_ainew[c->index].tbt, _companies_ainew[c->index].from_tile, 0, 0, _companies_ainew[c->index].from_direction, DC_EXEC); |
997 } else { |
996 } else { |
998 if (!IsTileType(_players_ainew[p->index].to_tile, MP_STATION)) |
997 if (!IsTileType(_companies_ainew[c->index].to_tile, MP_STATION)) |
999 res = AiNew_Build_Station(p, _players_ainew[p->index].tbt, _players_ainew[p->index].to_tile, 0, 0, _players_ainew[p->index].to_direction, DC_EXEC); |
998 res = AiNew_Build_Station(c, _companies_ainew[c->index].tbt, _companies_ainew[c->index].to_tile, 0, 0, _companies_ainew[c->index].to_direction, DC_EXEC); |
1000 _players_ainew[p->index].state = AI_STATE_BUILD_PATH; |
999 _companies_ainew[c->index].state = AI_STATE_BUILD_PATH; |
1001 } |
1000 } |
1002 if (CmdFailed(res)) { |
1001 if (CmdFailed(res)) { |
1003 DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", _players_ainew[p->index].to_tile); |
1002 DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", _companies_ainew[c->index].to_tile); |
1004 _players_ainew[p->index].state = AI_STATE_NOTHING; |
1003 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
1005 // If the first station _was_ build, destroy it |
1004 // If the first station _was_ build, destroy it |
1006 if (_players_ainew[p->index].temp != 0) |
1005 if (_companies_ainew[c->index].temp != 0) |
1007 AI_DoCommand(_players_ainew[p->index].from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
1006 AI_DoCommand(_companies_ainew[c->index].from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
1008 return; |
1007 return; |
1009 } |
1008 } |
1010 _players_ainew[p->index].temp++; |
1009 _companies_ainew[c->index].temp++; |
1011 } |
1010 } |
1012 |
1011 |
1013 |
1012 |
1014 // Build the path |
1013 // Build the path |
1015 static void AiNew_State_BuildPath(Player *p) |
1014 static void AiNew_State_BuildPath(Company *c) |
1016 { |
1015 { |
1017 assert(_players_ainew[p->index].state == AI_STATE_BUILD_PATH); |
1016 assert(_companies_ainew[c->index].state == AI_STATE_BUILD_PATH); |
1018 // _players_ainew[p->index].temp is set to -1 when this function is called for the first time |
1017 // _companies_ainew[c->index].temp is set to -1 when this function is called for the first time |
1019 if (_players_ainew[p->index].temp == -1) { |
1018 if (_companies_ainew[c->index].temp == -1) { |
1020 DEBUG(ai, 1, "Starting to build new path"); |
1019 DEBUG(ai, 1, "Starting to build new path"); |
1021 // Init the counter |
1020 // Init the counter |
1022 _players_ainew[p->index].counter = (4 - _settings_game.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1; |
1021 _companies_ainew[c->index].counter = (4 - _settings_game.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1; |
1023 // Set the position to the startingplace (-1 because in a minute we do ++) |
1022 // Set the position to the startingplace (-1 because in a minute we do ++) |
1024 _players_ainew[p->index].path_info.position = -1; |
1023 _companies_ainew[c->index].path_info.position = -1; |
1025 // And don't do this again |
1024 // And don't do this again |
1026 _players_ainew[p->index].temp = 0; |
1025 _companies_ainew[c->index].temp = 0; |
1027 } |
1026 } |
1028 // Building goes very fast on normal rate, so we are going to slow it down.. |
1027 // Building goes very fast on normal rate, so we are going to slow it down.. |
1029 // By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :) |
1028 // By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :) |
1030 if (--_players_ainew[p->index].counter != 0) return; |
1029 if (--_companies_ainew[c->index].counter != 0) return; |
1031 _players_ainew[p->index].counter = (4 - _settings_game.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1; |
1030 _companies_ainew[c->index].counter = (4 - _settings_game.difficulty.competitor_speed) * AI_BUILDPATH_PAUSE + 1; |
1032 |
1031 |
1033 // Increase the building position |
1032 // Increase the building position |
1034 _players_ainew[p->index].path_info.position++; |
1033 _companies_ainew[c->index].path_info.position++; |
1035 // Build route |
1034 // Build route |
1036 AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_EXEC); |
1035 AiNew_Build_RoutePart(c, &_companies_ainew[c->index].path_info, DC_EXEC); |
1037 if (_players_ainew[p->index].path_info.position == -2) { |
1036 if (_companies_ainew[c->index].path_info.position == -2) { |
1038 // This means we are done building! |
1037 // This means we are done building! |
1039 |
1038 |
1040 if (_players_ainew[p->index].tbt == AI_TRUCK && !_settings_game.pf.roadveh_queue) { |
1039 if (_companies_ainew[c->index].tbt == AI_TRUCK && !_settings_game.pf.roadveh_queue) { |
1041 // If they not queue, they have to go up and down to try again at a station... |
1040 // If they not queue, they have to go up and down to try again at a station... |
1042 // We don't want that, so try building some road left or right of the station |
1041 // We don't want that, so try building some road left or right of the station |
1043 DiagDirection dir1, dir2, dir3; |
1042 DiagDirection dir1, dir2, dir3; |
1044 TileIndex tile; |
1043 TileIndex tile; |
1045 CommandCost ret; |
1044 CommandCost ret; |
1046 for (int i = 0; i < 2; i++) { |
1045 for (int i = 0; i < 2; i++) { |
1047 if (i == 0) { |
1046 if (i == 0) { |
1048 tile = _players_ainew[p->index].from_tile + TileOffsByDiagDir(_players_ainew[p->index].from_direction); |
1047 tile = _companies_ainew[c->index].from_tile + TileOffsByDiagDir(_companies_ainew[c->index].from_direction); |
1049 dir1 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90LEFT); |
1048 dir1 = ChangeDiagDir(_companies_ainew[c->index].from_direction, DIAGDIRDIFF_90LEFT); |
1050 dir2 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90RIGHT); |
1049 dir2 = ChangeDiagDir(_companies_ainew[c->index].from_direction, DIAGDIRDIFF_90RIGHT); |
1051 dir3 = _players_ainew[p->index].from_direction; |
1050 dir3 = _companies_ainew[c->index].from_direction; |
1052 } else { |
1051 } else { |
1053 tile = _players_ainew[p->index].to_tile + TileOffsByDiagDir(_players_ainew[p->index].to_direction); |
1052 tile = _companies_ainew[c->index].to_tile + TileOffsByDiagDir(_companies_ainew[c->index].to_direction); |
1054 dir1 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90LEFT); |
1053 dir1 = ChangeDiagDir(_companies_ainew[c->index].to_direction, DIAGDIRDIFF_90LEFT); |
1055 dir2 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90RIGHT); |
1054 dir2 = ChangeDiagDir(_companies_ainew[c->index].to_direction, DIAGDIRDIFF_90RIGHT); |
1056 dir3 = _players_ainew[p->index].to_direction; |
1055 dir3 = _companies_ainew[c->index].to_direction; |
1057 } |
1056 } |
1058 |
1057 |
1059 ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir1)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD); |
1058 ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir1)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD); |
1060 if (CmdSucceeded(ret)) { |
1059 if (CmdSucceeded(ret)) { |
1061 TileIndex offset = TileOffsByDiagDir(dir1); |
1060 TileIndex offset = TileOffsByDiagDir(dir1); |
1092 } |
1091 } |
1093 } |
1092 } |
1094 } |
1093 } |
1095 } |
1094 } |
1096 |
1095 |
1097 DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)_players_ainew[p->index].new_cost); |
1096 DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)_companies_ainew[c->index].new_cost); |
1098 _players_ainew[p->index].state = AI_STATE_BUILD_DEPOT; |
1097 _companies_ainew[c->index].state = AI_STATE_BUILD_DEPOT; |
1099 } |
1098 } |
1100 } |
1099 } |
1101 |
1100 |
1102 |
1101 |
1103 // Builds the depot |
1102 // Builds the depot |
1104 static void AiNew_State_BuildDepot(Player *p) |
1103 static void AiNew_State_BuildDepot(Company *c) |
1105 { |
1104 { |
1106 CommandCost res; |
1105 CommandCost res; |
1107 assert(_players_ainew[p->index].state == AI_STATE_BUILD_DEPOT); |
1106 assert(_companies_ainew[c->index].state == AI_STATE_BUILD_DEPOT); |
1108 |
1107 |
1109 if (IsRoadDepotTile(_players_ainew[p->index].depot_tile)) { |
1108 if (IsRoadDepotTile(_companies_ainew[c->index].depot_tile)) { |
1110 if (IsTileOwner(_players_ainew[p->index].depot_tile, _current_player)) { |
1109 if (IsTileOwner(_companies_ainew[c->index].depot_tile, _current_company)) { |
1111 // The depot is already built |
1110 // The depot is already built |
1112 _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE; |
1111 _companies_ainew[c->index].state = AI_STATE_BUILD_VEHICLE; |
1113 return; |
1112 return; |
1114 } else { |
1113 } else { |
1115 // There is a depot, but not of our team! :( |
1114 // There is a depot, but not of our team! :( |
1116 _players_ainew[p->index].state = AI_STATE_NOTHING; |
1115 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
1117 return; |
1116 return; |
1118 } |
1117 } |
1119 } |
1118 } |
1120 |
1119 |
1121 // There is a bus on the tile we want to build road on... idle till he is gone! (BAD PERSON! :p) |
1120 // There is a bus on the tile we want to build road on... idle till he is gone! (BAD PERSON! :p) |
1122 if (!EnsureNoVehicleOnGround(_players_ainew[p->index].depot_tile + TileOffsByDiagDir(_players_ainew[p->index].depot_direction))) |
1121 if (!EnsureNoVehicleOnGround(_companies_ainew[c->index].depot_tile + TileOffsByDiagDir(_companies_ainew[c->index].depot_direction))) |
1123 return; |
1122 return; |
1124 |
1123 |
1125 res = AiNew_Build_Depot(p, _players_ainew[p->index].depot_tile, _players_ainew[p->index].depot_direction, DC_EXEC); |
1124 res = AiNew_Build_Depot(c, _companies_ainew[c->index].depot_tile, _companies_ainew[c->index].depot_direction, DC_EXEC); |
1126 if (CmdFailed(res)) { |
1125 if (CmdFailed(res)) { |
1127 DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", _players_ainew[p->index].depot_tile); |
1126 DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", _companies_ainew[c->index].depot_tile); |
1128 _players_ainew[p->index].state = AI_STATE_NOTHING; |
1127 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
1129 return; |
1128 return; |
1130 } |
1129 } |
1131 |
1130 |
1132 _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE; |
1131 _companies_ainew[c->index].state = AI_STATE_BUILD_VEHICLE; |
1133 _players_ainew[p->index].idle = 10; |
1132 _companies_ainew[c->index].idle = 10; |
1134 _players_ainew[p->index].veh_main_id = INVALID_VEHICLE; |
1133 _companies_ainew[c->index].veh_main_id = INVALID_VEHICLE; |
1135 } |
1134 } |
1136 |
1135 |
1137 |
1136 |
1138 // Build vehicles |
1137 // Build vehicles |
1139 static void AiNew_State_BuildVehicle(Player *p) |
1138 static void AiNew_State_BuildVehicle(Company *c) |
1140 { |
1139 { |
1141 CommandCost res; |
1140 CommandCost res; |
1142 assert(_players_ainew[p->index].state == AI_STATE_BUILD_VEHICLE); |
1141 assert(_companies_ainew[c->index].state == AI_STATE_BUILD_VEHICLE); |
1143 |
1142 |
1144 // Check if we need to build a vehicle |
1143 // Check if we need to build a vehicle |
1145 if (_players_ainew[p->index].amount_veh == 0) { |
1144 if (_companies_ainew[c->index].amount_veh == 0) { |
1146 // Nope, we are done! |
1145 // Nope, we are done! |
1147 // This means: we are all done! The route is open.. go back to NOTHING |
1146 // This means: we are all done! The route is open.. go back to NOTHING |
1148 // He will idle some time and it will all start over again.. :) |
1147 // He will idle some time and it will all start over again.. :) |
1149 _players_ainew[p->index].state = AI_STATE_ACTION_DONE; |
1148 _companies_ainew[c->index].state = AI_STATE_ACTION_DONE; |
1150 return; |
1149 return; |
1151 } |
1150 } |
1152 if (--_players_ainew[p->index].idle != 0) return; |
1151 if (--_companies_ainew[c->index].idle != 0) return; |
1153 // It is realistic that the AI can only build 1 vehicle a day.. |
1152 // It is realistic that the AI can only build 1 vehicle a day.. |
1154 // This makes sure of that! |
1153 // This makes sure of that! |
1155 _players_ainew[p->index].idle = AI_BUILD_VEHICLE_TIME_BETWEEN; |
1154 _companies_ainew[c->index].idle = AI_BUILD_VEHICLE_TIME_BETWEEN; |
1156 |
1155 |
1157 // Build the vehicle |
1156 // Build the vehicle |
1158 res = AiNew_Build_Vehicle(p, _players_ainew[p->index].depot_tile, DC_EXEC); |
1157 res = AiNew_Build_Vehicle(c, _companies_ainew[c->index].depot_tile, DC_EXEC); |
1159 if (CmdFailed(res)) { |
1158 if (CmdFailed(res)) { |
1160 // This happens when the AI can't build any more vehicles! |
1159 // This happens when the AI can't build any more vehicles! |
1161 _players_ainew[p->index].state = AI_STATE_NOTHING; |
1160 _companies_ainew[c->index].state = AI_STATE_NOTHING; |
1162 return; |
1161 return; |
1163 } |
1162 } |
1164 // Increase the current counter |
1163 // Increase the current counter |
1165 _players_ainew[p->index].cur_veh++; |
1164 _companies_ainew[c->index].cur_veh++; |
1166 // Decrease the total counter |
1165 // Decrease the total counter |
1167 _players_ainew[p->index].amount_veh--; |
1166 _companies_ainew[c->index].amount_veh--; |
1168 // Go give some orders! |
1167 // Go give some orders! |
1169 _players_ainew[p->index].state = AI_STATE_WAIT_FOR_BUILD; |
1168 _companies_ainew[c->index].state = AI_STATE_WAIT_FOR_BUILD; |
1170 } |
1169 } |
1171 |
1170 |
1172 |
1171 |
1173 // Put the stations in the order list |
1172 // Put the stations in the order list |
1174 static void AiNew_State_GiveOrders(Player *p) |
1173 static void AiNew_State_GiveOrders(Company *c) |
1175 { |
1174 { |
1176 int idx; |
1175 int idx; |
1177 Order order; |
1176 Order order; |
1178 |
1177 |
1179 assert(_players_ainew[p->index].state == AI_STATE_GIVE_ORDERS); |
1178 assert(_companies_ainew[c->index].state == AI_STATE_GIVE_ORDERS); |
1180 |
1179 |
1181 if (_players_ainew[p->index].veh_main_id != INVALID_VEHICLE) { |
1180 if (_companies_ainew[c->index].veh_main_id != INVALID_VEHICLE) { |
1182 AI_DoCommand(0, _players_ainew[p->index].veh_id + (_players_ainew[p->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER); |
1181 AI_DoCommand(0, _companies_ainew[c->index].veh_id + (_companies_ainew[c->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER); |
1183 |
1182 |
1184 _players_ainew[p->index].state = AI_STATE_START_VEHICLE; |
1183 _companies_ainew[c->index].state = AI_STATE_START_VEHICLE; |
1185 return; |
1184 return; |
1186 } else { |
1185 } else { |
1187 _players_ainew[p->index].veh_main_id = _players_ainew[p->index].veh_id; |
1186 _companies_ainew[c->index].veh_main_id = _companies_ainew[c->index].veh_id; |
1188 } |
1187 } |
1189 |
1188 |
1190 // Very handy for AI, goto depot.. but yeah, it needs to be activated ;) |
1189 // Very handy for AI, goto depot.. but yeah, it needs to be activated ;) |
1191 if (_settings_game.order.gotodepot) { |
1190 if (_settings_game.order.gotodepot) { |
1192 idx = 0; |
1191 idx = 0; |
1193 order.MakeGoToDepot(GetDepotByTile(_players_ainew[p->index].depot_tile)->index, ODTFB_PART_OF_ORDERS); |
1192 order.MakeGoToDepot(GetDepotByTile(_companies_ainew[c->index].depot_tile)->index, ODTFB_PART_OF_ORDERS); |
1194 AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); |
1193 AI_DoCommand(0, _companies_ainew[c->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); |
1195 } |
1194 } |
1196 |
1195 |
1197 idx = 0; |
1196 idx = 0; |
1198 order.MakeGoToStation(GetStationIndex(_players_ainew[p->index].to_tile)); |
1197 order.MakeGoToStation(GetStationIndex(_companies_ainew[c->index].to_tile)); |
1199 if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].to_deliver) order.SetLoadType(OLFB_FULL_LOAD); |
1198 if (_companies_ainew[c->index].tbt == AI_TRUCK && _companies_ainew[c->index].to_deliver) order.SetLoadType(OLFB_FULL_LOAD); |
1200 AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); |
1199 AI_DoCommand(0, _companies_ainew[c->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); |
1201 |
1200 |
1202 idx = 0; |
1201 idx = 0; |
1203 order.MakeGoToStation(GetStationIndex(_players_ainew[p->index].from_tile)); |
1202 order.MakeGoToStation(GetStationIndex(_companies_ainew[c->index].from_tile)); |
1204 if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].from_deliver) order.SetLoadType(OLFB_FULL_LOAD); |
1203 if (_companies_ainew[c->index].tbt == AI_TRUCK && _companies_ainew[c->index].from_deliver) order.SetLoadType(OLFB_FULL_LOAD); |
1205 AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); |
1204 AI_DoCommand(0, _companies_ainew[c->index].veh_id + (idx << 16), order.Pack(), DC_EXEC, CMD_INSERT_ORDER); |
1206 |
1205 |
1207 // Start the engines! |
1206 // Start the engines! |
1208 _players_ainew[p->index].state = AI_STATE_START_VEHICLE; |
1207 _companies_ainew[c->index].state = AI_STATE_START_VEHICLE; |
1209 } |
1208 } |
1210 |
1209 |
1211 |
1210 |
1212 // Start the vehicle |
1211 // Start the vehicle |
1213 static void AiNew_State_StartVehicle(Player *p) |
1212 static void AiNew_State_StartVehicle(Company *c) |
1214 { |
1213 { |
1215 assert(_players_ainew[p->index].state == AI_STATE_START_VEHICLE); |
1214 assert(_companies_ainew[c->index].state == AI_STATE_START_VEHICLE); |
1216 |
1215 |
1217 // Skip the first order if it is a second vehicle |
1216 // Skip the first order if it is a second vehicle |
1218 // This to make vehicles go different ways.. |
1217 // This to make vehicles go different ways.. |
1219 if (_players_ainew[p->index].cur_veh & 1) |
1218 if (_companies_ainew[c->index].cur_veh & 1) |
1220 AI_DoCommand(0, _players_ainew[p->index].veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER); |
1219 AI_DoCommand(0, _companies_ainew[c->index].veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER); |
1221 |
1220 |
1222 // 3, 2, 1... go! (give START_STOP command ;)) |
1221 // 3, 2, 1... go! (give START_STOP command ;)) |
1223 AI_DoCommand(0, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_START_STOP_VEHICLE); |
1222 AI_DoCommand(0, _companies_ainew[c->index].veh_id, 0, DC_EXEC, CMD_START_STOP_VEHICLE); |
1224 // Try to build an other vehicle (that function will stop building when needed) |
1223 // Try to build an other vehicle (that function will stop building when needed) |
1225 _players_ainew[p->index].idle = 10; |
1224 _companies_ainew[c->index].idle = 10; |
1226 _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE; |
1225 _companies_ainew[c->index].state = AI_STATE_BUILD_VEHICLE; |
1227 } |
1226 } |
1228 |
1227 |
1229 |
1228 |
1230 // Repays money |
1229 // Repays money |
1231 static void AiNew_State_RepayMoney(Player *p) |
1230 static void AiNew_State_RepayMoney(Company *c) |
1232 { |
1231 { |
1233 uint i; |
1232 uint i; |
1234 |
1233 |
1235 for (i = 0; i < AI_LOAN_REPAY; i++) { |
1234 for (i = 0; i < AI_LOAN_REPAY; i++) { |
1236 AI_DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN); |
1235 AI_DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN); |
1237 } |
1236 } |
1238 _players_ainew[p->index].state = AI_STATE_ACTION_DONE; |
1237 _companies_ainew[c->index].state = AI_STATE_ACTION_DONE; |
1239 } |
1238 } |
1240 |
1239 |
1241 |
1240 |
1242 static void AiNew_CheckVehicle(Player *p, Vehicle *v) |
1241 static void AiNew_CheckVehicle(Company *c, Vehicle *v) |
1243 { |
1242 { |
1244 // When a vehicle is under the 6 months, we don't check for anything |
1243 // When a vehicle is under the 6 months, we don't check for anything |
1245 if (v->age < 180) return; |
1244 if (v->age < 180) return; |
1246 |
1245 |
1247 // When a vehicle is older than 1 year, it should make money... |
1246 // When a vehicle is older than 1 year, it should make money... |