Ejemplo n.º 1
0
static void Grid_SetMoveData (pathing_t *path, const pos3_t toPos, const int c, const byte length, const int dir, const int oz, const int oc, priorityQueue_t *pqueue)
{
	pos4_t dummy;

	RT_AREA_TEST_POS(path, toPos, c);
	RT_AREA_POS(path, toPos, c) = length;	/**< Store TUs for this square. */
	RT_AREA_FROM_POS(path, toPos, c) = makeDV(dir, oz); /**< Store origination information for this square. */

	Vector4Set(dummy, toPos[0], toPos[1], toPos[2], c);
	/** @todo add heuristic for A* algorithm */
	PQueuePush(pqueue, dummy, length);
}
Ejemplo n.º 2
0
/**
 * @brief Tries to find a path from the given actor(-position) to a given target position
 *
 * Unlike Grid_CalcPathing, this function does not neccessarily calculate the TU values for
 * all positions reachable from 'from'. Instead it tries to find the shortest/fastest path to
 * the target position. There is no limit to maxTUs.
 *
 * @param[in] routing Reference to client or server side routing table (clMap, svMap)
 * @param[in] actorSize The size of thing to calc the move for (e.g. size=2 means 2x2).
 * The plan is to have the 'origin' in 2x2 units in the bottom-left (towards the lower coordinates) corner of the 2x2 square.
 * @param[in,out] path Pointer to client or server side pathing table (clMap, svMap)
 * @param[in] from The position to start the calculation from.
 * @param[in] targetPos The position where we want to end up.
 * @param[in] maxTUs The maximum TUs away from 'from' to calculate move-information for
 * @param[in] crouchingState Whether the actor is currently crouching, 1 is yes, 0 is no.
 * @param[in] fb_list Forbidden list (entities are standing at those points)
 * @param[in] fb_length Length of forbidden list
 * @sa G_MoveCalc
 * @sa CL_ConditionalMoveCalc
 */
bool Grid_FindPath (const Routing &routing, const actorSizeEnum_t actorSize, pathing_t *path, const pos3_t from, const pos3_t targetPos, byte crouchingState, int maxTUs, byte ** fb_list, int fb_length)
{
	bool found = false;
	int count;
	priorityQueue_t pqueue;
	pos4_t epos; /**< Extended position; includes crouching state */
	pos3_t pos;
	/* this is the position of the current actor- so the actor can stand in the cell it is in when pathfinding */
	pos3_t excludeFromForbiddenList;

	/* Confirm bounds */
	assert((from[2]) < PATHFINDING_HEIGHT);
	assert(crouchingState == 0 || crouchingState == 1);	/* s.a. ACTOR_MAX_STATES */

	/* reset move data */
	OBJSET(path->area,     ROUTING_NOT_REACHABLE);
	OBJSET(path->areaFrom, ROUTING_NOT_REACHABLE);
	path->fblist = fb_list;
	path->fblength = fb_length;

	/* Prepare exclusion of starting-location (i.e. this should be ent-pos or le-pos) in Grid_CheckForbidden */
	VectorCopy(from, excludeFromForbiddenList);
	/* set starting position to 0 TUs.*/
	RT_AREA_POS(path, from, crouchingState) = 0;

	PQueueInitialise(&pqueue, 1024);
	Vector4Set(epos, from[0], from[1], from[2], crouchingState);
	PQueuePush(&pqueue, epos, 0);

	count = 0;
	while (!PQueueIsEmpty(&pqueue)) {
		PQueuePop(&pqueue, epos);
		VectorCopy(epos, pos);
		count++;

		/* if reaching that square already took too many TUs,
		 * don't bother to reach new squares *from* there. */
		const byte usedTUs = RT_AREA_POS(path, pos, crouchingState);
		if (usedTUs >= maxTUs)
			continue;

		for (int dir = 0; dir < PATHFINDING_DIRECTIONS; dir++) {
			Step step(routing, pos, actorSize, crouchingState, dir);
			/* Directions 12, 14, and 15 are currently undefined. */
			if (dir == 12 || dir == 14 || dir == 15)
				continue;
			/* If this is a crouching or crouching move, forget it. */
			if (dir == DIRECTION_STAND_UP || dir == DIRECTION_CROUCH)
				continue;

			if (!step.init())
				continue;		/* either dir is irrelevant or something worse happened */

			if (!step.isPossible(path))
				continue;

			/* Is this a better move into this cell? */
			RT_AREA_TEST_POS(path, step.toPos, step.crouchingState);
			if (RT_AREA_POS(path, step.toPos, step.crouchingState) <= step.TUsAfter) {
				continue;	/* This move is not optimum. */
			}

			/* Test for forbidden (by other entities) areas. */
			/* Do NOT check the forbiddenList. We might find a multi-turn path. */
#if 0
			if (Grid_CheckForbidden(excludeFromForbiddenList, step.actorSize, path, step.toPos[0], step.toPos[1], step.toPos[2])) {
				continue;		/* That spot is occupied. */
			}
#endif

			/* Store move in pathing table. */
			Grid_SetMoveData(path, step.toPos, step.crouchingState, step.TUsAfter, step.dir, step.fromPos[2]);

			pos4_t dummy;
			const int dist = step.TUsAfter + (int) (2 * VectorDist(step.toPos, targetPos));
			Vector4Set(dummy, step.toPos[0], step.toPos[1], step.toPos[2], step.crouchingState);
			PQueuePush(&pqueue, dummy, dist);

			if (VectorEqual(step.toPos, targetPos)) {
				found = true;
				break;
			}
		}
		if (found)
			break;
	}
	/* Com_Printf("Loop: %i", count); */
	PQueueFree(&pqueue);
	return found;
}
Ejemplo n.º 3
0
/**
 * @brief Recalculate the pathing table for the given actor(-position)
 *
 * We calculate the table for ALL possible movement states (atm stand and crouch)
 * to be able to propose smart things like autostand.
 * @param[in] routing Reference to client or server side routing table (clMap, svMap)
 * @param[in] actorSize The size of thing to calc the move for (e.g. size=2 means 2x2).
 * The plan is to have the 'origin' in 2x2 units in the bottom-left (towards the lower coordinates) corner of the 2x2 square.
 * @param[in,out] path Pointer to client or server side pathing table (clMap, svMap)
 * @param[in] from The position to start the calculation from.
 * @param[in] maxTUs The maximum TUs away from 'from' to calculate move-information for
 * @param[in] fb_list Forbidden list (entities are standing at those points)
 * @param[in] fb_length Length of forbidden list
 * @sa G_MoveCalc
 * @sa CL_ConditionalMoveCalc
 */
void Grid_CalcPathing (const Routing &routing, const actorSizeEnum_t actorSize, pathing_t *path, const pos3_t from, int maxTUs, byte ** fb_list, int fb_length)
{
	priorityQueue_t pqueue;
	pos4_t epos; /**< Extended position; includes crouching state */
	pos3_t pos;
	int amst; /* acronym for actor movement state */
	/* this is the position of the current actor- so the actor can stand in the cell it is in when pathfinding */
	pos3_t excludeFromForbiddenList;

	/* Confirm bounds */
	assert((from[2]) < PATHFINDING_HEIGHT);

	/* reset move data */
	OBJSET(path->area,     ROUTING_NOT_REACHABLE);
	OBJSET(path->areaFrom, ROUTING_NOT_REACHABLE);
	path->fblist = fb_list;
	path->fblength = fb_length;

	maxTUs = std::min(maxTUs, MAX_ROUTE_TUS);

	/* Prepare exclusion of starting-location (i.e. this should be ent-pos or le-pos) in Grid_CheckForbidden */
	VectorCopy(from, excludeFromForbiddenList);

	for (amst = 0; amst < ACTOR_MAX_STATES; amst++) {
		/* set starting position to 0 TUs.*/
		RT_AREA_POS(path, from, amst) = 0;

		PQueueInitialise(&pqueue, 1024);
		Vector4Set(epos, from[0], from[1], from[2], amst);
		PQueuePush(&pqueue, epos, 0);

		int count = 0;
		while (!PQueueIsEmpty(&pqueue)) {
			int dir;
			PQueuePop(&pqueue, epos);
			VectorCopy(epos, pos);
			count++;

			/* if reaching that square already took too many TUs,
			 * don't bother to reach new squares *from* there. */
			const byte usedTUs = RT_AREA_POS(path, pos, amst);
			if (usedTUs >= maxTUs)
				continue;

			for (dir = 0; dir < PATHFINDING_DIRECTIONS; ++dir) {
				Step step(routing, pos, actorSize, amst, dir);
				/* Directions 12, 14, and 15 are currently undefined. */
				if (dir == 12 || dir == 14 || dir == 15)
					continue;
				/* If this is a crouching or crouching move, forget it. */
				if (dir == DIRECTION_STAND_UP || dir == DIRECTION_CROUCH)
					continue;

				if (!step.init())
					continue; /* either dir is irrelevant or something worse happened */

				if (step.isPossible(path)) {
					/* Is this a better move into this cell? */
					RT_AREA_TEST_POS(path, step.toPos, step.crouchingState);
					if (RT_AREA_POS(path, step.toPos, step.crouchingState) <= step.TUsAfter) {
						continue; /* This move is not optimum. */
					}

					/* Test for forbidden (by other entities) areas. */
					if (Grid_CheckForbidden(excludeFromForbiddenList, step.actorSize, path, step.toPos[0],
							step.toPos[1], step.toPos[2])) {
						continue; /* That spot is occupied. */
					}

					/* Store move in pathing table. */
					Grid_SetMoveData(path, step.toPos, step.crouchingState, step.TUsAfter, step.dir, step.fromPos[2]);

					pos4_t dummy;
					Vector4Set(dummy, step.toPos[0], step.toPos[1], step.toPos[2], step.crouchingState);
					PQueuePush(&pqueue, dummy, step.TUsAfter);
				}
			}
		}
		/* Com_Printf("Loop: %i", count); */
		PQueueFree(&pqueue);
	}
}
Ejemplo n.º 4
0
static void Grid_SetMoveData (pathing_t *path, const pos3_t toPos, const int crouch, const byte length, const int dir, const int oldZ)
{
	RT_AREA_TEST_POS(path, toPos, crouch);
	RT_AREA_POS(path, toPos, crouch) = length;	/**< Store TUs for this square. */
	RT_AREA_FROM_POS(path, toPos, crouch) = makeDV(dir, oldZ); /**< Store origination information for this square. */
}
Ejemplo n.º 5
0
/**
 * @param[in] map Pointer to client or server side routing table (clMap, svMap)
 * @param[in] exclude Exclude this position from the forbidden list check
 * @param[in] actorSize Give the field size of the actor (e.g. for 2x2 units) to check linked fields as well.
 * @param[in,out] path Pointer to client or server side pathing table (clMap, svMap)
 * @param[in] pos Current location in the map.
 * @param[in] crouchingState Whether the actor is currently crouching, 1 is yes, 0 is no.
 * @param[in] dir Direction vector index (see DIRECTIONS and dvecs)
 * @param[in,out] pqueue Priority queue (heap) to insert the now reached tiles for reconsidering
 * @sa Grid_CheckForbidden
 */
static void Grid_MoveMark (const routing_t *map, const pos3_t exclude, const actorSizeEnum_t actorSize, pathing_t *path, const pos3_t pos, byte crouchingState, const int dir, priorityQueue_t *pqueue)
{
	step_t step_;
	step_t *step = &step_;	/* temporary solution */
	pos3_t toPos;
	byte TUsSoFar, TUsForMove, TUsAfter;

	if (!Grid_StepInit(step, map, actorSize, crouchingState, dir))
		return;		/* either dir is irrelevant or something worse happened */

	TUsSoFar = RT_AREA_POS(path, pos, crouchingState);
	/* Find the number of TUs used (normally) to move in this direction. */
	TUsForMove = Grid_GetTUsForDirection(dir, crouchingState);

	/* calculate the position we would normally end up if moving in the given dir. */
	if (!Grid_StepCalcNewPos(step, pos, toPos, dir)) {
		return;
	}
	/* If there is no passageway (or rather lack of a wall) to the desired cell, then return. */
	/* If the flier is moving up or down diagonally, then passage height will also adjust */
	if (dir >= FLYING_DIRECTIONS) {
		if (!Grid_StepCheckFlyingDirections(step, pos, toPos, dir)) {
			return;
		}
	} else if (dir < CORE_DIRECTIONS) {
		/** note that this function may modify toPos ! */
		if (!Grid_StepCheckWalkingDirections(step, path, pos, toPos, dir, crouchingState)) {
			return;
		}
	} else {
		/* else there is no movement that uses passages. */
		/* If we are falling, the height difference is the floor value. */
		if (!Grid_StepCheckVerticalDirections(step, pos, dir)) {
			return;
		}
	}

	/* OK, at this point we are certain of a few things:
	 * There is not a wall obstructing access to the destination cell.
	 * If the actor is not a flier, the actor will not rise more than actor_stepup_height or fall more than
	 *    falling_height, unless climbing.
	 *
	 * If the actor is a flier, as long as there is a passage, it can be moved through.
	 * There are no floor difference restrictions for fliers, only obstructions. */

	/* nz can't move out of bounds */
	if (toPos[2] >= PATHFINDING_HEIGHT)
		toPos[2] = PATHFINDING_HEIGHT - 1;

	/* Now add the TUs needed to get to the originating cell. */
	TUsAfter = TUsSoFar + TUsForMove;

	/* Is this a better move into this cell? */
	RT_AREA_TEST_POS(path, toPos, crouchingState);
	if (RT_AREA_POS(path, toPos, crouchingState) <= TUsAfter) {
		return;	/* This move is not optimum. */
	}

	/* Test for forbidden (by other entities) areas. */
	if (Grid_CheckForbidden(exclude, actorSize, path, toPos[0], toPos[1], toPos[2])) {
		return;		/* That spot is occupied. */
	}

	/* Store move. */
	if (pqueue) {
		Grid_SetMoveData(path, toPos, crouchingState, TUsAfter, dir, pos[2], crouchingState, pqueue);
	}
}