00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "../../stdafx.h"
00021 #include "../../openttd.h"
00022 #include "../../debug.h"
00023 #include "../../road_map.h"
00024 #include "../../station_map.h"
00025 #include "../../command_func.h"
00026 #include "trolly.h"
00027 #include "../../town.h"
00028 #include "../../industry.h"
00029 #include "../../station.h"
00030 #include "../../engine.h"
00031 #include "../../gui.h"
00032 #include "../../depot.h"
00033 #include "../../vehicle_base.h"
00034 #include "../../vehicle_func.h"
00035 #include "../../date_func.h"
00036 #include "../ai.h"
00037 #include "../../order.h"
00038 #include "../../player_base.h"
00039 #include "../../player_func.h"
00040
00041 #include "table/strings.h"
00042
00043 PlayerAiNew _players_ainew[MAX_PLAYERS];
00044
00045
00046 static void AiNew_State_FirstTime(Player *p)
00047 {
00048
00049
00050
00051
00052 assert(_players_ainew[p->index].state == AI_STATE_FIRST_TIME);
00053
00054
00055 if (_current_player == 1) ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_IN_PROGRESS, 0, 0);
00056
00057
00058
00059
00060 _players_ainew[p->index].path_info.start_tile_tl = 0;
00061 _players_ainew[p->index].path_info.start_tile_br = 0;
00062 _players_ainew[p->index].path_info.end_tile_tl = 0;
00063 _players_ainew[p->index].path_info.end_tile_br = 0;
00064 _players_ainew[p->index].pathfinder = new_AyStar_AiPathFinder(12, &_players_ainew[p->index].path_info);
00065
00066 _players_ainew[p->index].idle = 0;
00067 _players_ainew[p->index].last_vehiclecheck_date = _date;
00068
00069
00070 _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
00071
00072
00073 _players_ainew[p->index].state = AI_STATE_WAKE_UP;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 static void AiNew_State_Nothing(Player *p)
00085 {
00086 assert(_players_ainew[p->index].state == AI_STATE_NOTHING);
00087
00088 if (_players_ainew[p->index].idle == 0) _players_ainew[p->index].idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS;
00089 if (--_players_ainew[p->index].idle == 0) {
00090
00091
00092 _players_ainew[p->index].state = AI_STATE_WAKE_UP;
00093 }
00094 }
00095
00096
00097
00098
00099
00100
00101
00102 static void AiNew_State_WakeUp(Player *p)
00103 {
00104 int c;
00105 assert(_players_ainew[p->index].state == AI_STATE_WAKE_UP);
00106
00107 if (p->location_of_house == 0) {
00108
00109
00110
00111 AiNew_Build_CompanyHQ(p, AI_Random() % MapSize());
00112
00113
00114 return;
00115 }
00116
00117 Money money = p->player_money - AI_MINIMUM_MONEY;
00118
00119
00120 if (_players_ainew[p->index].action == AI_ACTION_NONE) {
00121 c = AI_Random() & 0xFF;
00122 if (p->current_loan > 0 &&
00123 p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN &&
00124 c < 10) {
00125 _players_ainew[p->index].action = AI_ACTION_REPAY_LOAN;
00126 } else if (_players_ainew[p->index].last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
00127
00128 _players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES;
00129 _players_ainew[p->index].last_vehiclecheck_date = _date;
00130 } else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
00131
00132 if (GetFreeUnitNumber(VEH_ROAD) <= _patches.max_roadveh) {
00133 if (c < 85) {
00134 _players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE;
00135 } else {
00136 _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
00137 }
00138 }
00139 #if 0
00140 } else if (c < 200 && !_patches.ai_disable_veh_train) {
00141 if (GetFreeUnitNumber(VEH_TRAIN) <= _patches.max_trains) {
00142 _players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE;
00143 }
00144 #endif
00145 }
00146
00147 _players_ainew[p->index].counter = 0;
00148 }
00149
00150 if (_players_ainew[p->index].counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) {
00151 _players_ainew[p->index].action = AI_ACTION_NONE;
00152 return;
00153 }
00154
00155 if (_patches.ai_disable_veh_roadveh && (
00156 _players_ainew[p->index].action == AI_ACTION_BUS_ROUTE ||
00157 _players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE
00158 )) {
00159 _players_ainew[p->index].action = AI_ACTION_NONE;
00160 return;
00161 }
00162
00163 if (_players_ainew[p->index].action == AI_ACTION_REPAY_LOAN &&
00164 money > AI_MINIMUM_LOAN_REPAY_MONEY) {
00165
00166 _players_ainew[p->index].state = AI_STATE_REPAY_MONEY;
00167 return;
00168 }
00169
00170 if (_players_ainew[p->index].action == AI_ACTION_CHECK_ALL_VEHICLES) {
00171 _players_ainew[p->index].state = AI_STATE_CHECK_ALL_VEHICLES;
00172 return;
00173 }
00174
00175
00176
00177 if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE &&
00178 money > AI_MINIMUM_BUS_ROUTE_MONEY) {
00179 if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
00180 _players_ainew[p->index].action = AI_ACTION_NONE;
00181 return;
00182 }
00183 _players_ainew[p->index].cargo = AI_NEED_CARGO;
00184 _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
00185 _players_ainew[p->index].tbt = AI_BUS;
00186 return;
00187 }
00188 if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE &&
00189 money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
00190 if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
00191 _players_ainew[p->index].action = AI_ACTION_NONE;
00192 return;
00193 }
00194 _players_ainew[p->index].cargo = AI_NEED_CARGO;
00195 _players_ainew[p->index].last_id = 0;
00196 _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
00197 _players_ainew[p->index].tbt = AI_TRUCK;
00198 return;
00199 }
00200
00201 _players_ainew[p->index].state = AI_STATE_NOTHING;
00202 }
00203
00204
00205 static void AiNew_State_ActionDone(Player *p)
00206 {
00207 _players_ainew[p->index].action = AI_ACTION_NONE;
00208 _players_ainew[p->index].state = AI_STATE_NOTHING;
00209 }
00210
00211
00212
00213 static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type)
00214 {
00215 if (type == AI_CITY) {
00216 const Town* t = GetTown(ic);
00217 const Station* st;
00218 uint count = 0;
00219 int j = 0;
00220
00221
00222 if (t->road_build_months != 0) return false;
00223
00224
00225
00226 if (t->ratings[_current_player] < 0 && AI_CHANCE16(1, 4)) return false;
00227
00228 if (t->max_pass - t->act_pass < AI_CHECKCITY_NEEDED_CARGO && !AI_CHANCE16(1, AI_CHECKCITY_CITY_CHANCE)) return false;
00229
00230
00231
00232
00233
00234 FOR_ALL_STATIONS(st) {
00235
00236 if (st->owner == _current_player) {
00237
00238 if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) != FACIL_BUS_STOP) continue;
00239
00240 if (st->town != t) continue;
00241
00242 if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
00243
00244 count++;
00245 } else {
00246
00247
00248
00249
00250 if (!st->goods[CT_PASSENGERS].last_speed) continue;
00251
00252 if (DistanceManhattan(st->xy, t->xy) > 10) continue;
00253
00254 if (st->goods[CT_PASSENGERS].rating < AI_CHECKCITY_CARGO_RATING) continue;
00255 j++;
00256
00257 if (j == 1) continue;
00258
00259
00260
00261 if (j == 2 && AI_CHANCE16(1, AI_CHECKCITY_CARGO_RATING_CHANCE)) continue;
00262
00263 return false;
00264 }
00265 }
00266
00267
00268 count++;
00269
00270 if (count * AI_CHECKCITY_CARGO_PER_STATION > t->max_pass) return false;
00271
00272
00273 return true;
00274 }
00275 if (type == AI_INDUSTRY) {
00276 const Industry* i = GetIndustry(ic);
00277 const Station* st;
00278 int count = 0;
00279 int j = 0;
00280
00281 if (i->town != NULL && i->town->ratings[_current_player] < 0 && AI_CHANCE16(1, 4)) return false;
00282
00283
00284
00285 if (i->produced_cargo[0] == CT_INVALID || i->last_month_production[0] == 0) return true;
00286
00287 if (i->last_month_production[0] - i->last_month_transported[0] < AI_CHECKCITY_NEEDED_CARGO) return false;
00288
00289
00290
00291
00292 FOR_ALL_STATIONS(st) {
00293
00294 if (st->owner == _current_player) {
00295
00296 if (_players_ainew[p->index].tbt == AI_TRUCK && (FACIL_TRUCK_STOP & st->facilities) != FACIL_TRUCK_STOP) continue;
00297
00298 if (st->town != i->town) continue;
00299
00300 if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
00301
00302 count++;
00303 } else {
00304
00305
00306
00307
00308 if (i->produced_cargo[0] == CT_INVALID) continue;
00309
00310 if (!st->goods[i->produced_cargo[0]].last_speed) continue;
00311
00312 if (DistanceManhattan(st->xy, i->xy) > 5) continue;
00313
00314 if (st->goods[i->produced_cargo[0]].rating < AI_CHECKCITY_CARGO_RATING) continue;
00315 j++;
00316
00317
00318 if (j == 1 && AI_CHANCE16(1, AI_CHECKCITY_CARGO_RATING_CHANCE)) continue;
00319
00320 return false;
00321 }
00322 }
00323
00324
00325 count++;
00326
00327 if (count * AI_CHECKCITY_CARGO_PER_STATION > i->last_month_production[0]) return false;
00328
00329
00330 return true;
00331 }
00332
00333 return true;
00334 }
00335
00336
00337
00338 static void AiNew_State_LocateRoute(Player *p)
00339 {
00340 assert(_players_ainew[p->index].state == AI_STATE_LOCATE_ROUTE);
00341
00342
00343
00344 if (_players_ainew[p->index].cargo == AI_NEED_CARGO) {
00345 _players_ainew[p->index].new_cost = 0;
00346 _players_ainew[p->index].temp = -1;
00347
00348 _players_ainew[p->index].counter = 0;
00349
00350 _players_ainew[p->index].from_ic = -1;
00351 _players_ainew[p->index].to_ic = -1;
00352 if (_players_ainew[p->index].tbt == AI_BUS) {
00353
00354 _players_ainew[p->index].cargo = CT_PASSENGERS;
00355
00356
00357 _players_ainew[p->index].from_type = AI_CITY;
00358 _players_ainew[p->index].to_type = AI_CITY;
00359 } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
00360 _players_ainew[p->index].cargo = AI_NO_CARGO;
00361
00362 _players_ainew[p->index].from_type = AI_INDUSTRY;
00363 _players_ainew[p->index].to_type = AI_INDUSTRY;
00364 }
00365
00366
00367 return;
00368 }
00369
00370
00371 _players_ainew[p->index].counter++;
00372 if (_players_ainew[p->index].counter > AI_LOCATE_ROUTE_MAX_COUNTER) {
00373
00374 _players_ainew[p->index].state = AI_STATE_NOTHING;
00375 return;
00376 }
00377
00378
00379 if (_players_ainew[p->index].from_ic == -1) {
00380 if (_players_ainew[p->index].temp == -1) {
00381
00382 if (_players_ainew[p->index].from_type == AI_CITY) {
00383 _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
00384 } else {
00385 _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
00386 }
00387 }
00388
00389 if (!AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].from_type)) {
00390
00391
00392
00393 _players_ainew[p->index].temp++;
00394 if (_players_ainew[p->index].from_type == AI_CITY) {
00395 if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
00396 } else {
00397 if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
00398 }
00399
00400
00401 if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
00402 _players_ainew[p->index].last_id = _players_ainew[p->index].temp;
00403
00404 return;
00405 }
00406
00407
00408 _players_ainew[p->index].from_ic = _players_ainew[p->index].temp;
00409
00410
00411 _players_ainew[p->index].temp = -1;
00412 return;
00413 }
00414
00415
00416 if (_players_ainew[p->index].temp == -1) {
00417
00418 if (_players_ainew[p->index].to_type == AI_CITY) {
00419 _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
00420 } else {
00421 _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
00422 }
00423 }
00424
00425
00426
00427 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)) {
00428
00429
00430
00431
00432
00433
00434
00435 if (_players_ainew[p->index].from_type == AI_CITY && _players_ainew[p->index].tbt == AI_BUS) {
00436 const Town* town_from = GetTown(_players_ainew[p->index].from_ic);
00437 const Town* town_temp = GetTown(_players_ainew[p->index].temp);
00438 uint distance = DistanceManhattan(town_from->xy, town_temp->xy);
00439 int max_cargo;
00440
00441 max_cargo = town_from->max_pass + town_temp->max_pass;
00442 max_cargo -= town_from->act_pass + town_temp->act_pass;
00443
00444
00445
00446 if (distance <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
00447
00448 _players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
00449 _players_ainew[p->index].state = AI_STATE_FIND_STATION;
00450
00451 DEBUG(ai, 1, "[LocateRoute] found bus-route of %d tiles long (from %d to %d)",
00452 distance,
00453 _players_ainew[p->index].from_ic,
00454 _players_ainew[p->index].temp
00455 );
00456
00457 _players_ainew[p->index].from_tile = 0;
00458 _players_ainew[p->index].to_tile = 0;
00459
00460 return;
00461 }
00462 } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
00463 const Industry* ind_from = GetIndustry(_players_ainew[p->index].from_ic);
00464 const Industry* ind_temp = GetIndustry(_players_ainew[p->index].temp);
00465 bool found = false;
00466 int max_cargo = 0;
00467 uint i;
00468
00469
00470
00471 if (ind_from->produced_cargo[0] != CT_INVALID && ind_from->last_month_production[0] != 0) {
00472 for (i = 0; i < lengthof(ind_temp->accepts_cargo); i++) {
00473 if (ind_temp->accepts_cargo[i] == CT_INVALID) break;
00474 if (ind_from->produced_cargo[0] == ind_temp->accepts_cargo[i]) {
00475
00476 max_cargo = ind_from->last_month_production[0] - ind_from->last_month_transported[0];
00477 found = true;
00478 _players_ainew[p->index].from_deliver = true;
00479 _players_ainew[p->index].to_deliver = false;
00480 break;
00481 }
00482 }
00483 }
00484 if (!found && ind_temp->produced_cargo[0] != CT_INVALID && ind_temp->last_month_production[0] != 0) {
00485
00486 for (i = 0; i < lengthof(ind_from->accepts_cargo); i++) {
00487 if (ind_from->accepts_cargo[i] == CT_INVALID) break;
00488 if (ind_from->produced_cargo[0] == ind_from->accepts_cargo[i]) {
00489
00490 found = true;
00491 max_cargo = ind_temp->last_month_production[0] - ind_temp->last_month_transported[0];
00492 _players_ainew[p->index].from_deliver = false;
00493 _players_ainew[p->index].to_deliver = true;
00494 break;
00495 }
00496 }
00497 }
00498 if (found) {
00499
00500
00501 uint distance = DistanceManhattan(ind_from->xy, ind_temp->xy);
00502
00503 if (distance > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
00504 distance <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
00505 _players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
00506 if (_players_ainew[p->index].from_deliver) {
00507 _players_ainew[p->index].cargo = ind_from->produced_cargo[0];
00508 } else {
00509 _players_ainew[p->index].cargo = ind_temp->produced_cargo[0];
00510 }
00511 _players_ainew[p->index].state = AI_STATE_FIND_STATION;
00512
00513 DEBUG(ai, 1, "[LocateRoute] found truck-route of %d tiles long (from %d to %d)",
00514 distance,
00515 _players_ainew[p->index].from_ic,
00516 _players_ainew[p->index].temp
00517 );
00518
00519 _players_ainew[p->index].from_tile = 0;
00520 _players_ainew[p->index].to_tile = 0;
00521
00522 return;
00523 }
00524 }
00525 }
00526 }
00527
00528
00529
00530
00531 _players_ainew[p->index].temp++;
00532 if (_players_ainew[p->index].to_type == AI_CITY) {
00533 if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
00534 } else {
00535 if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
00536 }
00537
00538
00539 if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
00540 _players_ainew[p->index].last_id = _players_ainew[p->index].temp;
00541 }
00542
00543
00544
00545
00546 static bool AiNew_CheckVehicleStation(Player *p, Station *st)
00547 {
00548 int count = 0;
00549 Vehicle *v;
00550
00551
00552 FOR_ALL_VEHICLES(v) {
00553 if (v->owner == _current_player) {
00554 const Order *order;
00555
00556 FOR_VEHICLE_ORDERS(v, order) {
00557 if (order->type == OT_GOTO_STATION && GetStation(order->dest) == st) {
00558
00559 count++;
00560 }
00561 }
00562 }
00563 }
00564
00565 if (count > AI_CHECK_MAX_VEHICLE_PER_STATION) return false;
00566 return true;
00567 }
00568
00569
00570 static void AiNew_State_FindStation(Player *p)
00571 {
00572 TileIndex tile;
00573 Station *st;
00574 int count = 0;
00575 EngineID i;
00576 TileIndex new_tile = 0;
00577 DiagDirection direction = DIAGDIR_NE;
00578 Town *town = NULL;
00579 assert(_players_ainew[p->index].state == AI_STATE_FIND_STATION);
00580
00581 if (_players_ainew[p->index].from_tile == 0) {
00582
00583 if (_players_ainew[p->index].from_type == AI_CITY) {
00584 town = GetTown(_players_ainew[p->index].from_ic);
00585 tile = town->xy;
00586 } else {
00587 tile = GetIndustry(_players_ainew[p->index].from_ic)->xy;
00588 }
00589 } else if (_players_ainew[p->index].to_tile == 0) {
00590
00591 if (_players_ainew[p->index].to_type == AI_CITY) {
00592 town = GetTown(_players_ainew[p->index].to_ic);
00593 tile = town->xy;
00594 } else {
00595 tile = GetIndustry(_players_ainew[p->index].to_ic)->xy;
00596 }
00597 } else {
00598
00599
00600 _players_ainew[p->index].temp = -1;
00601 _players_ainew[p->index].state = AI_STATE_FIND_PATH;
00602 return;
00603 }
00604
00605
00606
00607
00608 i = AiNew_PickVehicle(p);
00609
00610
00611 if (i == INVALID_ENGINE) {
00612 _players_ainew[p->index].state = AI_STATE_NOTHING;
00613 return;
00614 }
00615
00616 FOR_ALL_STATIONS(st) {
00617 if (st->owner == _current_player) {
00618 if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
00619 if (st->town == town) {
00620
00621 if ((int)st->goods[_players_ainew[p->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
00622 if (AiNew_CheckVehicleStation(p, st)) {
00623
00624 new_tile = st->xy;
00625 direction = GetRoadStopDir(st->xy);
00626 break;
00627 }
00628 }
00629 count++;
00630 }
00631 }
00632 }
00633 }
00634
00635 if (new_tile == 0) count++;
00636
00637
00638 if (count > 2) {
00639 _players_ainew[p->index].state = AI_STATE_NOTHING;
00640 return;
00641 }
00642
00643 if (new_tile == 0 && _players_ainew[p->index].tbt == AI_BUS) {
00644 uint x, y, i = 0;
00645 CommandCost r;
00646 uint best;
00647 uint accepts[NUM_CARGO];
00648 TileIndex found_spot[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
00649 uint found_best[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
00650
00651
00652
00653
00654 for (x = TileX(tile) - AI_FINDSTATION_TILE_RANGE; x <= TileX(tile) + AI_FINDSTATION_TILE_RANGE; x++) {
00655 for (y = TileY(tile) - AI_FINDSTATION_TILE_RANGE; y <= TileY(tile) + AI_FINDSTATION_TILE_RANGE; y++) {
00656 new_tile = TileXY(x, y);
00657 if (IsTileType(new_tile, MP_CLEAR) || IsTileType(new_tile, MP_TREES)) {
00658
00659
00660
00661 GetAcceptanceAroundTiles(accepts, new_tile, 1, 1, 4);
00662
00663 if (accepts[_players_ainew[p->index].cargo] >> 3 == 0) continue;
00664
00665 r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
00666 if (CmdFailed(r)) continue;
00667
00668 found_spot[i] = new_tile;
00669 found_best[i++] = accepts[_players_ainew[p->index].cargo];
00670 }
00671 }
00672 }
00673
00674
00675 if (i == 0) {
00676 _players_ainew[p->index].state = AI_STATE_NOTHING;
00677 return;
00678 }
00679
00680
00681 best = 0;
00682 new_tile = 0;
00683
00684 for (x = 0; x < i; x++) {
00685 if (found_best[x] > best ||
00686 (found_best[x] == best && DistanceManhattan(tile, new_tile) > DistanceManhattan(tile, found_spot[x]))) {
00687 new_tile = found_spot[x];
00688 best = found_best[x];
00689 }
00690 }
00691
00692
00693 r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
00694 _players_ainew[p->index].new_cost += r.GetCost();
00695
00696 direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
00697 } else if (new_tile == 0 && _players_ainew[p->index].tbt == AI_TRUCK) {
00698
00699
00700
00701 new_tile = AI_STATION_RANGE;
00702 direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
00703 }
00704
00705 if (_players_ainew[p->index].from_tile == 0) {
00706 _players_ainew[p->index].from_tile = new_tile;
00707 _players_ainew[p->index].from_direction = direction;
00708
00709 return;
00710 } else if (_players_ainew[p->index].to_tile == 0) {
00711 _players_ainew[p->index].to_tile = new_tile;
00712 _players_ainew[p->index].to_direction = direction;
00713
00714 _players_ainew[p->index].temp = -1;
00715 _players_ainew[p->index].state = AI_STATE_FIND_PATH;
00716 return;
00717 }
00718 }
00719
00720
00721
00722 static void AiNew_State_FindPath(Player *p)
00723 {
00724 int r;
00725 assert(_players_ainew[p->index].state == AI_STATE_FIND_PATH);
00726
00727
00728 if (_players_ainew[p->index].temp == -1) {
00729
00730 if (_players_ainew[p->index].from_tile == AI_STATION_RANGE) {
00731 const Industry* i = GetIndustry(_players_ainew[p->index].from_ic);
00732
00733
00734 _players_ainew[p->index].path_info.start_tile_tl = i->xy - TileDiffXY(1, 1);
00735 _players_ainew[p->index].path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
00736 _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
00737 } else {
00738 _players_ainew[p->index].path_info.start_tile_tl = _players_ainew[p->index].from_tile;
00739 _players_ainew[p->index].path_info.start_tile_br = _players_ainew[p->index].from_tile;
00740 _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
00741 }
00742
00743 if (_players_ainew[p->index].to_tile == AI_STATION_RANGE) {
00744 const Industry* i = GetIndustry(_players_ainew[p->index].to_ic);
00745
00746 _players_ainew[p->index].path_info.end_tile_tl = i->xy - TileDiffXY(1, 1);
00747 _players_ainew[p->index].path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
00748 _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
00749 } else {
00750 _players_ainew[p->index].path_info.end_tile_tl = _players_ainew[p->index].to_tile;
00751 _players_ainew[p->index].path_info.end_tile_br = _players_ainew[p->index].to_tile;
00752 _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
00753 }
00754
00755 _players_ainew[p->index].path_info.rail_or_road = (_players_ainew[p->index].tbt == AI_TRAIN);
00756
00757
00758 clean_AyStar_AiPathFinder(_players_ainew[p->index].pathfinder, &_players_ainew[p->index].path_info);
00759
00760 _players_ainew[p->index].temp = 0;
00761 }
00762
00763
00764 r = _players_ainew[p->index].pathfinder->main(_players_ainew[p->index].pathfinder);
00765 switch (r) {
00766 case AYSTAR_NO_PATH:
00767 DEBUG(ai, 1, "No route found by pathfinder");
00768
00769 _players_ainew[p->index].state = AI_STATE_NOTHING;
00770 break;
00771
00772 case AYSTAR_FOUND_END_NODE:
00773 _players_ainew[p->index].temp = -1;
00774 _players_ainew[p->index].state = AI_STATE_FIND_DEPOT;
00775 break;
00776
00777
00778 default: break;
00779 }
00780 }
00781
00782
00783
00784 static void AiNew_State_FindDepot(Player *p)
00785 {
00786
00787
00788
00789
00790
00791 int g, i;
00792 CommandCost r;
00793 DiagDirection j;
00794 TileIndex tile;
00795 assert(_players_ainew[p->index].state == AI_STATE_FIND_DEPOT);
00796
00797 _players_ainew[p->index].depot_tile = 0;
00798
00799 for (i=2;i<_players_ainew[p->index].path_info.route_length-2;i++) {
00800 tile = _players_ainew[p->index].path_info.route[i];
00801 for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
00802 TileIndex t = tile + TileOffsByDiagDir(j);
00803
00804 if (IsRoadDepotTile(t) &&
00805 IsTileOwner(t, _current_player) &&
00806 GetRoadDepotDirection(t) == ReverseDiagDir(j)) {
00807 _players_ainew[p->index].depot_tile = t;
00808 _players_ainew[p->index].depot_direction = ReverseDiagDir(j);
00809 _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
00810 return;
00811 }
00812 }
00813 }
00814
00815
00816
00817 i = _players_ainew[p->index].path_info.route_length / 2;
00818 g = 1;
00819 while (i > 1 && i < _players_ainew[p->index].path_info.route_length - 2) {
00820 i += g;
00821 g *= -1;
00822 (g < 0?g--:g++);
00823
00824 if (_players_ainew[p->index].path_info.route_extra[i] != 0 || _players_ainew[p->index].path_info.route_extra[i+1] != 0) {
00825
00826 continue;
00827 }
00828
00829 tile = _players_ainew[p->index].path_info.route[i];
00830
00831 for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
00832 TileIndex t = tile + TileOffsByDiagDir(j);
00833
00834
00835
00836
00837 if (t == _players_ainew[p->index].path_info.route[i - 1] ||
00838 t == _players_ainew[p->index].path_info.route[i + 1]) {
00839 continue;
00840 }
00841
00842 if (_players_ainew[p->index].path_info.route_extra[i] != 0) continue;
00843 if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
00844
00845 if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) {
00846
00847 if (GetTileSlope(tile, NULL) != SLOPE_FLAT) continue;
00848
00849 r = AiNew_Build_Depot(p, t, ReverseDiagDir(j), 0);
00850 if (CmdFailed(r)) continue;
00851
00852 _players_ainew[p->index].new_cost += r.GetCost();
00853 _players_ainew[p->index].depot_tile = t;
00854 _players_ainew[p->index].depot_direction = ReverseDiagDir(j);
00855 _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
00856 return;
00857 }
00858 }
00859 }
00860
00861
00862 _players_ainew[p->index].state = AI_STATE_NOTHING;
00863 }
00864
00865
00866
00867
00868
00869
00870
00871 static int AiNew_HowManyVehicles(Player *p)
00872 {
00873 if (_players_ainew[p->index].tbt == AI_BUS) {
00874
00875 EngineID i;
00876 int length, tiles_a_day;
00877 int amount;
00878 i = AiNew_PickVehicle(p);
00879 if (i == INVALID_ENGINE) return 0;
00880
00881 length = _players_ainew[p->index].path_info.route_length;
00882
00883 tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
00884 if (tiles_a_day == 0) tiles_a_day = 1;
00885
00886
00887 amount = length * 2 * 2 / tiles_a_day / 30;
00888 if (amount == 0) amount = 1;
00889 return amount;
00890 } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
00891
00892 EngineID i;
00893 int length, amount, tiles_a_day;
00894 int max_cargo;
00895 i = AiNew_PickVehicle(p);
00896 if (i == INVALID_ENGINE) return 0;
00897
00898 length = _players_ainew[p->index].path_info.route_length;
00899
00900 tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
00901 if (tiles_a_day == 0) tiles_a_day = 1;
00902 if (_players_ainew[p->index].from_deliver) {
00903 max_cargo = GetIndustry(_players_ainew[p->index].from_ic)->last_month_production[0];
00904 } else {
00905 max_cargo = GetIndustry(_players_ainew[p->index].to_ic)->last_month_production[0];
00906 }
00907
00908
00909 max_cargo *= 6;
00910 max_cargo /= 10;
00911
00912
00913
00914 amount = 2 * length * max_cargo / tiles_a_day / 30 / RoadVehInfo(i)->capacity;
00915 amount += 1;
00916 return amount;
00917 } else {
00918
00919 return 0;
00920 }
00921 }
00922
00923
00924
00925
00926
00927
00928 static void AiNew_State_VerifyRoute(Player *p)
00929 {
00930 int res, i;
00931 assert(_players_ainew[p->index].state == AI_STATE_VERIFY_ROUTE);
00932
00933
00934
00935 _players_ainew[p->index].path_info.position = -1;
00936
00937 do {
00938 _players_ainew[p->index].path_info.position++;
00939 _players_ainew[p->index].new_cost += AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_QUERY_COST).GetCost();
00940 } while (_players_ainew[p->index].path_info.position != -2);
00941
00942
00943
00944 res = AiNew_HowManyVehicles(p);
00945
00946 if (res == 0) {
00947 _players_ainew[p->index].state = AI_STATE_NOTHING;
00948 return;
00949 }
00950 _players_ainew[p->index].amount_veh = res;
00951 _players_ainew[p->index].cur_veh = 0;
00952
00953
00954 for (i=0;i<res;i++) {
00955 _players_ainew[p->index].new_cost += AiNew_Build_Vehicle(p, 0, DC_QUERY_COST).GetCost();
00956 }
00957
00958
00959
00960 if (_players_ainew[p->index].new_cost > p->player_money - AI_MINIMUM_MONEY) {
00961
00962 DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)_players_ainew[p->index].new_cost);
00963 _players_ainew[p->index].state = AI_STATE_NOTHING;
00964 return;
00965 }
00966
00967
00968 if (_players_ainew[p->index].from_direction == AI_PATHFINDER_NO_DIRECTION) {
00969 _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]);
00970 }
00971 if (_players_ainew[p->index].to_direction == AI_PATHFINDER_NO_DIRECTION) {
00972 _players_ainew[p->index].to_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[0], _players_ainew[p->index].path_info.route[1]);
00973 }
00974 if (_players_ainew[p->index].from_tile == AI_STATION_RANGE)
00975 _players_ainew[p->index].from_tile = _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1];
00976 if (_players_ainew[p->index].to_tile == AI_STATION_RANGE)
00977 _players_ainew[p->index].to_tile = _players_ainew[p->index].path_info.route[0];
00978
00979 _players_ainew[p->index].state = AI_STATE_BUILD_STATION;
00980 _players_ainew[p->index].temp = 0;
00981
00982 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);
00983 }
00984
00985
00986
00987 static void AiNew_State_BuildStation(Player *p)
00988 {
00989 CommandCost res;
00990 assert(_players_ainew[p->index].state == AI_STATE_BUILD_STATION);
00991 if (_players_ainew[p->index].temp == 0) {
00992 if (!IsTileType(_players_ainew[p->index].from_tile, MP_STATION))
00993 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);
00994 } else {
00995 if (!IsTileType(_players_ainew[p->index].to_tile, MP_STATION))
00996 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);
00997 _players_ainew[p->index].state = AI_STATE_BUILD_PATH;
00998 }
00999 if (CmdFailed(res)) {
01000 DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", _players_ainew[p->index].to_tile);
01001 _players_ainew[p->index].state = AI_STATE_NOTHING;
01002
01003 if (_players_ainew[p->index].temp != 0)
01004 AI_DoCommand(_players_ainew[p->index].from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
01005 return;
01006 }
01007 _players_ainew[p->index].temp++;
01008 }
01009
01010
01011
01012 static void AiNew_State_BuildPath(Player *p)
01013 {
01014 assert(_players_ainew[p->index].state == AI_STATE_BUILD_PATH);
01015
01016 if (_players_ainew[p->index].temp == -1) {
01017 DEBUG(ai, 1, "Starting to build new path");
01018
01019 _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
01020
01021 _players_ainew[p->index].path_info.position = -1;
01022
01023 _players_ainew[p->index].temp = 0;
01024 }
01025
01026
01027 if (--_players_ainew[p->index].counter != 0) return;
01028 _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
01029
01030
01031 _players_ainew[p->index].path_info.position++;
01032
01033 AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_EXEC);
01034 if (_players_ainew[p->index].path_info.position == -2) {
01035
01036
01037 if (_players_ainew[p->index].tbt == AI_TRUCK && !_patches.roadveh_queue) {
01038
01039
01040 DiagDirection dir1, dir2, dir3;
01041 TileIndex tile;
01042 CommandCost ret;
01043 for (int i = 0; i < 2; i++) {
01044 if (i == 0) {
01045 tile = _players_ainew[p->index].from_tile + TileOffsByDiagDir(_players_ainew[p->index].from_direction);
01046 dir1 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90LEFT);
01047 dir2 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90RIGHT);
01048 dir3 = _players_ainew[p->index].from_direction;
01049 } else {
01050 tile = _players_ainew[p->index].to_tile + TileOffsByDiagDir(_players_ainew[p->index].to_direction);
01051 dir1 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90LEFT);
01052 dir2 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90RIGHT);
01053 dir3 = _players_ainew[p->index].to_direction;
01054 }
01055
01056 ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir1)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01057 if (CmdSucceeded(ret)) {
01058 TileIndex offset = TileOffsByDiagDir(dir1);
01059 if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
01060 ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01061 if (CmdSucceeded(ret)) {
01062 if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
01063 AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01064 }
01065 }
01066 }
01067
01068 ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir2)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01069 if (CmdSucceeded(ret)) {
01070 TileIndex offset = TileOffsByDiagDir(dir2);
01071 if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
01072 ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01073 if (CmdSucceeded(ret)) {
01074 if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
01075 AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01076 }
01077 }
01078 }
01079
01080 ret = AI_DoCommand(tile, DiagDirToRoadBits(dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01081 if (CmdSucceeded(ret)) {
01082 TileIndex offset = TileOffsByDiagDir(dir3);
01083 if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
01084 ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01085 if (CmdSucceeded(ret)) {
01086 if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
01087 AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
01088 }
01089 }
01090 }
01091 }
01092 }
01093
01094 DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)_players_ainew[p->index].new_cost);
01095 _players_ainew[p->index].state = AI_STATE_BUILD_DEPOT;
01096 }
01097 }
01098
01099
01100
01101 static void AiNew_State_BuildDepot(Player *p)
01102 {
01103 CommandCost res;
01104 assert(_players_ainew[p->index].state == AI_STATE_BUILD_DEPOT);
01105
01106 if (IsRoadDepotTile(_players_ainew[p->index].depot_tile)) {
01107 if (IsTileOwner(_players_ainew[p->index].depot_tile, _current_player)) {
01108
01109 _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
01110 return;
01111 } else {
01112
01113 _players_ainew[p->index].state = AI_STATE_NOTHING;
01114 return;
01115 }
01116 }
01117
01118
01119 if (!EnsureNoVehicleOnGround(_players_ainew[p->index].depot_tile + TileOffsByDiagDir(_players_ainew[p->index].depot_direction)))
01120 return;
01121
01122 res = AiNew_Build_Depot(p, _players_ainew[p->index].depot_tile, _players_ainew[p->index].depot_direction, DC_EXEC);
01123 if (CmdFailed(res)) {
01124 DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", _players_ainew[p->index].depot_tile);
01125 _players_ainew[p->index].state = AI_STATE_NOTHING;
01126 return;
01127 }
01128
01129 _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
01130 _players_ainew[p->index].idle = 10;
01131 _players_ainew[p->index].veh_main_id = INVALID_VEHICLE;
01132 }
01133
01134
01135
01136 static void AiNew_State_BuildVehicle(Player *p)
01137 {
01138 CommandCost res;
01139 assert(_players_ainew[p->index].state == AI_STATE_BUILD_VEHICLE);
01140
01141
01142 if (_players_ainew[p->index].amount_veh == 0) {
01143
01144
01145
01146 _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
01147 return;
01148 }
01149 if (--_players_ainew[p->index].idle != 0) return;
01150
01151
01152 _players_ainew[p->index].idle = AI_BUILD_VEHICLE_TIME_BETWEEN;
01153
01154
01155 res = AiNew_Build_Vehicle(p, _players_ainew[p->index].depot_tile, DC_EXEC);
01156 if (CmdFailed(res)) {
01157
01158 _players_ainew[p->index].state = AI_STATE_NOTHING;
01159 return;
01160 }
01161
01162 _players_ainew[p->index].cur_veh++;
01163
01164 _players_ainew[p->index].amount_veh--;
01165
01166 _players_ainew[p->index].state = AI_STATE_WAIT_FOR_BUILD;
01167 }
01168
01169
01170
01171 static void AiNew_State_GiveOrders(Player *p)
01172 {
01173 int idx;
01174 Order order;
01175
01176 assert(_players_ainew[p->index].state == AI_STATE_GIVE_ORDERS);
01177
01178 if (_players_ainew[p->index].veh_main_id != INVALID_VEHICLE) {
01179 AI_DoCommand(0, _players_ainew[p->index].veh_id + (_players_ainew[p->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
01180
01181 _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
01182 return;
01183 } else {
01184 _players_ainew[p->index].veh_main_id = _players_ainew[p->index].veh_id;
01185 }
01186
01187
01188 if (_patches.gotodepot) {
01189 idx = 0;
01190 order.type = OT_GOTO_DEPOT;
01191 order.flags = OFB_UNLOAD;
01192 order.dest = GetDepotByTile(_players_ainew[p->index].depot_tile)->index;
01193 AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
01194 }
01195
01196 idx = 0;
01197 order.type = OT_GOTO_STATION;
01198 order.flags = 0;
01199 order.dest = GetStationIndex(_players_ainew[p->index].to_tile);
01200 if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].to_deliver)
01201 order.flags |= OFB_FULL_LOAD;
01202 AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
01203
01204 idx = 0;
01205 order.type = OT_GOTO_STATION;
01206 order.flags = 0;
01207 order.dest = GetStationIndex(_players_ainew[p->index].from_tile);
01208 if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].from_deliver)
01209 order.flags |= OFB_FULL_LOAD;
01210 AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
01211
01212
01213 _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
01214 }
01215
01216
01217
01218 static void AiNew_State_StartVehicle(Player *p)
01219 {
01220 assert(_players_ainew[p->index].state == AI_STATE_START_VEHICLE);
01221
01222
01223
01224 if (_players_ainew[p->index].cur_veh & 1)
01225 AI_DoCommand(0, _players_ainew[p->index].veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER);
01226
01227
01228 AI_DoCommand(0, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
01229
01230 _players_ainew[p->index].idle = 10;
01231 _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
01232 }
01233
01234
01235
01236 static void AiNew_State_RepayMoney(Player *p)
01237 {
01238 uint i;
01239
01240 for (i = 0; i < AI_LOAN_REPAY; i++) {
01241 AI_DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
01242 }
01243 _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
01244 }
01245
01246
01247 static void AiNew_CheckVehicle(Player *p, Vehicle *v)
01248 {
01249
01250 if (v->age < 180) return;
01251
01252
01253 if (v->age > 360) {
01254
01255
01256 if (v->profit_last_year + v->profit_this_year < (Money)256 * AI_MINIMUM_ROUTE_PROFIT ||
01257 (v->reliability * 100 >> 16) < 40) {
01258
01259 if (v->cargo.DaysInTransit() > AI_VEHICLE_LOST_DAYS) {
01260
01261
01262
01263 }
01264
01265
01266
01267 if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) {
01268 if (v->type == VEH_ROAD && IsTileDepotType(v->tile, TRANSPORT_ROAD) &&
01269 (v->vehstatus&VS_STOPPED)) {
01270
01271 AI_DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
01272 }
01273 return;
01274 }
01275
01276 if (!AiNew_SetSpecialVehicleFlag(p, v, AI_VEHICLEFLAG_SELL)) return;
01277 {
01278 CommandCost ret;
01279 if (v->type == VEH_ROAD)
01280 ret = AI_DoCommand(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
01281
01282
01283 }
01284 }
01285 }
01286 }
01287
01288
01289
01290 static void AiNew_State_CheckAllVehicles(Player *p)
01291 {
01292 Vehicle *v;
01293
01294 FOR_ALL_VEHICLES(v) {
01295 if (v->owner != p->index) continue;
01296
01297 if (v->type != VEH_ROAD) continue;
01298
01299 AiNew_CheckVehicle(p, v);
01300 }
01301
01302 _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
01303 }
01304
01305
01306
01307
01308
01309 static AiNew_StateFunction* const _ainew_state[] = {
01310 NULL,
01311 AiNew_State_FirstTime,
01312 AiNew_State_Nothing,
01313 AiNew_State_WakeUp,
01314 AiNew_State_LocateRoute,
01315 AiNew_State_FindStation,
01316 AiNew_State_FindPath,
01317 AiNew_State_FindDepot,
01318 AiNew_State_VerifyRoute,
01319 AiNew_State_BuildStation,
01320 AiNew_State_BuildPath,
01321 AiNew_State_BuildDepot,
01322 AiNew_State_BuildVehicle,
01323 NULL,
01324 AiNew_State_GiveOrders,
01325 AiNew_State_StartVehicle,
01326 AiNew_State_RepayMoney,
01327 AiNew_State_CheckAllVehicles,
01328 AiNew_State_ActionDone,
01329 NULL,
01330 };
01331
01332 static void AiNew_OnTick(Player *p)
01333 {
01334 if (_ainew_state[_players_ainew[p->index].state] != NULL)
01335 _ainew_state[_players_ainew[p->index].state](p);
01336 }
01337
01338
01339 void AiNewDoGameLoop(Player *p)
01340 {
01341 if (_players_ainew[p->index].state == AI_STATE_STARTUP) {
01342
01343 _players_ainew[p->index].state = AI_STATE_FIRST_TIME;
01344 _players_ainew[p->index].tick = 0;
01345
01346
01347 return;
01348 }
01349
01350
01351 _players_ainew[p->index].tick++;
01352
01353
01354 AiNew_OnTick(p);
01355 }