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 }

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