Example #1
0
File: tile.c Project: l0b0/OpenDUNE
/**
 * Get a tile in the direction of a destination, randomized a bit.
 *
 * @param packed_from The origin.
 * @param packed_to The destination.
 * @return A packed tile.
 */
uint16 Tile_GetTileInDirectionOf(uint16 packed_from, uint16 packed_to)
{
    int16 distance;
    uint8 direction;
    uint8 i;

    if (packed_from == 0 || packed_to == 0) return 0;

    distance = Tile_GetDistancePacked(packed_from, packed_to);
    direction = Tile_GetDirectionPacked(packed_to, packed_from);

    if (distance <= 10) return 0;

    for (i = 0; i < 4; i++) {
        int16 dir;
        tile32 position;
        uint16 packed;

        dir = 29 + (Tools_Random_256() & 0x3F);

        if ((Tools_Random_256() & 1) != 0) dir = -dir;

        position = Tile_UnpackTile(packed_to);
        position = Tile_MoveByDirection(position, direction + dir, min(distance, 20) << 8);
        packed = Tile_PackTile(position);

        if (Map_IsValidPosition(packed)) return packed;
    }

    return 0;
}
Example #2
0
/**
 * Try to find a path between two points.
 *
 * @param packedSrc The start point.
 * @param packedDst The end point.
 * @param buffer The buffer to store the route in.
 * @param bufferSize The size of the buffer.
 * @return A struct with information about the found route.
 */
static Pathfinder_Data Script_Unit_Pathfinder(uint16 packedSrc, uint16 packedDst, void *buffer, int16 bufferSize)
{
	uint16 packedCur;
	Pathfinder_Data res;

	res.packed    = packedSrc;
	res.score     = 0;
	res.routeSize = 0;
	res.buffer    = buffer;

	res.buffer[0] = 0xFF;

	bufferSize--;

	packedCur = packedSrc;
	while (res.routeSize < bufferSize) {
		uint8  direction;
		uint16 packedNext;
		int16  score;

		if (packedCur == packedDst) break;

		/* Try going directly to the destination tile */
		direction = Tile_GetDirectionPacked(packedCur, packedDst) / 32;
		packedNext = packedCur + s_mapDirection[direction];

		/* Check for valid movement towards the tile */
		score = Script_Unit_Pathfind_GetScore(packedNext, direction);
		if (score <= 255) {
			res.buffer[res.routeSize++] = direction;
			res.score += score;
		} else {
			uint8 dir;
			bool foundCounterclockwise = false;
			bool foundClockwise = false;
			int16 routeSize;
			Pathfinder_Data routes[2];
			uint8 routesBuffer[2][102];
			Pathfinder_Data *bestRoute;

			while (true) {
				if (packedNext == packedDst) break;

				/* Find the first valid tile on the (direct) route. */
				dir = Tile_GetDirectionPacked(packedNext, packedDst) / 32;
				packedNext += s_mapDirection[dir];
				if (Script_Unit_Pathfind_GetScore(packedNext, dir) > 255) continue;

				/* Try to find a connection between our last valid tile and the new valid tile */
				routes[1].packed    = packedCur;
				routes[1].score     = 0;
				routes[1].routeSize = 0;
				routes[1].buffer    = routesBuffer[0];
				foundCounterclockwise = Script_Unit_Pathfinder_Connect(packedNext, &routes[1], -1, direction);

				routes[0].packed    = packedCur;
				routes[0].score     = 0;
				routes[0].routeSize = 0;
				routes[0].buffer    = routesBuffer[1];
				foundClockwise = Script_Unit_Pathfinder_Connect(packedNext, &routes[0], 1, direction);

				if (foundCounterclockwise || foundClockwise) break;

				do {
					if (packedNext == packedDst) break;

					dir = Tile_GetDirectionPacked(packedNext, packedDst) / 32;
					packedNext += s_mapDirection[dir];
				} while (Script_Unit_Pathfind_GetScore(packedNext, dir) <= 255);
			}

			if (foundCounterclockwise || foundClockwise) {
				/* Find the best (partial) route */
				if (!foundClockwise) {
					bestRoute = &routes[1];
				} else if (!foundCounterclockwise) {
					bestRoute = &routes[0];
				} else {
					bestRoute = &routes[routes[1].score < routes[0].score ? 1 : 0];
				}

				/* Calculate how much more we can copy into our own buffer */
				routeSize = min(bufferSize - res.routeSize, bestRoute->routeSize);
				if (routeSize <= 0) break;

				/* Copy the rest into our own buffer */
				memcpy(&res.buffer[res.routeSize], bestRoute->buffer, routeSize);
				res.routeSize += routeSize;
				res.score     += bestRoute->score;
			} else {
				/* Means we didn't find a route. packedNext is now equal to packedDst */
				break;
			}
		}

		packedCur = packedNext;
	}

	if (res.routeSize < bufferSize) res.buffer[res.routeSize++] = 0xFF;

	Script_Unit_Pathfinder_Smoothen(&res);

	return res;
}