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 }

Generated on Mon Sep 22 20:34:14 2008 for openttd by  doxygen 1.5.6