default.cpp

Go to the documentation of this file.
00001 /* $Id: default.cpp 14464 2008-10-14 18:38:51Z rubidium $ */
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 // remove some day perhaps?
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       /* replace engine? */
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       /* not profitable? */
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       /* not reliable? */
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     /* Don't choose an engine designated for passenger use for freight. */
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     /* Skip vehicles which can't take our cargo type */
00184     if (rvi->cargo_type != cargo && !CanRefitTo(i, cargo)) continue;
00185 
00186     /* Rate and compare the engine by speed & capacity */
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     /* Add the cost of refitting */
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   // adjust base price when more expensive vehicles are available
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   /* determine forbidden aircraft bits */
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; // no planes for heliports / oil rigs
00274     if (flags & AirportFTAClass::SHORT_STRIP) forbidden |= AIR_FAST; // no fast planes for small airports
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   // XXX: check if a wagon
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   /* Ships are not implemented in this (broken) AI */
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   // wait until the vehicle reaches the depot.
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   /* Ships are not implemented in this (broken) AI */
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   // vehicle is not owned by the company anymore, something went very wrong.
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   // initially error
00492   fr->distance = -1;
00493 
00494   // Randomize subsidy index..
00495   i = RandomRange(lengthof(_subsidies) * 3);
00496   if (i >= lengthof(_subsidies)) return;
00497 
00498   s = &_subsidies[i];
00499 
00500   // Don't want passengers or mail
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; // error
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   // initially error
00535   fr->distance = -1;
00536 
00537   // Randomize subsidy index..
00538   i = RandomRange(lengthof(_subsidies) * 3);
00539   if (i >= lengthof(_subsidies)) return;
00540 
00541   s = &_subsidies[i];
00542 
00543   // Only want passengers
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   // They must be big enough
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   // initially error
00563   fr->distance = -1;
00564 
00565   r = Random();
00566 
00567   // pick a source
00568   fr->from = i = AiFindRandomIndustry();
00569   if (i == NULL) return;
00570 
00571   // pick a random produced cargo
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   // don't allow passengers
00578   if (cargo == CT_INVALID || cargo == CT_PASSENGERS) return;
00579 
00580   if (cargo != CT_GOODS && cargo != CT_FOOD) {
00581     // pick a dest, and see if it can receive
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     // pick a dest town, and see if it's big enough
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   // initially error
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 // Warn: depends on 'xy' being the first element in both Town and Industry
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   // To prevent the AI from building ten busstations in the same town, do some calculations
00646   //  For each road or airport station, we want 350 of population!
00647   if ((bitmask == 2 || bitmask == 4) &&
00648       same_station > 2 &&
00649       ((Town*)fr->from)->population < same_station * 350) {
00650     return false;
00651   }
00652 
00653   /* Requiring distance to nearest station to be always under 37 tiles may be suboptimal,
00654    * Especially for longer aircraft routes that start and end pretty at any arbitrary place on map
00655    * While it may be nice for AI to cluster their creations together, hardcoded limit is not ideal.
00656    * If AI will randomly start on some isolated spot, it will never get out of there.
00657    * AI will have chance of randomly rejecting routes further than 37 tiles from their network,
00658    * so there will be some attempt to cluster the network together */
00659 
00660   /* Random value between 37 and 292. Low values are exponentially more likely
00661    * With 50% chance the value will be under 52 tiles */
00662   int min_distance = 36 + (1 << (Random() % 9)); // 0..8
00663 
00664   /* Make sure distance to closest station is < min_distance tiles. */
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     // Make sure it has a reasonably good rating
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     // look for one from the subsidy list
00723     AiFindSubsidyIndustryRoute(&fr);
00724     if (IsInsideMM(fr.distance, 60, 90 + 1)) break;
00725 
00726     // try a random one
00727     AiFindRandomIndustryRoute(&fr);
00728     if (IsInsideMM(fr.distance, 60, 90 + 1)) break;
00729 
00730     // only test 60 times
00731     if (--i == 0) return;
00732   }
00733 
00734   if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00735 
00736   // Fill the source field
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   // Fill the dest field
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   // Fill middle field 1
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   // Fill middle field 2
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   // Fill common fields
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     // look for one from the subsidy list
00826     AiFindSubsidyIndustryRoute(&fr);
00827     if (IsInsideMM(fr.distance, 40, 60 + 1)) break;
00828 
00829     // try a random one
00830     AiFindRandomIndustryRoute(&fr);
00831     if (IsInsideMM(fr.distance, 40, 60 + 1)) break;
00832 
00833     // only test 60 times
00834     if (--i == 0) return;
00835   }
00836 
00837   if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00838 
00839   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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     // look for one from the subsidy list
00894     AiFindSubsidyIndustryRoute(&fr);
00895     if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
00896 
00897     // try a random one
00898     AiFindRandomIndustryRoute(&fr);
00899     if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
00900 
00901     // only test 60 times
00902     if (--i == 0) return;
00903   }
00904 
00905   if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00906 
00907   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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     // look for one from the subsidy list
00962     AiFindSubsidyPassengerRoute(&fr);
00963     if (IsInsideMM(fr.distance, 60, 110 + 1)) break;
00964 
00965     // try a random one
00966     AiFindRandomPassengerRoute(&fr);
00967     if (IsInsideMM(fr.distance, 60, 110 + 1)) break;
00968 
00969     // only test 60 times
00970     if (--i == 0) return;
00971   }
00972 
00973   fr.cargo = CT_MAIL;
00974   if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
00975 
00976   // Fill the source field
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   // Fill the dest field
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   // Fill middle field 1
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   // Fill middle field 2
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   // Fill common fields
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     // look for one from the subsidy list
01063     AiFindSubsidyPassengerRoute(&fr);
01064     if (IsInsideMM(fr.distance, 0, 55 + 1)) break;
01065 
01066     // try a random one
01067     AiFindRandomPassengerRoute(&fr);
01068     if (IsInsideMM(fr.distance, 0, 55 + 1)) break;
01069 
01070     // only test 60 times
01071     if (--i == 0) return;
01072   }
01073 
01074   fr.cargo = CT_PASSENGERS;
01075   if (!AiCheckIfRouteIsGood(c, &fr, 1)) return;
01076 
01077   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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     // look for one from the subsidy list
01151     AiFindSubsidyIndustryRoute(&fr);
01152     if (IsInsideMM(fr.distance, 35, 55 + 1)) break;
01153 
01154     // try a random one
01155     AiFindRandomIndustryRoute(&fr);
01156     if (IsInsideMM(fr.distance, 35, 55 + 1)) break;
01157 
01158     // only test 60 times
01159     if (--i == 0) return;
01160   }
01161 
01162   if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01163 
01164   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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 //  _companies_ai[c->index].loco_id = INVALID_VEHICLE;
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     // look for one from the subsidy list
01207     AiFindSubsidyIndustryRoute(&fr);
01208     if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
01209 
01210     // try a random one
01211     AiFindRandomIndustryRoute(&fr);
01212     if (IsInsideMM(fr.distance, 15, 40 + 1)) break;
01213 
01214     // only test 60 times
01215     if (--i == 0) return;
01216   }
01217 
01218   if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01219 
01220   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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 //  _companies_ai[c->index].loco_id = INVALID_VEHICLE;
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     // look for one from the subsidy list
01263     AiFindSubsidyPassengerRoute(&fr);
01264     if (IsInsideMM(fr.distance, 55, 180 + 1)) break;
01265 
01266     // try a random one
01267     AiFindRandomPassengerRoute(&fr);
01268     if (IsInsideMM(fr.distance, 55, 180 + 1)) break;
01269 
01270     // only test 60 times
01271     if (--i == 0) return;
01272   }
01273 
01274   fr.cargo = CT_PASSENGERS;
01275 
01276   if (!AiCheckIfRouteIsGood(c, &fr, 2)) return;
01277 
01278   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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 //  _companies_ai[c->index].loco_id = INVALID_VEHICLE;
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     // Find a town big enough
01322     t = AiFindRandomTown();
01323     if (t != NULL && t->population >= 700) break;
01324 
01325     // only test 60 times
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   // Fill the source field
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   // Fill the dest field
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   // Fill common fields
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 //  _companies_ai[c->index].loco_id = INVALID_VEHICLE;
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   /* Get aircraft that would be bought for this route
01390    * (probably, as conditions may change before the route is fully built,
01391    * like running out of money and having to select different aircraft, etc ...) */
01392   EngineID veh = AiChooseAircraftToBuild(c->money, _companies_ai[c->index].build_kind != 0 ? AIR_CTOL : 0);
01393 
01394   /* No aircraft buildable mean no aircraft route */
01395   if (veh == INVALID_ENGINE) return;
01396 
01397   const AircraftVehicleInfo *avi = AircraftVehInfo(veh);
01398 
01399   /* For passengers, "optimal" number of days in transit is about 80 to 100
01400    * Calculate "maximum optimal number of squares" from speed for 80 days
01401    * 20 days should be enough for takeoff, land, taxi, etc ...
01402    *
01403    * "A vehicle traveling at 100kph will cross 5.6 tiles per day" ->
01404    * Since in table aircraft speeds are in "real km/h", this should be accurate
01405    * We get max_squares = avi->max_speed * 5.6 / 100.0 * 80 */
01406   int max_squares = avi->max_speed * 448 / 100;
01407 
01408   /* For example this will be 10456 tiles for 2334 km/h aircrafts with realistic aircraft speeds
01409    * and 836 with "unrealistic" speeds, much more than the original 95 squares limit
01410    *
01411    * Size of the map, if not rectangular, it is the larger dimension of it
01412    */
01413   int map_size = max(MapSizeX(), MapSizeY());
01414 
01415   /* Minimum distance between airports is half of map size, clamped between 1% and 20% of optimum.
01416    * May prevent building plane routes at all on small maps, but they will be ineffective there, so
01417    * it is feature, not a bug.
01418    * On smaller distances, buses or trains are usually more effective approach anyway.
01419    * Additional safeguard is needing at least 20 squares,
01420    * which may trigger in highly unusual configurations */
01421   int min_squares = max(20, max(max_squares / 100, min(max_squares / 5, map_size / 2)));
01422 
01423   /* Should not happen, unless aircraft with real speed under approx. 5 km/h is selected.
01424    * No such exist, unless using some NewGRF with ballons, zeppelins or similar
01425    * slow-moving stuff. In that case, bail out, it is faster to walk by foot anyway :). */
01426   if (max_squares < min_squares) return;
01427 
01428   i = 60;
01429   for (;;) {
01430 
01431     // look for one from the subsidy list
01432     AiFindSubsidyPassengerRoute(&fr);
01433     if (IsInsideMM(fr.distance, min_squares, max_squares + 1)) break;
01434 
01435     // try a random one
01436     AiFindRandomPassengerRoute(&fr);
01437     if (IsInsideMM<