00001
00002
00005 #include "../../stdafx.h"
00006 #include "../../openttd.h"
00007 #include "../../aircraft.h"
00008 #include "../../bridge_map.h"
00009 #include "../../tile_cmd.h"
00010 #include "../../landscape.h"
00011 #include "../../rail_map.h"
00012 #include "../../road_map.h"
00013 #include "../../roadveh.h"
00014 #include "../../station_map.h"
00015 #include "../../tunnel_map.h"
00016 #include "../../command_func.h"
00017 #include "../../town.h"
00018 #include "../../industry.h"
00019 #include "../../pathfind.h"
00020 #include "../../airport.h"
00021 #include "../../variables.h"
00022 #include "../../bridge.h"
00023 #include "../../date_func.h"
00024 #include "../../tunnelbridge_map.h"
00025 #include "../../window_func.h"
00026 #include "../../vehicle_func.h"
00027 #include "../../functions.h"
00028 #include "../../saveload.h"
00029 #include "../../company_func.h"
00030 #include "../../company_base.h"
00031 #include "../../settings_type.h"
00032 #include "default.h"
00033 #include "../../tunnelbridge.h"
00034 #include "../../order_func.h"
00035
00036 #include "../../table/ai_rail.h"
00037
00038
00039 static uint _ai_service_interval;
00040 CompanyAI _companies_ai[MAX_COMPANIES];
00041
00042 typedef void AiStateAction(Company *c);
00043
00044 enum {
00045 AIS_0 = 0,
00046 AIS_1 = 1,
00047 AIS_VEH_LOOP = 2,
00048 AIS_VEH_CHECK_REPLACE_VEHICLE = 3,
00049 AIS_VEH_DO_REPLACE_VEHICLE = 4,
00050 AIS_WANT_NEW_ROUTE = 5,
00051 AIS_BUILD_DEFAULT_RAIL_BLOCKS = 6,
00052 AIS_BUILD_RAIL = 7,
00053 AIS_BUILD_RAIL_VEH = 8,
00054 AIS_DELETE_RAIL_BLOCKS = 9,
00055 AIS_BUILD_DEFAULT_ROAD_BLOCKS = 10,
00056 AIS_BUILD_ROAD = 11,
00057 AIS_BUILD_ROAD_VEHICLES = 12,
00058 AIS_DELETE_ROAD_BLOCKS = 13,
00059 AIS_AIRPORT_STUFF = 14,
00060 AIS_BUILD_DEFAULT_AIRPORT_BLOCKS = 15,
00061 AIS_BUILD_AIRCRAFT_VEHICLES = 16,
00062 AIS_CHECK_SHIP_STUFF = 17,
00063 AIS_BUILD_DEFAULT_SHIP_BLOCKS = 18,
00064 AIS_DO_SHIP_STUFF = 19,
00065 AIS_SELL_VEHICLE = 20,
00066 AIS_REMOVE_STATION = 21,
00067 AIS_REMOVE_TRACK = 22,
00068 AIS_REMOVE_SINGLE_RAIL_TILE = 23
00069 };
00070
00071
00072 static inline TrackBits GetRailTrackStatus(TileIndex tile)
00073 {
00074 return TrackStatusToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, 0));
00075 }
00076
00077
00078 static void AiCase0(Company *c)
00079 {
00080 _companies_ai[c->index].state = AIS_REMOVE_TRACK;
00081 _companies_ai[c->index].state_counter = 0;
00082 }
00083
00084 static void AiCase1(Company *c)
00085 {
00086 _companies_ai[c->index].cur_veh = NULL;
00087 _companies_ai[c->index].state = AIS_VEH_LOOP;
00088 }
00089
00090 static void AiStateVehLoop(Company *c)
00091 {
00092 Vehicle *v;
00093 uint index;
00094
00095 index = (_companies_ai[c->index].cur_veh == NULL) ? 0 : _companies_ai[c->index].cur_veh->index + 1;
00096
00097 FOR_ALL_VEHICLES_FROM(v, index) {
00098 if (v->owner != _current_company) continue;
00099
00100 if ((v->type == VEH_TRAIN && v->subtype == 0) ||
00101 v->type == VEH_ROAD ||
00102 (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
00103 v->type == VEH_SHIP) {
00104
00105 if (v->type == VEH_TRAIN && v->engine_type < 3 &&
00106 (_price.build_railvehicle >> 3) < c->money) {
00107 _companies_ai[c->index].state = AIS_VEH_CHECK_REPLACE_VEHICLE;
00108 _companies_ai[c->index].cur_veh = v;
00109 return;
00110 }
00111
00112
00113 if (v->age >= 730 &&
00114 v->profit_last_year < _price.station_value * 5 * 256 &&
00115 v->profit_this_year < _price.station_value * 5 * 256) {
00116 _companies_ai[c->index].state_counter = 0;
00117 _companies_ai[c->index].state = AIS_SELL_VEHICLE;
00118 _companies_ai[c->index].cur_veh = v;
00119 return;
00120 }
00121
00122
00123 if (v->age >= v->max_age || (
00124 v->age != 0 &&
00125 GetEngine(v->engine_type)->reliability < 35389
00126 )) {
00127 _companies_ai[c->index].state = AIS_VEH_CHECK_REPLACE_VEHICLE;
00128 _companies_ai[c->index].cur_veh = v;
00129 return;
00130 }
00131 }
00132 }
00133
00134 _companies_ai[c->index].state = AIS_WANT_NEW_ROUTE;
00135 _companies_ai[c->index].state_counter = 0;
00136 }
00137
00138 static EngineID AiChooseTrainToBuild(RailType railtype, Money money, byte flag, TileIndex tile)
00139 {
00140 EngineID best_veh_index = INVALID_ENGINE;
00141 byte best_veh_score = 0;
00142 const Engine *e;
00143
00144 FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
00145 EngineID i = e->index;
00146 const RailVehicleInfo *rvi = &e->u.rail;
00147
00148 if (!IsCompatibleRail(rvi->railtype, railtype) ||
00149 rvi->railveh_type == RAILVEH_WAGON ||
00150 (rvi->railveh_type == RAILVEH_MULTIHEAD && flag & 1) ||
00151 !HasBit(e->company_avail, _current_company) ||
00152 e->reliability < 0x8A3D) {
00153 continue;
00154 }
00155
00156
00157 if (rvi->ai_passenger_only != 0 && flag == 1) continue;
00158
00159 CommandCost ret = DoCommand(tile, i, 0, 0, CMD_BUILD_RAIL_VEHICLE);
00160 if (CmdSucceeded(ret) && ret.GetCost() <= money && rvi->ai_rank >= best_veh_score) {
00161 best_veh_score = rvi->ai_rank;
00162 best_veh_index = i;
00163 }
00164 }
00165
00166 return best_veh_index;
00167 }
00168
00169 static EngineID AiChooseRoadVehToBuild(CargoID cargo, Money money, TileIndex tile)
00170 {
00171 EngineID best_veh_index = INVALID_ENGINE;
00172 int32 best_veh_rating = 0;
00173 const Engine *e;
00174
00175 FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
00176 EngineID i = e->index;
00177 const RoadVehicleInfo *rvi = &e->u.road;
00178
00179 if (!HasBit(e->company_avail, _current_company) || e->reliability < 0x8A3D) {
00180 continue;
00181 }
00182
00183
00184 if (rvi->cargo_type != cargo && !CanRefitTo(i, cargo)) continue;
00185
00186
00187 int rating = rvi->max_speed * rvi->capacity;
00188 if (rating <= best_veh_rating) continue;
00189
00190 CommandCost ret = DoCommand(tile, i, 0, 0, CMD_BUILD_ROAD_VEH);
00191 if (CmdFailed(ret)) continue;
00192
00193
00194 if (rvi->cargo_type != cargo) ret.AddCost(GetRefitCost(i));
00195 if (ret.GetCost() > money) continue;
00196
00197 best_veh_rating = rating;
00198 best_veh_index = i;
00199 }
00200
00201 return best_veh_index;
00202 }
00203
00210 static EngineID AiChooseAircraftToBuild(Money money, byte forbidden)
00211 {
00212 EngineID best_veh_index = INVALID_ENGINE;
00213 Money best_veh_cost = 0;
00214 const Engine *e;
00215
00216 FOR_ALL_ENGINES_OF_TYPE(e, VEH_AIRCRAFT) {
00217 EngineID i = e->index;
00218 const AircraftVehicleInfo *avi = &e->u.air;
00219
00220 if (!HasBit(e->company_avail, _current_company) || e->reliability < 0x8A3D) {
00221 continue;
00222 }
00223
00224 if ((avi->subtype & forbidden) != 0) continue;
00225
00226 CommandCost ret = DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_AIRCRAFT);
00227 if (CmdSucceeded(ret) && ret.GetCost() <= money && ret.GetCost() >= best_veh_cost) {
00228 best_veh_cost = ret.GetCost();
00229 best_veh_index = i;
00230 }
00231 }
00232
00233 return best_veh_index;
00234 }
00235
00236 static Money AiGetBasePrice(const Company *c)
00237 {
00238 Money base = _price.station_value;
00239
00240
00241 switch (_companies_ai[c->index].railtype_to_use) {
00242 default: NOT_REACHED();
00243 case RAILTYPE_RAIL: break;
00244 case RAILTYPE_ELECTRIC: break;
00245 case RAILTYPE_MONO: base = (base * 3) >> 1; break;
00246 case RAILTYPE_MAGLEV: base *= 2; break;
00247 }
00248
00249 return base;
00250 }
00251
00252 static EngineID AiChooseRoadVehToReplaceWith(const Company *c, const Vehicle *v)
00253 {
00254 Money avail_money = c->money + v->value;
00255 return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile);
00256 }
00257
00258 static EngineID AiChooseAircraftToReplaceWith(const Company *c, const Vehicle *v)
00259 {
00260 Money avail_money = c->money + v->value;
00261
00262
00263 byte forbidden = 0;
00264 const Order *o;
00265
00266 FOR_VEHICLE_ORDERS(v, o) {
00267 if (!o->IsValid()) continue;
00268 if (!IsValidStationID(o->GetDestination())) continue;
00269 const Station *st = GetStation(o->GetDestination());
00270 if (!(st->facilities & FACIL_AIRPORT)) continue;
00271
00272 AirportFTAClass::Flags flags = st->Airport()->flags;
00273 if (!(flags & AirportFTAClass::AIRPLANES)) forbidden |= AIR_CTOL | AIR_FAST;
00274 if (flags & AirportFTAClass::SHORT_STRIP) forbidden |= AIR_FAST;
00275 }
00276
00277 return AiChooseAircraftToBuild(
00278 avail_money, forbidden
00279 );
00280 }
00281
00282 static EngineID AiChooseTrainToReplaceWith(const Company *c, const Vehicle *v)
00283 {
00284 Money avail_money = c->money + v->value;
00285 const Vehicle *u = v;
00286 int num = 0;
00287
00288 while (++num, u->Next() != NULL) {
00289 u = u->Next();
00290 }
00291
00292
00293 return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile);
00294 }
00295
00296 static EngineID AiChooseShipToReplaceWith(const Company *c, const Vehicle *v)
00297 {
00298
00299 return INVALID_ENGINE;
00300 }
00301
00302 static void AiHandleGotoDepot(Company *c, int cmd)
00303 {
00304 if (!_companies_ai[c->index].cur_veh->current_order.IsType(OT_GOTO_DEPOT))
00305 DoCommand(0, _companies_ai[c->index].cur_veh->index, 0, DC_EXEC, cmd);
00306
00307 if (++_companies_ai[c->index].state_counter <= 1387) {
00308 _companies_ai[c->index].state = AIS_VEH_DO_REPLACE_VEHICLE;
00309 return;
00310 }
00311
00312 if (_companies_ai[c->index].cur_veh->current_order.IsType(OT_GOTO_DEPOT)) {
00313 _companies_ai[c->index].cur_veh->current_order.MakeDummy();
00314 InvalidateWindow(WC_VEHICLE_VIEW, _companies_ai[c->index].cur_veh->index);
00315 }
00316 }
00317
00318 static void AiRestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
00319 {
00320 if (bak->order == NULL) return;
00321
00322 for (uint i = 0; !bak->order[i].IsType(OT_NOTHING); i++) {
00323 if (!DoCommandP(0, v->index + (i << 16), bak->order[i].Pack(), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK))
00324 break;
00325 }
00326 }
00327
00328 static void AiHandleReplaceTrain(Company *c)
00329 {
00330 const Vehicle* v = _companies_ai[c->index].cur_veh;
00331 BackuppedOrders orderbak;
00332 EngineID veh;
00333
00334
00335 if (!IsRailDepotTile(v->tile) || v->u.rail.track != TRACK_BIT_DEPOT || !(v->vehstatus & VS_STOPPED)) {
00336 AiHandleGotoDepot(c, CMD_SEND_TRAIN_TO_DEPOT);
00337 return;
00338 }
00339
00340 veh = AiChooseTrainToReplaceWith(c, v);
00341 if (veh != INVALID_ENGINE) {
00342 TileIndex tile;
00343
00344 BackupVehicleOrders(v, &orderbak);
00345 tile = v->tile;
00346
00347 if (CmdSucceeded(DoCommand(0, v->index, 2, DC_EXEC, CMD_SELL_RAIL_WAGON)) &&
00348 CmdSucceeded(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE))) {
00349 VehicleID veh = _new_vehicle_id;
00350 AiRestoreVehicleOrders(GetVehicle(veh), &orderbak);
00351 DoCommand(0, veh, 0, DC_EXEC, CMD_START_STOP_VEHICLE);
00352
00353 DoCommand(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
00354 }
00355 }
00356 }
00357
00358 static void AiHandleReplaceRoadVeh(Company *c)
00359 {
00360 const Vehicle* v = _companies_ai[c->index].cur_veh;
00361 BackuppedOrders orderbak;
00362 EngineID veh;
00363
00364 if (!v->IsStoppedInDepot()) {
00365 AiHandleGotoDepot(c, CMD_SEND_ROADVEH_TO_DEPOT);
00366 return;
00367 }
00368
00369 veh = AiChooseRoadVehToReplaceWith(c, v);
00370 if (veh != INVALID_ENGINE) {
00371 TileIndex tile;
00372
00373 BackupVehicleOrders(v, &orderbak);
00374 tile = v->tile;
00375
00376 if (CmdSucceeded(DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH)) &&
00377 CmdSucceeded(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH))) {
00378 VehicleID veh = _new_vehicle_id;
00379
00380 AiRestoreVehicleOrders(GetVehicle(veh), &orderbak);
00381 DoCommand(0, veh, 0, DC_EXEC, CMD_START_STOP_VEHICLE);
00382 DoCommand(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
00383 }
00384 }
00385 }
00386
00387 static void AiHandleReplaceAircraft(Company *c)
00388 {
00389 const Vehicle* v = _companies_ai[c->index].cur_veh;
00390 BackuppedOrders orderbak;
00391 EngineID veh;
00392
00393 if (!v->IsStoppedInDepot()) {
00394 AiHandleGotoDepot(c, CMD_SEND_AIRCRAFT_TO_HANGAR);
00395 return;
00396 }
00397
00398 veh = AiChooseAircraftToReplaceWith(c, v);
00399 if (veh != INVALID_ENGINE) {
00400 TileIndex tile;
00401
00402 BackupVehicleOrders(v, &orderbak);
00403 tile = v->tile;
00404
00405 if (CmdSucceeded(DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT)) &&
00406 CmdSucceeded(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) {
00407 VehicleID veh = _new_vehicle_id;
00408 AiRestoreVehicleOrders(GetVehicle(veh), &orderbak);
00409 DoCommand(0, veh, 0, DC_EXEC, CMD_START_STOP_VEHICLE);
00410
00411 DoCommand(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
00412 }
00413 }
00414 }
00415
00416 static void AiHandleReplaceShip(Company *c)
00417 {
00418
00419 }
00420
00421 typedef EngineID CheckReplaceProc(const Company *c, const Vehicle* v);
00422
00423 static CheckReplaceProc* const _veh_check_replace_proc[] = {
00424 AiChooseTrainToReplaceWith,
00425 AiChooseRoadVehToReplaceWith,
00426 AiChooseShipToReplaceWith,
00427 AiChooseAircraftToReplaceWith,
00428 };
00429
00430 typedef void DoReplaceProc(Company *c);
00431 static DoReplaceProc* const _veh_do_replace_proc[] = {
00432 AiHandleReplaceTrain,
00433 AiHandleReplaceRoadVeh,
00434 AiHandleReplaceShip,
00435 AiHandleReplaceAircraft
00436 };
00437
00438 static void AiStateCheckReplaceVehicle(Company *c)
00439 {
00440 const Vehicle* v = _companies_ai[c->index].cur_veh;
00441
00442 if (!v->IsValid() ||
00443 v->owner != _current_company ||
00444 v->type > VEH_SHIP ||
00445 _veh_check_replace_proc[v->type - VEH_TRAIN](c, v) == INVALID_ENGINE) {
00446 _companies_ai[c->index].state = AIS_VEH_LOOP;
00447 } else {
00448 _companies_ai[c->index].state_counter = 0;
00449 _companies_ai[c->index].state = AIS_VEH_DO_REPLACE_VEHICLE;
00450 }
00451 }
00452
00453 static void AiStateDoReplaceVehicle(Company *c)
00454 {
00455 const Vehicle* v = _companies_ai[c->index].cur_veh;
00456
00457 _companies_ai[c->index].state = AIS_VEH_LOOP;
00458
00459 if (!v->IsValid() || v->owner != _current_company) return;
00460 _veh_do_replace_proc[v->type - VEH_TRAIN](c);
00461 }
00462
00463 struct FoundRoute {
00464 int distance;
00465 CargoID cargo;
00466 void *from;
00467 void *to;
00468 };
00469
00470 static Town *AiFindRandomTown()
00471 {
00472 return GetRandomTown();
00473 }
00474
00475 static Industry *AiFindRandomIndustry()
00476 {
00477 int num = RandomRange(GetMaxIndustryIndex());
00478 if (IsValidIndustryID(num)) return GetIndustry(num);
00479
00480 return NULL;
00481 }
00482
00483 static void AiFindSubsidyIndustryRoute(FoundRoute *fr)
00484 {
00485 uint i;
00486 CargoID cargo;
00487 const Subsidy* s;
00488 Industry* from;
00489 TileIndex to_xy;
00490
00491
00492 fr->distance = -1;
00493
00494
00495 i = RandomRange(lengthof(_subsidies) * 3);
00496 if (i >= lengthof(_subsidies)) return;
00497
00498 s = &_subsidies[i];
00499
00500
00501 cargo = s->cargo_type;
00502 if (cargo == CT_INVALID ||
00503 cargo == CT_PASSENGERS ||
00504 cargo == CT_MAIL ||
00505 s->age > 7) {
00506 return;
00507 }
00508 fr->cargo = cargo;
00509
00510 fr->from = from = GetIndustry(s->from);
00511
00512 if (cargo == CT_GOODS || cargo == CT_FOOD) {
00513 Town* to_tow = GetTown(s->to);
00514
00515 if (to_tow->population < (cargo == CT_FOOD ? 200U : 900U)) return;
00516 fr->to = to_tow;
00517 to_xy = to_tow->xy;
00518 } else {
00519 Industry* to_ind = GetIndustry(s->to);
00520
00521 fr->to = to_ind;
00522 to_xy = to_ind->xy;
00523 }
00524
00525 fr->distance = DistanceManhattan(from->xy, to_xy);
00526 }
00527
00528 static void AiFindSubsidyPassengerRoute(FoundRoute *fr)
00529 {
00530 uint i;
00531 const Subsidy* s;
00532 Town *from, *to;
00533
00534
00535 fr->distance = -1;
00536
00537
00538 i = RandomRange(lengthof(_subsidies) * 3);
00539 if (i >= lengthof(_subsidies)) return;
00540
00541 s = &_subsidies[i];
00542
00543
00544 if (s->cargo_type != CT_PASSENGERS || s->age > 7) return;
00545 fr->cargo = s->cargo_type;
00546
00547 fr->from = from = GetTown(s->from);
00548 fr->to = to = GetTown(s->to);
00549
00550
00551 if (from->population < 400 || to->population < 400) return;
00552
00553 fr->distance = DistanceManhattan(from->xy, to->xy);
00554 }
00555
00556 static void AiFindRandomIndustryRoute(FoundRoute *fr)
00557 {
00558 Industry* i;
00559 uint32 r;
00560 CargoID cargo;
00561
00562
00563 fr->distance = -1;
00564
00565 r = Random();
00566
00567
00568 fr->from = i = AiFindRandomIndustry();
00569 if (i == NULL) return;
00570
00571
00572 cargo = i->produced_cargo[0];
00573 if (r & 1 && i->produced_cargo[1] != CT_INVALID) cargo = i->produced_cargo[1];
00574
00575 fr->cargo = cargo;
00576
00577
00578 if (cargo == CT_INVALID || cargo == CT_PASSENGERS) return;
00579
00580 if (cargo != CT_GOODS && cargo != CT_FOOD) {
00581
00582 Industry* i2 = AiFindRandomIndustry();
00583 if (i2 == NULL || i == i2 ||
00584 (i2->accepts_cargo[0] != cargo &&
00585 i2->accepts_cargo[1] != cargo &&
00586 i2->accepts_cargo[2] != cargo)) {
00587 return;
00588 }
00589
00590 fr->to = i2;
00591 fr->distance = DistanceManhattan(i->xy, i2->xy);
00592 } else {
00593
00594 Town* t = AiFindRandomTown();
00595
00596 if (t == NULL || t->population < (cargo == CT_FOOD ? 200U : 900U)) return;
00597
00598 fr->to = t;
00599 fr->distance = DistanceManhattan(i->xy, t->xy);
00600 }
00601 }
00602
00603 static void AiFindRandomPassengerRoute(FoundRoute *fr)
00604 {
00605 Town* source;
00606 Town* dest;
00607
00608
00609 fr->distance = -1;
00610
00611 fr->from = source = AiFindRandomTown();
00612 if (source == NULL || source->population < 400) return;
00613
00614 fr->to = dest = AiFindRandomTown();
00615 if (dest == NULL || source == dest || dest->population < 400) return;
00616
00617 fr->distance = DistanceManhattan(source->xy, dest->xy);
00618 }
00619
00620
00621 #define GET_TOWN_OR_INDUSTRY_TILE(p) (((Town*)(p))->xy)
00622
00623 static bool AiCheckIfRouteIsGood(Company *c, FoundRoute *fr, byte bitmask)
00624 {
00625 TileIndex from_tile, to_tile;
00626 Station *st;
00627 int dist;
00628 uint same_station = 0;
00629
00630 from_tile = GET_TOWN_OR_INDUSTRY_TILE(fr->from);
00631 to_tile = GET_TOWN_OR_INDUSTRY_TILE(fr->to);
00632
00633 dist = 0xFFFF;
00634 FOR_ALL_STATIONS(st) {
00635 int cur;
00636
00637 if (st->owner != _current_company) continue;
00638 cur = DistanceMax(from_tile, st->xy);
00639 if (cur < dist) dist = cur;
00640 cur = DistanceMax(to_tile, st->xy);
00641 if (cur < dist) dist = cur;
00642 if (to_tile == from_tile && st->xy == to_tile) same_station++;
00643 }
00644
00645
00646
00647 if ((bitmask == 2 || bitmask == 4) &&
00648 same_station > 2 &&
00649 ((Town*)fr->from)->population < same_station * 350) {
00650 return false;
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 int min_distance = 36 + (1 << (Random() % 9));
00663
00664
00665 if (dist != 0xFFFF && dist > min_distance) return false;
00666
00667 if (_companies_ai[c->index].route_type_mask != 0 &&
00668 !(_companies_ai[c->index].route_type_mask & bitmask) &&
00669 !Chance16(1, 5)) {
00670 return false;
00671 }
00672
00673 if (fr->cargo == CT_PASSENGERS || fr->cargo == CT_MAIL) {
00674 const Town* from = (const Town*)fr->from;
00675 const Town* to = (const Town*)fr->to;
00676
00677 if (from->pct_pass_transported > 0x99 ||
00678 to->pct_pass_transported > 0x99) {
00679 return false;
00680 }
00681
00682
00683 if (from->ratings[_current_company] < -100 ||
00684 to->ratings[_current_company] < -100) {
00685 return false;
00686 }
00687 } else {
00688 const Industry* i = (const Industry*)fr->from;
00689
00690 if (i->last_month_pct_transported[fr->cargo != i->produced_cargo[0]] > 0x99 ||
00691 i->last_month_production[fr->cargo != i->produced_cargo[0]] == 0) {
00692 return false;
00693 }
00694 }
00695
00696 _companies_ai[c->index].route_type_mask |= bitmask;
00697 return true;
00698 }
00699
00700 static byte AiGetDirectionBetweenTiles(TileIndex a, TileIndex b)
00701 {
00702 byte i = (TileX(a) < TileX(b)) ? 1 : 0;
00703 if (TileY(a) >= TileY(b)) i ^= 3;
00704 return i;
00705 }
00706
00707 static TileIndex AiGetPctTileBetween(TileIndex a, TileIndex b, byte pct)
00708 {
00709 return TileXY(
00710 TileX(a) + ((TileX(b) - TileX(a)) * pct >> 8),
00711 TileY(a) + ((TileY(b) - TileY(a)) * pct >> 8)
00712 );
00713 }
00714
00715 static void AiWantLongIndustryRoute(Company *c)
00716 {
00717 int i;
00718 FoundRoute fr;
00719
00720 i = 60;
00721 for (;;) {
00722
00723 AiFindSubsidyIndustryRoute(&fr);
00724 if (IsInsideMM(fr.distance, 60, 90 + 1)) break;
00725
00726
00727 AiFindRandomIndustryRoute(&fr);
00728 if (IsInsideMM(fr.distance, 60, 90 + 1)) break;
00729
00730
00731 if (--i == 0) return;
00732 }
00733
00734 if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00735
00736
00737 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
00738 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
00739
00740 _companies_ai[c->index].src.use_tile = 0;
00741 _companies_ai[c->index].src.rand_rng = 9;
00742 _companies_ai[c->index].src.cur_building_rule = 0xFF;
00743 _companies_ai[c->index].src.unk6 = 1;
00744 _companies_ai[c->index].src.unk7 = 0;
00745 _companies_ai[c->index].src.buildcmd_a = 0x24;
00746 _companies_ai[c->index].src.buildcmd_b = 0xFF;
00747 _companies_ai[c->index].src.direction = AiGetDirectionBetweenTiles(
00748 _companies_ai[c->index].src.spec_tile,
00749 _companies_ai[c->index].dst.spec_tile
00750 );
00751 _companies_ai[c->index].src.cargo = fr.cargo | 0x80;
00752
00753
00754
00755 _companies_ai[c->index].dst.use_tile = 0;
00756 _companies_ai[c->index].dst.rand_rng = 9;
00757 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
00758 _companies_ai[c->index].dst.unk6 = 1;
00759 _companies_ai[c->index].dst.unk7 = 0;
00760 _companies_ai[c->index].dst.buildcmd_a = 0x34;
00761 _companies_ai[c->index].dst.buildcmd_b = 0xFF;
00762 _companies_ai[c->index].dst.direction = AiGetDirectionBetweenTiles(
00763 _companies_ai[c->index].dst.spec_tile,
00764 _companies_ai[c->index].src.spec_tile
00765 );
00766 _companies_ai[c->index].dst.cargo = fr.cargo;
00767
00768
00769 _companies_ai[c->index].mid1.spec_tile = AiGetPctTileBetween(
00770 _companies_ai[c->index].src.spec_tile,
00771 _companies_ai[c->index].dst.spec_tile,
00772 0x55
00773 );
00774 _companies_ai[c->index].mid1.use_tile = 0;
00775 _companies_ai[c->index].mid1.rand_rng = 6;
00776 _companies_ai[c->index].mid1.cur_building_rule = 0xFF;
00777 _companies_ai[c->index].mid1.unk6 = 2;
00778 _companies_ai[c->index].mid1.unk7 = 1;
00779 _companies_ai[c->index].mid1.buildcmd_a = 0x30;
00780 _companies_ai[c->index].mid1.buildcmd_b = 0xFF;
00781 _companies_ai[c->index].mid1.direction = _companies_ai[c->index].src.direction;
00782 _companies_ai[c->index].mid1.cargo = fr.cargo;
00783
00784
00785 _companies_ai[c->index].mid2.spec_tile = AiGetPctTileBetween(
00786 _companies_ai[c->index].src.spec_tile,
00787 _companies_ai[c->index].dst.spec_tile,
00788 0xAA
00789 );
00790 _companies_ai[c->index].mid2.use_tile = 0;
00791 _companies_ai[c->index].mid2.rand_rng = 6;
00792 _companies_ai[c->index].mid2.cur_building_rule = 0xFF;
00793 _companies_ai[c->index].mid2.unk6 = 2;
00794 _companies_ai[c->index].mid2.unk7 = 1;
00795 _companies_ai[c->index].mid2.buildcmd_a = 0xFF;
00796 _companies_ai[c->index].mid2.buildcmd_b = 0xFF;
00797 _companies_ai[c->index].mid2.direction = _companies_ai[c->index].dst.direction;
00798 _companies_ai[c->index].mid2.cargo = fr.cargo;
00799
00800
00801 _companies_ai[c->index].cargo_type = fr.cargo;
00802 _companies_ai[c->index].num_wagons = 3;
00803 _companies_ai[c->index].build_kind = 2;
00804 _companies_ai[c->index].num_build_rec = 4;
00805 _companies_ai[c->index].num_loco_to_build = 2;
00806 _companies_ai[c->index].num_want_fullload = 2;
00807 _companies_ai[c->index].wagon_list[0] = INVALID_VEHICLE;
00808 _companies_ai[c->index].order_list_blocks[0] = 0;
00809 _companies_ai[c->index].order_list_blocks[1] = 1;
00810 _companies_ai[c->index].order_list_blocks[2] = 255;
00811
00812 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
00813 _companies_ai[c->index].state_mode = UCHAR_MAX;
00814 _companies_ai[c->index].state_counter = 0;
00815 _companies_ai[c->index].timeout_counter = 0;
00816 }
00817
00818 static void AiWantMediumIndustryRoute(Company *c)
00819 {
00820 int i;
00821 FoundRoute fr;
00822
00823 i = 60;
00824 for (;;) {
00825
00826 AiFindSubsidyIndustryRoute(&fr);
00827 if (IsInsideMM(fr.distance, 40, 60 + 1)) break;
00828
00829
00830 AiFindRandomIndustryRoute(&fr);
00831 if (IsInsideMM(fr.distance, 40, 60 + 1)) break;
00832
00833
00834 if (--i == 0) return;
00835 }
00836
00837 if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00838
00839
00840 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
00841 _companies_ai[c->index].src.use_tile = 0;
00842 _companies_ai[c->index].src.rand_rng = 9;
00843 _companies_ai[c->index].src.cur_building_rule = 0xFF;
00844 _companies_ai[c->index].src.unk6 = 1;
00845 _companies_ai[c->index].src.unk7 = 0;
00846 _companies_ai[c->index].src.buildcmd_a = 0x10;
00847 _companies_ai[c->index].src.buildcmd_b = 0xFF;
00848 _companies_ai[c->index].src.direction = AiGetDirectionBetweenTiles(
00849 GET_TOWN_OR_INDUSTRY_TILE(fr.from),
00850 GET_TOWN_OR_INDUSTRY_TILE(fr.to)
00851 );
00852 _companies_ai[c->index].src.cargo = fr.cargo | 0x80;
00853
00854
00855 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
00856 _companies_ai[c->index].dst.use_tile = 0;
00857 _companies_ai[c->index].dst.rand_rng = 9;
00858 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
00859 _companies_ai[c->index].dst.unk6 = 1;
00860 _companies_ai[c->index].dst.unk7 = 0;
00861 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
00862 _companies_ai[c->index].dst.buildcmd_b = 0xFF;
00863 _companies_ai[c->index].dst.direction = AiGetDirectionBetweenTiles(
00864 GET_TOWN_OR_INDUSTRY_TILE(fr.to),
00865 GET_TOWN_OR_INDUSTRY_TILE(fr.from)
00866 );
00867 _companies_ai[c->index].dst.cargo = fr.cargo;
00868
00869
00870 _companies_ai[c->index].cargo_type = fr.cargo;
00871 _companies_ai[c->index].num_wagons = 3;
00872 _companies_ai[c->index].build_kind = 1;
00873 _companies_ai[c->index].num_build_rec = 2;
00874 _companies_ai[c->index].num_loco_to_build = 1;
00875 _companies_ai[c->index].num_want_fullload = 1;
00876 _companies_ai[c->index].wagon_list[0] = INVALID_VEHICLE;
00877 _companies_ai[c->index].order_list_blocks[0] = 0;
00878 _companies_ai[c->index].order_list_blocks[1] = 1;
00879 _companies_ai[c->index].order_list_blocks[2] = 255;
00880 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
00881 _companies_ai[c->index].state_mode = UCHAR_MAX;
00882 _companies_ai[c->index].state_counter = 0;
00883 _companies_ai[c->index].timeout_counter = 0;
00884 }
00885
00886 static void AiWantShortIndustryRoute(Company *c)
00887 {
00888 int i;
00889 FoundRoute fr;
00890
00891 i = 60;
00892 for (;;) {
00893
00894 AiFindSubsidyIndustryRoute(&fr);
00895 if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
00896
00897
00898 AiFindRandomIndustryRoute(&fr);
00899 if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
00900
00901
00902 if (--i == 0) return;
00903 }
00904
00905 if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00906
00907
00908 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
00909 _companies_ai[c->index].src.use_tile = 0;
00910 _companies_ai[c->index].src.rand_rng = 9;
00911 _companies_ai[c->index].src.cur_building_rule = 0xFF;
00912 _companies_ai[c->index].src.unk6 = 1;
00913 _companies_ai[c->index].src.unk7 = 0;
00914 _companies_ai[c->index].src.buildcmd_a = 0x10;
00915 _companies_ai[c->index].src.buildcmd_b = 0xFF;
00916 _companies_ai[c->index].src.direction = AiGetDirectionBetweenTiles(
00917 GET_TOWN_OR_INDUSTRY_TILE(fr.from),
00918 GET_TOWN_OR_INDUSTRY_TILE(fr.to)
00919 );
00920 _companies_ai[c->index].src.cargo = fr.cargo | 0x80;
00921
00922
00923 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
00924 _companies_ai[c->index].dst.use_tile = 0;
00925 _companies_ai[c->index].dst.rand_rng = 9;
00926 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
00927 _companies_ai[c->index].dst.unk6 = 1;
00928 _companies_ai[c->index].dst.unk7 = 0;
00929 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
00930 _companies_ai[c->index].dst.buildcmd_b = 0xFF;
00931 _companies_ai[c->index].dst.direction = AiGetDirectionBetweenTiles(
00932 GET_TOWN_OR_INDUSTRY_TILE(fr.to),
00933 GET_TOWN_OR_INDUSTRY_TILE(fr.from)
00934 );
00935 _companies_ai[c->index].dst.cargo = fr.cargo;
00936
00937
00938 _companies_ai[c->index].cargo_type = fr.cargo;
00939 _companies_ai[c->index].num_wagons = 2;
00940 _companies_ai[c->index].build_kind = 1;
00941 _companies_ai[c->index].num_build_rec = 2;
00942 _companies_ai[c->index].num_loco_to_build = 1;
00943 _companies_ai[c->index].num_want_fullload = 1;
00944 _companies_ai[c->index].wagon_list[0] = INVALID_VEHICLE;
00945 _companies_ai[c->index].order_list_blocks[0] = 0;
00946 _companies_ai[c->index].order_list_blocks[1] = 1;
00947 _companies_ai[c->index].order_list_blocks[2] = 255;
00948 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
00949 _companies_ai[c->index].state_mode = UCHAR_MAX;
00950 _companies_ai[c->index].state_counter = 0;
00951 _companies_ai[c->index].timeout_counter = 0;
00952 }
00953
00954 static void AiWantMailRoute(Company *c)
00955 {
00956 int i;
00957 FoundRoute fr;
00958
00959 i = 60;
00960 for (;;) {
00961
00962 AiFindSubsidyPassengerRoute(&fr);
00963 if (IsInsideMM(fr.distance, 60, 110 + 1)) break;
00964
00965
00966 AiFindRandomPassengerRoute(&fr);
00967 if (IsInsideMM(fr.distance, 60, 110 + 1)) break;
00968
00969
00970 if (--i == 0) return;
00971 }
00972
00973 fr.cargo = CT_MAIL;
00974 if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00975
00976
00977 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
00978 _companies_ai[c->index].src.use_tile = 0;
00979 _companies_ai[c->index].src.rand_rng = 7;
00980 _companies_ai[c->index].src.cur_building_rule = 0xFF;
00981 _companies_ai[c->index].src.unk6 = 1;
00982 _companies_ai[c->index].src.unk7 = 0;
00983 _companies_ai[c->index].src.buildcmd_a = 0x24;
00984 _companies_ai[c->index].src.buildcmd_b = 0xFF;
00985 _companies_ai[c->index].src.direction = AiGetDirectionBetweenTiles(
00986 GET_TOWN_OR_INDUSTRY_TILE(fr.from),
00987 GET_TOWN_OR_INDUSTRY_TILE(fr.to)
00988 );
00989 _companies_ai[c->index].src.cargo = fr.cargo;
00990
00991
00992 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
00993 _companies_ai[c->index].dst.use_tile = 0;
00994 _companies_ai[c->index].dst.rand_rng = 7;
00995 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
00996 _companies_ai[c->index].dst.unk6 = 1;
00997 _companies_ai[c->index].dst.unk7 = 0;
00998 _companies_ai[c->index].dst.buildcmd_a = 0x34;
00999 _companies_ai[c->index].dst.buildcmd_b = 0xFF;
01000 _companies_ai[c->index].dst.direction = AiGetDirectionBetweenTiles(
01001 GET_TOWN_OR_INDUSTRY_TILE(fr.to),
01002 GET_TOWN_OR_INDUSTRY_TILE(fr.from)
01003 );
01004 _companies_ai[c->index].dst.cargo = fr.cargo;
01005
01006
01007 _companies_ai[c->index].mid1.spec_tile = AiGetPctTileBetween(
01008 GET_TOWN_OR_INDUSTRY_TILE(fr.from),
01009 GET_TOWN_OR_INDUSTRY_TILE(fr.to),
01010 0x55
01011 );
01012 _companies_ai[c->index].mid1.use_tile = 0;
01013 _companies_ai[c->index].mid1.rand_rng = 6;
01014 _companies_ai[c->index].mid1.cur_building_rule = 0xFF;
01015 _companies_ai[c->index].mid1.unk6 = 2;
01016 _companies_ai[c->index].mid1.unk7 = 1;
01017 _companies_ai[c->index].mid1.buildcmd_a = 0x30;
01018 _companies_ai[c->index].mid1.buildcmd_b = 0xFF;
01019 _companies_ai[c->index].mid1.direction = _companies_ai[c->index].src.direction;
01020 _companies_ai[c->index].mid1.cargo = fr.cargo;
01021
01022
01023 _companies_ai[c->index].mid2.spec_tile = AiGetPctTileBetween(
01024 GET_TOWN_OR_INDUSTRY_TILE(fr.from),
01025 GET_TOWN_OR_INDUSTRY_TILE(fr.to),
01026 0xAA
01027 );
01028 _companies_ai[c->index].mid2.use_tile = 0;
01029 _companies_ai[c->index].mid2.rand_rng = 6;
01030 _companies_ai[c->index].mid2.cur_building_rule = 0xFF;
01031 _companies_ai[c->index].mid2.unk6 = 2;
01032 _companies_ai[c->index].mid2.unk7 = 1;
01033 _companies_ai[c->index].mid2.buildcmd_a = 0xFF;
01034 _companies_ai[c->index].mid2.buildcmd_b = 0xFF;
01035 _companies_ai[c->index].mid2.direction = _companies_ai[c->index].dst.direction;
01036 _companies_ai[c->index].mid2.cargo = fr.cargo;
01037
01038
01039 _companies_ai[c->index].cargo_type = fr.cargo;
01040 _companies_ai[c->index].num_wagons = 3;
01041 _companies_ai[c->index].build_kind = 2;
01042 _companies_ai[c->index].num_build_rec = 4;
01043 _companies_ai[c->index].num_loco_to_build = 2;
01044 _companies_ai[c->index].num_want_fullload = 0;
01045 _companies_ai[c->index].wagon_list[0] = INVALID_VEHICLE;
01046 _companies_ai[c->index].order_list_blocks[0] = 0;
01047 _companies_ai[c->index].order_list_blocks[1] = 1;
01048 _companies_ai[c->index].order_list_blocks[2] = 255;
01049 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
01050 _companies_ai[c->index].state_mode = UCHAR_MAX;
01051 _companies_ai[c->index].state_counter = 0;
01052 _companies_ai[c->index].timeout_counter = 0;
01053 }
01054
01055 static void AiWantPassengerRoute(Company *c)
01056 {
01057 int i;
01058 FoundRoute fr;
01059
01060 i = 60;
01061 for (;;) {
01062
01063 AiFindSubsidyPassengerRoute(&fr);
01064 if (IsInsideMM(fr.distance, 0, 55 + 1)) break;
01065
01066
01067 AiFindRandomPassengerRoute(&fr);
01068 if (IsInsideMM(fr.distance, 0, 55 + 1)) break;
01069
01070
01071 if (--i == 0) return;
01072 }
01073
01074 fr.cargo = CT_PASSENGERS;
01075 if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
01076
01077
01078 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
01079 _companies_ai[c->index].src.use_tile = 0;
01080 _companies_ai[c->index].src.rand_rng = 7;
01081 _companies_ai[c->index].src.cur_building_rule = 0xFF;
01082 _companies_ai[c->index].src.unk6 = 1;
01083 _companies_ai[c->index].src.unk7 = 0;
01084 _companies_ai[c->index].src.buildcmd_a = 0x10;
01085 _companies_ai[c->index].src.buildcmd_b = 0xFF;
01086 _companies_ai[c->index].src.direction = AiGetDirectionBetweenTiles(
01087 GET_TOWN_OR_INDUSTRY_TILE(fr.from),
01088 GET_TOWN_OR_INDUSTRY_TILE(fr.to)
01089 );
01090 _companies_ai[c->index].src.cargo = fr.cargo;
01091
01092
01093 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
01094 _companies_ai[c->index].dst.use_tile = 0;
01095 _companies_ai[c->index].dst.rand_rng = 7;
01096 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
01097 _companies_ai[c->index].dst.unk6 = 1;
01098 _companies_ai[c->index].dst.unk7 = 0;
01099 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
01100 _companies_ai[c->index].dst.buildcmd_b = 0xFF;
01101 _companies_ai[c->index].dst.direction = AiGetDirectionBetweenTiles(
01102 GET_TOWN_OR_INDUSTRY_TILE(fr.to),
01103 GET_TOWN_OR_INDUSTRY_TILE(fr.from)
01104 );
01105 _companies_ai[c->index].dst.cargo = fr.cargo;
01106
01107
01108 _companies_ai[c->index].cargo_type = fr.cargo;
01109 _companies_ai[c->index].num_wagons = 2;
01110 _companies_ai[c->index].build_kind = 1;
01111 _companies_ai[c->index].num_build_rec = 2;
01112 _companies_ai[c->index].num_loco_to_build = 1;
01113 _companies_ai[c->index].num_want_fullload = 0;
01114 _companies_ai[c->index].wagon_list[0] = INVALID_VEHICLE;
01115 _companies_ai[c->index].order_list_blocks[0] = 0;
01116 _companies_ai[c->index].order_list_blocks[1] = 1;
01117 _companies_ai[c->index].order_list_blocks[2] = 255;
01118 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
01119 _companies_ai[c->index].state_mode = UCHAR_MAX;
01120 _companies_ai[c->index].state_counter = 0;
01121 _companies_ai[c->index].timeout_counter = 0;
01122 }
01123
01124 static void AiWantTrainRoute(Company *c)
01125 {
01126 uint16 r = GB(Random(), 0, 16);
01127
01128 _companies_ai[c->index].railtype_to_use = GetBestRailtype(c->index);
01129
01130 if (r > 0xD000) {
01131 AiWantLongIndustryRoute(c);
01132 } else if (r > 0x6000) {
01133 AiWantMediumIndustryRoute(c);
01134 } else if (r > 0x1000) {
01135 AiWantShortIndustryRoute(c);
01136 } else if (r > 0x800) {
01137 AiWantPassengerRoute(c);
01138 } else {
01139 AiWantMailRoute(c);
01140 }
01141 }
01142
01143 static void AiWantLongRoadIndustryRoute(Company *c)
01144 {
01145 int i;
01146 FoundRoute fr;
01147
01148 i = 60;
01149 for (;;) {
01150
01151 AiFindSubsidyIndustryRoute(&fr);
01152 if (IsInsideMM(fr.distance, 35, 55 + 1)) break;
01153
01154
01155 AiFindRandomIndustryRoute(&fr);
01156 if (IsInsideMM(fr.distance, 35, 55 + 1)) break;
01157
01158
01159 if (--i == 0) return;
01160 }
01161
01162 if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01163
01164
01165 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
01166 _companies_ai[c->index].src.use_tile = 0;
01167 _companies_ai[c->index].src.rand_rng = 9;
01168 _companies_ai[c->index].src.cur_building_rule = 0xFF;
01169 _companies_ai[c->index].src.buildcmd_a = 1;
01170 _companies_ai[c->index].src.direction = 0;
01171 _companies_ai[c->index].src.cargo = fr.cargo | 0x80;
01172
01173
01174 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
01175 _companies_ai[c->index].dst.use_tile = 0;
01176 _companies_ai[c->index].dst.rand_rng = 9;
01177 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
01178 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
01179 _companies_ai[c->index].dst.direction = 0;
01180 _companies_ai[c->index].dst.cargo = fr.cargo;
01181
01182
01183 _companies_ai[c->index].cargo_type = fr.cargo;
01184 _companies_ai[c->index].num_build_rec = 2;
01185 _companies_ai[c->index].num_loco_to_build = 5;
01186 _companies_ai[c->index].num_want_fullload = 5;
01187
01188
01189 _companies_ai[c->index].order_list_blocks[0] = 0;
01190 _companies_ai[c->index].order_list_blocks[1] = 1;
01191 _companies_ai[c->index].order_list_blocks[2] = 255;
01192
01193 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
01194 _companies_ai[c->index].state_mode = UCHAR_MAX;
01195 _companies_ai[c->index].state_counter = 0;
01196 _companies_ai[c->index].timeout_counter = 0;
01197 }
01198
01199 static void AiWantMediumRoadIndustryRoute(Company *c)
01200 {
01201 int i;
01202 FoundRoute fr;
01203
01204 i = 60;
01205 for (;;) {
01206
01207 AiFindSubsidyIndustryRoute(&fr);
01208 if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
01209
01210
01211 AiFindRandomIndustryRoute(&fr);
01212 if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
01213
01214
01215 if (--i == 0) return;
01216 }
01217
01218 if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01219
01220
01221 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
01222 _companies_ai[c->index].src.use_tile = 0;
01223 _companies_ai[c->index].src.rand_rng = 9;
01224 _companies_ai[c->index].src.cur_building_rule = 0xFF;
01225 _companies_ai[c->index].src.buildcmd_a = 1;
01226 _companies_ai[c->index].src.direction = 0;
01227 _companies_ai[c->index].src.cargo = fr.cargo | 0x80;
01228
01229
01230 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
01231 _companies_ai[c->index].dst.use_tile = 0;
01232 _companies_ai[c->index].dst.rand_rng = 9;
01233 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
01234 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
01235 _companies_ai[c->index].dst.direction = 0;
01236 _companies_ai[c->index].dst.cargo = fr.cargo;
01237
01238
01239 _companies_ai[c->index].cargo_type = fr.cargo;
01240 _companies_ai[c->index].num_build_rec = 2;
01241 _companies_ai[c->index].num_loco_to_build = 3;
01242 _companies_ai[c->index].num_want_fullload = 3;
01243
01244
01245 _companies_ai[c->index].order_list_blocks[0] = 0;
01246 _companies_ai[c->index].order_list_blocks[1] = 1;
01247 _companies_ai[c->index].order_list_blocks[2] = 255;
01248
01249 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
01250 _companies_ai[c->index].state_mode = UCHAR_MAX;
01251 _companies_ai[c->index].state_counter = 0;
01252 _companies_ai[c->index].timeout_counter = 0;
01253 }
01254
01255 static void AiWantLongRoadPassengerRoute(Company *c)
01256 {
01257 int i;
01258 FoundRoute fr;
01259
01260 i = 60;
01261 for (;;) {
01262
01263 AiFindSubsidyPassengerRoute(&fr);
01264 if (IsInsideMM(fr.distance, 55, 180 + 1)) break;
01265
01266
01267 AiFindRandomPassengerRoute(&fr);
01268 if (IsInsideMM(fr.distance, 55, 180 + 1)) break;
01269
01270
01271 if (--i == 0) return;
01272 }
01273
01274 fr.cargo = CT_PASSENGERS;
01275
01276 if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01277
01278
01279 _companies_ai[c->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
01280 _companies_ai[c->index].src.use_tile = 0;
01281 _companies_ai[c->index].src.rand_rng = 10;
01282 _companies_ai[c->index].src.cur_building_rule = 0xFF;
01283 _companies_ai[c->index].src.buildcmd_a = 1;
01284 _companies_ai[c->index].src.direction = 0;
01285 _companies_ai[c->index].src.cargo = CT_PASSENGERS;
01286
01287
01288 _companies_ai[c->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
01289 _companies_ai[c->index].dst.use_tile = 0;
01290 _companies_ai[c->index].dst.rand_rng = 10;
01291 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
01292 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
01293 _companies_ai[c->index].dst.direction = 0;
01294 _companies_ai[c->index].dst.cargo = CT_PASSENGERS;
01295
01296
01297 _companies_ai[c->index].cargo_type = CT_PASSENGERS;
01298 _companies_ai[c->index].num_build_rec = 2;
01299 _companies_ai[c->index].num_loco_to_build = 4;
01300 _companies_ai[c->index].num_want_fullload = 0;
01301
01302
01303 _companies_ai[c->index].order_list_blocks[0] = 0;
01304 _companies_ai[c->index].order_list_blocks[1] = 1;
01305 _companies_ai[c->index].order_list_blocks[2] = 255;
01306
01307 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
01308 _companies_ai[c->index].state_mode = UCHAR_MAX;
01309 _companies_ai[c->index].state_counter = 0;
01310 _companies_ai[c->index].timeout_counter = 0;
01311 }
01312
01313 static void AiWantPassengerRouteInsideTown(Company *c)
01314 {
01315 int i;
01316 FoundRoute fr;
01317 Town *t;
01318
01319 i = 60;
01320 for (;;) {
01321
01322 t = AiFindRandomTown();
01323 if (t != NULL && t->population >= 700) break;
01324
01325
01326 if (--i == 0) return;
01327 }
01328
01329 fr.cargo = CT_PASSENGERS;
01330 fr.from = fr.to = t;
01331
01332 if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01333
01334
01335 _companies_ai[c->index].src.spec_tile = t->xy;
01336 _companies_ai[c->index].src.use_tile = 0;
01337 _companies_ai[c->index].src.rand_rng = 10;
01338 _companies_ai[c->index].src.cur_building_rule = 0xFF;
01339 _companies_ai[c->index].src.buildcmd_a = 1;
01340 _companies_ai[c->index].src.direction = 0;
01341 _companies_ai[c->index].src.cargo = CT_PASSENGERS;
01342
01343
01344 _companies_ai[c->index].dst.spec_tile = t->xy;
01345 _companies_ai[c->index].dst.use_tile = 0;
01346 _companies_ai[c->index].dst.rand_rng = 10;
01347 _companies_ai[c->index].dst.cur_building_rule = 0xFF;
01348 _companies_ai[c->index].dst.buildcmd_a = 0xFF;
01349 _companies_ai[c->index].dst.direction = 0;
01350 _companies_ai[c->index].dst.cargo = CT_PASSENGERS;
01351
01352
01353 _companies_ai[c->index].cargo_type = CT_PASSENGERS;
01354 _companies_ai[c->index].num_build_rec = 2;
01355 _companies_ai[c->index].num_loco_to_build = 2;
01356 _companies_ai[c->index].num_want_fullload = 0;
01357
01358
01359 _companies_ai[c->index].order_list_blocks[0] = 0;
01360 _companies_ai[c->index].order_list_blocks[1] = 1;
01361 _companies_ai[c->index].order_list_blocks[2] = 255;
01362
01363 _companies_ai[c->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
01364 _companies_ai[c->index].state_mode = UCHAR_MAX;
01365 _companies_ai[c->index].state_counter = 0;
01366 _companies_ai[c->index].timeout_counter = 0;
01367 }
01368
01369 static void AiWantRoadRoute(Company *c)
01370 {
01371 uint16 r = GB(Random(), 0, 16);
01372
01373 if (r > 0x4000) {
01374 AiWantLongRoadIndustryRoute(c);
01375 } else if (r > 0x2000) {
01376 AiWantMediumRoadIndustryRoute(c);
01377 } else if (r > 0x1000) {
01378 AiWantLongRoadPassengerRoute(c);
01379 } else {
01380 AiWantPassengerRouteInsideTown(c);
01381 }
01382 }
01383
01384 static void AiWantPassengerAircraftRoute(Company *c)
01385 {
01386 FoundRoute fr;
01387 int i;
01388
01389
01390
01391
01392 EngineID veh = AiChooseAircraftToBuild(c->money, _companies_ai[c->index].build_kind != 0 ? AIR_CTOL : 0);
01393
01394
01395 if (veh == INVALID_ENGINE) return;
01396
01397 const AircraftVehicleInfo *avi = AircraftVehInfo(veh);
01398
01399
01400
01401
01402
01403
01404
01405
01406 int max_squares = avi->max_speed * 448 / 100;
01407
01408
01409
01410
01411
01412
01413 int map_size = max(MapSizeX(), MapSizeY());
01414
01415
01416
01417
01418
01419
01420
01421 int min_squares = max(20, max(max_squares / 100, min(max_squares / 5, map_size / 2)));
01422
01423
01424
01425
01426 if (max_squares < min_squares) return;
01427
01428 i = 60;
01429 for (;;) {
01430
01431
01432 AiFindSubsidyPassengerRoute(&fr);
01433 if (IsInsideMM(fr.distance, min_squares, max_squares + 1)) break;
01434
01435
01436 AiFindRandomPassengerRoute(&fr);
01437 if (IsInsideMM<