120 |
120 |
121 p->ai.state = AIS_WANT_NEW_ROUTE; |
121 p->ai.state = AIS_WANT_NEW_ROUTE; |
122 p->ai.state_counter = 0; |
122 p->ai.state_counter = 0; |
123 } |
123 } |
124 |
124 |
125 static int AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex tile) |
125 static EngineID AiChooseTrainToBuild(byte railtype, int32 money, byte flag, TileIndex tile) |
126 { |
126 { |
127 int best_veh_index = -1; |
127 EngineID best_veh_index = INVALID_ENGINE; |
128 byte best_veh_score = 0; |
128 byte best_veh_score = 0; |
129 int32 ret; |
129 int32 ret; |
130 int i; |
130 EngineID i; |
131 |
131 |
132 for (i = 0; i < NUM_TRAIN_ENGINES; i++) { |
132 for (i = 0; i < NUM_TRAIN_ENGINES; i++) { |
133 const RailVehicleInfo *rvi = RailVehInfo(i); |
133 const RailVehicleInfo *rvi = RailVehInfo(i); |
134 const Engine* e = GetEngine(i); |
134 const Engine* e = GetEngine(i); |
135 |
135 |
150 } |
150 } |
151 |
151 |
152 return best_veh_index; |
152 return best_veh_index; |
153 } |
153 } |
154 |
154 |
155 static int AiChooseRoadVehToBuild(byte cargo, int32 money, TileIndex tile) |
155 static EngineID AiChooseRoadVehToBuild(byte cargo, int32 money, TileIndex tile) |
156 { |
156 { |
157 int best_veh_index = -1; |
157 EngineID best_veh_index = INVALID_ENGINE; |
158 int32 best_veh_cost = 0; |
158 int32 best_veh_cost = 0; |
159 int32 ret; |
159 int32 ret; |
160 |
160 |
161 int i = _cargoc.ai_roadveh_start[cargo]; |
161 EngineID i = _cargoc.ai_roadveh_start[cargo]; |
162 int end = i + _cargoc.ai_roadveh_count[cargo]; |
162 EngineID end = i + _cargoc.ai_roadveh_count[cargo]; |
163 const Engine* e = GetEngine(i); |
163 const Engine* e = GetEngine(i); |
164 |
164 |
165 do { |
165 do { |
166 if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) |
166 if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) |
167 continue; |
167 continue; |
174 } while (++e, ++i != end); |
174 } while (++e, ++i != end); |
175 |
175 |
176 return best_veh_index; |
176 return best_veh_index; |
177 } |
177 } |
178 |
178 |
179 static int AiChooseAircraftToBuild(int32 money, byte flag) |
179 static EngineID AiChooseAircraftToBuild(int32 money, byte flag) |
180 { |
180 { |
181 int best_veh_index = -1; |
181 EngineID best_veh_index = INVALID_ENGINE; |
182 int32 best_veh_cost = 0; |
182 int32 best_veh_cost = 0; |
183 int32 ret; |
183 int32 ret; |
184 |
184 |
185 int i = AIRCRAFT_ENGINES_INDEX; |
185 EngineID i = AIRCRAFT_ENGINES_INDEX; |
186 int end = i + NUM_AIRCRAFT_ENGINES; |
186 EngineID end = i + NUM_AIRCRAFT_ENGINES; |
187 const Engine* e = GetEngine(i); |
187 const Engine* e = GetEngine(i); |
188 |
188 |
189 do { |
189 do { |
190 if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) |
190 if (!HASBIT(e->player_avail, _current_player) || e->reliability < 0x8A3D) |
191 continue; |
191 continue; |
216 |
216 |
217 return base; |
217 return base; |
218 } |
218 } |
219 |
219 |
220 #if 0 |
220 #if 0 |
221 static int AiChooseShipToBuild(byte cargo, int32 money) |
221 static EngineID AiChooseShipToBuild(byte cargo, int32 money) |
222 { |
222 { |
223 // XXX: not done |
223 // XXX: not done |
224 return 0; |
224 return INVALID_ENGINE; |
225 } |
225 } |
226 #endif |
226 #endif |
227 |
227 |
228 static int AiChooseRoadVehToReplaceWith(Player *p, Vehicle *v) |
228 static EngineID AiChooseRoadVehToReplaceWith(Player* p, Vehicle* v) |
229 { |
229 { |
230 int32 avail_money = p->player_money + v->value; |
230 int32 avail_money = p->player_money + v->value; |
231 return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile); |
231 return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile); |
232 } |
232 } |
233 |
233 |
234 static int AiChooseAircraftToReplaceWith(Player *p, Vehicle *v) |
234 static EngineID AiChooseAircraftToReplaceWith(Player* p, Vehicle* v) |
235 { |
235 { |
236 int32 avail_money = p->player_money + v->value; |
236 int32 avail_money = p->player_money + v->value; |
237 return AiChooseAircraftToBuild(avail_money, v->engine_type>=253?1:0); |
237 return AiChooseAircraftToBuild(avail_money, v->engine_type>=253?1:0); |
238 } |
238 } |
239 |
239 |
240 static int AiChooseTrainToReplaceWith(Player *p, Vehicle *v) |
240 static EngineID AiChooseTrainToReplaceWith(Player* p, Vehicle* v) |
241 { |
241 { |
242 int32 avail_money = p->player_money + v->value; |
242 int32 avail_money = p->player_money + v->value; |
243 int num=0; |
243 int num=0; |
244 Vehicle *u = v; |
244 Vehicle *u = v; |
245 |
245 |
249 |
249 |
250 // XXX: check if a wagon |
250 // XXX: check if a wagon |
251 return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile); |
251 return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile); |
252 } |
252 } |
253 |
253 |
254 static int AiChooseShipToReplaceWith(Player *p, Vehicle *v) |
254 static EngineID AiChooseShipToReplaceWith(Player* p, Vehicle* v) |
255 { |
255 { |
256 error("!AiChooseShipToReplaceWith"); |
256 error("!AiChooseShipToReplaceWith"); |
257 |
257 |
258 /* maybe useless, but avoids compiler warning this way */ |
258 /* maybe useless, but avoids compiler warning this way */ |
259 return 0; |
259 return INVALID_ENGINE; |
260 } |
260 } |
261 |
261 |
262 static void AiHandleGotoDepot(Player *p, int cmd) |
262 static void AiHandleGotoDepot(Player *p, int cmd) |
263 { |
263 { |
264 if (p->ai.cur_veh->current_order.type != OT_GOTO_DEPOT) |
264 if (p->ai.cur_veh->current_order.type != OT_GOTO_DEPOT) |
287 |
287 |
288 static void AiHandleReplaceTrain(Player *p) |
288 static void AiHandleReplaceTrain(Player *p) |
289 { |
289 { |
290 Vehicle *v = p->ai.cur_veh; |
290 Vehicle *v = p->ai.cur_veh; |
291 BackuppedOrders orderbak[1]; |
291 BackuppedOrders orderbak[1]; |
292 int veh; |
292 EngineID veh; |
293 |
293 |
294 // wait until the vehicle reaches the depot. |
294 // wait until the vehicle reaches the depot. |
295 if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { |
295 if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) { |
296 AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT); |
296 AiHandleGotoDepot(p, CMD_TRAIN_GOTO_DEPOT); |
297 return; |
297 return; |
298 } |
298 } |
299 |
299 |
300 veh = AiChooseTrainToReplaceWith(p, v); |
300 veh = AiChooseTrainToReplaceWith(p, v); |
301 if (veh != -1) { |
301 if (veh != INVALID_ENGINE) { |
302 TileIndex tile; |
302 TileIndex tile; |
303 |
303 |
304 BackupVehicleOrders(v, orderbak); |
304 BackupVehicleOrders(v, orderbak); |
305 tile = v->tile; |
305 tile = v->tile; |
306 |
306 |
307 if (!CmdFailed(DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON)) && |
307 if (!CmdFailed(DoCommandByTile(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON)) && |
308 !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE)) ) { |
308 !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE)) ) { |
309 veh = _new_train_id; |
309 VehicleID veh = _new_train_id; |
310 AiRestoreVehicleOrders(GetVehicle(veh), orderbak); |
310 AiRestoreVehicleOrders(GetVehicle(veh), orderbak); |
311 DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN); |
311 DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_TRAIN); |
312 |
312 |
313 DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); |
313 DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); |
314 } |
314 } |
317 |
317 |
318 static void AiHandleReplaceRoadVeh(Player *p) |
318 static void AiHandleReplaceRoadVeh(Player *p) |
319 { |
319 { |
320 Vehicle *v = p->ai.cur_veh; |
320 Vehicle *v = p->ai.cur_veh; |
321 BackuppedOrders orderbak[1]; |
321 BackuppedOrders orderbak[1]; |
322 int veh; |
322 EngineID veh; |
323 |
323 |
324 if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { |
324 if (!IsTileDepotType(v->tile, TRANSPORT_ROAD) || v->u.road.state != 254 || !(v->vehstatus&VS_STOPPED)) { |
325 AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT); |
325 AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT); |
326 return; |
326 return; |
327 } |
327 } |
328 |
328 |
329 veh = AiChooseRoadVehToReplaceWith(p, v); |
329 veh = AiChooseRoadVehToReplaceWith(p, v); |
330 if (veh != -1) { |
330 if (veh != INVALID_ENGINE) { |
331 TileIndex tile; |
331 TileIndex tile; |
332 |
332 |
333 BackupVehicleOrders(v, orderbak); |
333 BackupVehicleOrders(v, orderbak); |
334 tile = v->tile; |
334 tile = v->tile; |
335 |
335 |
336 if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH)) && |
336 if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH)) && |
337 !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH)) ) { |
337 !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH)) ) { |
338 veh = _new_roadveh_id; |
338 VehicleID veh = _new_roadveh_id; |
339 AiRestoreVehicleOrders(GetVehicle(veh), orderbak); |
339 AiRestoreVehicleOrders(GetVehicle(veh), orderbak); |
340 DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH); |
340 DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_ROADVEH); |
341 |
341 |
342 DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); |
342 DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); |
343 } |
343 } |
345 } |
345 } |
346 |
346 |
347 static void AiHandleReplaceAircraft(Player *p) |
347 static void AiHandleReplaceAircraft(Player *p) |
348 { |
348 { |
349 Vehicle *v = p->ai.cur_veh; |
349 Vehicle *v = p->ai.cur_veh; |
350 int veh; |
|
351 BackuppedOrders orderbak[1]; |
350 BackuppedOrders orderbak[1]; |
|
351 EngineID veh; |
352 |
352 |
353 if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) { |
353 if (!IsAircraftHangarTile(v->tile) && !(v->vehstatus&VS_STOPPED)) { |
354 AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR); |
354 AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR); |
355 return; |
355 return; |
356 } |
356 } |
357 |
357 |
358 veh = AiChooseAircraftToReplaceWith(p, v); |
358 veh = AiChooseAircraftToReplaceWith(p, v); |
359 if (veh != -1) { |
359 if (veh != INVALID_ENGINE) { |
360 TileIndex tile; |
360 TileIndex tile; |
361 |
361 |
362 BackupVehicleOrders(v, orderbak); |
362 BackupVehicleOrders(v, orderbak); |
363 tile = v->tile; |
363 tile = v->tile; |
364 |
364 |
365 if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT)) && |
365 if (!CmdFailed(DoCommandByTile(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT)) && |
366 !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT)) ) { |
366 !CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT)) ) { |
367 veh = _new_aircraft_id; |
367 VehicleID veh = _new_aircraft_id; |
368 AiRestoreVehicleOrders(GetVehicle(veh), orderbak); |
368 AiRestoreVehicleOrders(GetVehicle(veh), orderbak); |
369 DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT); |
369 DoCommandByTile(0, veh, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT); |
370 |
370 |
371 DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); |
371 DoCommandByTile(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_TRAIN_SERVICE_INT); |
372 } |
372 } |
376 static void AiHandleReplaceShip(Player *p) |
376 static void AiHandleReplaceShip(Player *p) |
377 { |
377 { |
378 error("!AiHandleReplaceShip"); |
378 error("!AiHandleReplaceShip"); |
379 } |
379 } |
380 |
380 |
381 typedef int CheckReplaceProc(Player *p, Vehicle *v); |
381 typedef EngineID CheckReplaceProc(Player* p, Vehicle* v); |
382 |
382 |
383 static CheckReplaceProc * const _veh_check_replace_proc[] = { |
383 static CheckReplaceProc * const _veh_check_replace_proc[] = { |
384 AiChooseTrainToReplaceWith, |
384 AiChooseTrainToReplaceWith, |
385 AiChooseRoadVehToReplaceWith, |
385 AiChooseRoadVehToReplaceWith, |
386 AiChooseShipToReplaceWith, |
386 AiChooseShipToReplaceWith, |
397 |
397 |
398 static void AiStateCheckReplaceVehicle(Player *p) |
398 static void AiStateCheckReplaceVehicle(Player *p) |
399 { |
399 { |
400 Vehicle *v = p->ai.cur_veh; |
400 Vehicle *v = p->ai.cur_veh; |
401 |
401 |
402 if (v->type == 0 || v->owner != _current_player || v->type > VEH_Ship || _veh_check_replace_proc[v->type - VEH_Train](p, v) == -1) { |
402 if (v->type == 0 || |
|
403 v->owner != _current_player || |
|
404 v->type > VEH_Ship || |
|
405 _veh_check_replace_proc[v->type - VEH_Train](p, v) == INVALID_ENGINE) { |
403 p->ai.state = AIS_VEH_LOOP; |
406 p->ai.state = AIS_VEH_LOOP; |
404 } else { |
407 } else { |
405 p->ai.state_counter = 0; |
408 p->ai.state_counter = 0; |
406 p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE; |
409 p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE; |
407 } |
410 } |
2404 break; |
2408 break; |
2405 } |
2409 } |
2406 |
2410 |
2407 // Which locomotive to build? |
2411 // Which locomotive to build? |
2408 veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0, tile); |
2412 veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, (cargo!=CT_PASSENGERS)?1:0, tile); |
2409 if (veh == -1) { |
2413 if (veh == INVALID_ENGINE) { |
2410 handle_nocash: |
2414 handle_nocash: |
2411 // after a while, if AI still doesn't have cash, get out of this block by selling the wagons. |
2415 // after a while, if AI still doesn't have cash, get out of this block by selling the wagons. |
2412 if (++p->ai.state_counter == 1000) { |
2416 if (++p->ai.state_counter == 1000) { |
2413 for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) { |
2417 for(i=0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) { |
2414 cost = DoCommandByTile(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON); |
2418 cost = DoCommandByTile(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON); |
3495 |
3499 |
3496 static void AiStateBuildAircraftVehicles(Player *p) |
3500 static void AiStateBuildAircraftVehicles(Player *p) |
3497 { |
3501 { |
3498 const AiDefaultBlockData *ptr; |
3502 const AiDefaultBlockData *ptr; |
3499 TileIndex tile; |
3503 TileIndex tile; |
3500 int veh; |
3504 EngineID veh; |
3501 int i; |
3505 int i; |
3502 uint loco_id; |
3506 uint loco_id; |
3503 |
3507 |
3504 ptr = _airport_default_block_data[p->ai.src.cur_building_rule]; |
3508 ptr = _airport_default_block_data[p->ai.src.cur_building_rule]; |
3505 for(;ptr->mode!=0;ptr++) {} |
3509 for(;ptr->mode!=0;ptr++) {} |
3506 |
3510 |
3507 tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs)); |
3511 tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs)); |
3508 |
3512 |
3509 veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind!=0 ? 1 : 0); |
3513 veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind!=0 ? 1 : 0); |
3510 if (veh == -1) return; |
3514 if (veh == INVALID_ENGINE) return; |
3511 |
3515 |
3512 /* XXX - Have the AI pick the hangar terminal in an airport. Eg get airport-type |
3516 /* XXX - Have the AI pick the hangar terminal in an airport. Eg get airport-type |
3513 * and offset to the FIRST depot because the AI picks the st->xy tile */ |
3517 * and offset to the FIRST depot because the AI picks the st->xy tile */ |
3514 tile += ToTileIndexDiff(GetAirport(GetStation(_m[tile].m2)->airport_type)->airport_depots[0]); |
3518 tile += ToTileIndexDiff(GetAirport(GetStation(_m[tile].m2)->airport_type)->airport_depots[0]); |
3515 if (CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return; |
3519 if (CmdFailed(DoCommandByTile(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return; |