# default.cpp

    00001 /* $Id: default.cpp 14266 2008-09-07 21:26:26Z rubidium $ */
    00002
    00003 #include "../../stdafx.h"
    00004 #include "../../openttd.h"
    00005 #include "../../aircraft.h"
    00006 #include "../../bridge_map.h"
    00007 #include "../../tile_cmd.h"
    00008 #include "../../landscape.h"
    00009 #include "../../rail_map.h"
    00010 #include "../../road_map.h"
    00011 #include "../../roadveh.h"
    00012 #include "../../station_map.h"
    00013 #include "../../tunnel_map.h"
    00014 #include "../../engine.h"
    00015 #include "../../command_func.h"
    00016 #include "../../town.h"
    00017 #include "../../industry.h"
    00018 #include "../../station.h"
    00019 #include "../../pathfind.h"
    00020 #include "../../airport.h"
    00021 #include "../../depot.h"
    00022 #include "../../variables.h"
    00023 #include "../../bridge.h"
    00024 #include "../../date_func.h"
    00025 #include "../../tunnelbridge_map.h"
    00026 #include "../../window_func.h"
    00027 #include "../../vehicle_func.h"
    00028 #include "../../functions.h"
    00029 #include "../../saveload.h"
    00030 #include "../../player_func.h"
    00031 #include "../../player_base.h"
    00032 #include "../../settings_type.h"
    00033 #include "default.h"
    00034 #include "../../tunnelbridge.h"
    00035
    00036 #include "../../table/ai_rail.h"
    00037
    00038 // remove some day perhaps?
    00039 static uint _ai_service_interval;
    00040 PlayerAI _players_ai[MAX_PLAYERS];
    00041
    00042 typedef void AiStateAction(Player *p);
    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(Player *p)
    00079 {
    00080   _players_ai[p->index].state = AIS_REMOVE_TRACK;
    00081   _players_ai[p->index].state_counter = 0;
    00082 }
    00083
    00084 static void AiCase1(Player *p)
    00085 {
    00086   _players_ai[p->index].cur_veh = NULL;
    00087   _players_ai[p->index].state = AIS_VEH_LOOP;
    00088 }
    00089
    00090 static void AiStateVehLoop(Player *p)
    00091 {
    00092   Vehicle *v;
    00093   uint index;
    00094
    00095   index = (_players_ai[p->index].cur_veh == NULL) ? 0 : _players_ai[p->index].cur_veh->index + 1;
    00096
    00097   FOR_ALL_VEHICLES_FROM(v, index) {
    00098     if (v->owner != _current_player) 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) < p->player_money) {
    00107         _players_ai[p->index].state = AIS_VEH_CHECK_REPLACE_VEHICLE;
    00108         _players_ai[p->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         _players_ai[p->index].state_counter = 0;
    00117         _players_ai[p->index].state = AIS_SELL_VEHICLE;
    00118         _players_ai[p->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         _players_ai[p->index].state = AIS_VEH_CHECK_REPLACE_VEHICLE;
    00128         _players_ai[p->index].cur_veh = v;
    00129         return;
    00130       }
    00131     }
    00132   }
    00133
    00134   _players_ai[p->index].state = AIS_WANT_NEW_ROUTE;
    00135   _players_ai[p->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   EngineID i;
    00143
    00144   FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_TRAIN) {
    00145     const RailVehicleInfo *rvi = RailVehInfo(i);
    00146     const Engine* e = GetEngine(i);
    00147
    00148     if (!IsCompatibleRail(rvi->railtype, railtype) ||
    00149         rvi->railveh_type == RAILVEH_WAGON ||
    00150         (rvi->railveh_type == RAILVEH_MULTIHEAD && flag & 1) ||
    00151         !HasBit(e->player_avail, _current_player) ||
    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   EngineID i;
    00174
    00175   FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_ROAD) {
    00176     const RoadVehicleInfo *rvi = RoadVehInfo(i);
    00177     const Engine* e = GetEngine(i);
    00178
    00179     if (!HasBit(e->player_avail, _current_player) || 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   EngineID i;
    00215
    00216   FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_AIRCRAFT) {
    00217     const Engine* e = GetEngine(i);
    00218
    00219     if (!HasBit(e->player_avail, _current_player) || e->reliability < 0x8A3D) {
    00220       continue;
    00221     }
    00222
    00223     if ((AircraftVehInfo(i)->subtype & forbidden) != 0) continue;
    00224
    00225     CommandCost ret = DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_AIRCRAFT);
    00226     if (CmdSucceeded(ret) && ret.GetCost() <= money && ret.GetCost() >= best_veh_cost) {
    00227       best_veh_cost = ret.GetCost();
    00228       best_veh_index = i;
    00229     }
    00230   }
    00231
    00232   return best_veh_index;
    00233 }
    00234
    00235 static Money AiGetBasePrice(const Player* p)
    00236 {
    00237   Money base = _price.station_value;
    00238
    00239   // adjust base price when more expensive vehicles are available
    00240   switch (_players_ai[p->index].railtype_to_use) {
    00241     default: NOT_REACHED();
    00242     case RAILTYPE_RAIL:     break;
    00243     case RAILTYPE_ELECTRIC: break;
    00244     case RAILTYPE_MONO:     base = (base * 3) >> 1; break;
    00245     case RAILTYPE_MAGLEV:   base *= 2; break;
    00246   }
    00247
    00248   return base;
    00249 }
    00250
    00251 static EngineID AiChooseRoadVehToReplaceWith(const Player* p, const Vehicle* v)
    00252 {
    00253   Money avail_money = p->player_money + v->value;
    00254   return AiChooseRoadVehToBuild(v->cargo_type, avail_money, v->tile);
    00255 }
    00256
    00257 static EngineID AiChooseAircraftToReplaceWith(const Player* p, const Vehicle* v)
    00258 {
    00259   Money avail_money = p->player_money + v->value;
    00260
    00261   /* determine forbidden aircraft bits */
    00262   byte forbidden = 0;
    00263   const Order *o;
    00264
    00265   FOR_VEHICLE_ORDERS(v, o) {
    00266     if (!o->IsValid()) continue;
    00267     if (!IsValidStationID(o->dest)) continue;
    00268     const Station *st = GetStation(o->dest);
    00269     if (!(st->facilities & FACIL_AIRPORT)) continue;
    00270
    00271     AirportFTAClass::Flags flags = st->Airport()->flags;
    00272     if (!(flags & AirportFTAClass::AIRPLANES)) forbidden |= AIR_CTOL | AIR_FAST; // no planes for heliports / oil rigs
    00273     if (flags & AirportFTAClass::SHORT_STRIP) forbidden |= AIR_FAST; // no fast planes for small airports
    00274   }
    00275
    00276   return AiChooseAircraftToBuild(
    00277     avail_money, forbidden
    00278   );
    00279 }
    00280
    00281 static EngineID AiChooseTrainToReplaceWith(const Player* p, const Vehicle* v)
    00282 {
    00283   Money avail_money = p->player_money + v->value;
    00284   const Vehicle* u = v;
    00285   int num = 0;
    00286
    00287   while (++num, u->Next() != NULL) {
    00288     u = u->Next();
    00289   }
    00290
    00291   // XXX: check if a wagon
    00292   return AiChooseTrainToBuild(v->u.rail.railtype, avail_money, 0, v->tile);
    00293 }
    00294
    00295 static EngineID AiChooseShipToReplaceWith(const Player* p, const Vehicle* v)
    00296 {
    00297   /* Ships are not implemented in this (broken) AI */
    00298   return INVALID_ENGINE;
    00299 }
    00300
    00301 static void AiHandleGotoDepot(Player *p, int cmd)
    00302 {
    00303   if (_players_ai[p->index].cur_veh->current_order.type != OT_GOTO_DEPOT)
    00304     DoCommand(0, _players_ai[p->index].cur_veh->index, 0, DC_EXEC, cmd);
    00305
    00306   if (++_players_ai[p->index].state_counter <= 1387) {
    00307     _players_ai[p->index].state = AIS_VEH_DO_REPLACE_VEHICLE;
    00308     return;
    00309   }
    00310
    00311   if (_players_ai[p->index].cur_veh->current_order.type == OT_GOTO_DEPOT) {
    00312     _players_ai[p->index].cur_veh->current_order.type = OT_DUMMY;
    00313     _players_ai[p->index].cur_veh->current_order.flags = 0;
    00314     InvalidateWindow(WC_VEHICLE_VIEW, _players_ai[p->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].type != OT_NOTHING; i++) {
    00323     if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK))
    00324       break;
    00325   }
    00326 }
    00327
    00328 static void AiHandleReplaceTrain(Player *p)
    00329 {
    00330   const Vehicle* v = _players_ai[p->index].cur_veh;
    00331   BackuppedOrders orderbak;
    00332   EngineID veh;
    00333
    00334   // wait until the vehicle reaches the depot.
    00335   if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
    00336     AiHandleGotoDepot(p, CMD_SEND_TRAIN_TO_DEPOT);
    00337     return;
    00338   }
    00339
    00340   veh = AiChooseTrainToReplaceWith(p, 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_TRAIN);
    00352
    00353       DoCommand(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
    00354     }
    00355   }
    00356 }
    00357
    00358 static void AiHandleReplaceRoadVeh(Player *p)
    00359 {
    00360   const Vehicle* v = _players_ai[p->index].cur_veh;
    00361   BackuppedOrders orderbak;
    00362   EngineID veh;
    00363
    00364   if (!v->IsStoppedInDepot()) {
    00365     AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT);
    00366     return;
    00367   }
    00368
    00369   veh = AiChooseRoadVehToReplaceWith(p, 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_ROADVEH);
    00382       DoCommand(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
    00383     }
    00384   }
    00385 }
    00386
    00387 static void AiHandleReplaceAircraft(Player *p)
    00388 {
    00389   const Vehicle* v = _players_ai[p->index].cur_veh;
    00390   BackuppedOrders orderbak;
    00391   EngineID veh;
    00392
    00393   if (!v->IsStoppedInDepot()) {
    00394     AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR);
    00395     return;
    00396   }
    00397
    00398   veh = AiChooseAircraftToReplaceWith(p, 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_AIRCRAFT);
    00410
    00411       DoCommand(0, veh, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
    00412     }
    00413   }
    00414 }
    00415
    00416 static void AiHandleReplaceShip(Player *p)
    00417 {
    00418   /* Ships are not implemented in this (broken) AI */
    00419 }
    00420
    00421 typedef EngineID CheckReplaceProc(const Player* p, 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(Player *p);
    00431 static DoReplaceProc* const _veh_do_replace_proc[] = {
    00432   AiHandleReplaceTrain,
    00433   AiHandleReplaceRoadVeh,
    00434   AiHandleReplaceShip,
    00435   AiHandleReplaceAircraft
    00436 };
    00437
    00438 static void AiStateCheckReplaceVehicle(Player *p)
    00439 {
    00440   const Vehicle* v = _players_ai[p->index].cur_veh;
    00441
    00442   if (!v->IsValid() ||
    00443       v->owner != _current_player ||
    00444       v->type > VEH_SHIP ||
    00445       _veh_check_replace_proc[v->type - VEH_TRAIN](p, v) == INVALID_ENGINE) {
    00446     _players_ai[p->index].state = AIS_VEH_LOOP;
    00447   } else {
    00448     _players_ai[p->index].state_counter = 0;
    00449     _players_ai[p->index].state = AIS_VEH_DO_REPLACE_VEHICLE;
    00450   }
    00451 }
    00452
    00453 static void AiStateDoReplaceVehicle(Player *p)
    00454 {
    00455   const Vehicle* v = _players_ai[p->index].cur_veh;
    00456
    00457   _players_ai[p->index].state = AIS_VEH_LOOP;
    00458   // vehicle is not owned by the player anymore, something went very wrong.
    00459   if (!v->IsValid() || v->owner != _current_player) return;
    00460   _veh_do_replace_proc[v->type - VEH_TRAIN](p);
    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(Player *p, 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_player) 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 (_players_ai[p->index].route_type_mask != 0 &&
    00668       !(_players_ai[p->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_player] < -100 ||
    00684         to->ratings[_current_player] < -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   _players_ai[p->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(Player *p)
    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(p, &fr, 1)) return;
    00735
    00736   // Fill the source field
    00737   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    00738   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    00739
    00740   _players_ai[p->index].src.use_tile = 0;
    00741   _players_ai[p->index].src.rand_rng = 9;
    00742   _players_ai[p->index].src.cur_building_rule = 0xFF;
    00743   _players_ai[p->index].src.unk6 = 1;
    00744   _players_ai[p->index].src.unk7 = 0;
    00745   _players_ai[p->index].src.buildcmd_a = 0x24;
    00746   _players_ai[p->index].src.buildcmd_b = 0xFF;
    00747   _players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
    00748     _players_ai[p->index].src.spec_tile,
    00749     _players_ai[p->index].dst.spec_tile
    00750   );
    00751   _players_ai[p->index].src.cargo = fr.cargo | 0x80;
    00752
    00753   // Fill the dest field
    00754
    00755   _players_ai[p->index].dst.use_tile = 0;
    00756   _players_ai[p->index].dst.rand_rng = 9;
    00757   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    00758   _players_ai[p->index].dst.unk6 = 1;
    00759   _players_ai[p->index].dst.unk7 = 0;
    00760   _players_ai[p->index].dst.buildcmd_a = 0x34;
    00761   _players_ai[p->index].dst.buildcmd_b = 0xFF;
    00762   _players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
    00763     _players_ai[p->index].dst.spec_tile,
    00764     _players_ai[p->index].src.spec_tile
    00765   );
    00766   _players_ai[p->index].dst.cargo = fr.cargo;
    00767
    00768   // Fill middle field 1
    00769   _players_ai[p->index].mid1.spec_tile = AiGetPctTileBetween(
    00770     _players_ai[p->index].src.spec_tile,
    00771     _players_ai[p->index].dst.spec_tile,
    00772     0x55
    00773   );
    00774   _players_ai[p->index].mid1.use_tile = 0;
    00775   _players_ai[p->index].mid1.rand_rng = 6;
    00776   _players_ai[p->index].mid1.cur_building_rule = 0xFF;
    00777   _players_ai[p->index].mid1.unk6 = 2;
    00778   _players_ai[p->index].mid1.unk7 = 1;
    00779   _players_ai[p->index].mid1.buildcmd_a = 0x30;
    00780   _players_ai[p->index].mid1.buildcmd_b = 0xFF;
    00781   _players_ai[p->index].mid1.direction = _players_ai[p->index].src.direction;
    00782   _players_ai[p->index].mid1.cargo = fr.cargo;
    00783
    00784   // Fill middle field 2
    00785   _players_ai[p->index].mid2.spec_tile = AiGetPctTileBetween(
    00786     _players_ai[p->index].src.spec_tile,
    00787     _players_ai[p->index].dst.spec_tile,
    00788     0xAA
    00789   );
    00790   _players_ai[p->index].mid2.use_tile = 0;
    00791   _players_ai[p->index].mid2.rand_rng = 6;
    00792   _players_ai[p->index].mid2.cur_building_rule = 0xFF;
    00793   _players_ai[p->index].mid2.unk6 = 2;
    00794   _players_ai[p->index].mid2.unk7 = 1;
    00795   _players_ai[p->index].mid2.buildcmd_a = 0xFF;
    00796   _players_ai[p->index].mid2.buildcmd_b = 0xFF;
    00797   _players_ai[p->index].mid2.direction = _players_ai[p->index].dst.direction;
    00798   _players_ai[p->index].mid2.cargo = fr.cargo;
    00799
    00800   // Fill common fields
    00801   _players_ai[p->index].cargo_type = fr.cargo;
    00802   _players_ai[p->index].num_wagons = 3;
    00803   _players_ai[p->index].build_kind = 2;
    00804   _players_ai[p->index].num_build_rec = 4;
    00805   _players_ai[p->index].num_loco_to_build = 2;
    00806   _players_ai[p->index].num_want_fullload = 2;
    00807   _players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
    00808   _players_ai[p->index].order_list_blocks[0] = 0;
    00809   _players_ai[p->index].order_list_blocks[1] = 1;
    00810   _players_ai[p->index].order_list_blocks[2] = 255;
    00811
    00812   _players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
    00813   _players_ai[p->index].state_mode = UCHAR_MAX;
    00814   _players_ai[p->index].state_counter = 0;
    00815   _players_ai[p->index].timeout_counter = 0;
    00816 }
    00817
    00818 static void AiWantMediumIndustryRoute(Player *p)
    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(p, &fr, 1)) return;
    00838
    00839   // Fill the source field
    00840   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    00841   _players_ai[p->index].src.use_tile = 0;
    00842   _players_ai[p->index].src.rand_rng = 9;
    00843   _players_ai[p->index].src.cur_building_rule = 0xFF;
    00844   _players_ai[p->index].src.unk6 = 1;
    00845   _players_ai[p->index].src.unk7 = 0;
    00846   _players_ai[p->index].src.buildcmd_a = 0x10;
    00847   _players_ai[p->index].src.buildcmd_b = 0xFF;
    00848   _players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
    00849     GET_TOWN_OR_INDUSTRY_TILE(fr.from),
    00850     GET_TOWN_OR_INDUSTRY_TILE(fr.to)
    00851   );
    00852   _players_ai[p->index].src.cargo = fr.cargo | 0x80;
    00853
    00854   // Fill the dest field
    00855   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    00856   _players_ai[p->index].dst.use_tile = 0;
    00857   _players_ai[p->index].dst.rand_rng = 9;
    00858   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    00859   _players_ai[p->index].dst.unk6 = 1;
    00860   _players_ai[p->index].dst.unk7 = 0;
    00861   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    00862   _players_ai[p->index].dst.buildcmd_b = 0xFF;
    00863   _players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
    00864     GET_TOWN_OR_INDUSTRY_TILE(fr.to),
    00865     GET_TOWN_OR_INDUSTRY_TILE(fr.from)
    00866   );
    00867   _players_ai[p->index].dst.cargo = fr.cargo;
    00868
    00869   // Fill common fields
    00870   _players_ai[p->index].cargo_type = fr.cargo;
    00871   _players_ai[p->index].num_wagons = 3;
    00872   _players_ai[p->index].build_kind = 1;
    00873   _players_ai[p->index].num_build_rec = 2;
    00874   _players_ai[p->index].num_loco_to_build = 1;
    00875   _players_ai[p->index].num_want_fullload = 1;
    00876   _players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
    00877   _players_ai[p->index].order_list_blocks[0] = 0;
    00878   _players_ai[p->index].order_list_blocks[1] = 1;
    00879   _players_ai[p->index].order_list_blocks[2] = 255;
    00880   _players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
    00881   _players_ai[p->index].state_mode = UCHAR_MAX;
    00882   _players_ai[p->index].state_counter = 0;
    00883   _players_ai[p->index].timeout_counter = 0;
    00884 }
    00885
    00886 static void AiWantShortIndustryRoute(Player *p)
    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(p, &fr, 1)) return;
    00906
    00907   // Fill the source field
    00908   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    00909   _players_ai[p->index].src.use_tile = 0;
    00910   _players_ai[p->index].src.rand_rng = 9;
    00911   _players_ai[p->index].src.cur_building_rule = 0xFF;
    00912   _players_ai[p->index].src.unk6 = 1;
    00913   _players_ai[p->index].src.unk7 = 0;
    00914   _players_ai[p->index].src.buildcmd_a = 0x10;
    00915   _players_ai[p->index].src.buildcmd_b = 0xFF;
    00916   _players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
    00917     GET_TOWN_OR_INDUSTRY_TILE(fr.from),
    00918     GET_TOWN_OR_INDUSTRY_TILE(fr.to)
    00919   );
    00920   _players_ai[p->index].src.cargo = fr.cargo | 0x80;
    00921
    00922   // Fill the dest field
    00923   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    00924   _players_ai[p->index].dst.use_tile = 0;
    00925   _players_ai[p->index].dst.rand_rng = 9;
    00926   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    00927   _players_ai[p->index].dst.unk6 = 1;
    00928   _players_ai[p->index].dst.unk7 = 0;
    00929   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    00930   _players_ai[p->index].dst.buildcmd_b = 0xFF;
    00931   _players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
    00932     GET_TOWN_OR_INDUSTRY_TILE(fr.to),
    00933     GET_TOWN_OR_INDUSTRY_TILE(fr.from)
    00934   );
    00935   _players_ai[p->index].dst.cargo = fr.cargo;
    00936
    00937   // Fill common fields
    00938   _players_ai[p->index].cargo_type = fr.cargo;
    00939   _players_ai[p->index].num_wagons = 2;
    00940   _players_ai[p->index].build_kind = 1;
    00941   _players_ai[p->index].num_build_rec = 2;
    00942   _players_ai[p->index].num_loco_to_build = 1;
    00943   _players_ai[p->index].num_want_fullload = 1;
    00944   _players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
    00945   _players_ai[p->index].order_list_blocks[0] = 0;
    00946   _players_ai[p->index].order_list_blocks[1] = 1;
    00947   _players_ai[p->index].order_list_blocks[2] = 255;
    00948   _players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
    00949   _players_ai[p->index].state_mode = UCHAR_MAX;
    00950   _players_ai[p->index].state_counter = 0;
    00951   _players_ai[p->index].timeout_counter = 0;
    00952 }
    00953
    00954 static void AiWantMailRoute(Player *p)
    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(p, &fr, 1)) return;
    00975
    00976   // Fill the source field
    00977   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    00978   _players_ai[p->index].src.use_tile = 0;
    00979   _players_ai[p->index].src.rand_rng = 7;
    00980   _players_ai[p->index].src.cur_building_rule = 0xFF;
    00981   _players_ai[p->index].src.unk6 = 1;
    00982   _players_ai[p->index].src.unk7 = 0;
    00983   _players_ai[p->index].src.buildcmd_a = 0x24;
    00984   _players_ai[p->index].src.buildcmd_b = 0xFF;
    00985   _players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
    00986     GET_TOWN_OR_INDUSTRY_TILE(fr.from),
    00987     GET_TOWN_OR_INDUSTRY_TILE(fr.to)
    00988   );
    00989   _players_ai[p->index].src.cargo = fr.cargo;
    00990
    00991   // Fill the dest field
    00992   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    00993   _players_ai[p->index].dst.use_tile = 0;
    00994   _players_ai[p->index].dst.rand_rng = 7;
    00995   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    00996   _players_ai[p->index].dst.unk6 = 1;
    00997   _players_ai[p->index].dst.unk7 = 0;
    00998   _players_ai[p->index].dst.buildcmd_a = 0x34;
    00999   _players_ai[p->index].dst.buildcmd_b = 0xFF;
    01000   _players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
    01001     GET_TOWN_OR_INDUSTRY_TILE(fr.to),
    01002     GET_TOWN_OR_INDUSTRY_TILE(fr.from)
    01003   );
    01004   _players_ai[p->index].dst.cargo = fr.cargo;
    01005
    01006   // Fill middle field 1
    01007   _players_ai[p->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   _players_ai[p->index].mid1.use_tile = 0;
    01013   _players_ai[p->index].mid1.rand_rng = 6;
    01014   _players_ai[p->index].mid1.cur_building_rule = 0xFF;
    01015   _players_ai[p->index].mid1.unk6 = 2;
    01016   _players_ai[p->index].mid1.unk7 = 1;
    01017   _players_ai[p->index].mid1.buildcmd_a = 0x30;
    01018   _players_ai[p->index].mid1.buildcmd_b = 0xFF;
    01019   _players_ai[p->index].mid1.direction = _players_ai[p->index].src.direction;
    01020   _players_ai[p->index].mid1.cargo = fr.cargo;
    01021
    01022   // Fill middle field 2
    01023   _players_ai[p->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   _players_ai[p->index].mid2.use_tile = 0;
    01029   _players_ai[p->index].mid2.rand_rng = 6;
    01030   _players_ai[p->index].mid2.cur_building_rule = 0xFF;
    01031   _players_ai[p->index].mid2.unk6 = 2;
    01032   _players_ai[p->index].mid2.unk7 = 1;
    01033   _players_ai[p->index].mid2.buildcmd_a = 0xFF;
    01034   _players_ai[p->index].mid2.buildcmd_b = 0xFF;
    01035   _players_ai[p->index].mid2.direction = _players_ai[p->index].dst.direction;
    01036   _players_ai[p->index].mid2.cargo = fr.cargo;
    01037
    01038   // Fill common fields
    01039   _players_ai[p->index].cargo_type = fr.cargo;
    01040   _players_ai[p->index].num_wagons = 3;
    01041   _players_ai[p->index].build_kind = 2;
    01042   _players_ai[p->index].num_build_rec = 4;
    01043   _players_ai[p->index].num_loco_to_build = 2;
    01044   _players_ai[p->index].num_want_fullload = 0;
    01045   _players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
    01046   _players_ai[p->index].order_list_blocks[0] = 0;
    01047   _players_ai[p->index].order_list_blocks[1] = 1;
    01048   _players_ai[p->index].order_list_blocks[2] = 255;
    01049   _players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
    01050   _players_ai[p->index].state_mode = UCHAR_MAX;
    01051   _players_ai[p->index].state_counter = 0;
    01052   _players_ai[p->index].timeout_counter = 0;
    01053 }
    01054
    01055 static void AiWantPassengerRoute(Player *p)
    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(p, &fr, 1)) return;
    01076
    01077   // Fill the source field
    01078   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    01079   _players_ai[p->index].src.use_tile = 0;
    01080   _players_ai[p->index].src.rand_rng = 7;
    01081   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01082   _players_ai[p->index].src.unk6 = 1;
    01083   _players_ai[p->index].src.unk7 = 0;
    01084   _players_ai[p->index].src.buildcmd_a = 0x10;
    01085   _players_ai[p->index].src.buildcmd_b = 0xFF;
    01086   _players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
    01087     GET_TOWN_OR_INDUSTRY_TILE(fr.from),
    01088     GET_TOWN_OR_INDUSTRY_TILE(fr.to)
    01089   );
    01090   _players_ai[p->index].src.cargo = fr.cargo;
    01091
    01092   // Fill the dest field
    01093   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    01094   _players_ai[p->index].dst.use_tile = 0;
    01095   _players_ai[p->index].dst.rand_rng = 7;
    01096   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01097   _players_ai[p->index].dst.unk6 = 1;
    01098   _players_ai[p->index].dst.unk7 = 0;
    01099   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    01100   _players_ai[p->index].dst.buildcmd_b = 0xFF;
    01101   _players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
    01102     GET_TOWN_OR_INDUSTRY_TILE(fr.to),
    01103     GET_TOWN_OR_INDUSTRY_TILE(fr.from)
    01104   );
    01105   _players_ai[p->index].dst.cargo = fr.cargo;
    01106
    01107   // Fill common fields
    01108   _players_ai[p->index].cargo_type = fr.cargo;
    01109   _players_ai[p->index].num_wagons = 2;
    01110   _players_ai[p->index].build_kind = 1;
    01111   _players_ai[p->index].num_build_rec = 2;
    01112   _players_ai[p->index].num_loco_to_build = 1;
    01113   _players_ai[p->index].num_want_fullload = 0;
    01114   _players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
    01115   _players_ai[p->index].order_list_blocks[0] = 0;
    01116   _players_ai[p->index].order_list_blocks[1] = 1;
    01117   _players_ai[p->index].order_list_blocks[2] = 255;
    01118   _players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
    01119   _players_ai[p->index].state_mode = UCHAR_MAX;
    01120   _players_ai[p->index].state_counter = 0;
    01121   _players_ai[p->index].timeout_counter = 0;
    01122 }
    01123
    01124 static void AiWantTrainRoute(Player *p)
    01125 {
    01126   uint16 r = GB(Random(), 0, 16);
    01127
    01128   _players_ai[p->index].railtype_to_use = GetBestRailtype(p->index);
    01129
    01130   if (r > 0xD000) {
    01131     AiWantLongIndustryRoute(p);
    01132   } else if (r > 0x6000) {
    01133     AiWantMediumIndustryRoute(p);
    01134   } else if (r > 0x1000) {
    01135     AiWantShortIndustryRoute(p);
    01136   } else if (r > 0x800) {
    01137     AiWantPassengerRoute(p);
    01138   } else {
    01139     AiWantMailRoute(p);
    01140   }
    01141 }
    01142
    01143 static void AiWantLongRoadIndustryRoute(Player *p)
    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(p, &fr, 2)) return;
    01163
    01164   // Fill the source field
    01165   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    01166   _players_ai[p->index].src.use_tile = 0;
    01167   _players_ai[p->index].src.rand_rng = 9;
    01168   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01169   _players_ai[p->index].src.buildcmd_a = 1;
    01170   _players_ai[p->index].src.direction = 0;
    01171   _players_ai[p->index].src.cargo = fr.cargo | 0x80;
    01172
    01173   // Fill the dest field
    01174   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    01175   _players_ai[p->index].dst.use_tile = 0;
    01176   _players_ai[p->index].dst.rand_rng = 9;
    01177   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01178   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    01179   _players_ai[p->index].dst.direction = 0;
    01180   _players_ai[p->index].dst.cargo = fr.cargo;
    01181
    01182   // Fill common fields
    01183   _players_ai[p->index].cargo_type = fr.cargo;
    01184   _players_ai[p->index].num_build_rec = 2;
    01185   _players_ai[p->index].num_loco_to_build = 5;
    01186   _players_ai[p->index].num_want_fullload = 5;
    01187
    01188 //  _players_ai[p->index].loco_id = INVALID_VEHICLE;
    01189   _players_ai[p->index].order_list_blocks[0] = 0;
    01190   _players_ai[p->index].order_list_blocks[1] = 1;
    01191   _players_ai[p->index].order_list_blocks[2] = 255;
    01192
    01193   _players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
    01194   _players_ai[p->index].state_mode = UCHAR_MAX;
    01195   _players_ai[p->index].state_counter = 0;
    01196   _players_ai[p->index].timeout_counter = 0;
    01197 }
    01198
    01199 static void AiWantMediumRoadIndustryRoute(Player *p)
    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(p, &fr, 2)) return;
    01219
    01220   // Fill the source field
    01221   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    01222   _players_ai[p->index].src.use_tile = 0;
    01223   _players_ai[p->index].src.rand_rng = 9;
    01224   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01225   _players_ai[p->index].src.buildcmd_a = 1;
    01226   _players_ai[p->index].src.direction = 0;
    01227   _players_ai[p->index].src.cargo = fr.cargo | 0x80;
    01228
    01229   // Fill the dest field
    01230   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    01231   _players_ai[p->index].dst.use_tile = 0;
    01232   _players_ai[p->index].dst.rand_rng = 9;
    01233   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01234   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    01235   _players_ai[p->index].dst.direction = 0;
    01236   _players_ai[p->index].dst.cargo = fr.cargo;
    01237
    01238   // Fill common fields
    01239   _players_ai[p->index].cargo_type = fr.cargo;
    01240   _players_ai[p->index].num_build_rec = 2;
    01241   _players_ai[p->index].num_loco_to_build = 3;
    01242   _players_ai[p->index].num_want_fullload = 3;
    01243
    01244 //  _players_ai[p->index].loco_id = INVALID_VEHICLE;
    01245   _players_ai[p->index].order_list_blocks[0] = 0;
    01246   _players_ai[p->index].order_list_blocks[1] = 1;
    01247   _players_ai[p->index].order_list_blocks[2] = 255;
    01248
    01249   _players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
    01250   _players_ai[p->index].state_mode = UCHAR_MAX;
    01251   _players_ai[p->index].state_counter = 0;
    01252   _players_ai[p->index].timeout_counter = 0;
    01253 }
    01254
    01255 static void AiWantLongRoadPassengerRoute(Player *p)
    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(p, &fr, 2)) return;
    01277
    01278   // Fill the source field
    01279   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    01280   _players_ai[p->index].src.use_tile = 0;
    01281   _players_ai[p->index].src.rand_rng = 10;
    01282   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01283   _players_ai[p->index].src.buildcmd_a = 1;
    01284   _players_ai[p->index].src.direction = 0;
    01285   _players_ai[p->index].src.cargo = CT_PASSENGERS;
    01286
    01287   // Fill the dest field
    01288   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    01289   _players_ai[p->index].dst.use_tile = 0;
    01290   _players_ai[p->index].dst.rand_rng = 10;
    01291   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01292   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    01293   _players_ai[p->index].dst.direction = 0;
    01294   _players_ai[p->index].dst.cargo = CT_PASSENGERS;
    01295
    01296   // Fill common fields
    01297   _players_ai[p->index].cargo_type = CT_PASSENGERS;
    01298   _players_ai[p->index].num_build_rec = 2;
    01299   _players_ai[p->index].num_loco_to_build = 4;
    01300   _players_ai[p->index].num_want_fullload = 0;
    01301
    01302 //  _players_ai[p->index].loco_id = INVALID_VEHICLE;
    01303   _players_ai[p->index].order_list_blocks[0] = 0;
    01304   _players_ai[p->index].order_list_blocks[1] = 1;
    01305   _players_ai[p->index].order_list_blocks[2] = 255;
    01306
    01307   _players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
    01308   _players_ai[p->index].state_mode = UCHAR_MAX;
    01309   _players_ai[p->index].state_counter = 0;
    01310   _players_ai[p->index].timeout_counter = 0;
    01311 }
    01312
    01313 static void AiWantPassengerRouteInsideTown(Player *p)
    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(p, &fr, 2)) return;
    01333
    01334   // Fill the source field
    01335   _players_ai[p->index].src.spec_tile = t->xy;
    01336   _players_ai[p->index].src.use_tile = 0;
    01337   _players_ai[p->index].src.rand_rng = 10;
    01338   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01339   _players_ai[p->index].src.buildcmd_a = 1;
    01340   _players_ai[p->index].src.direction = 0;
    01341   _players_ai[p->index].src.cargo = CT_PASSENGERS;
    01342
    01343   // Fill the dest field
    01344   _players_ai[p->index].dst.spec_tile = t->xy;
    01345   _players_ai[p->index].dst.use_tile = 0;
    01346   _players_ai[p->index].dst.rand_rng = 10;
    01347   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01348   _players_ai[p->index].dst.buildcmd_a = 0xFF;
    01349   _players_ai[p->index].dst.direction = 0;
    01350   _players_ai[p->index].dst.cargo = CT_PASSENGERS;
    01351
    01352   // Fill common fields
    01353   _players_ai[p->index].cargo_type = CT_PASSENGERS;
    01354   _players_ai[p->index].num_build_rec = 2;
    01355   _players_ai[p->index].num_loco_to_build = 2;
    01356   _players_ai[p->index].num_want_fullload = 0;
    01357
    01358 //  _players_ai[p->index].loco_id = INVALID_VEHICLE;
    01359   _players_ai[p->index].order_list_blocks[0] = 0;
    01360   _players_ai[p->index].order_list_blocks[1] = 1;
    01361   _players_ai[p->index].order_list_blocks[2] = 255;
    01362
    01363   _players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
    01364   _players_ai[p->index].state_mode = UCHAR_MAX;
    01365   _players_ai[p->index].state_counter = 0;
    01366   _players_ai[p->index].timeout_counter = 0;
    01367 }
    01368
    01369 static void AiWantRoadRoute(Player *p)
    01370 {
    01371   uint16 r = GB(Random(), 0, 16);
    01372
    01373   if (r > 0x4000) {
    01374     AiWantLongRoadIndustryRoute(p);
    01375   } else if (r > 0x2000) {
    01376     AiWantMediumRoadIndustryRoute(p);
    01377   } else if (r > 0x1000) {
    01378     AiWantLongRoadPassengerRoute(p);
    01379   } else {
    01380     AiWantPassengerRouteInsideTown(p);
    01381   }
    01382 }
    01383
    01384 static void AiWantPassengerAircraftRoute(Player *p)
    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(p->player_money, _players_ai[p->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(fr.distance, min_squares, max_squares + 1)) break;
    01438
    01439     // only test 60 times
    01440     if (--i == 0) return;
    01441   }
    01442
    01443   fr.cargo = CT_PASSENGERS;
    01444   if (!AiCheckIfRouteIsGood(p, &fr, 4)) return;
    01445
    01446
    01447   // Fill the source field
    01448   _players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
    01449   _players_ai[p->index].src.use_tile = 0;
    01450   _players_ai[p->index].src.rand_rng = 12;
    01451   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01452   _players_ai[p->index].src.cargo = fr.cargo;
    01453
    01454   // Fill the dest field
    01455   _players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
    01456   _players_ai[p->index].dst.use_tile = 0;
    01457   _players_ai[p->index].dst.rand_rng = 12;
    01458   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01459   _players_ai[p->index].dst.cargo = fr.cargo;
    01460
    01461   // Fill common fields
    01462   _players_ai[p->index].cargo_type = fr.cargo;
    01463   _players_ai[p->index].build_kind = 0;
    01464   _players_ai[p->index].num_build_rec = 2;
    01465   _players_ai[p->index].num_loco_to_build = 1;
    01466   /* Using full load always may not be the best.
    01467    * Pick random value and rely on selling the vehicle & route
    01468    * afterwards if the choice was utterly wrong (or maybe altering the value if AI is improved)
    01469    * When traffic is very low or very assymetric, is is better not to full load
    01470    * When traffic is high, full/non-full make no difference
    01471    * It should be better to run with aircraft only one way full 6 times per year,
    01472    * rather than two way full 1 times.
    01473    * Practical experiments with AI show that the non-full-load aircrafts are usually
    01474    * those that survive
    01475    * Also, non-full load is more resistant against starving (by building better stations
    01476    * or using exclusive rights)
    01477    */
    01478   _players_ai[p->index].num_want_fullload = Chance16(1, 5); // 20% chance
    01479 //  _players_ai[p->index].loco_id = INVALID_VEHICLE;
    01480   _players_ai[p->index].order_list_blocks[0] = 0;
    01481   _players_ai[p->index].order_list_blocks[1] = 1;
    01482   _players_ai[p->index].order_list_blocks[2] = 255;
    01483
    01484   _players_ai[p->index].state = AIS_AIRPORT_STUFF;
    01485   _players_ai[p->index].timeout_counter = 0;
    01486 }
    01487
    01488 static void AiWantOilRigAircraftRoute(Player *p)
    01489 {
    01490   int i;
    01491   FoundRoute fr;
    01492   Town *t;
    01493   Industry *in;
    01494
    01495   i = 60;
    01496   for (;;) {
    01497     // Find a town
    01498     t = AiFindRandomTown();
    01499     if (t != NULL) {
    01500       // Find a random oil rig industry
    01501       in = AiFindRandomIndustry();
    01502       if (in != NULL && GetIndustrySpec(in->type)->behaviour & INDUSTRYBEH_AI_AIRSHIP_ROUTES) {
    01503         if (DistanceManhattan(t->xy, in->xy) < 60)
    01504           break;
    01505       }
    01506     }
    01507
    01508     // only test 60 times
    01509     if (--i == 0) return;
    01510   }
    01511
    01512   fr.cargo = CT_PASSENGERS;
    01513   fr.from = fr.to = t;
    01514
    01515   if (!AiCheckIfRouteIsGood(p, &fr, 4)) return;
    01516
    01517   // Fill the source field
    01518   _players_ai[p->index].src.spec_tile = t->xy;
    01519   _players_ai[p->index].src.use_tile = 0;
    01520   _players_ai[p->index].src.rand_rng = 12;
    01521   _players_ai[p->index].src.cur_building_rule = 0xFF;
    01522   _players_ai[p->index].src.cargo = CT_PASSENGERS;
    01523
    01524   // Fill the dest field
    01525   _players_ai[p->index].dst.spec_tile = in->xy;
    01526   _players_ai[p->index].dst.use_tile = 0;
    01527   _players_ai[p->index].dst.rand_rng = 5;
    01528   _players_ai[p->index].dst.cur_building_rule = 0xFF;
    01529   _players_ai[p->index].dst.cargo = CT_PASSENGERS;
    01530
    01531   // Fill common fields
    01532   _players_ai[p->index].cargo_type = CT_PASSENGERS;
    01533   _players_ai[p->index].build_kind = 1;
    01534   _players_ai[p->index].num_build_rec = 2;
    01535   _players_ai[p->index].num_loco_to_build = 1;
    01536   _players_ai[p->index].num_want_fullload = 0;
    01537 //  _players_ai[p->index].loco_id = INVALID_VEHICLE;
    01538   _players_ai[p->index].order_list_blocks[0] = 0;
    01539   _players_ai[p->index].order_list_blocks[1] = 1;
    01540   _players_ai[p->index].order_list_blocks[2] = 255;
    01541
    01542   _players_ai[p->index].state = AIS_AIRPORT_STUFF;
    01543   _players_ai[p->index].timeout_counter = 0;
    01544 }
    01545
    01546 static void AiWantAircraftRoute(Player *p)
    01547 {
    01548   uint16 r = (uint16)Random();
    01549
    01550   if (r >= 0x2AAA || _date < 0x3912 + DAYS_TILL_ORIGINAL_BASE_YEAR) {
    01551     AiWantPassengerAircraftRoute(p);
    01552   } else {
    01553     AiWantOilRigAircraftRoute(p);
    01554   }
    01555 }
    01556
    01557
    01558
    01559 static void AiStateWantNewRoute(Player *p)
    01560 {
    01561   uint16 r;
    01562   int i;
    01563
    01564   if (p->player_money < AiGetBasePrice(p) * 500) {
    01565     _players_ai[p->index].state = AIS_0;
    01566     return;
    01567   }
    01568
    01569   i = 200;
    01570   for (;;) {
    01571     r = (uint16)Random();
    01572
    01573     if (_patches.ai_disable_veh_train &&
    01574         _patches.ai_disable_veh_roadveh &&
    01575         _patches.ai_disable_veh_aircraft &&
    01576         _patches.ai_disable_veh_ship) {
    01577       return;
    01578     }
    01579
    01580     if (r < 0x7626) {
    01581       if (_patches.ai_disable_veh_train) continue;
    01582       AiWantTrainRoute(p);
    01583     } else if (r < 0xC4EA) {
    01584       if (_patches.ai_disable_veh_roadveh) continue;
    01585       AiWantRoadRoute(p);
    01586     } else if (r < 0xD89B) {
    01587       if (_patches.ai_disable_veh_aircraft) continue;
    01588       AiWantAircraftRoute(p);
    01589     } else {
    01590       /* Ships are not implemented in this (broken) AI */
    01591     }
    01592
    01593     // got a route?
    01594     if (_players_ai[p->index].state != AIS_WANT_NEW_ROUTE) break;
    01595
    01596     // time out?
    01597     if (--i == 0) {
    01598       if (++_players_ai[p->index].state_counter == 556) _players_ai[p->index].state = AIS_0;
    01599       break;
    01600     }
    01601   }
    01602 }
    01603
    01604 static bool AiCheckTrackResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo)
    01605 {
    01606   uint rad = (_patches.modified_catchment) ? CA_TRAIN : CA_UNMODIFIED;
    01607
    01608   for (; p->mode != 4; p++) {
    01609     AcceptedCargo values;
    01610     TileIndex tile2;
    01611     uint w;
    01612     uint h;
    01613
    01614     if (p->mode != 1) continue;
    01615
    01616     tile2 = TILE_ADD(tile, ToTileIndexDiff(p->tileoffs));
    01617     w = GB(p->attr, 1, 3);
    01618     h = GB(p->attr, 4, 3);
    01619
    01620     if (p->attr & 1) Swap(w, h);
    01621
    01622     if (cargo & 0x80) {
    01623       GetProductionAroundTiles(values, tile2, w, h, rad);
    01624       return values[cargo & 0x7F] != 0;
    01625     } else {
    01626       GetAcceptanceAroundTiles(values, tile2, w, h, rad);
    01627       if (!(values[cargo] & ~7))
    01628         return false;
    01629       if (cargo != CT_MAIL)
    01630         return true;
    01631       return !!((values[cargo] >> 1) & ~7);
    01632     }
    01633   }
    01634
    01635   return true;
    01636 }
    01637
    01638 static CommandCost AiDoBuildDefaultRailTrack(TileIndex tile, const AiDefaultBlockData* p, RailType railtype, byte flag)
    01639 {
    01640   CommandCost ret;
    01641   CommandCost total_cost(EXPENSES_CONSTRUCTION);
    01642   Town *t = NULL;
    01643   int rating = 0;
    01644   int i, j, k;
    01645
    01646   for (;;) {
    01647     // This will seldomly overflow for valid reasons. Mask it to be on the safe side.
    01648     uint c = TILE_MASK(tile + ToTileIndexDiff(p->tileoffs));
    01649
    01650     _cleared_town = NULL;
    01651
    01652     if (p->mode < 2) {
    01653       if (p->mode == 0) {
    01654         // Depot
    01655         ret = DoCommand(c, railtype, p->attr, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_TRAIN_DEPOT);
    01656       } else {
    01657         // Station
    01658         ret = DoCommand(c, (p->attr & 1) | (p->attr >> 4) << 8 | (p->attr >> 1 & 7) << 16, railtype, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_RAILROAD_STATION);
    01659       }
    01660
    01661       if (CmdFailed(ret)) return CMD_ERROR;
    01662       total_cost.AddCost(ret);
    01663
    01664 clear_town_stuff:;
    01665       if (_cleared_town != NULL) {
    01666         if (t != NULL && t != _cleared_town)
    01667           return CMD_ERROR;
    01668         t = _cleared_town;
    01669         rating += _cleared_town_rating;
    01670       }
    01671     } else if (p->mode == 2) {
    01672       /* Rail */
    01673       if (IsTileType(c, MP_RAILWAY)) return CMD_ERROR;
    01674
    01675       j = p->attr;
    01676       k = 0;
    01677
    01678       /* Build the rail
    01679        * note: FOR_EACH_SET_BIT cannot be used here
    01680        */
    01681       for (i = 0; i != 6; i++, j >>= 1) {
    01682         if (j & 1) {
    01683           k = i;
    01684           ret = DoCommand(c, railtype, i, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
    01685           if (CmdFailed(ret)) return CMD_ERROR;
    01686           total_cost.AddCost(ret);
    01687         }
    01688       }
    01689
    01690       /* signals too? */
    01691       if (j & 3) {
    01692         // Can't build signals on a road.
    01693         if (IsTileType(c, MP_ROAD)) return CMD_ERROR;
    01694
    01695         if (flag & DC_EXEC) {
    01696           j = 4 - j;
    01697           do {
    01698             ret = DoCommand(c, k, 0, flag, CMD_BUILD_SIGNALS);
    01699           } while (--j);
    01700         } else {
    01701           ret.AddCost(_price.build_signals);
    01702         }
    01703         if (CmdFailed(ret)) return CMD_ERROR;
    01704         total_cost.AddCost(ret);
    01705       }
    01706     } else if (p->mode == 3) {
    01707       //Clear stuff and then build single rail.
    01708       if (GetTileSlope(c, NULL) != SLOPE_FLAT) return CMD_ERROR;
    01709       ret = DoCommand(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR);
    01710       if (CmdFailed(ret)) return CMD_ERROR;
    01711       total_cost.AddCost(ret);
    01712       total_cost.AddCost(_price.build_rail);
    01713
    01714       if (flag & DC_EXEC) {
    01715         DoCommand(c, railtype, p->attr & 1, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_SINGLE_RAIL);
    01716       }
    01717
    01718       goto clear_town_stuff;
    01719     } else {
    01720       // Unk
    01721       break;
    01722     }
    01723
    01724     p++;
    01725   }
    01726
    01727   if (!(flag & DC_EXEC)) {
    01728     if (t != NULL && rating > t->ratings[_current_player]) {
    01729       return CMD_ERROR;
    01730     }
    01731   }
    01732
    01733   return total_cost;
    01734 }
    01735
    01736 // Returns rule and cost
    01737 static int AiBuildDefaultRailTrack(TileIndex tile, byte p0, byte p1, byte p2, byte p3, byte dir, byte cargo, RailType railtype, CommandCost* cost)
    01738 {
    01739   int i;
    01740   const AiDefaultRailBlock *p;
    01741
    01742   for (i = 0; (p = _default_rail_track_data[i]) != NULL; i++) {
    01743     if (p->p0 == p0 && p->p1 == p1 && p->p2 == p2 && p->p3 == p3 &&
    01744         (p->dir == 0xFF || p->dir == dir || ((p->dir - 1) & 3) == dir)) {
    01745       *cost = AiDoBuildDefaultRailTrack(tile, p->data, railtype, DC_NO_TOWN_RATING);
    01746       if (CmdSucceeded(*cost) && AiCheckTrackResources(tile, p->data, cargo))
    01747         return i;
    01748     }
    01749   }
    01750
    01751   return -1;
    01752 }
    01753
    01754 static const byte _terraform_up_flags[] = {
    01755   14, 13, 12, 11,
    01756   10,  9,  8,  7,
    01757    6,  5,  4,  3,
    01758    2,  1,  0,  1,
    01759    2,  1,  4,  1,
    01760    2,  1,  8,  1,
    01761    2,  1,  4,  2,
    01762    2,  1
    01763 };
    01764
    01765 static const byte _terraform_down_flags[] = {
    01766   1,  2, 3,  4,
    01767   5,  6, 1,  8,
    01768   9, 10, 8, 12,
    01769   4,  2, 0,  0,
    01770   1,  2, 3,  4,
    01771   5,  6, 2,  8,
    01772   9, 10, 1, 12,
    01773   8,  4
    01774 };
    01775
    01776 static void AiDoTerraformLand(TileIndex tile, DiagDirection dir, int unk, int mode)
    01777 {
    01778   PlayerID old_player;
    01779   uint32 r;
    01780   Slope slope;
    01781   uint h;
    01782
    01783   old_player = _current_player;
    01784   _current_player = OWNER_NONE;
    01785
    01786   r = Random();
    01787
    01788   unk &= (int)r;
    01789
    01790   do {
    01791     tile = TILE_MASK(tile + TileOffsByDiagDir(dir));
    01792
    01793     r >>= 2;
    01794     if (r & 2) {
    01795       dir = ChangeDiagDir(dir, (r & 1) ? DIAGDIRDIFF_90LEFT : DIAGDIRDIFF_90RIGHT);
    01796     }
    01797   } while (--unk >= 0);
    01798
    01799   slope = GetTileSlope(tile, &h);
    01800
    01801   if (slope != SLOPE_FLAT) {
    01802     if (mode > 0 || (mode == 0 && !(r & 0xC))) {
    01803       // Terraform up
    01804       DoCommand(tile, _terraform_up_flags[slope - 1], 1,
    01805         DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
    01806     } else if (h != 0) {
    01807       // Terraform down
    01808       DoCommand(tile, _terraform_down_flags[slope - 1], 0,
    01809         DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_TERRAFORM_LAND);
    01810     }
    01811   }
    01812
    01813   _current_player = old_player;
    01814 }
    01815
    01816 static void AiStateBuildDefaultRailBlocks(Player *p)
    01817 {
    01818   uint i;
    01819   int j;
    01820   AiBuildRec *aib;
    01821   int rule;
    01822   CommandCost cost;
    01823
    01824   // time out?
    01825   if (++_players_ai[p->index].timeout_counter == 1388) {
    01826     _players_ai[p->index].state = AIS_DELETE_RAIL_BLOCKS;
    01827     return;
    01828   }
    01829
    01830   // do the following 8 times
    01831   for (i = 0; i < 8; i++) {
    01832     // check if we can build the default track
    01833     aib = &_players_ai[p->index].src;
    01834     j = _players_ai[p->index].num_build_rec;
    01835     do {
    01836       // this item has already been built?
    01837       if (aib->cur_building_rule != 255) continue;
    01838
    01839       // adjust the coordinate randomly,
    01840       // to make sure that we find a position.
    01841       aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng);
    01842
    01843       // check if the track can be build there.
    01844       rule = AiBuildDefaultRailTrack(aib->use_tile,
    01845         _players_ai[p->index].build_kind, _players_ai[p->index].num_wagons,
    01846         aib->unk6, aib->unk7,
    01847         aib->direction, aib->cargo,
    01848         _players_ai[p->index].railtype_to_use,
    01849         &cost
    01850       );
    01851
    01852       if (rule == -1) {
    01853         // cannot build, terraform after a while
    01854         if (_players_ai[p->index].state_counter >= 600) {
    01855           AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)_players_ai[p->index].state_mode);
    01856         }
    01857         // also try the other terraform direction
    01858         if (++_players_ai[p->index].state_counter >= 1000) {
    01859           _players_ai[p->index].state_counter = 0;
    01860           _players_ai[p->index].state_mode = -_players_ai[p->index].state_mode;
    01861         }
    01862       } else if (CheckPlayerHasMoney(cost)) {
    01863         // player has money, build it.
    01864         aib->cur_building_rule = rule;
    01865
    01866         AiDoBuildDefaultRailTrack(
    01867           aib->use_tile,
    01868           _default_rail_track_data[rule]->data,
    01869           _players_ai[p->index].railtype_to_use,
    01870           DC_EXEC | DC_NO_TOWN_RATING
    01871         );
    01872       }
    01873     } while (++aib, --j);
    01874   }
    01875
    01876   // check if we're done with all of them
    01877   aib = &_players_ai[p->index].src;
    01878   j = _players_ai[p->index].num_build_rec;
    01879   do {
    01880     if (aib->cur_building_rule == 255) return;
    01881   } while (++aib, --j);
    01882
    01883   // yep, all are done. switch state to the rail building state.
    01884   _players_ai[p->index].state = AIS_BUILD_RAIL;
    01885   _players_ai[p->index].state_mode = 255;
    01886 }
    01887
    01888 static TileIndex AiGetEdgeOfDefaultRailBlock(byte rule, TileIndex tile, byte cmd, DiagDirection *dir)
    01889 {
    01890   const AiDefaultBlockData *p = _default_rail_track_data[rule]->data;
    01891
    01892   while (p->mode != 3 || !((--cmd) & 0x80)) p++;
    01893
    01894   return tile + ToTileIndexDiff(p->tileoffs) - TileOffsByDiagDir(*dir = p->attr);
    01895 }
    01896
    01897 struct AiRailPathFindData {
    01898   TileIndex tile;
    01899   TileIndex tile2;
    01900   int count;
    01901   bool flag;
    01902 };
    01903
    01904 static bool AiEnumFollowTrack(TileIndex tile, AiRailPathFindData *a, int track, uint length)
    01905 {
    01906   if (a->flag) return true;
    01907
    01908   if (length > 20 || tile == a->tile) {
    01909     a->flag = true;
    01910     return true;
    01911   }
    01912
    01913   if (DistanceMax(tile, a->tile2) < 4) a->count++;
    01914
    01915   return false;
    01916 }
    01917
    01918 static bool AiDoFollowTrack(const Player* p)
    01919 {
    01920   AiRailPathFindData arpfd;
    01921
    01922   arpfd.tile = _players_ai[p->index].start_tile_a;
    01923   arpfd.tile2 = _players_ai[p->index].cur_tile_a;
    01924   arpfd.flag = false;
    01925   arpfd.count = 0;
    01926   FollowTrack(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a), TRANSPORT_RAIL, 0, ReverseDiagDir(_players_ai[p->index].cur_dir_a),
    01927     (TPFEnumProc*)AiEnumFollowTrack, NULL, &arpfd);
    01928   return arpfd.count > 8;
    01929 }
    01930
    01931 struct AiRailFinder {
    01932   TileIndex final_tile;
    01933   DiagDirection final_dir;
    01934   byte depth;
    01935   byte recursive_mode;
    01936   DiagDirection cur_best_dir;
    01937   DiagDirection best_dir;
    01938   byte cur_best_depth;
    01939   byte best_depth;
    01940   uint cur_best_dist;
    01941   const byte *best_ptr;
    01942   uint best_dist;
    01943   TileIndex cur_best_tile, best_tile;
    01944   TileIndex bridge_end_tile;
    01945   Player *player;
    01946 };
    01947
    01948 static const byte _ai_table_15[4][8] = {
    01949   {0, 0, 4, 3, 3, 1, 128 + 0, 64},
    01950   {1, 1, 2, 0, 4, 2, 128 + 1, 65},
    01951   {0, 2, 2, 3, 5, 1, 128 + 2, 66},
    01952   {1, 3, 5, 0, 3, 2, 128 + 3, 67}
    01953 };
    01954
    01955 static const byte _dir_table_1[] = { 3, 9, 12, 6};
    01956 static const byte _dir_table_2[] = {12, 6,  3, 9};
    01957
    01958
    01959 static bool AiIsTileBanned(const Player* p, TileIndex tile, byte val)
    01960 {
    01961   int i;
    01962
    01963   for (i = 0; i != _players_ai[p->index].banned_tile_count; i++) {
    01964     if (_players_ai[p->index].banned_tiles[i] == tile && _players_ai[p->index].banned_val[i] == val) {
    01965       return true;
    01966     }
    01967   }
    01968   return false;
    01969 }
    01970
    01971 static void AiBanTile(Player* p, TileIndex tile, byte val)
    01972 {
    01973   uint i;
    01974
    01975   for (i = lengthof(_players_ai[p->index].banned_tiles) - 1; i != 0; i--) {
    01976     _players_ai[p->index].banned_tiles[i] = _players_ai[p->index].banned_tiles[i - 1];
    01977     _players_ai[p->index].banned_val[i] = _players_ai[p->index].banned_val[i - 1];
    01978   }
    01979
    01980   _players_ai[p->index].banned_tiles[0] = tile;
    01981   _players_ai[p->index].banned_val[0] = val;
    01982
    01983   if (_players_ai[p->index].banned_tile_count != lengthof(_players_ai[p->index].banned_tiles)) {
    01984     _players_ai[p->index].banned_tile_count++;
    01985   }
    01986 }
    01987
    01988 static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, DiagDirection dir);
    01989
    01990 static bool AiCheckRailPathBetter(AiRailFinder *arf, const byte *p)
    01991 {
    01992   bool better = false;
    01993
    01994   if (arf->recursive_mode < 1) {
    01995     // Mode is 0. This means destination has not been found yet.
    01996     // If the found path is shorter than the current one, remember it.
    01997     if (arf->cur_best_dist < arf->best_dist) {
    01998       arf->best_dir = arf->cur_best_dir;
    01999       arf->best_dist = arf->cur_best_dist;
    02000       arf->best_ptr = p;
    02001       arf->best_tile = arf->cur_best_tile;
    02002       better = true;
    02003     }
    02004   } else if (arf->recursive_mode > 1) {
    02005     // Mode is 2.
    02006     if (arf->best_dist != 0 || arf->cur_best_depth < arf->best_depth) {
    02007       arf->best_depth = arf->cur_best_depth;
    02008       arf->best_dist = 0;
    02009       arf->best_ptr = p;
    02010       arf->best_tile = 0;
    02011       better = true;
    02012     }
    02013   }
    02014   arf->recursive_mode = 0;
    02015   arf->cur_best_dist = UINT_MAX;
    02016   arf->cur_best_depth = 0xff;
    02017
    02018   return better;
    02019 }
    02020
    02021 static inline void AiCheckBuildRailBridgeHere(AiRailFinder *arf, TileIndex tile, const byte *p)
    02022 {
    02023   Slope tileh;
    02024   uint z;
    02025   bool flag;
    02026
    02027   DiagDirection dir2 = (DiagDirection)(p[0] & 3);
    02028
    02029   tileh = GetTileSlope(tile, &z);
    02030   if (tileh == _dir_table_1[dir2] || (tileh == SLOPE_FLAT && z != 0)) {
    02031     TileIndex tile_new = tile;
    02032
    02033     // Allow bridges directly over bottom tiles
    02034     flag = z == 0;
    02035     for (;;) {
    02036       TileType type;
    02037
    02038       if ((TileIndexDiff)tile_new < -TileOffsByDiagDir(dir2)) return; // Wraping around map, no bridge possible!
    02039       tile_new = TILE_MASK(tile_new + TileOffsByDiagDir(dir2));
    02040       type = GetTileType(tile_new);
    02041
    02042       if (type == MP_CLEAR || type == MP_TREES || GetTileSlope(tile_new, NULL) != SLOPE_FLAT) {
    02043         if (!flag) return;
    02044         break;
    02045       }
    02046       if (type != MP_WATER && type != MP_RAILWAY && type != MP_ROAD) return;
    02047       flag = true;
    02048     }
    02049
    02050     // Is building a (rail)bridge possible at this place (type doesn't matter)?
    02051     if (CmdFailed(DoCommand(tile_new, tile, 0 | _players_ai[arf->player->index].railtype_to_use << 8, DC_AUTO, CMD_BUILD_BRIDGE))) {
    02052       return;
    02053     }
    02054     AiBuildRailRecursive(arf, tile_new, dir2);
    02055
    02056     // At the bottom depth, check if the new path is better than the old one.
    02057     if (arf->depth == 1) {
    02058       if (AiCheckRailPathBetter(arf, p)) arf->bridge_end_tile = tile_new;
    02059     }
    02060   }
    02061 }
    02062
    02063 static inline void AiCheckBuildRailTunnelHere(AiRailFinder *arf, TileIndex tile, const byte *p)
    02064 {
    02065   uint z;
    02066
    02067   if (GetTileSlope(tile, &z) == _dir_table_2[p[0] & 3] && z != 0) {
    02068     CommandCost cost = DoCommand(tile, _players_ai[arf->player->index].railtype_to_use, 0, DC_AUTO, CMD_BUILD_TUNNEL);
    02069
    02070     if (CmdSucceeded(cost) && cost.GetCost() <= (arf->player->player_money >> 4)) {
    02071       AiBuildRailRecursive(arf, _build_tunnel_endtile, (DiagDirection)(p[0] & 3));
    02072       if (arf->depth == 1) AiCheckRailPathBetter(arf, p);
    02073     }
    02074   }
    02075 }
    02076
    02077
    02078 static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, DiagDirection dir)
    02079 {
    02080   const byte *p;
    02081
    02082   tile = TILE_MASK(tile + TileOffsByDiagDir(dir));
    02083
    02084   // Reached destination?
    02085   if (tile == arf->final_tile) {
    02086     if (arf->final_dir != ReverseDiagDir(dir)) {
    02087       if (arf->recursive_mode != 2) arf->recursive_mode = 1;
    02088     } else if (arf->recursive_mode != 2) {
    02089       arf->recursive_mode = 2;
    02090       arf->cur_best_depth = arf->depth;
    02091     } else {
    02092       if (arf->depth < arf->cur_best_depth) arf->cur_best_depth = arf->depth;
    02093     }
    02094     return;
    02095   }
    02096
    02097   // Depth too deep?
    02098   if (arf->depth >= 4) {
    02099     uint dist = DistanceMaxPlusManhattan(tile, arf->final_tile);
    02100
    02101     if (dist < arf->cur_best_dist) {
    02102       // Store the tile that is closest to the final position.
    02103       arf->cur_best_depth = arf->depth;
    02104       arf->cur_best_dist = dist;
    02105       arf->cur_best_tile = tile;
    02106       arf->cur_best_dir = dir;
    02107     }
    02108     return;
    02109   }
    02110
    02111   // Increase recursion depth
    02112   arf->depth++;
    02113
    02114   // Grab pointer to list of stuff that is possible to build
    02115   p = _ai_table_15[dir];
    02116
    02117   // Try to build a single rail in all directions.
    02118   if (GetTileZ(tile) == 0) {
    02119     p += 6;
    02120   } else {
    02121     do {
    02122       // Make sure the tile is not in the list of banned tiles and that a rail can be built here.
    02123       if (!AiIsTileBanned(arf->player, tile, p[0]) &&
    02124           CmdSucceeded(DoCommand(tile, _players_ai[arf->player->index].railtype_to_use, p[0], DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL))) {
    02125         AiBuildRailRecursive(arf, tile, (DiagDirection)p[1]);
    02126       }
    02127
    02128       // At the bottom depth?
    02129       if (arf->depth == 1) AiCheckRailPathBetter(arf, p);
    02130
    02131       p += 2;
    02132     } while (!(p[0] & 0x80));
    02133   }
    02134
    02135   AiCheckBuildRailBridgeHere(arf, tile, p);
    02136   AiCheckBuildRailTunnelHere(arf, tile, p + 1);
    02137
    02138   arf->depth--;
    02139 }
    02140
    02141
    02142 static const byte _dir_table_3[] = {0x25, 0x2A, 0x19, 0x16};
    02143
    02144 static void AiBuildRailConstruct(Player *p)
    02145 {
    02146   AiRailFinder arf;
    02147   int i;
    02148
    02149   // Check too much lookahead?
    02150   if (AiDoFollowTrack(p)) {
    02151     _players_ai[p->index].state_counter = (Random()&0xE)+6; // Destruct this amount of blocks
    02152     _players_ai[p->index].state_mode = 1; // Start destruct
    02153
    02154     // Ban this tile and don't reach it for a while.
    02155     AiBanTile(p, _players_ai[p->index].cur_tile_a, FindFirstBit(GetRailTrackStatus(_players_ai[p->index].cur_tile_a)));
    02156     return;
    02157   }
    02158
    02159   // Setup recursive finder and call it.
    02160   arf.player = p;
    02161   arf.final_tile = _players_ai[p->index].cur_tile_b;
    02162   arf.final_dir = _players_ai[p->index].cur_dir_b;
    02163   arf.depth = 0;
    02164   arf.recursive_mode = 0;
    02165   arf.best_ptr = NULL;
    02166   arf.cur_best_dist = (uint)-1;
    02167   arf.cur_best_depth = 0xff;
    02168   arf.best_dist = (uint)-1;
    02169   arf.best_depth = 0xff;
    02170   arf.cur_best_tile = 0;
    02171   arf.best_tile = 0;
    02172   AiBuildRailRecursive(&arf, _players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a);
    02173
    02174   // Reached destination?
    02175   if (arf.recursive_mode == 2 && arf.cur_best_depth == 0) {
    02176     _players_ai[p->index].state_mode = 255;
    02177     return;
    02178   }
    02179
    02180   // Didn't find anything to build?
    02181   if (arf.best_ptr == NULL) {
    02182     // Terraform some
    02183     for (i = 0; i != 5; i++) {
    02184       AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
    02185     }
    02186
    02187     if (++_players_ai[p->index].state_counter == 21) {
    02188       _players_ai[p->index].state_counter = 40;
    02189       _players_ai[p->index].state_mode = 1;
    02190
    02191       // Ban this tile
    02192       AiBanTile(p, _players_ai[p->index].cur_tile_a, FindFirstBit(GetRailTrackStatus(_players_ai[p->index].cur_tile_a)));
    02193     }
    02194     return;
    02195   }
    02196
    02197   _players_ai[p->index].cur_tile_a += TileOffsByDiagDir(_players_ai[p->index].cur_dir_a);
    02198
    02199   if (arf.best_ptr[0] & 0x80) {
    02200     TileIndex t1 = _players_ai[p->index].cur_tile_a;
    02201     TileIndex t2 = arf.bridge_end_tile;
    02202
    02203     int32 bridge_len = GetTunnelBridgeLength(t1, t2);
    02204
    02205     DiagDirection dir = (TileX(t1) == TileX(t2) ? DIAGDIR_SE : DIAGDIR_SW);
    02206     Track track = AxisToTrack(DiagDirToAxis(dir));
    02207
    02208     if (t2 < t1) dir = ReverseDiagDir(dir);
    02209
    02210     /* try to build a long rail instead of bridge... */
    02211     bool fail = false;
    02212     CommandCost cost;
    02213     TileIndex t = t1;
    02214
    02215     /* try to build one rail on each tile - can't use CMD_BUILD_RAILROAD_TRACK now, it can build one part of track without failing */
    02216     do {
    02217       cost = DoCommand(t, _players_ai[p->index].railtype_to_use, track, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
    02218       /* do not allow building over existing track */
    02219       if (CmdFailed(cost) || IsTileType(t, MP_RAILWAY)) {
    02220         fail = true;
    02221         break;
    02222       }
    02223       t += TileOffsByDiagDir(dir);
    02224     } while (t != t2);
    02225
    02226     /* can we build long track? */
    02227     if (!fail) cost = DoCommand(t1, t2, _players_ai[p->index].railtype_to_use | (track << 4), DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_TRACK);
    02228
    02229     if (!fail && CmdSucceeded(cost) && cost.GetCost() <= p->player_money) {
    02230       DoCommand(t1, t2, _players_ai[p->index].railtype_to_use | (track << 4), DC_AUTO | DC_NO_WATER | DC_EXEC, CMD_BUILD_RAILROAD_TRACK);
    02231     } else {
    02232
    02233       /* Figure out which (rail)bridge type to build
    02234        * start with best bridge, then go down to worse and worse bridges
    02235        * unnecessary to check for worst bridge (i=0), since AI will always build that. */
    02236       int i;
    02237       for (i = MAX_BRIDGES - 1; i != 0; i--) {
    02238         if (CheckBridge_Stuff(i, bridge_len)) {
    02239           CommandCost cost = DoCommand(t1, t2, i | (_players_ai[p->index].railtype_to_use << 8), DC_AUTO, CMD_BUILD_BRIDGE);
    02240           if (CmdSucceeded(cost) && cost.GetCost() < (p->player_money >> 1) && cost.GetCost() < ((p->player_money + _economy.max_loan - p->current_loan) >> 5)) break;
    02241         }
    02242       }
    02243
    02244       /* Build it */
    02245       DoCommand(t1, t2, i | (_players_ai[p->index].railtype_to_use << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
    02246     }
    02247
    02248     _players_ai[p->index].cur_tile_a = t2;
    02249     _players_ai[p->index].state_counter = 0;
    02250   } else if (arf.best_ptr[0] & 0x40) {
    02251     // tunnel
    02252     DoCommand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].railtype_to_use, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL);
    02253     _players_ai[p->index].cur_tile_a = _build_tunnel_endtile;
    02254     _players_ai[p->index].state_counter = 0;
    02255   } else {
    02256     // rail
    02257     _players_ai[p->index].cur_dir_a = (DiagDirection)(arf.best_ptr[1] & 3);
    02258     DoCommand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].railtype_to_use, arf.best_ptr[0],
    02259       DC_EXEC | DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL);
    02260     _players_ai[p->index].state_counter = 0;
    02261   }
    02262
    02263   if (arf.best_tile != 0) {
    02264     for (i = 0; i != 2; i++) {
    02265       AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0);
    02266     }
    02267   }
    02268 }
    02269
    02270 static bool AiRemoveTileAndGoForward(Player *p)
    02271 {
    02272   byte b;
    02273   int bit;
    02274   const byte *ptr;
    02275   TileIndex tile = _players_ai[p->index].cur_tile_a;
    02276   TileIndex tilenew;
    02277
    02278   if (IsTileType(tile, MP_TUNNELBRIDGE)) {
    02279     if (IsTunnel(tile)) {
    02280       // Clear the tunnel and continue at the other side of it.
    02281       if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)))
    02282         return false;
    02283       _players_ai[p->index].cur_tile_a = TILE_MASK(_build_tunnel_endtile - TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
    02284       return true;
    02285     } else { // IsBridge(tile)
    02286       // Check if the bridge points in the right direction.
    02287       // This is not really needed the first place AiRemoveTileAndGoForward is called.
    02288       if (DiagDirToAxis(GetTunnelBridgeDirection(tile)) != (_players_ai[p->index].cur_dir_a & 1)) return false;
    02289
    02290       tile = GetOtherBridgeEnd(tile);
    02291
    02292       tilenew = TILE_MASK(tile - TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
    02293       // And clear the bridge.
    02294       if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)))
    02295         return false;
    02296       _players_ai[p->index].cur_tile_a = tilenew;
    02297       return true;
    02298     }
    02299   }
    02300
    02301   // Find the railtype at the position. Quit if no rail there.
    02302   b = GetRailTrackStatus(tile) & _dir_table_3[_players_ai[p->index].cur_dir_a];
    02303   if (b == 0) return false;
    02304
    02305   // Convert into a bit position that CMD_REMOVE_SINGLE_RAIL expects.
    02306   bit = FindFirstBit(b);
    02307
    02308   // Then remove and signals if there are any.
    02309   if (IsTileType(tile, MP_RAILWAY) &&
    02310       GetRailTileType(tile) == RAIL_TILE_SIGNALS) {
    02311     DoCommand(tile, 0, 0, DC_EXEC, CMD_REMOVE_SIGNALS);
    02312   }
    02313
    02314   // And also remove the rail.
    02315   if (CmdFailed(DoCommand(tile, 0, bit, DC_EXEC, CMD_REMOVE_SINGLE_RAIL)))
    02316     return false;
    02317
    02318   // Find the direction at the other edge of the rail.
    02319   ptr = _ai_table_15[ReverseDiagDir(_players_ai[p->index].cur_dir_a)];
    02320   while (ptr[0] != bit) ptr += 2;
    02321   _players_ai[p->index].cur_dir_a = ReverseDiagDir((DiagDirection)ptr[1]);
    02322
    02323   // And then also switch tile.
    02324   _players_ai[p->index].cur_tile_a = TILE_MASK(_players_ai[p->index].cur_tile_a - TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
    02325
    02326   return true;
    02327 }
    02328
    02329
    02330 static void AiBuildRailDestruct(Player *p)
    02331 {
    02332   // Decrease timeout.
    02333   if (!--_players_ai[p->index].state_counter) {
    02334     _players_ai[p->index].state_mode = 2;
    02335     _players_ai[p->index].state_counter = 0;
    02336   }
    02337
    02338   // Don't do anything if the destination is already reached.
    02339   if (_players_ai[p->index].cur_tile_a == _players_ai[p->index].start_tile_a) return;
    02340
    02341   AiRemoveTileAndGoForward(p);
    02342 }
    02343
    02344
    02345 static void AiBuildRail(Player *p)
    02346 {
    02347   switch (_players_ai[p->index].state_mode) {
    02348     case 0: // Construct mode, build new rail.
    02349       AiBuildRailConstruct(p);
    02350       break;
    02351
    02352     case 1: // Destruct mode, destroy the rail currently built.
    02353       AiBuildRailDestruct(p);
    02354       break;
    02355
    02356     case 2: {
    02357       uint i;
    02358
    02359       // Terraform some and then try building again.
    02360       for (i = 0; i != 4; i++) {
    02361         AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
    02362       }
    02363
    02364       if (++_players_ai[p->index].state_counter == 4) {
    02365         _players_ai[p->index].state_counter = 0;
    02366         _players_ai[p->index].state_mode = 0;
    02367       }
    02368     }
    02369
    02370     default: break;
    02371   }
    02372 }
    02373
    02374 static void AiStateBuildRail(Player *p)
    02375 {
    02376   int num;
    02377   AiBuildRec *aib;
    02378   byte cmd;
    02379   TileIndex tile;
    02380   DiagDirection dir;
    02381
    02382   // time out?
    02383   if (++_players_ai[p->index].timeout_counter == 1388) {
    02384     _players_ai[p->index].state = AIS_DELETE_RAIL_BLOCKS;
    02385     return;
    02386   }
    02387
    02388   // Currently building a rail between two points?
    02389   if (_players_ai[p->index].state_mode != 255) {
    02390     AiBuildRail(p);
    02391
    02392     // Alternate between edges
    02393     Swap(_players_ai[p->index].start_tile_a, _players_ai[p->index].start_tile_b);
    02394     Swap(_players_ai[p->index].cur_tile_a,   _players_ai[p->index].cur_tile_b);
    02395     Swap(_players_ai[p->index].start_dir_a,  _players_ai[p->index].start_dir_b);
    02396     Swap(_players_ai[p->index].cur_dir_a,    _players_ai[p->index].cur_dir_b);
    02397     return;
    02398   }
    02399
    02400   // Now, find two new points to build between
    02401   num = _players_ai[p->index].num_build_rec;
    02402   aib = &_players_ai[p->index].src;
    02403
    02404   for (;;) {
    02405     cmd = aib->buildcmd_a;
    02406     aib->buildcmd_a = 255;
    02407     if (cmd != 255) break;
    02408
    02409     cmd = aib->buildcmd_b;
    02410     aib->buildcmd_b = 255;
    02411     if (cmd != 255) break;
    02412
    02413     aib++;
    02414     if (--num == 0) {
    02415       _players_ai[p->index].state = AIS_BUILD_RAIL_VEH;
    02416       _players_ai[p->index].state_counter = 0; // timeout
    02417       return;
    02418     }
    02419   }
    02420
    02421   // Find first edge to build from.
    02422   tile = AiGetEdgeOfDefaultRailBlock(aib->cur_building_rule, aib->use_tile, cmd & 3, &dir);
    02423   _players_ai[p->index].start_tile_a = tile;
    02424   _players_ai[p->index].cur_tile_a = tile;
    02425   _players_ai[p->index].start_dir_a = dir;
    02426   _players_ai[p->index].cur_dir_a = dir;
    02427   DoCommand(TILE_MASK(tile + TileOffsByDiagDir(dir)), 0, (dir & 1) ? 1 : 0, DC_EXEC, CMD_REMOVE_SINGLE_RAIL);
    02428
    02429   assert(TILE_MASK(tile) != 0xFF00);
    02430
    02431   // Find second edge to build to
    02432   aib = (&_players_ai[p->index].src) + ((cmd >> 4) & 0xF);
    02433   tile = AiGetEdgeOfDefaultRailBlock(aib->cur_building_rule, aib->use_tile, (cmd >> 2) & 3, &dir);
    02434   _players_ai[p->index].start_tile_b = tile;
    02435   _players_ai[p->index].cur_tile_b = tile;
    02436   _players_ai[p->index].start_dir_b = dir;
    02437   _players_ai[p->index].cur_dir_b = dir;
    02438   DoCommand(TILE_MASK(tile + TileOffsByDiagDir(dir)), 0, (dir & 1) ? 1 : 0, DC_EXEC, CMD_REMOVE_SINGLE_RAIL);
    02439
    02440   assert(TILE_MASK(tile) != 0xFF00);
    02441
    02442   // And setup state.
    02443   _players_ai[p->index].state_mode = 2;
    02444   _players_ai[p->index].state_counter = 0;
    02445   _players_ai[p->index].banned_tile_count = 0;
    02446 }
    02447
    02448 static StationID AiGetStationIdByDef(TileIndex tile, int id)
    02449 {
    02450   const AiDefaultBlockData *p = _default_rail_track_data[id]->data;
    02451   while (p->mode != 1) p++;
    02452   return GetStationIndex(TILE_ADD(tile, ToTileIndexDiff(p->tileoffs)));
    02453 }
    02454
    02455 static EngineID AiFindBestWagon(CargoID cargo, RailType railtype)
    02456 {
    02457   EngineID best_veh_index = INVALID_ENGINE;
    02458   EngineID i;
    02459   uint16 best_capacity = 0;
    02460   uint16 best_speed    = 0;
    02461   uint speed;
    02462
    02463   for (i = 0; i < NUM_TRAIN_ENGINES; i++) {
    02464     const RailVehicleInfo *rvi = RailVehInfo(i);
    02465     const Engine* e = GetEngine(i);
    02466
    02467     if (!IsCompatibleRail(rvi->railtype, railtype) ||
    02468         rvi->railveh_type != RAILVEH_WAGON ||
    02469         !HasBit(e->player_avail, _current_player)) {
    02470       continue;
    02471     }
    02472
    02473     if (rvi->cargo_type != cargo) continue;
    02474
    02475     /* max_speed of 0 indicates no speed limit */
    02476     speed = rvi->max_speed == 0 ? 0xFFFF : rvi->max_speed;
    02477
    02478     if (rvi->capacity >= best_capacity && speed >= best_speed) {
    02479       best_capacity = rvi->capacity;
    02480       best_speed    = best_speed;
    02481       best_veh_index = i;
    02482     }
    02483   }
    02484
    02485   return best_veh_index;
    02486 }
    02487
    02488 static void AiStateBuildRailVeh(Player *p)
    02489 {
    02490   const AiDefaultBlockData *ptr;
    02491   TileIndex tile;
    02492   EngineID veh;
    02493   int i;
    02494   CargoID cargo;
    02495   CommandCost cost;
    02496   Vehicle *v;
    02497   VehicleID loco_id;
    02498
    02499   ptr = _default_rail_track_data[_players_ai[p->index].src.cur_building_rule]->data;
    02500   while (ptr->mode != 0) ptr++;
    02501
    02502   tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
    02503
    02504
    02505   cargo = _players_ai[p->index].cargo_type;
    02506   for (i = 0;;) {
    02507     if (_players_ai[p->index].wagon_list[i] == INVALID_VEHICLE) {
    02508       veh = AiFindBestWagon(cargo, _players_ai[p->index].railtype_to_use);
    02509       /* veh will return INVALID_ENGINE if no suitable wagon is available.
    02510        * We shall treat this in the same way as having no money */
    02511       if (veh == INVALID_ENGINE) goto handle_nocash;
    02512       cost = DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE);
    02513       if (CmdFailed(cost)) goto handle_nocash;
    02514       _players_ai[p->index].wagon_list[i] = _new_vehicle_id;
    02515       _players_ai[p->index].wagon_list[i + 1] = INVALID_VEHICLE;
    02516       return;
    02517     }
    02518     if (cargo == CT_MAIL) cargo = CT_PASSENGERS;
    02519     if (++i == _players_ai[p->index].num_wagons * 2 - 1) break;
    02520   }
    02521
    02522   // Which locomotive to build?
    02523   veh = AiChooseTrainToBuild(_players_ai[p->index].railtype_to_use, p->player_money, cargo != CT_PASSENGERS ? 1 : 0, tile);
    02524   if (veh == INVALID_ENGINE) {
    02525 handle_nocash:
    02526     // after a while, if AI still doesn't have cash, get out of this block by selling the wagons.
    02527     if (++_players_ai[p->index].state_counter == 1000) {
    02528       for (i = 0; _players_ai[p->index].wagon_list[i] != INVALID_VEHICLE; i++) {
    02529         cost = DoCommand(tile, _players_ai[p->index].wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
    02530         assert(CmdSucceeded(cost));
    02531       }
    02532       _players_ai[p->index].state = AIS_0;
    02533     }
    02534     return;
    02535   }
    02536
    02537   // Try to build the locomotive
    02538   cost = DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE);
    02539   assert(CmdSucceeded(cost));
    02540   loco_id = _new_vehicle_id;
    02541
    02542   // Sell a vehicle if the train is double headed.
    02543   v = GetVehicle(loco_id);
    02544   if (v->Next() != NULL) {
    02545     i = _players_ai[p->index].wagon_list[_players_ai[p->index].num_wagons * 2 - 2];
    02546     _players_ai[p->index].wagon_list[_players_ai[p->index].num_wagons * 2 - 2] = INVALID_VEHICLE;
    02547     DoCommand(tile, i, 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
    02548   }
    02549
    02550   // Move the wagons onto the train
    02551   for (i = 0; _players_ai[p->index].wagon_list[i] != INVALID_VEHICLE; i++) {
    02552     DoCommand(tile, _players_ai[p->index].wagon_list[i] | (loco_id << 16), 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
    02553   }
    02554
    02555   for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
    02556     const AiBuildRec* aib = &_players_ai[p->index].src + _players_ai[p->index].order_list_blocks[i];
    02557     bool is_pass = (
    02558       _players_ai[p->index].cargo_type == CT_PASSENGERS ||
    02559       _players_ai[p->index].cargo_type == CT_MAIL ||
    02560       (_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
    02561     );
    02562     Order order;
    02563
    02564     order.type = OT_GOTO_STATION;
    02565     order.flags = 0;
    02566     order.dest = AiGetStationIdByDef(aib->use_tile, aib->cur_building_rule);
    02567
    02568     if (!is_pass && i == 1) order.flags |= OFB_UNLOAD;
    02569     if (_players_ai[p->index].num_want_fullload != 0 && (is_pass || i == 0))
    02570       order.flags |= OFB_FULL_LOAD;
    02571
    02572     DoCommand(0, loco_id + (i << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
    02573   }
    02574
    02575   DoCommand(0, loco_id, 0, DC_EXEC, CMD_START_STOP_TRAIN);
    02576
    02577   DoCommand(0, loco_id, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
    02578
    02579   if (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
    02580
    02581   if (--_players_ai[p->index].num_loco_to_build != 0) {
    02582 //    _players_ai[p->index].loco_id = INVALID_VEHICLE;
    02583     _players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
    02584   } else {
    02585     _players_ai[p->index].state = AIS_0;
    02586   }
    02587 }
    02588
    02589 static void AiStateDeleteRailBlocks(Player *p)
    02590 {
    02591   const AiBuildRec* aib = &_players_ai[p->index].src;
    02592   uint num = _players_ai[p->index].num_build_rec;
    02593
    02594   do {
    02595     const AiDefaultBlockData* b;
    02596
    02597     if (aib->cur_building_rule == 255) continue;
    02598     for (b = _default_rail_track_data[aib->cur_building_rule]->data; b->mode != 4; b++) {
    02599       DoCommand(TILE_ADD(aib->use_tile, ToTileIndexDiff(b->tileoffs)), 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
    02600     }
    02601   } while (++aib, --num);
    02602
    02603   _players_ai[p->index].state = AIS_0;
    02604 }
    02605
    02606 static bool AiCheckRoadResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo)
    02607 {
    02608   uint values[NUM_CARGO];
    02609   int rad;
    02610
    02611   if (_patches.modified_catchment) {
    02612     rad = CA_TRUCK; // Same as CA_BUS at the moment?
    02613   } else { // change that at some point?
    02614     rad = 4;
    02615   }
    02616
    02617   for (;; p++) {
    02618     if (p->mode == 4) {
    02619       return true;
    02620     } else if (p->mode == 1) {
    02621       TileIndex tile2 = TILE_ADD(tile, ToTileIndexDiff(p->tileoffs));
    02622
    02623       if (cargo & 0x80) {
    02624         GetProductionAroundTiles(values, tile2, 1, 1, rad);
    02625         return values[cargo & 0x7F] != 0;
    02626       } else {
    02627         GetAcceptanceAroundTiles(values, tile2, 1, 1, rad);
    02628         return (values[cargo]&~7) != 0;
    02629       }
    02630     }
    02631   }
    02632 }
    02633
    02634 static bool _want_road_truck_station;
    02635 static CommandCost AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag);
    02636
    02637 // Returns rule and cost
    02638 static int AiFindBestDefaultRoadBlock(TileIndex tile, byte direction, byte cargo, CommandCost *cost)
    02639 {
    02640   int i;
    02641   const AiDefaultRoadBlock *p;
    02642
    02643   _want_road_truck_station = (cargo & 0x7F) != CT_PASSENGERS;
    02644
    02645   for (i = 0; (p = _road_default_block_data[i]) != NULL; i++) {
    02646     if (p->dir == direction) {
    02647       *cost = AiDoBuildDefaultRoadBlock(tile, p->data, 0);
    02648       if (CmdSucceeded(*cost) && AiCheckRoadResources(tile, p->data, cargo))
    02649         return i;
    02650     }
    02651   }
    02652
    02653   return -1;
    02654 }
    02655
    02656 static CommandCost AiDoBuildDefaultRoadBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag)
    02657 {
    02658   CommandCost ret;
    02659   CommandCost total_cost(EXPENSES_CONSTRUCTION);
    02660   Town *t = NULL;
    02661   int rating = 0;
    02662   int roadflag = 0;
    02663
    02664   for (;p->mode != 4;p++) {
    02665     TileIndex c = TILE_MASK(tile + ToTileIndexDiff(p->tileoffs));
    02666
    02667     _cleared_town = NULL;
    02668
    02669     if (p->mode == 2) {
    02670       if (IsNormalRoadTile(c) &&
    02671           (GetRoadBits(c, ROADTYPE_ROAD) & p->attr) != 0) {
    02672         roadflag |= 2;
    02673
    02674         // all bits are already built?
    02675         if ((GetRoadBits(c, ROADTYPE_ROAD) & p->attr) == p->attr) continue;
    02676       }
    02677
    02678       ret = DoCommand(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
    02679       if (CmdFailed(ret)) return CMD_ERROR;
    02680       total_cost.AddCost(ret);
    02681
    02682       continue;
    02683     }
    02684
    02685     if (p->mode == 0) {
    02686       // Depot
    02687       ret = DoCommand(c, p->attr, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_DEPOT);
    02688       goto clear_town_stuff;
    02689     } else if (p->mode == 1) {
    02690       if (_want_road_truck_station) {
    02691         // Truck station
    02692         ret = DoCommand(c, p->attr, ROADTYPES_ROAD << 2 | RoadStop::TRUCK, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_STOP);
    02693       } else {
    02694         // Bus station
    02695         ret = DoCommand(c, p->attr, ROADTYPES_ROAD << 2 | RoadStop::BUS, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_BUILD_ROAD_STOP);
    02696       }
    02697 clear_town_stuff:;
    02698
    02699       if (CmdFailed(ret)) return CMD_ERROR;
    02700       total_cost.AddCost(ret);
    02701
    02702       if (_cleared_town != NULL) {
    02703         if (t != NULL && t != _cleared_town) return CMD_ERROR;
    02704         t = _cleared_town;
    02705         rating += _cleared_town_rating;
    02706       }
    02707     } else if (p->mode == 3) {
    02708       if (flag & DC_EXEC) continue;
    02709
    02710       if (GetTileSlope(c, NULL) != SLOPE_FLAT) return CMD_ERROR;
    02711
    02712       if (!IsNormalRoadTile(c)) {
    02713         ret = DoCommand(c, 0, 0, flag | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, CMD_LANDSCAPE_CLEAR);
    02714         if (CmdFailed(ret)) return CMD_ERROR;
    02715       }
    02716
    02717     }
    02718   }
    02719
    02720   if (!_want_road_truck_station && !(roadflag & 2)) return CMD_ERROR;
    02721
    02722   if (!(flag & DC_EXEC)) {
    02723     if (t != NULL && rating > t->ratings[_current_player]) return CMD_ERROR;
    02724   }
    02725   return total_cost;
    02726 }
    02727
    02728 // Make sure the blocks are not too close to each other
    02729 static bool AiCheckBlockDistances(Player *p, TileIndex tile)
    02730 {
    02731   const AiBuildRec* aib = &_players_ai[p->index].src;
    02732   uint num = _players_ai[p->index].num_build_rec;
    02733
    02734   do {
    02735     if (aib->cur_building_rule != 255) {
    02736       if (DistanceManhattan(aib->use_tile, tile) < 9) return false;
    02737     }
    02738   } while (++aib, --num);
    02739
    02740   return true;
    02741 }
    02742
    02743
    02744 static void AiStateBuildDefaultRoadBlocks(Player *p)
    02745 {
    02746   uint i;
    02747   int j;
    02748   AiBuildRec *aib;
    02749   int rule;
    02750   CommandCost cost;
    02751
    02752   // time out?
    02753   if (++_players_ai[p->index].timeout_counter == 1388) {
    02754     _players_ai[p->index].state = AIS_DELETE_RAIL_BLOCKS;
    02755     return;
    02756   }
    02757
    02758   // do the following 8 times
    02759   for (i = 0; i != 8; i++) {
    02760     // check if we can build the default track
    02761     aib = &_players_ai[p->index].src;
    02762     j = _players_ai[p->index].num_build_rec;
    02763     do {
    02764       // this item has already been built?
    02765       if (aib->cur_building_rule != 255) continue;
    02766
    02767       // adjust the coordinate randomly,
    02768       // to make sure that we find a position.
    02769       aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng);
    02770
    02771       // check if the road can be built there.
    02772       rule = AiFindBestDefaultRoadBlock(
    02773         aib->use_tile, aib->direction, aib->cargo, &cost
    02774       );
    02775
    02776       if (rule == -1) {
    02777         // cannot build, terraform after a while
    02778         if (_players_ai[p->index].state_counter >= 600) {
    02779           AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)_players_ai[p->index].state_mode);
    02780         }
    02781         // also try the other terraform direction
    02782         if (++_players_ai[p->index].state_counter >= 1000) {
    02783           _players_ai[p->index].state_counter = 0;
    02784           _players_ai[p->index].state_mode = -_players_ai[p->index].state_mode;
    02785         }
    02786       } else if (CheckPlayerHasMoney(cost) && AiCheckBlockDistances(p, aib->use_tile)) {
    02787         CommandCost r;
    02788
    02789         // player has money, build it.
    02790         aib->cur_building_rule = rule;
    02791
    02792         r = AiDoBuildDefaultRoadBlock(
    02793           aib->use_tile,
    02794           _road_default_block_data[rule]->data,
    02795           DC_EXEC | DC_NO_TOWN_RATING
    02796         );
    02797         assert(CmdSucceeded(r));
    02798       }
    02799     } while (++aib, --j);
    02800   }
    02801
    02802   // check if we're done with all of them
    02803   aib = &_players_ai[p->index].src;
    02804   j = _players_ai[p->index].num_build_rec;
    02805   do {
    02806     if (aib->cur_building_rule == 255) return;
    02807   } while (++aib, --j);
    02808
    02809   // yep, all are done. switch state to the rail building state.
    02810   _players_ai[p->index].state = AIS_BUILD_ROAD;
    02811   _players_ai[p->index].state_mode = 255;
    02812 }
    02813
    02814 struct AiRoadFinder {
    02815   TileIndex final_tile;
    02816   DiagDirection final_dir;
    02817   byte depth;
    02818   byte recursive_mode;
    02819   DiagDirection cur_best_dir;
    02820   DiagDirection best_dir;
    02821   byte cur_best_depth;
    02822   byte best_depth;
    02823   uint cur_best_dist;
    02824   const byte *best_ptr;
    02825   uint best_dist;
    02826   TileIndex cur_best_tile, best_tile;
    02827   TileIndex bridge_end_tile;
    02828   Player *player;
    02829 };
    02830
    02831 struct AiRoadEnum {
    02832   TileIndex dest;
    02833   TileIndex best_tile;
    02834   int best_track;
    02835   uint best_dist;
    02836 };
    02837
    02838 static const DiagDirection _dir_by_track[] = {
    02839   DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_SW, DIAGDIR_SE,
    02840   DIAGDIR_NE, DIAGDIR_NE,
    02841   DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE,
    02842 };
    02843
    02844 static void AiBuildRoadRecursive(AiRoadFinder *arf, TileIndex tile, DiagDirection dir);
    02845
    02846 static bool AiCheckRoadPathBetter(AiRoadFinder *arf, const byte *p)
    02847 {
    02848   bool better = false;
    02849
    02850   if (arf->recursive_mode < 1) {
    02851     // Mode is 0. This means destination has not been found yet.
    02852     // If the found path is shorter than the current one, remember it.
    02853     if (arf->cur_best_dist < arf->best_dist ||
    02854       (arf->cur_best_dist == arf->best_dist && arf->cur_best_depth < arf->best_depth)) {
    02855       arf->best_depth = arf->cur_best_depth;
    02856       arf->best_dist = arf->cur_best_dist;
    02857       arf->best_dir = arf->cur_best_dir;
    02858       arf->best_ptr = p;
    02859       arf->best_tile = arf->cur_best_tile;
    02860       better = true;
    02861     }
    02862   } else if (arf->recursive_mode > 1) {
    02863     // Mode is 2.
    02864     if (arf->best_dist != 0 || arf->cur_best_depth < arf->best_depth) {
    02865       arf->best_depth = arf->cur_best_depth;
    02866       arf->best_dist = 0;
    02867       arf->best_ptr = p;
    02868       arf->best_tile = 0;
    02869       better = true;
    02870     }
    02871   }
    02872   arf->recursive_mode = 0;
    02873   arf->cur_best_dist = (uint)-1;
    02874   arf->cur_best_depth = 0xff;
    02875
    02876   return better;
    02877 }
    02878
    02879
    02880 static bool AiEnumFollowRoad(TileIndex tile, AiRoadEnum *a, int track, uint length)
    02881 {
    02882   uint dist = DistanceManhattan(tile, a->dest);
    02883
    02884   if (dist <= a->best_dist) {
    02885     TileIndex tile2 = TILE_MASK(tile + TileOffsByDiagDir(_dir_by_track[track]));
    02886
    02887     if (IsNormalRoadTile(tile2)) {
    02888       a->best_dist = dist;
    02889       a->best_tile = tile;
    02890       a->best_track = track;
    02891     }
    02892   }
    02893
    02894   return false;
    02895 }
    02896
    02897 static const uint16 _ai_road_table_and[4] = {
    02898   0x1009,
    02899   0x16,
    02900   0x520,
    02901   0x2A00,
    02902 };
    02903
    02904 static bool AiCheckRoadFinished(Player *p)
    02905 {
    02906   AiRoadEnum are;
    02907   TileIndex tile;
    02908   DiagDirection dir = _players_ai[p->index].cur_dir_a;
    02909   uint32 bits;
    02910
    02911   are.dest = _players_ai[p->index].cur_tile_b;
    02912   tile = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(dir));
    02913
    02914   if (IsRoadStopTile(tile) || IsTileDepotType(tile, TRANSPORT_ROAD)) return false;
    02915   bits = TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, ROADTYPES_ROAD)) & _ai_road_table_and[dir];
    02916   if (bits == 0) return false;
    02917
    02918   are.best_dist = (uint)-1;
    02919
    02920   uint i;
    02921   FOR_EACH_SET_BIT(i, bits) {
    02922     FollowTrack(tile, 0x1000 | TRANSPORT_ROAD, ROADTYPES_ROAD, (DiagDirection)_dir_by_track[i], (TPFEnumProc*)AiEnumFollowRoad, NULL, &are);
    02923   }
    02924
    02925   if (DistanceManhattan(tile, are.dest) <= are.best_dist) return false;
    02926
    02927   if (are.best_dist == 0) return true;
    02928
    02929   _players_ai[p->index].cur_tile_a = are.best_tile;
    02930   _players_ai[p->index].cur_dir_a = _dir_by_track[are.best_track];
    02931   return false;
    02932 }
    02933
    02934
    02935 static bool AiBuildRoadHelper(TileIndex tile, int flags, int type)
    02936 {
    02937   static const RoadBits _road_bits[] = {
    02938     ROAD_X,
    02939     ROAD_Y,
    02940     ROAD_NW | ROAD_NE,
    02941     ROAD_SW | ROAD_SE,
    02942     ROAD_NW | ROAD_SW,
    02943     ROAD_SE | ROAD_NE
    02944   };
    02945   return CmdSucceeded(DoCommand(tile, _road_bits[type], 0, flags, CMD_BUILD_ROAD));
    02946 }
    02947
    02948 static inline void AiCheckBuildRoadBridgeHere(AiRoadFinder *arf, TileIndex tile, const byte *p)
    02949 {
    02950   Slope tileh;
    02951   uint z;
    02952   bool flag;
    02953
    02954   DiagDirection dir2 = (DiagDirection)(p[0] & 3);
    02955
    02956   tileh = GetTileSlope(tile, &z);
    02957   if (tileh == _dir_table_1[dir2] || (tileh == SLOPE_FLAT && z != 0)) {
    02958     TileIndex tile_new = tile;
    02959
    02960     // Allow bridges directly over bottom tiles
    02961     flag = z == 0;
    02962     for (;;) {
    02963       TileType type;
    02964
    02965       if ((TileIndexDiff)tile_new < -TileOffsByDiagDir(dir2)) return; // Wraping around map, no bridge possible!
    02966       tile_new = TILE_MASK(tile_new + TileOffsByDiagDir(dir2));
    02967       type = GetTileType(tile_new);
    02968
    02969       if (type == MP_CLEAR || type == MP_TREES || GetTileSlope(tile_new, NULL) != SLOPE_FLAT) {
    02970         // Allow a bridge if either we have a tile that's water, rail or street,
    02971         // or if we found an up tile.
    02972         if (!flag) return;
    02973         break;
    02974       }
    02975       if (type != MP_WATER && type != MP_RAILWAY && type != MP_ROAD) return;
    02976       flag = true;
    02977     }
    02978
    02979     // Is building a (rail)bridge possible at this place (type doesn't matter)?
    02980     if (CmdFailed(DoCommand(tile_new, tile, ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE)))
    02981       return;
    02982     AiBuildRoadRecursive(arf, tile_new, dir2);
    02983
    02984     // At the bottom depth, check if the new path is better than the old one.
    02985     if (arf->depth == 1) {
    02986       if (AiCheckRoadPathBetter(arf, p)) arf->bridge_end_tile = tile_new;
    02987     }
    02988   }
    02989 }
    02990
    02991 static inline void AiCheckBuildRoadTunnelHere(AiRoadFinder *arf, TileIndex tile, const byte *p)
    02992 {
    02993   uint z;
    02994
    02995   if (GetTileSlope(tile, &z) == _dir_table_2[p[0] & 3] && z != 0) {
    02996     CommandCost cost = DoCommand(tile, 0x200, 0, DC_AUTO, CMD_BUILD_TUNNEL);
    02997
    02998     if (CmdSucceeded(cost) && cost.GetCost() <= (arf->player->player_money >> 4)) {
    02999       AiBuildRoadRecursive(arf, _build_tunnel_endtile, (DiagDirection)(p[0] & 3));
    03000       if (arf->depth == 1)  AiCheckRoadPathBetter(arf, p);
    03001     }
    03002   }
    03003 }
    03004
    03005
    03006
    03007 static void AiBuildRoadRecursive(AiRoadFinder *arf, TileIndex tile, DiagDirection dir)
    03008 {
    03009   const byte *p;
    03010
    03011   tile = TILE_MASK(tile + TileOffsByDiagDir(dir));
    03012
    03013   // Reached destination?
    03014   if (tile == arf->final_tile) {
    03015     if (ReverseDiagDir(arf->final_dir) == dir) {
    03016       arf->recursive_mode = 2;
    03017       arf->cur_best_depth = arf->depth;
    03018     }
    03019     return;
    03020   }
    03021
    03022   // Depth too deep?
    03023   if (arf->depth >= 4) {
    03024     uint dist = DistanceMaxPlusManhattan(tile, arf->final_tile);
    03025     if (dist < arf->cur_best_dist) {
    03026       // Store the tile that is closest to the final position.
    03027       arf->cur_best_dist = dist;
    03028       arf->cur_best_tile = tile;
    03029       arf->cur_best_dir = dir;
    03030       arf->cur_best_depth = arf->depth;
    03031     }
    03032     return;
    03033   }
    03034
    03035   // Increase recursion depth
    03036   arf->depth++;
    03037
    03038   // Grab pointer to list of stuff that is possible to build
    03039   p = _ai_table_15[dir];
    03040
    03041   // Try to build a single rail in all directions.
    03042   if (GetTileZ(tile) == 0) {
    03043     p += 6;
    03044   } else {
    03045     do {
    03046       // Make sure that a road can be built here.
    03047       if (AiBuildRoadHelper(tile, DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, p[0])) {
    03048         AiBuildRoadRecursive(arf, tile, (DiagDirection)p[1]);
    03049       }
    03050
    03051       // At the bottom depth?
    03052       if (arf->depth == 1) AiCheckRoadPathBetter(arf, p);
    03053
    03054       p += 2;
    03055     } while (!(p[0] & 0x80));
    03056   }
    03057
    03058   AiCheckBuildRoadBridgeHere(arf, tile, p);
    03059   AiCheckBuildRoadTunnelHere(arf, tile, p + 1);
    03060
    03061   arf->depth--;
    03062 }
    03063
    03064
    03065 static void AiBuildRoadConstruct(Player *p)
    03066 {
    03067   AiRoadFinder arf;
    03068   int i;
    03069   TileIndex tile;
    03070
    03071   // Reached destination?
    03072   if (AiCheckRoadFinished(p)) {
    03073     _players_ai[p->index].state_mode = 255;
    03074     return;
    03075   }
    03076
    03077   // Setup recursive finder and call it.
    03078   arf.player = p;
    03079   arf.final_tile = _players_ai[p->index].cur_tile_b;
    03080   arf.final_dir = _players_ai[p->index].cur_dir_b;
    03081   arf.depth = 0;
    03082   arf.recursive_mode = 0;
    03083   arf.best_ptr = NULL;
    03084   arf.cur_best_dist = (uint)-1;
    03085   arf.cur_best_depth = 0xff;
    03086   arf.best_dist = (uint)-1;
    03087   arf.best_depth =  0xff;
    03088   arf.cur_best_tile = 0;
    03089   arf.best_tile = 0;
    03090   AiBuildRoadRecursive(&arf, _players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a);
    03091
    03092   // Reached destination?
    03093   if (arf.recursive_mode == 2 && arf.cur_best_depth == 0) {
    03094     _players_ai[p->index].state_mode = 255;
    03095     return;
    03096   }
    03097
    03098   // Didn't find anything to build?
    03099   if (arf.best_ptr == NULL) {
    03100     // Terraform some
    03101 do_some_terraform:
    03102     for (i = 0; i != 5; i++)
    03103       AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
    03104
    03105     if (++_players_ai[p->index].state_counter == 21) {
    03106       _players_ai[p->index].state_mode = 1;
    03107
    03108       _players_ai[p->index].cur_tile_a = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
    03109       _players_ai[p->index].cur_dir_a = ReverseDiagDir(_players_ai[p->index].cur_dir_a);
    03110       _players_ai[p->index].state_counter = 0;
    03111     }
    03112     return;
    03113   }
    03114
    03115   tile = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
    03116
    03117   if (arf.best_ptr[0] & 0x80) {
    03118     TileIndex t1 = tile;
    03119     TileIndex t2 = arf.bridge_end_tile;
    03120
    03121     int32 bridge_len = GetTunnelBridgeLength(t1, t2);
    03122
    03123     Axis axis = (TileX(t1) == TileX(t2) ? AXIS_Y : AXIS_X);
    03124
    03125     /* try to build a long road instead of bridge - CMD_BUILD_LONG_ROAD has to fail if it couldn't build at least one piece! */
    03126     CommandCost cost = DoCommand(t2, t1, (t2 < t1 ? 1 : 2) | (axis << 2) | (ROADTYPE_ROAD << 3), DC_AUTO | DC_NO_WATER, CMD_BUILD_LONG_ROAD);
    03127
    03128     if (CmdSucceeded(cost) && cost.GetCost() <= p->player_money) {
    03129       DoCommand(t2, t1, (t2 < t1 ? 1 : 2) | (axis << 2) | (ROADTYPE_ROAD << 3), DC_AUTO | DC_EXEC | DC_NO_WATER, CMD_BUILD_LONG_ROAD);
    03130     } else {
    03131       int i;
    03132
    03133       /* Figure out what (road)bridge type to build
    03134        * start with best bridge, then go down to worse and worse bridges
    03135        * unnecessary to check for worse bridge (i=0), since AI will always build that */
    03136       for (i = MAX_BRIDGES - 1; i != 0; i--) {
    03137         if (CheckBridge_Stuff(i, bridge_len)) {
    03138           CommandCost cost = DoCommand(t1, t2, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE);
    03139           if (CmdSucceeded(cost) && cost.GetCost() < (p->player_money >> 1) && cost.GetCost() < ((p->player_money + _economy.max_loan - p->current_loan) >> 5)) break;
    03140         }
    03141       }
    03142
    03143       /* Build it */
    03144       DoCommand(t1, t2, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
    03145     }
    03146
    03147     _players_ai[p->index].cur_tile_a = t2;
    03148     _players_ai[p->index].state_counter = 0;
    03149   } else if (arf.best_ptr[0] & 0x40) {
    03150     // tunnel
    03151     DoCommand(tile, 0x200, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL);
    03152     _players_ai[p->index].cur_tile_a = _build_tunnel_endtile;
    03153     _players_ai[p->index].state_counter = 0;
    03154   } else {
    03155     // road
    03156     if (!AiBuildRoadHelper(tile, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, arf.best_ptr[0]))
    03157       goto do_some_terraform;
    03158
    03159     _players_ai[p->index].cur_dir_a = (DiagDirection)(arf.best_ptr[1] & 3);
    03160     _players_ai[p->index].cur_tile_a = tile;
    03161     _players_ai[p->index].state_counter = 0;
    03162   }
    03163
    03164   if (arf.best_tile != 0) {
    03165     for (i = 0; i != 2; i++)
    03166       AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0);
    03167   }
    03168 }
    03169
    03170
    03171 static void AiBuildRoad(Player *p)
    03172 {
    03173   if (_players_ai[p->index].state_mode < 1) {
    03174     // Construct mode, build new road.
    03175     AiBuildRoadConstruct(p);
    03176   } else if (_players_ai[p->index].state_mode == 1) {
    03177     // Destruct mode, not implemented for roads.
    03178     _players_ai[p->index].state_mode = 2;
    03179     _players_ai[p->index].state_counter = 0;
    03180   } else if (_players_ai[p->index].state_mode == 2) {
    03181     uint i;
    03182
    03183     // Terraform some and then try building again.
    03184     for (i = 0; i != 4; i++) {
    03185       AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
    03186     }
    03187
    03188     if (++_players_ai[p->index].state_counter == 4) {
    03189       _players_ai[p->index].state_counter = 0;
    03190       _players_ai[p->index].state_mode = 0;
    03191     }
    03192   }
    03193 }
    03194
    03195 static TileIndex AiGetRoadBlockEdge(byte rule, TileIndex tile, DiagDirection *dir)
    03196 {
    03197   const AiDefaultBlockData *p = _road_default_block_data[rule]->data;
    03198   while (p->mode != 1) p++;
    03199   *dir = p->attr;
    03200   return TILE_ADD(tile, ToTileIndexDiff(p->tileoffs));
    03201 }
    03202
    03203
    03204 static void AiStateBuildRoad(Player *p)
    03205 {
    03206   int num;
    03207   AiBuildRec *aib;
    03208   byte cmd;
    03209   TileIndex tile;
    03210   DiagDirection dir;
    03211
    03212   // time out?
    03213   if (++_players_ai[p->index].timeout_counter == 1388) {
    03214     _players_ai[p->index].state = AIS_DELETE_ROAD_BLOCKS;
    03215     return;
    03216   }
    03217
    03218   // Currently building a road between two points?
    03219   if (_players_ai[p->index].state_mode != 255) {
    03220     AiBuildRoad(p);
    03221
    03222     // Alternate between edges
    03223     Swap(_players_ai[p->index].start_tile_a, _players_ai[p->index].start_tile_b);
    03224     Swap(_players_ai[p->index].cur_tile_a,   _players_ai[p->index].cur_tile_b);
    03225     Swap(_players_ai[p->index].start_dir_a,  _players_ai[p->index].start_dir_b);
    03226     Swap(_players_ai[p->index].cur_dir_a,    _players_ai[p->index].cur_dir_b);
    03227
    03228     return;
    03229   }
    03230
    03231   // Now, find two new points to build between
    03232   num = _players_ai[p->index].num_build_rec;
    03233   aib = &_players_ai[p->index].src;
    03234
    03235   for (;;) {
    03236     cmd = aib->buildcmd_a;
    03237     aib->buildcmd_a = 255;
    03238     if (cmd != 255) break;
    03239
    03240     aib++;
    03241     if (--num == 0) {
    03242       _players_ai[p->index].state = AIS_BUILD_ROAD_VEHICLES;
    03243       return;
    03244     }
    03245   }
    03246
    03247   // Find first edge to build from.
    03248   tile = AiGetRoadBlockEdge(aib->cur_building_rule, aib->use_tile, &dir);
    03249   _players_ai[p->index].start_tile_a = tile;
    03250   _players_ai[p->index].cur_tile_a = tile;
    03251   _players_ai[p->index].start_dir_a = dir;
    03252   _players_ai[p->index].cur_dir_a = dir;
    03253
    03254   // Find second edge to build to
    03255   aib = (&_players_ai[p->index].src) + (cmd & 0xF);
    03256   tile = AiGetRoadBlockEdge(aib->cur_building_rule, aib->use_tile, &dir);
    03257   _players_ai[p->index].start_tile_b = tile;
    03258   _players_ai[p->index].cur_tile_b = tile;
    03259   _players_ai[p->index].start_dir_b = dir;
    03260   _players_ai[p->index].cur_dir_b = dir;
    03261
    03262   // And setup state.
    03263   _players_ai[p->index].state_mode = 2;
    03264   _players_ai[p->index].state_counter = 0;
    03265   _players_ai[p->index].banned_tile_count = 0;
    03266 }
    03267
    03268 static StationID AiGetStationIdFromRoadBlock(TileIndex tile, int id)
    03269 {
    03270   const AiDefaultBlockData *p = _road_default_block_data[id]->data;
    03271   while (p->mode != 1) p++;
    03272   return GetStationIndex(TILE_ADD(tile, ToTileIndexDiff(p->tileoffs)));
    03273 }
    03274
    03275 static void AiStateBuildRoadVehicles(Player *p)
    03276 {
    03277   const AiDefaultBlockData *ptr;
    03278   TileIndex tile;
    03279   VehicleID loco_id;
    03280   EngineID veh;
    03281   uint i;
    03282
    03283   ptr = _road_default_block_data[_players_ai[p->index].src.cur_building_rule]->data;
    03284   for (; ptr->mode != 0; ptr++) {}
    03285   tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
    03286
    03287   veh = AiChooseRoadVehToBuild(_players_ai[p->index].cargo_type, p->player_money, tile);
    03288   if (veh == INVALID_ENGINE) {
    03289     _players_ai[p->index].state = AIS_0;
    03290     return;
    03291   }
    03292
    03293   if (CmdFailed(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH))) return;
    03294
    03295   loco_id = _new_vehicle_id;
    03296
    03297   if (GetVehicle(loco_id)->cargo_type != _players_ai[p->index].cargo_type) {
    03298     /* Cargo type doesn't match, so refit it */
    03299     if (CmdFailed(DoCommand(tile, loco_id, _players_ai[p->index].cargo_type, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
    03300       /* Refit failed... sell the vehicle */
    03301       DoCommand(tile, loco_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
    03302       return;
    03303     }
    03304   }
    03305
    03306   for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
    03307     const AiBuildRec* aib = &_players_ai[p->index].src + _players_ai[p->index].order_list_blocks[i];
    03308     bool is_pass = (
    03309       _players_ai[p->index].cargo_type == CT_PASSENGERS ||
    03310       _players_ai[p->index].cargo_type == CT_MAIL ||
    03311       (_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
    03312     );
    03313     Order order;
    03314
    03315     order.type = OT_GOTO_STATION;
    03316     order.flags = 0;
    03317     order.dest = AiGetStationIdFromRoadBlock(aib->use_tile, aib->cur_building_rule);
    03318
    03319     if (!is_pass && i == 1) order.flags |= OFB_UNLOAD;
    03320     if (_players_ai[p->index].num_want_fullload != 0 && (is_pass || i == 0))
    03321       order.flags |= OFB_FULL_LOAD;
    03322
    03323     DoCommand(0, loco_id + (i << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
    03324   }
    03325
    03326   DoCommand(0, loco_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
    03327   DoCommand(0, loco_id, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
    03328
    03329   if (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
    03330   if (--_players_ai[p->index].num_loco_to_build == 0) _players_ai[p->index].state = AIS_0;
    03331 }
    03332
    03333 static void AiStateDeleteRoadBlocks(Player *p)
    03334 {
    03335   const AiBuildRec* aib = &_players_ai[p->index].src;
    03336   uint num = _players_ai[p->index].num_build_rec;
    03337
    03338   do {
    03339     const AiDefaultBlockData* b;
    03340
    03341     if (aib->cur_building_rule == 255) continue;
    03342     for (b = _road_default_block_data[aib->cur_building_rule]->data; b->mode != 4; b++) {
    03343       if (b->mode > 1) continue;
    03344       DoCommand(TILE_ADD(aib->use_tile, ToTileIndexDiff(b->tileoffs)), 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
    03345     }
    03346   } while (++aib, --num);
    03347
    03348   _players_ai[p->index].state = AIS_0;
    03349 }
    03350
    03351
    03352 static void AiStateAirportStuff(Player *p)
    03353 {
    03354   const Station* st;
    03355   int i;
    03356   AiBuildRec *aib;
    03357   byte rule;
    03358
    03359   // Here we look for an airport we could use instead of building a new
    03360   // one. If we find such an aiport for any waypoint,
    03361   // AiStateBuildDefaultAirportBlocks() will kindly skip that one when
    03362   // building the waypoints.
    03363
    03364   i = 0;
    03365   do {
    03366     // We do this all twice - once for the source (town in the case
    03367     // of oilrig route) and then for the destination (oilrig in the
    03368     // case of oilrig route).
    03369     aib = &_players_ai[p->index].src + i;
    03370
    03371     FOR_ALL_STATIONS(st) {
    03372       // Is this an airport?
    03373       if (!(st->facilities & FACIL_AIRPORT)) continue;
    03374
    03375       // Do we own the airport? (Oilrigs aren't owned, though.)
    03376       if (st->owner != OWNER_NONE && st->owner != _current_player) continue;
    03377
    03378       AirportFTAClass::Flags flags = st->Airport()->flags;
    03379
    03380       /* if airport doesn't accept our kind of plane, dismiss it */
    03381       if (!(flags & (_players_ai[p->index].build_kind == 1 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) {
    03382         continue;
    03383       }
    03384
    03385       // Dismiss airports too far away.
    03386       if (DistanceMax(st->airport_tile, aib->spec_tile) > aib->rand_rng)
    03387         continue;
    03388
    03389       // It's ideal airport, let's take it!
    03390
    03391       /* XXX: This part is utterly broken - rule should
    03392        * contain number of the rule appropriate for the
    03393        * airport type (country, town, ...), see
    03394        * _airport_default_block_data (rule is just an index
    03395        * in this array). But the only difference between the
    03396        * currently existing two rules (rule 0 - town and rule
    03397        * 1 - country) is the attr field which is used only
    03398        * when building new airports - and that's irrelevant
    03399        * for us. So using just about any rule will suffice
    03400        * here for now (some of the new airport types would be
    03401        * broken because they will probably need different
    03402        * tileoff values etc), no matter that
    03403        * IsHangarTile() makes no sense. --pasky */
    03404       if (!(flags & AirportFTAClass::AIRPLANES)) {
    03405         /* Heliports should have maybe own rulesets but
    03406          * OTOH we don't want AI to pick them up when
    03407          * looking for a suitable airport type to build.
    03408          * So any of rules 0 or 1 would do for now. The
    03409          * original rule number was 2 but that's a bug
    03410          * because we have no such rule. */
    03411         rule = 1;
    03412       } else {
    03413         rule = IsHangarTile(st->airport_tile);
    03414       }
    03415
    03416       aib->cur_building_rule = rule;
    03417       aib->use_tile = st->airport_tile;
    03418       break;
    03419     }
    03420   } while (++i != _players_ai[p->index].num_build_rec);
    03421
    03422   _players_ai[p->index].state = AIS_BUILD_DEFAULT_AIRPORT_BLOCKS;
    03423   _players_ai[p->index].state_mode = 255;
    03424   _players_ai[p->index].state_counter = 0;
    03425 }
    03426
    03427 static CommandCost AiDoBuildDefaultAirportBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag)
    03428 {
    03429   uint32 avail_airports = GetValidAirports();
    03430   CommandCost ret,total_cost(EXPENSES_CONSTRUCTION);
    03431
    03432   for (; p->mode == 0; p++) {
    03433     if (!HasBit(avail_airports, p->attr)) return CMD_ERROR;
    03434     ret = DoCommand(TILE_MASK(tile + ToTileIndexDiff(p->tileoffs)), p->attr, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_AIRPORT);
    03435     if (CmdFailed(ret)) return CMD_ERROR;
    03436     total_cost.AddCost(ret);
    03437   }
    03438
    03439   return total_cost;
    03440 }
    03441
    03442 static bool AiCheckAirportResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo)
    03443 {
    03444   uint values[NUM_CARGO];
    03445
    03446   for (; p->mode == 0; p++) {
    03447     TileIndex tile2 = TILE_ADD(tile, ToTileIndexDiff(p->tileoffs));
    03448     const AirportFTAClass* airport = GetAirport(p->attr);
    03449     uint w = airport->size_x;
    03450     uint h = airport->size_y;
    03451     uint rad = _patches.modified_catchment ? airport->catchment : (uint)CA_UNMODIFIED;
    03452
    03453     if (cargo & 0x80) {
    03454       GetProductionAroundTiles(values, tile2, w, h, rad);
    03455       return values[cargo & 0x7F] != 0;
    03456     } else {
    03457       GetAcceptanceAroundTiles(values, tile2, w, h, rad);
    03458       return values[cargo] >= 8;
    03459     }
    03460   }
    03461   return true;
    03462 }
    03463
    03464 static int AiFindBestDefaultAirportBlock(TileIndex tile, byte cargo, byte heli, CommandCost *cost)
    03465 {
    03466   const AiDefaultBlockData *p;
    03467
    03468   bool no_small = false;
    03469
    03470   if (!heli) {
    03471     /* do not build small airport if we have large available and we are not building heli route */
    03472     uint valid = GetValidAirports();
    03473     for (uint i = 0; (p = _airport_default_block_data[i]) != NULL; i++) {
    03474       uint flags = GetAirport(p->attr)->flags;
    03475       if (HasBit(valid, p->attr) && (flags & AirportFTAClass::AIRPLANES) && !(flags & AirportFTAClass::SHORT_STRIP)) {
    03476         no_small = true;
    03477         break;
    03478       }
    03479     }
    03480   }
    03481
    03482   for (uint i = 0; (p = _airport_default_block_data[i]) != NULL; i++) {
    03483     uint flags = GetAirport(p->attr)->flags;
    03484     /* If we are doing a helicopter service, avoid building airports where they can't land */
    03485     if (heli && !(flags & AirportFTAClass::HELICOPTERS)) continue;
    03486     /* Similiar with aircraft ... */
    03487     if (!heli && !(flags & AirportFTAClass::AIRPLANES)) continue;
    03488     /* Do not build small airport if we prefer large */
    03489     if (no_small && (flags & AirportFTAClass::SHORT_STRIP)) continue;
    03490
    03491     *cost = AiDoBuildDefaultAirportBlock(tile, p, 0);
    03492     if (CmdSucceeded(*cost) && AiCheckAirportResources(tile, p, cargo))
    03493       return i;
    03494   }
    03495   return -1;
    03496 }
    03497
    03498 static void AiStateBuildDefaultAirportBlocks(Player *p)
    03499 {
    03500   int i, j;
    03501   AiBuildRec *aib;
    03502   int rule;
    03503   CommandCost cost;
    03504
    03505   // time out?
    03506   if (++_players_ai[p->index].timeout_counter == 1388) {
    03507     _players_ai[p->index].state = AIS_0;
    03508     return;
    03509   }
    03510
    03511   // do the following 8 times
    03512   i = 8;
    03513   do {
    03514     // check if we can build the default
    03515     aib = &_players_ai[p->index].src;
    03516     j = _players_ai[p->index].num_build_rec;
    03517     do {
    03518       // this item has already been built?
    03519       if (aib->cur_building_rule != 255) continue;
    03520
    03521       // adjust the coordinate randomly,
    03522       // to make sure that we find a position.
    03523       aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng);
    03524
    03525       // check if the aircraft stuff can be built there.
    03526       rule = AiFindBestDefaultAirportBlock(aib->use_tile, aib->cargo, _players_ai[p->index].build_kind, &cost);
    03527
    03528 //      SetRedErrorSquare(aib->use_tile);
    03529
    03530       if (rule == -1) {
    03531         // cannot build, terraform after a while
    03532         if (_players_ai[p->index].state_counter >= 600) {
    03533           AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)_players_ai[p->index].state_mode);
    03534         }
    03535         // also try the other terraform direction
    03536         if (++_players_ai[p->index].state_counter >= 1000) {
    03537           _players_ai[p->index].state_counter = 0;
    03538           _players_ai[p->index].state_mode = -_players_ai[p->index].state_mode;
    03539         }
    03540       } else if (CheckPlayerHasMoney(cost) && AiCheckBlockDistances(p, aib->use_tile)) {
    03541         // player has money, build it.
    03542         CommandCost r;
    03543
    03544         aib->cur_building_rule = rule;
    03545
    03546         r = AiDoBuildDefaultAirportBlock(
    03547           aib->use_tile,
    03548           _airport_default_block_data[rule],
    03549           DC_EXEC | DC_NO_TOWN_RATING
    03550         );
    03551         assert(CmdSucceeded(r));
    03552       }
    03553     } while (++aib, --j);
    03554   } while (--i);
    03555
    03556   // check if we're done with all of them
    03557   aib = &_players_ai[p->index].src;
    03558   j = _players_ai[p->index].num_build_rec;
    03559   do {
    03560     if (aib->cur_building_rule == 255) return;
    03561   } while (++aib, --j);
    03562
    03563   // yep, all are done. switch state.
    03564   _players_ai[p->index].state = AIS_BUILD_AIRCRAFT_VEHICLES;
    03565 }
    03566
    03567 static StationID AiGetStationIdFromAircraftBlock(TileIndex tile, int id)
    03568 {
    03569   const AiDefaultBlockData *p = _airport_default_block_data[id];
    03570   while (p->mode != 1) p++;
    03571   return GetStationIndex(TILE_ADD(tile, ToTileIndexDiff(p->tileoffs)));
    03572 }
    03573
    03574 static void AiStateBuildAircraftVehicles(Player *p)
    03575 {
    03576   const AiDefaultBlockData *ptr;
    03577   TileIndex tile;
    03578   EngineID veh;
    03579   int i;
    03580   VehicleID loco_id;
    03581
    03582   ptr = _airport_default_block_data[_players_ai[p->index].src.cur_building_rule];
    03583   for (; ptr->mode != 0; ptr++) {}
    03584
    03585   tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
    03586
    03587   /* determine forbidden aircraft bits */
    03588   byte forbidden = 0;
    03589   for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
    03590     const AiBuildRec *aib = (&_players_ai[p->index].src) + _players_ai[p->index].order_list_blocks[i];
    03591     const Station *st = GetStationByTile(aib->use_tile);
    03592
    03593     if (st == NULL || !(st->facilities & FACIL_AIRPORT)) continue;
    03594
    03595     AirportFTAClass::Flags flags = st->Airport()->flags;
    03596     if (!(flags & AirportFTAClass::AIRPLANES)) forbidden |= AIR_CTOL | AIR_FAST; // no planes for heliports / oil rigs
    03597     if (flags & AirportFTAClass::SHORT_STRIP) forbidden |= AIR_FAST; // no fast planes for small airports
    03598   }
    03599
    03600   veh = AiChooseAircraftToBuild(p->player_money, forbidden);
    03601   if (veh == INVALID_ENGINE) return;
    03602   if (GetStationByTile(tile)->Airport()->nof_depots == 0) return;
    03603
    03604   /* XXX - Have the AI pick the hangar terminal in an airport. Eg get airport-type
    03605    * and offset to the FIRST depot because the AI picks the st->xy tile */
    03606   tile += ToTileIndexDiff(GetStationByTile(tile)->Airport()->airport_depots[0]);
    03607   if (CmdFailed(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return;
    03608   loco_id = _new_vehicle_id;
    03609
    03610   for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
    03611     AiBuildRec *aib = (&_players_ai[p->index].src) + _players_ai[p->index].order_list_blocks[i];
    03612     bool is_pass = (_players_ai[p->index].cargo_type == CT_PASSENGERS || _players_ai[p->index].cargo_type == CT_MAIL);
    03613     Order order;
    03614
    03615     order.type = OT_GOTO_STATION;
    03616     order.flags = 0;
    03617     order.dest = AiGetStationIdFromAircraftBlock(aib->use_tile, aib->cur_building_rule);
    03618
    03619     if (!is_pass && i == 1) order.flags |= OFB_UNLOAD;
    03620     if (_players_ai[p->index].num_want_fullload != 0 && (is_pass || i == 0))
    03621       order.flags |= OFB_FULL_LOAD;
    03622
    03623     DoCommand(0, loco_id + (i << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
    03624   }
    03625
    03626   DoCommand(0, loco_id, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT);
    03627
    03628   DoCommand(0, loco_id, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
    03629
    03630   if (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
    03631
    03632   if (--_players_ai[p->index].num_loco_to_build == 0) _players_ai[p->index].state = AIS_0;
    03633 }
    03634
    03635 static void AiStateCheckShipStuff(Player *p)
    03636 {
    03637   /* Ships are not implemented in this (broken) AI */
    03638 }
    03639
    03640 static void AiStateBuildDefaultShipBlocks(Player *p)
    03641 {
    03642   /* Ships are not implemented in this (broken) AI */
    03643 }
    03644
    03645 static void AiStateDoShipStuff(Player *p)
    03646 {
    03647   /* Ships are not implemented in this (broken) AI */
    03648 }
    03649
    03650 static void AiStateSellVeh(Player *p)
    03651 {
    03652   Vehicle *v = _players_ai[p->index].cur_veh;
    03653
    03654   if (v->owner == _current_player) {
    03655     if (v->type == VEH_TRAIN) {
    03656
    03657       if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
    03658         if (v->current_order.type != OT_GOTO_DEPOT)
    03659           DoCommand(0, v->index, 0, DC_EXEC, CMD_SEND_TRAIN_TO_DEPOT);
    03660         goto going_to_depot;
    03661       }
    03662
    03663       // Sell whole train
    03664       DoCommand(v->tile, v->index, 1, DC_EXEC, CMD_SELL_RAIL_WAGON);
    03665
    03666     } else if (v->type == VEH_ROAD) {
    03667       if (!v->IsStoppedInDepot()) {
    03668         if (v->current_order.type != OT_GOTO_DEPOT)
    03669           DoCommand(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
    03670         goto going_to_depot;
    03671       }
    03672
    03673       DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
    03674     } else if (v->type == VEH_AIRCRAFT) {
    03675       if (!v->IsStoppedInDepot()) {
    03676         if (v->current_order.type != OT_GOTO_DEPOT)
    03677           DoCommand(0, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
    03678         goto going_to_depot;
    03679       }
    03680
    03681       DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_AIRCRAFT);
    03682     } else if (v->type == VEH_SHIP) {
    03683       /* Ships are not implemented in this (broken) AI */
    03684     }
    03685   }
    03686
    03687   goto return_to_loop;
    03688 going_to_depot:;
    03689   if (++_players_ai[p->index].state_counter <= 832) return;
    03690
    03691   if (v->current_order.type == OT_GOTO_DEPOT) {
    03692     v->current_order.type = OT_DUMMY;
    03693     v->current_order.flags = 0;
    03694     InvalidateWindow(WC_VEHICLE_VIEW, v->index);
    03695   }
    03696 return_to_loop:;
    03697   _players_ai[p->index].state = AIS_VEH_LOOP;
    03698 }
    03699
    03700 static void AiStateRemoveStation(Player *p)
    03701 {
    03702   // Remove stations that aren't in use by any vehicle
    03703   const Order *ord;
    03704   const Station *st;
    03705   TileIndex tile;
    03706
    03707   // Go to this state when we're done.
    03708   _players_ai[p->index].state = AIS_1;
    03709
    03710   // Get a list of all stations that are in use by a vehicle
    03711   byte *in_use = MallocT<byte>(GetMaxStationIndex() + 1);
    03712   memset(in_use, 0, GetMaxStationIndex() + 1);
    03713   FOR_ALL_ORDERS(ord) {
    03714     if (ord->type == OT_GOTO_STATION) in_use[ord->dest] = 1;
    03715   }
    03716
    03717   // Go through all stations and delete those that aren't in use
    03718   FOR_ALL_STATIONS(st) {
    03719     if (st->owner == _current_player && !in_use[st->index] &&
    03720         ( (st->bus_stops != NULL && (tile = st->bus_stops->xy) != 0) ||
    03721           (st->truck_stops != NULL && (tile = st->truck_stops->xy)) != 0 ||
    03722           (tile = st->train_tile) != 0 ||
    03723           (tile = st->dock_tile) != 0 ||
    03724           (tile = st->airport_tile) != 0)) {
    03725       DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
    03726     }
    03727   }
    03728
    03729   free(in_use);
    03730 }
    03731
    03732 static void AiRemovePlayerRailOrRoad(Player *p, TileIndex tile)
    03733 {
    03734   TrackBits rails;
    03735
    03736   if (IsTileType(tile, MP_RAILWAY)) {
    03737     if (!IsTileOwner(tile, _current_player)) return;
    03738
    03739     if (IsPlainRailTile(tile)) {
    03740 is_rail_crossing:;
    03741       rails = GetRailTrackStatus(tile);
    03742
    03743       if (rails == TRACK_BIT_HORZ || rails == TRACK_BIT_VERT) return;
    03744
    03745       if (rails & TRACK_BIT_3WAY_NE) {
    03746 pos_0:
    03747         if ((GetRailTrackStatus(TILE_MASK(tile - TileDiffXY(1, 0))) & TRACK_BIT_3WAY_SW) == 0) {
    03748           _players_ai[p->index].cur_dir_a = DIAGDIR_NE;
    03749           _players_ai[p->index].cur_tile_a = tile;
    03750           _players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
    03751           return;
    03752         }
    03753       }
    03754
    03755       if (rails & TRACK_BIT_3WAY_SE) {
    03756 pos_1:
    03757         if ((GetRailTrackStatus(TILE_MASK(tile + TileDiffXY(0, 1))) & TRACK_BIT_3WAY_NW) == 0) {
    03758           _players_ai[p->index].cur_dir_a = DIAGDIR_SE;
    03759           _players_ai[p->index].cur_tile_a = tile;
    03760           _players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
    03761           return;
    03762         }
    03763       }
    03764
    03765       if (rails & TRACK_BIT_3WAY_SW) {
    03766 pos_2:
    03767         if ((GetRailTrackStatus(TILE_MASK(tile + TileDiffXY(1, 0))) & TRACK_BIT_3WAY_NE) == 0) {
    03768           _players_ai[p->index].cur_dir_a = DIAGDIR_SW;
    03769           _players_ai[p->index].cur_tile_a = tile;
    03770           _players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
    03771           return;
    03772         }
    03773       }
    03774
    03775       if (rails & TRACK_BIT_3WAY_NW) {
    03776 pos_3:
    03777         if ((GetRailTrackStatus(TILE_MASK(tile - TileDiffXY(0, 1))) & TRACK_BIT_3WAY_SE) == 0) {
    03778           _players_ai[p->index].cur_dir_a = DIAGDIR_NW;
    03779           _players_ai[p->index].cur_tile_a = tile;
    03780           _players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
    03781           return;
    03782         }
    03783       }
    03784     } else {
    03785       static const byte _depot_bits[] = {0x19, 0x16, 0x25, 0x2A};
    03786
    03787       DiagDirection dir = GetRailDepotDirection(tile);
    03788
    03789       if (GetRailTrackStatus(tile + TileOffsByDiagDir(dir)) & _depot_bits[dir])
    03790         return;
    03791
    03792       DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
    03793     }
    03794   } else if (IsTileType(tile, MP_ROAD)) {
    03795     if (!IsTileOwner(tile, _current_player)) return;
    03796
    03797     if (IsLevelCrossing(tile)) goto is_rail_crossing;
    03798
    03799     if (IsRoadDepot(tile)) {
    03800       DiagDirection dir;
    03801       TileIndex t;
    03802
    03803       // Check if there are any stations around.
    03804       t = tile + TileDiffXY(-1, 0);
    03805       if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
    03806
    03807       t = tile + TileDiffXY(1, 0);
    03808       if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
    03809
    03810       t = tile + TileDiffXY(0, -1);
    03811       if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
    03812
    03813       t = tile + TileDiffXY(0, 1);
    03814       if (IsTileType(t, MP_STATION) && IsTileOwner(t, _current_player)) return;
    03815
    03816       dir = GetRoadDepotDirection(tile);
    03817
    03818       DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
    03819       DoCommand(
    03820         TILE_MASK(tile + TileOffsByDiagDir(dir)),
    03821         DiagDirToRoadBits(ReverseDiagDir(dir)),
    03822         0,
    03823         DC_EXEC,
    03824         CMD_REMOVE_ROAD);
    03825     }
    03826   } else if (IsTileType(tile, MP_TUNNELBRIDGE)) {
    03827     if (!IsTileOwner(tile, _current_player) ||
    03828         !IsBridge(tile) ||
    03829         GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) {
    03830       return;
    03831     }
    03832
    03833     rails = TRACK_BIT_NONE;
    03834
    03835     switch (GetTunnelBridgeDirection(tile)) {
    03836       default:
    03837       case DIAGDIR_NE: goto pos_2;
    03838       case DIAGDIR_SE: goto pos_3;
    03839       case DIAGDIR_SW: goto pos_0;
    03840       case DIAGDIR_NW: goto pos_1;
    03841     }
    03842   }
    03843 }
    03844
    03845 static void AiStateRemoveTrack(Player *p)
    03846 {
    03847   /* Was 1000 for standard 8x8 maps. */
    03848   int num = MapSizeX() * 4;
    03849
    03850   do {
    03851     TileIndex tile = ++_players_ai[p->index].state_counter;
    03852
    03853     // Iterated all tiles?
    03854     if (tile >= MapSize()) {
    03855       _players_ai[p->index].state = AIS_REMOVE_STATION;
    03856       return;
    03857     }
    03858
    03859     // Remove player stuff in that tile
    03860     AiRemovePlayerRailOrRoad(p, tile);
    03861     if (_players_ai[p->index].state != AIS_REMOVE_TRACK) return;
    03862   } while (--num);
    03863 }
    03864
    03865 static void AiStateRemoveSingleRailTile(Player *p)
    03866 {
    03867   // Remove until we can't remove more.
    03868   if (!AiRemoveTileAndGoForward(p)) _players_ai[p->index].state = AIS_REMOVE_TRACK;
    03869 }
    03870
    03871 static AiStateAction * const _ai_actions[] = {
    03872   AiCase0,
    03873   AiCase1,
    03874   AiStateVehLoop,
    03875   AiStateCheckReplaceVehicle,
    03876   AiStateDoReplaceVehicle,
    03877   AiStateWantNewRoute,
    03878
    03879   AiStateBuildDefaultRailBlocks,
    03880   AiStateBuildRail,
    03881   AiStateBuildRailVeh,
    03882   AiStateDeleteRailBlocks,
    03883
    03884   AiStateBuildDefaultRoadBlocks,
    03885   AiStateBuildRoad,
    03886   AiStateBuildRoadVehicles,
    03887   AiStateDeleteRoadBlocks,
    03888
    03889   AiStateAirportStuff,
    03890   AiStateBuildDefaultAirportBlocks,
    03891   AiStateBuildAircraftVehicles,
    03892
    03893   AiStateCheckShipStuff,
    03894   AiStateBuildDefaultShipBlocks,
    03895   AiStateDoShipStuff,
    03896
    03897   AiStateSellVeh,
    03898   AiStateRemoveStation,
    03899   AiStateRemoveTrack,
    03900
    03901   AiStateRemoveSingleRailTile
    03902 };
    03903
    03904 extern void ShowBuyCompanyDialog(uint player);
    03905
    03906 static void AiHandleTakeover(Player *p)
    03907 {
    03908   if (p->bankrupt_timeout != 0) {
    03909     p->bankrupt_timeout -= 8;
    03910     if (p->bankrupt_timeout > 0) return;
    03911     p->bankrupt_timeout = 0;
    03912     DeleteWindowById(WC_BUY_COMPANY, _current_player);
    03913     if (IsLocalPlayer()) {
    03914       AskExitToGameMenu();
    03915       return;
    03916     }
    03917     if (IsHumanPlayer(_current_player)) return;
    03918   }
    03919
    03920   if (p->bankrupt_asked == 255) return;
    03921
    03922   {
    03923     uint asked = p->bankrupt_asked;
    03924     Player *pp, *best_pl = NULL;
    03925     int32 best_val = -1;
    03926
    03927     // Ask the guy with the highest performance hist.
    03928     FOR_ALL_PLAYERS(pp) {
    03929       if (pp->is_active &&
    03930           !(asked & 1) &&
    03931           pp->bankrupt_asked == 0 &&
    03932           best_val < pp->old_economy[1].performance_history) {
    03933         best_val = pp->old_economy[1].performance_history;
    03934         best_pl = pp;
    03935       }
    03936       asked >>= 1;
    03937     }
    03938
    03939     // Asked all players?
    03940     if (best_val == -1) {
    03941       p->bankrupt_asked = 255;
    03942       return;
    03943     }
    03944
    03945     SetBit(p->bankrupt_asked, best_pl->index);
    03946
    03947     if (best_pl->index == _local_player) {
    03948       p->bankrupt_timeout = 4440;
    03949       ShowBuyCompanyDialog(_current_player);
    03950       return;
    03951     }
    03952     if (IsHumanPlayer(best_pl->index)) return;
    03953
    03954     // Too little money for computer to buy it?
    03955     if (best_pl->player_money >> 1 >= p->bankrupt_value) {
    03956       // Computer wants to buy it.
    03957       PlayerID old_p = _current_player;
    03958       _current_player = best_pl->index;
    03959       DoCommand(0, old_p, 0, DC_EXEC, CMD_BUY_COMPANY);
    03960       _current_player = old_p;
    03961     }
    03962   }
    03963 }
    03964
    03965 static void AiAdjustLoan(const Player* p)
    03966 {
    03967   Money base = AiGetBasePrice(p);
    03968
    03969   if (p->player_money > base * 1400) {
    03970     // Decrease loan
    03971     if (p->current_loan != 0) {
    03972       DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
    03973     }
    03974   } else if (p->player_money < base * 500) {
    03975     // Increase loan
    03976     if (p->current_loan < _economy.max_loan &&
    03977         p->num_valid_stat_ent >= 2 &&
    03978         -(p->old_economy[0].expenses + p->old_economy[1].expenses) < base * 60) {
    03979       DoCommand(0, 0, 0, DC_EXEC, CMD_INCREASE_LOAN);
    03980     }
    03981   }
    03982 }
    03983
    03984 static void AiBuildCompanyHQ(Player *p)
    03985 {
    03986   TileIndex tile;
    03987
    03988   if (p->location_of_house == 0 &&
    03989       p->last_build_coordinate != 0) {
    03990     tile = AdjustTileCoordRandomly(p->last_build_coordinate, 8);
    03991     DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
    03992   }
    03993 }
    03994
    03995
    03996 void AiDoGameLoop(Player *p)
    03997 {
    03998   if (p->bankrupt_asked != 0) {
    03999     AiHandleTakeover(p);
    04000     return;
    04001   }
    04002
    04003   // Ugly hack to make sure the service interval of the AI is good, not looking
    04004   //  to the patch-setting
    04005   // Also, it takes into account the setting if the service-interval is in days
    04006   //  or in %
    04007   _ai_service_interval = _patches.servint_ispercent ? 80 : 180;
    04008
    04009   if (IsHumanPlayer(_current_player)) return;
    04010
    04011   AiAdjustLoan(p);
    04012   AiBuildCompanyHQ(p);
    04013
    04014 #if 0
    04015   {
    04016     static byte old_state = 99;
    04017     static bool hasdots = false;
    04018     char *_ai_state_names[] = {
    04019       "AiCase0",
    04020       "AiCase1",
    04021       "AiStateVehLoop",
    04022       "AiStateCheckReplaceVehicle",
    04023       "AiStateDoReplaceVehicle",
    04024       "AiStateWantNewRoute",
    04025       "AiStateBuildDefaultRailBlocks",
    04026       "AiStateBuildRail",
    04027       "AiStateBuildRailVeh",
    04028       "AiStateDeleteRailBlocks",
    04029       "AiStateBuildDefaultRoadBlocks",
    04030       "AiStateBuildRoad",
    04031       "AiStateBuildRoadVehicles",
    04032       "AiStateDeleteRoadBlocks",
    04033       "AiStateAirportStuff",
    04034       "AiStateBuildDefaultAirportBlocks",
    04035       "AiStateBuildAircraftVehicles",
    04036       "AiStateCheckShipStuff",
    04037       "AiStateBuildDefaultShipBlocks",
    04038       "AiStateDoShipStuff",
    04039       "AiStateSellVeh",
    04040       "AiStateRemoveStation",
    04041       "AiStateRemoveTrack",
    04042       "AiStateRemoveSingleRailTile"
    04043     };
    04044
    04045     if (_players_ai[p->index].state != old_state) {
    04046       if (hasdots)
    04047         printf("\n");
    04048       hasdots=false;
    04049       printf("AiState: %s\n", _ai_state_names[old_state=_players_ai[p->index].state]);
    04050     } else {
    04051       printf(".");
    04052       hasdots=true;
    04053     }
    04054   }
    04055 #endif
    04056
    04057   _ai_actions[_players_ai[p->index].state](p);
    04058 }
    04059
    04060
    04061 static const SaveLoad _player_ai_desc[] = {
    04062       SLE_VAR(PlayerAI, state,             SLE_UINT8),
    04063       SLE_VAR(PlayerAI, tick,              SLE_UINT8),
    04064   SLE_CONDVAR(PlayerAI, state_counter,     SLE_FILE_U16 | SLE_VAR_U32,  0, 12),
    04065   SLE_CONDVAR(PlayerAI, state_counter,     SLE_UINT32,                 13, SL_MAX_VERSION),
    04066       SLE_VAR(PlayerAI, timeout_counter,   SLE_UINT16),
    04067
    04068       SLE_VAR(PlayerAI, state_mode,        SLE_UINT8),
    04069       SLE_VAR(PlayerAI, banned_tile_count, SLE_UINT8),
    04070       SLE_VAR(PlayerAI, railtype_to_use,   SLE_UINT8),
    04071
    04072       SLE_VAR(PlayerAI, cargo_type,        SLE_UINT8),
    04073       SLE_VAR(PlayerAI, num_wagons,        SLE_UINT8),
    04074       SLE_VAR(PlayerAI, build_kind,        SLE_UINT8),
    04075       SLE_VAR(PlayerAI, num_build_rec,     SLE_UINT8),
    04076       SLE_VAR(PlayerAI, num_loco_to_build, SLE_UINT8),
    04077       SLE_VAR(PlayerAI, num_want_fullload, SLE_UINT8),
    04078
    04079       SLE_VAR(PlayerAI, route_type_mask,   SLE_UINT8),
    04080
    04081   SLE_CONDVAR(PlayerAI, start_tile_a,      SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
    04082   SLE_CONDVAR(PlayerAI, start_tile_a,      SLE_UINT32,                  6, SL_MAX_VERSION),
    04083   SLE_CONDVAR(PlayerAI, cur_tile_a,        SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
    04084   SLE_CONDVAR(PlayerAI, cur_tile_a,        SLE_UINT32,                  6, SL_MAX_VERSION),
    04085       SLE_VAR(PlayerAI, start_dir_a,       SLE_UINT8),
    04086       SLE_VAR(PlayerAI, cur_dir_a,         SLE_UINT8),
    04087
    04088   SLE_CONDVAR(PlayerAI, start_tile_b,      SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
    04089   SLE_CONDVAR(PlayerAI, start_tile_b,      SLE_UINT32,                  6, SL_MAX_VERSION),
    04090   SLE_CONDVAR(PlayerAI, cur_tile_b,        SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
    04091   SLE_CONDVAR(PlayerAI, cur_tile_b,        SLE_UINT32,                  6, SL_MAX_VERSION),
    04092       SLE_VAR(PlayerAI, start_dir_b,       SLE_UINT8),
    04093       SLE_VAR(PlayerAI, cur_dir_b,         SLE_UINT8),
    04094
    04095       SLE_REF(PlayerAI, cur_veh,           REF_VEHICLE),
    04096
    04097       SLE_ARR(PlayerAI, wagon_list,        SLE_UINT16, 9),
    04098       SLE_ARR(PlayerAI, order_list_blocks, SLE_UINT8, 20),
    04099       SLE_ARR(PlayerAI, banned_tiles,      SLE_UINT16, 16),
    04100
    04101   SLE_CONDNULL(64, 2, SL_MAX_VERSION),
    04102   SLE_END()
    04103 };
    04104
    04105 static const SaveLoad _player_ai_build_rec_desc[] = {
    04106   SLE_CONDVAR(AiBuildRec, spec_tile,         SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
    04107   SLE_CONDVAR(AiBuildRec, spec_tile,         SLE_UINT32,                 6, SL_MAX_VERSION),
    04108   SLE_CONDVAR(AiBuildRec, use_tile,          SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
    04109   SLE_CONDVAR(AiBuildRec, use_tile,          SLE_UINT32,                 6, SL_MAX_VERSION),
    04110       SLE_VAR(AiBuildRec, rand_rng,          SLE_UINT8),
    04111       SLE_VAR(AiBuildRec, cur_building_rule, SLE_UINT8),
    04112       SLE_VAR(AiBuildRec, unk6,              SLE_UINT8),
    04113       SLE_VAR(AiBuildRec, unk7,              SLE_UINT8),
    04114       SLE_VAR(AiBuildRec, buildcmd_a,        SLE_UINT8),
    04115       SLE_VAR(AiBuildRec, buildcmd_b,        SLE_UINT8),
    04116       SLE_VAR(AiBuildRec, direction,         SLE_UINT8),
    04117       SLE_VAR(AiBuildRec, cargo,             SLE_UINT8),
    04118   SLE_END()
    04119 };
    04120
    04121
    04122 void SaveLoad_AI(PlayerID id)
    04123 {
    04124   PlayerAI *pai = &_players_ai[id];
    04125   SlObject(pai, _player_ai_desc);
    04126   for (int i = 0; i != pai->num_build_rec; i++) {
    04127     SlObject(&pai->src + i, _player_ai_build_rec_desc);
    04128   }
    04129 }