# build.cpp

    00001 /* $Id: build.cpp 11968 2008-01-23 22:34:04Z smatz $ */
    00002
    00003 #include "../../stdafx.h"
    00004 #include "../../openttd.h"
    00005 #include "../../debug.h"
    00006 #include "../../road_map.h"
    00007 #include "../../command_func.h"
    00008 #include "trolly.h"
    00009 #include "../../engine.h"
    00010 #include "../../station.h"
    00011 #include "../../variables.h"
    00012 #include "../../bridge.h"
    00013 #include "../../vehicle_func.h"
    00014 #include "../../vehicle_base.h"
    00015 #include "../../player_base.h"
    00016 #include "../../player_func.h"
    00017 #include "../ai.h"
    00018 #include "../../tunnelbridge.h"
    00019
    00020
    00021 // Build HQ
    00022 //  Params:
    00023 //    tile : tile where HQ is going to be build
    00024 bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
    00025 {
    00026   if (CmdFailed(AI_DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
    00027     return false;
    00028   AI_DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
    00029   return true;
    00030 }
    00031
    00032
    00033 // Build station
    00034 //  Params:
    00035 //    type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
    00036 //    tile : tile where station is going to be build
    00037 //    length : in case of AI_TRAIN: length of station
    00038 //    numtracks : in case of AI_TRAIN: tracks of station
    00039 //    direction : the direction of the station
    00040 //    flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
    00041 CommandCost AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
    00042 {
    00043   if (type == AI_TRAIN)
    00044     return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
    00045
    00046   if (type == AI_BUS)
    00047     return AI_DoCommand(tile, direction, ROADTYPES_ROAD << 2 | RoadStop::BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
    00048
    00049   return AI_DoCommand(tile, direction, ROADTYPES_ROAD << 2 | RoadStop::TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
    00050 }
    00051
    00052
    00053 // Builds a brdige. The second best out of the ones available for this player
    00054 //  Params:
    00055 //   tile_a : starting point
    00056 //   tile_b : end point
    00057 //   flag : flag passed to DoCommand
    00058 CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
    00059 {
    00060   int bridge_type, bridge_len, type, type2;
    00061
    00062   // Find a good bridgetype (the best money can buy)
    00063   bridge_len = GetTunnelBridgeLength(tile_a, tile_b);
    00064   type = type2 = 0;
    00065   for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
    00066     if (CheckBridge_Stuff(bridge_type, bridge_len)) {
    00067       type2 = type;
    00068       type = bridge_type;
    00069       // We found two bridges, exit
    00070       if (type2 != 0) break;
    00071     }
    00072   }
    00073   // There is only one bridge that can be built
    00074   if (type2 == 0 && type != 0) type2 = type;
    00075
    00076   // Now, simply, build the bridge!
    00077   if (_players_ainew[p->index].tbt == AI_TRAIN) {
    00078     return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
    00079   } else {
    00080     return AI_DoCommand(tile_a, tile_b, ((0x80 | ROADTYPES_ROAD) << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
    00081   }
    00082 }
    00083
    00084
    00085 // Build the route part by part
    00086 // Basicly what this function do, is build that amount of parts of the route
    00087 //  that go in the same direction. It sets 'part' to the last part of the route builded.
    00088 //  The return value is the cost for the builded parts
    00089 //
    00090 //  Params:
    00091 //   PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
    00092 //   part : Which part we need to build
    00093 //
    00094 // TODO: skip already builded road-pieces (e.g.: cityroad)
    00095 CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
    00096 {
    00097   int part = PathFinderInfo->position;
    00098   byte *route_extra = PathFinderInfo->route_extra;
    00099   TileIndex *route = PathFinderInfo->route;
    00100   int dir;
    00101   int old_dir = -1;
    00102   CommandCost cost;
    00103   CommandCost res;
    00104   // We need to calculate the direction with the parent of the parent.. so we skip
    00105   //  the first pieces and the last piece
    00106   if (part < 1) part = 1;
    00107   // When we are done, stop it
    00108   if (part >= PathFinderInfo->route_length - 1) {
    00109     PathFinderInfo->position = -2;
    00110     return CommandCost();
    00111   }
    00112
    00113
    00114   if (PathFinderInfo->rail_or_road) {
    00115     // Tunnel code
    00116     if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
    00117       cost.AddCost(AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL));
    00118       PathFinderInfo->position++;
    00119       // TODO: problems!
    00120       if (CmdFailed(cost)) {
    00121         DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
    00122         return CommandCost();
    00123       }
    00124       return cost;
    00125     }
    00126     // Bridge code
    00127     if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
    00128       cost.AddCost(AiNew_Build_Bridge(p, route[part], route[part - 1], flag));
    00129       PathFinderInfo->position++;
    00130       // TODO: problems!
    00131       if (CmdFailed(cost)) {
    00132         DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part - 1]);
    00133         return CommandCost();
    00134       }
    00135       return cost;
    00136     }
    00137
    00138     // Build normal rail
    00139     // Keep it doing till we go an other way
    00140     if (route_extra[part - 1] == 0 && route_extra[part] == 0) {
    00141       while (route_extra[part] == 0) {
    00142         // Get the current direction
    00143         dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
    00144         // Is it the same as the last one?
    00145         if (old_dir != -1 && old_dir != dir) break;
    00146         old_dir = dir;
    00147         // Build the tile
    00148         res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
    00149         if (CmdFailed(res)) {
    00150           // Problem.. let's just abort it all!
    00151           _players_ainew[p->index].state = AI_STATE_NOTHING;
    00152           return CommandCost();
    00153         }
    00154         cost.AddCost(res);
    00155         // Go to the next tile
    00156         part++;
    00157         // Check if it is still in range..
    00158         if (part >= PathFinderInfo->route_length - 1) break;
    00159       }
    00160       part--;
    00161     }
    00162     // We want to return the last position, so we go back one
    00163     PathFinderInfo->position = part;
    00164   } else {
    00165     // Tunnel code
    00166     if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
    00167       cost.AddCost(AI_DoCommand(route[part], 0x200 | ROADTYPES_ROAD, 0, flag, CMD_BUILD_TUNNEL));
    00168       PathFinderInfo->position++;
    00169       // TODO: problems!
    00170       if (CmdFailed(cost)) {
    00171         DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
    00172         return CommandCost();
    00173       }
    00174       return cost;
    00175     }
    00176     // Bridge code
    00177     if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
    00178       cost.AddCost(AiNew_Build_Bridge(p, route[part], route[part + 1], flag));
    00179       PathFinderInfo->position++;
    00180       // TODO: problems!
    00181       if (CmdFailed(cost)) {
    00182         DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part + 1]);
    00183         return CommandCost();
    00184       }
    00185       return cost;
    00186     }
    00187
    00188     // Build normal road
    00189     // Keep it doing till we go an other way
    00190     // EnsureNoVehicleOnGround makes sure we don't build on a tile where a vehicle is. This way
    00191     //  it will wait till the vehicle is gone..
    00192     if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicleOnGround(route[part]))) {
    00193       while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicleOnGround(route[part]))) {
    00194         // Get the current direction
    00195         dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
    00196         // Is it the same as the last one?
    00197         if (old_dir != -1 && old_dir != dir) break;
    00198         old_dir = dir;
    00199         // There is already some road, and it is a bridge.. don't build!!!
    00200         if (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
    00201           // Build the tile
    00202           res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
    00203           // Currently, we ignore CMD_ERRORs!
    00204           if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_ROAD) && !EnsureNoVehicleOnGround(route[part])) {
    00205             // Problem.. let's just abort it all!
    00206             DEBUG(ai, 0, "[BuidPath] route building failed at tile 0x%X, aborting", route[part]);
    00207             _players_ainew[p->index].state = AI_STATE_NOTHING;
    00208             return CommandCost();
    00209           }
    00210
    00211           if (CmdSucceeded(res)) cost.AddCost(res);
    00212         }
    00213         // Go to the next tile
    00214         part++;
    00215         // Check if it is still in range..
    00216         if (part >= PathFinderInfo->route_length - 1) break;
    00217       }
    00218       part--;
    00219       // We want to return the last position, so we go back one
    00220     }
    00221     if (!EnsureNoVehicleOnGround(route[part]) && flag == DC_EXEC) part--;
    00222     PathFinderInfo->position = part;
    00223   }
    00224
    00225   return cost;
    00226 }
    00227
    00228
    00229 // This functions tries to find the best vehicle for this type of cargo
    00230 // It returns INVALID_ENGINE if not suitable engine is found
    00231 EngineID AiNew_PickVehicle(Player *p)
    00232 {
    00233   if (_players_ainew[p->index].tbt == AI_TRAIN) {
    00234     // Not supported yet
    00235     return INVALID_ENGINE;
    00236   } else {
    00237     EngineID best_veh_index = INVALID_ENGINE;
    00238     int32 best_veh_rating = 0;
    00239     EngineID i;
    00240
    00241     /* Loop through all road vehicles */
    00242     FOR_ALL_ENGINEIDS_OF_TYPE(i, VEH_ROAD) {
    00243       const RoadVehicleInfo *rvi = RoadVehInfo(i);
    00244       const Engine* e = GetEngine(i);
    00245
    00246       /* Skip vehicles which can't take our cargo type */
    00247       if (rvi->cargo_type != _players_ainew[p->index].cargo && !CanRefitTo(i, _players_ainew[p->index].cargo)) continue;
    00248
    00249       /* Skip trams */
    00250       if (HasBit(EngInfo(i)->misc_flags, EF_ROAD_TRAM)) continue;
    00251
    00252       // Is it availiable?
    00253       // Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
    00254       if (!HasBit(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
    00255
    00256       /* Rate and compare the engine by speed & capacity */
    00257       int rating = rvi->max_speed * rvi->capacity;
    00258       if (rating <= best_veh_rating) continue;
    00259
    00260       // Can we build it?
    00261       CommandCost ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
    00262       if (CmdFailed(ret)) continue;
    00263
    00264       best_veh_rating = rating;
    00265       best_veh_index = i;
    00266     }
    00267
    00268     return best_veh_index;
    00269   }
    00270 }
    00271
    00272
    00273 void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
    00274 {
    00275   Player* p = GetPlayer(_current_player);
    00276
    00277   if (success) {
    00278     _players_ainew[p->index].state = AI_STATE_GIVE_ORDERS;
    00279     _players_ainew[p->index].veh_id = _new_vehicle_id;
    00280
    00281     if (GetVehicle(_players_ainew[p->index].veh_id)->cargo_type != _players_ainew[p->index].cargo) {
    00282       /* Cargo type doesn't match, so refit it */
    00283       if (CmdFailed(DoCommand(tile, _players_ainew[p->index].veh_id, _players_ainew[p->index].cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
    00284         /* Refit failed, so sell the vehicle */
    00285         DoCommand(tile, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
    00286         _players_ainew[p->index].state = AI_STATE_NOTHING;
    00287       }
    00288     }
    00289   } else {
    00290     /* XXX this should be handled more gracefully */
    00291     _players_ainew[p->index].state = AI_STATE_NOTHING;
    00292   }
    00293 }
    00294
    00295
    00296 // Builds the best vehicle possible
    00297 CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
    00298 {
    00299   EngineID i = AiNew_PickVehicle(p);
    00300
    00301   if (i == INVALID_ENGINE) return CMD_ERROR;
    00302   if (_players_ainew[p->index].tbt == AI_TRAIN) return CMD_ERROR;
    00303
    00304   if (flag & DC_EXEC) {
    00305     return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
    00306   } else {
    00307     return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
    00308   }
    00309 }
    00310
    00311 CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
    00312 {
    00313   CommandCost ret, ret2;
    00314   if (_players_ainew[p->index].tbt == AI_TRAIN) {
    00315     return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
    00316   } else {
    00317     ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
    00318     if (CmdFailed(ret2)) return ret;
    00319     // Try to build the road from the depot
    00320     ret2 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
    00321     // If it fails, ignore it..
    00322     if (CmdFailed(ret2)) return ret;
    00323     ret.AddCost(ret2);
    00324     return ret;
    00325   }
    00326 }