src/ai/trolly/build.cpp
branchcustombridgeheads
changeset 5649 55c8267c933f
parent 5643 3778051e8095
equal deleted inserted replaced
5648:1608018c5ff2 5649:55c8267c933f
       
     1 /* $Id$ */
       
     2 
       
     3 #include "../../stdafx.h"
       
     4 #include "../../openttd.h"
       
     5 #include "../../debug.h"
       
     6 #include "../../functions.h"
       
     7 #include "../../map.h"
       
     8 #include "../../road_map.h"
       
     9 #include "../../tile.h"
       
    10 #include "../../vehicle.h"
       
    11 #include "../../command.h"
       
    12 #include "trolly.h"
       
    13 #include "../../engine.h"
       
    14 #include "../../station.h"
       
    15 #include "../../variables.h"
       
    16 #include "../../bridge.h"
       
    17 #include "../ai.h"
       
    18 
       
    19 // Build HQ
       
    20 //  Params:
       
    21 //    tile : tile where HQ is going to be build
       
    22 bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
       
    23 {
       
    24 	if (CmdFailed(AI_DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
       
    25 		return false;
       
    26 	AI_DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
       
    27 	return true;
       
    28 }
       
    29 
       
    30 
       
    31 // Build station
       
    32 //  Params:
       
    33 //    type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
       
    34 //    tile : tile where station is going to be build
       
    35 //    length : in case of AI_TRAIN: length of station
       
    36 //    numtracks : in case of AI_TRAIN: tracks of station
       
    37 //    direction : the direction of the station
       
    38 //    flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
       
    39 int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
       
    40 {
       
    41 	if (type == AI_TRAIN)
       
    42 		return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
       
    43 
       
    44 	if (type == AI_BUS)
       
    45 		return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
       
    46 
       
    47 	return AI_DoCommand(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
       
    48 }
       
    49 
       
    50 
       
    51 // Builds a brdige. The second best out of the ones available for this player
       
    52 //  Params:
       
    53 //   tile_a : starting point
       
    54 //   tile_b : end point
       
    55 //   flag : flag passed to DoCommand
       
    56 int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
       
    57 {
       
    58 	int bridge_type, bridge_len, type, type2;
       
    59 
       
    60 	// Find a good bridgetype (the best money can buy)
       
    61 	bridge_len = GetBridgeLength(tile_a, tile_b);
       
    62 	type = type2 = 0;
       
    63 	for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
       
    64 		if (CheckBridge_Stuff(bridge_type, bridge_len)) {
       
    65 			type2 = type;
       
    66 			type = bridge_type;
       
    67 			// We found two bridges, exit
       
    68 			if (type2 != 0) break;
       
    69 		}
       
    70 	}
       
    71 	// There is only one bridge that can be built
       
    72 	if (type2 == 0 && type != 0) type2 = type;
       
    73 
       
    74 	// Now, simply, build the bridge!
       
    75 	if (p->ainew.tbt == AI_TRAIN) {
       
    76 		return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
       
    77 	} else {
       
    78 		return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
       
    79 	}
       
    80 }
       
    81 
       
    82 
       
    83 // Build the route part by part
       
    84 // Basicly what this function do, is build that amount of parts of the route
       
    85 //  that go in the same direction. It sets 'part' to the last part of the route builded.
       
    86 //  The return value is the cost for the builded parts
       
    87 //
       
    88 //  Params:
       
    89 //   PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
       
    90 //   part : Which part we need to build
       
    91 //
       
    92 // TODO: skip already builded road-pieces (e.g.: cityroad)
       
    93 int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
       
    94 {
       
    95 	int part = PathFinderInfo->position;
       
    96 	byte *route_extra = PathFinderInfo->route_extra;
       
    97 	TileIndex *route = PathFinderInfo->route;
       
    98 	int dir;
       
    99 	int old_dir = -1;
       
   100 	int cost = 0;
       
   101 	int res;
       
   102 	// We need to calculate the direction with the parent of the parent.. so we skip
       
   103 	//  the first pieces and the last piece
       
   104 	if (part < 1) part = 1;
       
   105 	// When we are done, stop it
       
   106 	if (part >= PathFinderInfo->route_length - 1) {
       
   107 		PathFinderInfo->position = -2;
       
   108 		return 0;
       
   109 	}
       
   110 
       
   111 
       
   112 	if (PathFinderInfo->rail_or_road) {
       
   113 		// Tunnel code
       
   114 		if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
       
   115 			cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
       
   116 			PathFinderInfo->position++;
       
   117 			// TODO: problems!
       
   118 			if (CmdFailed(cost)) {
       
   119 				DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
       
   120 				return 0;
       
   121 			}
       
   122 			return cost;
       
   123 		}
       
   124 		// Bridge code
       
   125 		if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
       
   126 			cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
       
   127 			PathFinderInfo->position++;
       
   128 			// TODO: problems!
       
   129 			if (CmdFailed(cost)) {
       
   130 				DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part - 1]);
       
   131 				return 0;
       
   132 			}
       
   133 			return cost;
       
   134 		}
       
   135 
       
   136 		// Build normal rail
       
   137 		// Keep it doing till we go an other way
       
   138 		if (route_extra[part - 1] == 0 && route_extra[part] == 0) {
       
   139 			while (route_extra[part] == 0) {
       
   140 				// Get the current direction
       
   141 				dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
       
   142 				// Is it the same as the last one?
       
   143 				if (old_dir != -1 && old_dir != dir) break;
       
   144 				old_dir = dir;
       
   145 				// Build the tile
       
   146 				res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
       
   147 				if (CmdFailed(res)) {
       
   148 					// Problem.. let's just abort it all!
       
   149 					p->ainew.state = AI_STATE_NOTHING;
       
   150 					return 0;
       
   151 				}
       
   152 				cost += res;
       
   153 				// Go to the next tile
       
   154 				part++;
       
   155 				// Check if it is still in range..
       
   156 				if (part >= PathFinderInfo->route_length - 1) break;
       
   157 			}
       
   158 			part--;
       
   159 		}
       
   160 		// We want to return the last position, so we go back one
       
   161 		PathFinderInfo->position = part;
       
   162 	} else {
       
   163 		// Tunnel code
       
   164 		if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
       
   165 			cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
       
   166 			PathFinderInfo->position++;
       
   167 			// TODO: problems!
       
   168 			if (CmdFailed(cost)) {
       
   169 				DEBUG(ai, 0, "[BuildPath] tunnel could not be built (0x%X)", route[part]);
       
   170 				return 0;
       
   171 			}
       
   172 			return cost;
       
   173 		}
       
   174 		// Bridge code
       
   175 		if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
       
   176 			cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
       
   177 			PathFinderInfo->position++;
       
   178 			// TODO: problems!
       
   179 			if (CmdFailed(cost)) {
       
   180 				DEBUG(ai, 0, "[BuildPath] bridge could not be built (0x%X, 0x%X)", route[part], route[part + 1]);
       
   181 				return 0;
       
   182 			}
       
   183 			return cost;
       
   184 		}
       
   185 
       
   186 		// Build normal road
       
   187 		// Keep it doing till we go an other way
       
   188 		// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
       
   189 		//  it will wait till the vehicle is gone..
       
   190 		if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
       
   191 			while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
       
   192 				// Get the current direction
       
   193 				dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
       
   194 				// Is it the same as the last one?
       
   195 				if (old_dir != -1 && old_dir != dir) break;
       
   196 				old_dir = dir;
       
   197 				// There is already some road, and it is a bridge.. don't build!!!
       
   198 				if (!(IsTileType(route[part], MP_TUNNEL) || IsTileType(route[part], MP_STREET_BRIDGE) || IsTileType(route[part], MP_RAILWAY_BRIDGE))) {
       
   199 					// Build the tile
       
   200 					res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
       
   201 					// Currently, we ignore CMD_ERRORs!
       
   202 					if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
       
   203 						// Problem.. let's just abort it all!
       
   204 						DEBUG(ai, 0, "[BuidPath] route building failed at tile 0x%X, aborting", route[part]);
       
   205 						p->ainew.state = AI_STATE_NOTHING;
       
   206 						return 0;
       
   207 					}
       
   208 
       
   209 					if (!CmdFailed(res)) cost += res;
       
   210 				}
       
   211 				// Go to the next tile
       
   212 				part++;
       
   213 				// Check if it is still in range..
       
   214 				if (part >= PathFinderInfo->route_length - 1) break;
       
   215 			}
       
   216 			part--;
       
   217 			// We want to return the last position, so we go back one
       
   218 		}
       
   219 		if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
       
   220 		PathFinderInfo->position = part;
       
   221 	}
       
   222 
       
   223 	return cost;
       
   224 }
       
   225 
       
   226 
       
   227 // This functions tries to find the best vehicle for this type of cargo
       
   228 // It returns INVALID_ENGINE if not suitable engine is found
       
   229 EngineID AiNew_PickVehicle(Player *p)
       
   230 {
       
   231 	if (p->ainew.tbt == AI_TRAIN) {
       
   232 		// Not supported yet
       
   233 		return INVALID_ENGINE;
       
   234 	} else {
       
   235 		EngineID best_veh_index = INVALID_ENGINE;
       
   236 		int32 best_veh_rating = 0;
       
   237 		EngineID start = ROAD_ENGINES_INDEX;
       
   238 		EngineID end   = ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES;
       
   239 		EngineID i;
       
   240 
       
   241 		/* Loop through all road vehicles */
       
   242 		for (i = start; i != end; i++) {
       
   243 			const RoadVehicleInfo *rvi = RoadVehInfo(i);
       
   244 			const Engine* e = GetEngine(i);
       
   245 			int32 rating;
       
   246 			int32 ret;
       
   247 
       
   248 			/* Skip vehicles which can't take our cargo type */
       
   249 			if (rvi->cargo_type != p->ainew.cargo && !CanRefitTo(i, p->ainew.cargo)) continue;
       
   250 
       
   251 			// Is it availiable?
       
   252 			// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
       
   253 			if (!HASBIT(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
       
   254 
       
   255 			/* Rate and compare the engine by speed & capacity */
       
   256 			rating = rvi->max_speed * rvi->capacity;
       
   257 			if (rating <= best_veh_rating) continue;
       
   258 
       
   259 			// Can we build it?
       
   260 			ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
       
   261 			if (CmdFailed(ret)) continue;
       
   262 
       
   263 			best_veh_rating = rating;
       
   264 			best_veh_index = i;
       
   265 		}
       
   266 
       
   267 		return best_veh_index;
       
   268 	}
       
   269 }
       
   270 
       
   271 
       
   272 void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
       
   273 {
       
   274 	Player* p = GetPlayer(_current_player);
       
   275 
       
   276 	if (success) {
       
   277 		p->ainew.state = AI_STATE_GIVE_ORDERS;
       
   278 		p->ainew.veh_id = _new_vehicle_id;
       
   279 
       
   280 		if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
       
   281 			/* Cargo type doesn't match, so refit it */
       
   282 			if (CmdFailed(DoCommand(tile, p->ainew.veh_id, p->ainew.cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
       
   283 				/* Refit failed, so sell the vehicle */
       
   284 				DoCommand(tile, p->ainew.veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
       
   285 				p->ainew.state = AI_STATE_NOTHING;
       
   286 			}
       
   287 		}
       
   288 	} else {
       
   289 		/* XXX this should be handled more gracefully */
       
   290 		p->ainew.state = AI_STATE_NOTHING;
       
   291 	}
       
   292 }
       
   293 
       
   294 
       
   295 // Builds the best vehicle possible
       
   296 int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
       
   297 {
       
   298 	EngineID i = AiNew_PickVehicle(p);
       
   299 
       
   300 	if (i == INVALID_ENGINE) return CMD_ERROR;
       
   301 	if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
       
   302 
       
   303 	if (flag & DC_EXEC) {
       
   304 		return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
       
   305 	} else {
       
   306 		return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
       
   307 	}
       
   308 }
       
   309 
       
   310 int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
       
   311 {
       
   312 	int ret, ret2;
       
   313 	if (p->ainew.tbt == AI_TRAIN) {
       
   314 		return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
       
   315 	} else {
       
   316 		ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
       
   317 		if (CmdFailed(ret)) return ret;
       
   318 		// Try to build the road from the depot
       
   319 		ret2 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
       
   320 		// If it fails, ignore it..
       
   321 		if (CmdFailed(ret2)) return ret;
       
   322 		return ret + ret2;
       
   323 	}
       
   324 }