src/ai/api/ai_road.cpp
branchnoai
changeset 10993 203b90795f80
parent 10975 6bbc826d7812
equal deleted inserted replaced
10992:4dd4f4327c3a 10993:203b90795f80
     2 
     2 
     3 /** @file ai_road.cpp Implementation of AIRoad. */
     3 /** @file ai_road.cpp Implementation of AIRoad. */
     4 
     4 
     5 #include "ai_road.hpp"
     5 #include "ai_road.hpp"
     6 #include "ai_map.hpp"
     6 #include "ai_map.hpp"
       
     7 #include "ai_list.hpp"
     7 #include "../../openttd.h"
     8 #include "../../openttd.h"
     8 #include "../../road_map.h"
     9 #include "../../road_map.h"
     9 #include "../../station_map.h"
    10 #include "../../station_map.h"
    10 #include "../../command_type.h"
    11 #include "../../command_type.h"
    11 #include "../../player_func.h"
    12 #include "../../player_func.h"
       
    13 #include "../../settings_type.h"
       
    14 #include "../../squirrel_helper_type.hpp"
    12 
    15 
    13 /* static */ bool AIRoad::IsRoadTile(TileIndex tile)
    16 /* static */ bool AIRoad::IsRoadTile(TileIndex tile)
    14 {
    17 {
    15 	if (!::IsValidTile(tile)) return false;
    18 	if (!::IsValidTile(tile)) return false;
    16 
    19 
    77 	uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3);
    80 	uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3);
    78 	uint dir_2 = 2 ^ dir_1;
    81 	uint dir_2 = 2 ^ dir_1;
    79 
    82 
    80 	return HasBit(r1, dir_1) && HasBit(r2, dir_2);
    83 	return HasBit(r1, dir_1) && HasBit(r2, dir_2);
    81 }
    84 }
       
    85 
       
    86 /* Helper functions for AIRoad::CanBuildConnectedRoadParts(). */
       
    87 
       
    88 /**
       
    89  * Check whether the given existing bits the start and end part can be build.
       
    90  *  As the function assumes the bits being build on a slope that does not
       
    91  *  allow level foundations all of the existing parts will always be in
       
    92  *  a straight line. This also needs to hold for the start and end parts,
       
    93  *  otherwise it is for sure not valid. Finally a check will be done to
       
    94  *  determine whether the existing road parts match the to-be-build parts.
       
    95  *  As they can only be placed in one direction, just checking the start
       
    96  *  part with the first existing part is enough.
       
    97  * @param existing The existing road parts.
       
    98  * @param start The part that should be build first.
       
    99  * @param end The part that will be build second.
       
   100  * @return True if and only if the road bits can be build.
       
   101  */
       
   102 static bool CheckAutoExpandedRoadBits(const Array *existing, int32 start, int32 end)
       
   103 {
       
   104 	return (start + end == 0) && (existing->size == 0 || existing->array[0] == start || existing->array[0] == end);
       
   105 }
       
   106 
       
   107 /**
       
   108  * Lookup function for building road parts when building on slopes is disabled.
       
   109  * @param slope The slope of the tile to examine.
       
   110  * @param existing The existing road parts.
       
   111  * @param start The part that should be build first.
       
   112  * @param end The part that will be build second.
       
   113  * @return 0 when the build parts do not connect, 1 when they do connect once
       
   114  *         they are build or 2 when building the first part automatically
       
   115  *         builds the second part.
       
   116  */
       
   117 static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array *existing, int32 start, int32 end)
       
   118 {
       
   119 	switch (slope) {
       
   120 		/* Flat slopes can always be build. */
       
   121 		case SLOPE_FLAT:
       
   122 			return 1;
       
   123 
       
   124 		/* Only 4 of the slopes can be build upon. Testing the existing bits is
       
   125 		 * necessary because these bits can be something else when the settings
       
   126 		 * in the game have been changed.
       
   127 		 */
       
   128 		case SLOPE_NE: case SLOPE_SW:
       
   129 			return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing->size == 0 ? 2 : 1) : 0;
       
   130 		case SLOPE_SE: case SLOPE_NW:
       
   131 			return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing->size == 0 ? 2 : 1) : 0;
       
   132 
       
   133 		/* Any other tile cannot be built on. */
       
   134 		default:
       
   135 			return 0;
       
   136 	}
       
   137 }
       
   138 
       
   139 /**
       
   140  * Rotate a neighbour bit a single time clockwise.
       
   141  * @param neighbour The neighbour.
       
   142  * @return The rotate neighbour data.
       
   143  */
       
   144 static int32 RotateNeighbour(int32 neighbour)
       
   145 {
       
   146 	switch (neighbour) {
       
   147 		case -2: return -1;
       
   148 		case -1: return  2;
       
   149 		case  1: return -2;
       
   150 		case  2: return  1;
       
   151 		default: NOT_REACHED();
       
   152 	}
       
   153 }
       
   154 
       
   155 /**
       
   156  * Convert a neighbour to a road bit representation for easy internal use.
       
   157  * @param neighbour The neighbour.
       
   158  * @return The bits representing the direction.
       
   159  */
       
   160 static RoadBits NeighbourToRoadBits(int32 neighbour)
       
   161 {
       
   162 	switch (neighbour) {
       
   163 		case -2: return ROAD_NW;
       
   164 		case -1: return ROAD_NE;
       
   165 		case  2: return ROAD_SE;
       
   166 		case  1: return ROAD_SW;
       
   167 		default: NOT_REACHED();
       
   168 	}
       
   169 }
       
   170 
       
   171 /**
       
   172  * Lookup function for building road parts when building on slopes is enabled.
       
   173  * @param slope The slope of the tile to examine.
       
   174  * @param existing The existing neighbours.
       
   175  * @param start The part that should be build first.
       
   176  * @param end The part that will be build second.
       
   177  * @return 0 when the build parts do not connect, 1 when they do connect once
       
   178  *         they are build or 2 when building the first part automatically
       
   179  *         builds the second part.
       
   180  */
       
   181 static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start, int32 end)
       
   182 {
       
   183 	if (::IsSteepSlope(slope)) {
       
   184 		switch (slope) {
       
   185 			/* On steep slopes one can only build straight roads that will be
       
   186 			 * automatically expanded to a straight road. Just check that the existing
       
   187 			 * road parts are in the same direction. */
       
   188 			case SLOPE_STEEP_S:
       
   189 			case SLOPE_STEEP_W:
       
   190 			case SLOPE_STEEP_N:
       
   191 			case SLOPE_STEEP_E:
       
   192 				return CheckAutoExpandedRoadBits(existing, start, end) ? (existing->size == 0 ? 2 : 1) : 0;
       
   193 
       
   194 			/* All other slopes are invalid slopes!. */
       
   195 			default:
       
   196 				return -1;
       
   197 		}
       
   198 	}
       
   199 
       
   200 	/* The slope is not steep. Furthermore lots of slopes are generally the
       
   201 	 * same but are only rotated. So to reduce the amount of lookup work that
       
   202 	 * needs to be done the data is made uniform. This means rotating the
       
   203 	 * existing parts and updating the slope. */
       
   204 	static const ::Slope base_slopes[] = {
       
   205 		SLOPE_FLAT, SLOPE_W,   SLOPE_W,   SLOPE_SW,
       
   206 		SLOPE_W,    SLOPE_EW,  SLOPE_SW,  SLOPE_WSE,
       
   207 		SLOPE_W,    SLOPE_SW,  SLOPE_EW,  SLOPE_WSE,
       
   208 		SLOPE_SW,   SLOPE_WSE, SLOPE_WSE};
       
   209 	static const byte base_rotates[] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 2, 3, 2, 2, 1};
       
   210 
       
   211 	if (slope >= (::Slope)lengthof(base_slopes)) {
       
   212 		/* This slope is an invalid slope, so ignore it. */
       
   213 		return -1;
       
   214 	}
       
   215 	byte base_rotate = base_rotates[slope];
       
   216 	slope = base_slopes[slope];
       
   217 
       
   218 	/* Some slopes don't need rotating, so return early when we know we do
       
   219 	 * not need to rotate. */
       
   220 	switch (slope) {
       
   221 		case SLOPE_FLAT:
       
   222 			/* Flat slopes can always be build. */
       
   223 			return 1;
       
   224 
       
   225 		case SLOPE_EW:
       
   226 		case SLOPE_WSE:
       
   227 			/* A slope similar to a SLOPE_EW or SLOPE_WSE will always cause
       
   228 			 * foundations which makes them accessible from all sides. */
       
   229 			return 1;
       
   230 
       
   231 		case SLOPE_W:
       
   232 		case SLOPE_SW:
       
   233 			/* A slope for which we need perform some calculations. */
       
   234 			break;
       
   235 
       
   236 		default:
       
   237 			/* An invalid slope. */
       
   238 			return -1;
       
   239 	}
       
   240 
       
   241 	/* Now perform the actual rotation. */
       
   242 	for (int j = 0; j < base_rotate; j++) {
       
   243 		for (int i = 0; i < existing->size; i++) {
       
   244 			existing->array[i] = RotateNeighbour(existing->array[i]);
       
   245 		}
       
   246 		start = RotateNeighbour(start);
       
   247 		end   = RotateNeighbour(end);
       
   248 	}
       
   249 
       
   250 	/* Create roadbits out of the data for easier handling. */
       
   251 	RoadBits start_roadbits    = NeighbourToRoadBits(start);
       
   252 	RoadBits new_roadbits      = start_roadbits | NeighbourToRoadBits(end);
       
   253 	RoadBits existing_roadbits = ROAD_NONE;
       
   254 	for (int i = 0; i < existing->size; i++) {
       
   255 		existing_roadbits |= NeighbourToRoadBits(existing->array[i]);
       
   256 	}
       
   257 
       
   258 	switch (slope) {
       
   259 		case SLOPE_W:
       
   260 			/* A slope similar to a SLOPE_W. */
       
   261 			switch (new_roadbits) {
       
   262 				case  6: // ROAD_SE | ROAD_SW:
       
   263 				case  9: // ROAD_NE | ROAD_NW:
       
   264 				case 12: // ROAD_NE | ROAD_SE:
       
   265 					/* Cannot build anything with a turn from the low side. */
       
   266 					return 0;
       
   267 
       
   268 				case  5: // ROAD_SE | ROAD_NW:
       
   269 				case 10: // ROAD_NE | ROAD_SW:
       
   270 					/* A 'sloped' tile is going to be build. */
       
   271 					if ((existing_roadbits | new_roadbits) != new_roadbits) {
       
   272 						/* There is already a foundation on the tile, or at least
       
   273 						 * another slope that is not compatible with the new one. */
       
   274 						return 0;
       
   275 					}
       
   276 					/* If the start is in the low part, it is automatically
       
   277 					 * building the second part too. */
       
   278 					return ((start_roadbits & (ROAD_NE | ROAD_SE)) && !(existing_roadbits & (ROAD_SW | ROAD_NW))) ? 2 : 1;
       
   279 
       
   280 				default:
       
   281 					/* Roadbits causing a foundation are going to be build.
       
   282 					 * When the existing roadbits are slopes (the lower bits
       
   283 					 * are used), this cannot be done. */
       
   284 					if ((existing_roadbits | new_roadbits) == new_roadbits) return 1;
       
   285 					return (existing_roadbits & (ROAD_NE | ROAD_SE)) ? 0 : 1;
       
   286 			}
       
   287 
       
   288 		case SLOPE_SW:
       
   289 			/* A slope similar to a SLOPE_SW. */
       
   290 			switch (new_roadbits) {
       
   291 				case  9: // ROAD_NE | ROAD_NW:
       
   292 				case 12: // ROAD_NE | ROAD_SE:
       
   293 					/* Cannot build anything with a turn from the low side. */
       
   294 					return 0;
       
   295 
       
   296 				case 10: // ROAD_NE | ROAD_SW:
       
   297 					/* A 'sloped' tile is going to be build. */
       
   298 					if ((existing_roadbits | new_roadbits) != new_roadbits) {
       
   299 						/* There is already a foundation on the tile, or at least
       
   300 						 * another slope that is not compatible with the new one. */
       
   301 						return 0;
       
   302 					}
       
   303 					/* If the start is in the low part, it is automatically
       
   304 					 * building the second part too. */
       
   305 					return ((start_roadbits & ROAD_NE) && !(existing_roadbits & ROAD_SW)) ? 2 : 1;
       
   306 
       
   307 				default:
       
   308 					/* Roadbits causing a foundation are going to be build.
       
   309 					 * When the existing roadbits are slopes (the lower bits
       
   310 					 * are used), this cannot be done. */
       
   311 					return (existing_roadbits & ROAD_NE) ? 0 : 1;
       
   312 			}
       
   313 
       
   314 		default:
       
   315 			NOT_REACHED();
       
   316 	}
       
   317 }
       
   318 
       
   319 /**
       
   320  * Normalise all input data so we can easily handle it without needing
       
   321  * to call the API lots of times or create large if-elseif-elseif-else
       
   322  * constructs.
       
   323  * In this case it means that a TileXY(0, -1) becomes -2 and TileXY(0, 1)
       
   324  * becomes 2. TileXY(-1, 0) and TileXY(1, 0) stay respectively -1 and 1.
       
   325  * Any other value means that it is an invalid tile offset.
       
   326  * @param tile The tile to normalise.
       
   327  * @return True if and only if the tile offset is valid.
       
   328  */
       
   329 static bool NormaliseTileOffset(int32 *tile)
       
   330 {
       
   331 		if (*tile == 1 || *tile == -1) return true;
       
   332 		if (*tile == ::TileDiffXY(0, -1)) {
       
   333 			*tile = -2;
       
   334 			return true;
       
   335 		}
       
   336 		if (*tile == ::TileDiffXY(0, 1)) {
       
   337 			*tile = 2;
       
   338 			return true;
       
   339 		}
       
   340 		return false;
       
   341 }
       
   342 
       
   343 /* static */ int32 AIRoad::CanBuildConnectedRoadParts(AITile::Slope slope_, Array *existing, TileIndex start_, TileIndex end_)
       
   344 {
       
   345 	::Slope slope = (::Slope)slope_;
       
   346 	int32 start = start_;
       
   347 	int32 end = end_;
       
   348 
       
   349 	/* The start tile and end tile cannot be the same tile either. */
       
   350 	if (start == end) return -1;
       
   351 
       
   352 	for (int i = 0; i < existing->size; i++) {
       
   353 		if (!NormaliseTileOffset(&existing->array[i])) return -1;
       
   354 	}
       
   355 
       
   356 	if (!NormaliseTileOffset(&start)) return -1;
       
   357 	if (!NormaliseTileOffset(&end)) return -1;
       
   358 
       
   359 	/* Without build on slopes the characteristics are vastly different, so use
       
   360 	 * a different helper function (one that is much simpler). */
       
   361 	return _settings_game.construction.build_on_slopes ? LookupWithBuildOnSlopes(slope, existing, start, end) : LookupWithoutBuildOnSlopes(slope, existing, start, end);
       
   362 }
       
   363 
       
   364 /* static */ int32 AIRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end)
       
   365 {
       
   366 	if (!::IsValidTile(tile) || !::IsValidTile(start) || !::IsValidTile(end)) return -1;
       
   367 	if (::DistanceManhattan(tile, start) != 1 || ::DistanceManhattan(tile, end) != 1) return -1;
       
   368 
       
   369 	static const TileIndex neighbours[] = {::TileDiffXY(-1, 0), ::TileDiffXY(1, 0), ::TileDiffXY(0, -1), ::TileDiffXY(0, 1)};
       
   370 	Array *existing = (Array*)alloca(sizeof(Array) + lengthof(neighbours) * sizeof(int32));
       
   371 	existing->size = 0;
       
   372 
       
   373 	for (uint i = 0; i < lengthof(neighbours); i++) {
       
   374 		if (AIRoad::AreRoadTilesConnected(tile, tile + neighbours[i])) existing->array[existing->size++] = neighbours[i];
       
   375 	}
       
   376 
       
   377 	return AIRoad::CanBuildConnectedRoadParts(AITile::GetSlope(tile), existing, start - tile, end - tile);
       
   378 }
       
   379 
    82 
   380 
    83 /* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile)
   381 /* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile)
    84 {
   382 {
    85 	if (!::IsValidTile(tile)) return false;
   383 	if (!::IsValidTile(tile)) return false;
    86 
   384