int fc_solve_PQueuePop( PQUEUE *pq, fcs_state_extra_info_t * * val) { int32 i; int32 child; pq_element_t * Elements = pq->Elements; int32 CurrentSize = pq->CurrentSize; pq_element_t pMaxElement; pq_element_t pLastElement; if( PQueueIsEmpty( pq ) ) { *val = NULL; return 1; } pMaxElement = Elements[PQ_FIRST_ENTRY]; /* get pointer to last element in tree */ pLastElement = Elements[ CurrentSize-- ]; { /* code to pop an element from an ascending (top to bottom) pqueue */ /* UNTESTED */ for( i=PQ_FIRST_ENTRY; (child = PQ_LEFT_CHILD_INDEX(i)) <= CurrentSize; i=child ) { /* set child to the smaller of the two children... */ if( (child != CurrentSize) && (PGetRating(Elements[child + 1]) > PGetRating(Elements[child])) ) { child ++; } if( PGetRating( pLastElement ) < PGetRating( Elements[ child ] ) ) { Elements[ i ] = Elements[ child ]; } else { break; } } } Elements[i] = pLastElement; pq->CurrentSize = CurrentSize; *val = pMaxElement.val; return 0; }
static void ip_noise_delayer_check_pq(ip_noise_delayer_t * delayer) { ip_noise_delayer_pq_element_t current_time_pseudo_msg; #ifndef __KERNEL__ ip_noise_delayer_pq_element_t * msg; #else ip_noise_delayer_pq_element_t msg; #endif #ifndef __KERNEL__ gettimeofday(&(current_time_pseudo_msg.tv), &tz); #else current_time_pseudo_msg.tv = jiffies; #endif while (!PQueueIsEmpty(&(delayer->pq))) { /* See if the message should have been sent by now. */ msg = PQueuePeekMinimum(&(delayer->pq)); #ifndef __KERNEL__ if (msg == NULL) #else if (msg.tv == 0) #endif { break; } if (ip_noise_timeval_cmp(msg, current_time_pseudo_msg, NULL) <= 0) { delayer->release_callback(&(msg.m), delayer->release_callback_context); PQueuePop(&(delayer->pq)); #ifndef __KERNEL__ free(msg) #endif } else { break;
/** * @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; }
/** * @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); } }
/** * @brief Recalculate the pathing table for the given actor(-position) * @param[in] map Pointer 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] distance 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 Grid_MoveMark * @sa G_MoveCalc * @sa CL_ConditionalMoveCalc */ void Grid_MoveCalc (const routing_t *map, const actorSizeEnum_t actorSize, pathing_t *path, const pos3_t from, byte crouchingState, int distance, byte ** fb_list, int fb_length) { int dir; 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; /* reset move data */ OBJSET(path->area, ROUTING_NOT_REACHABLE); OBJSET(path->areaFrom, ROUTING_NOT_REACHABLE); path->fblist = fb_list; path->fblength = fb_length; if (distance > MAX_ROUTE + 3) /* +3 is added to calc at least one square (diagonal) more */ distance = MAX_ROUTE + 3; /* and later show one step beyond the walkable path in red */ /* Prepare exclusion of starting-location (i.e. this should be ent-pos or le-pos) in Grid_CheckForbidden */ VectorCopy(from, excludeFromForbiddenList); PQueueInitialise(&pqueue, 1024); Vector4Set(epos, from[0], from[1], from[2], crouchingState); PQueuePush(&pqueue, epos, 0); /* Confirm bounds */ assert((from[2]) < PATHFINDING_HEIGHT); assert(crouchingState == 0 || crouchingState == 1); /* s.a. ACTOR_MAX_STATES */ /* set starting position to 0 TUs.*/ RT_AREA_POS(path, from, crouchingState) = 0; Com_DPrintf(DEBUG_PATHING, "Grid_MoveCalc: Start at (%i %i %i) c:%i\n", from[0], from[1], from[2], crouchingState); count = 0; while (!PQueueIsEmpty(&pqueue)) { byte TUsSoFar; 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. */ TUsSoFar = RT_AREA_POS(path, pos, crouchingState); if (TUsSoFar >= distance || TUsSoFar >= MAX_MOVELENGTH) continue; for (dir = 0; dir < PATHFINDING_DIRECTIONS; 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; Grid_MoveMark(map, excludeFromForbiddenList, actorSize, path, pos, epos[3], dir, &pqueue); } } /* Com_Printf("Loop: %i", count); */ PQueueFree(&pqueue); Com_DPrintf(DEBUG_PATHING, "Grid_MoveCalc: Done\n\n"); }
pq_element_t PQueuePop( PQUEUE *pq) { int32 i; int32 child; pq_element_t pMaxElement; pq_element_t pLastElement; if( PQueueIsEmpty( pq ) ) { #ifndef __KERNEL__ return NULL; #else pq_element_t ret; ret.tv = 0; return ret; #endif } pMaxElement = pq->Elements[PQ_FIRST_ENTRY]; /* get pointer to last element in tree */ pLastElement = pq->Elements[ pq->CurrentSize-- ]; if( pq->IsAscendingHeap == TRUE ) { /* code to pop an element from an ascending (top to bottom) pqueue */ /* UNTESTED */ for( i=PQ_FIRST_ENTRY; PQ_LEFT_CHILD_INDEX(i) <= pq->CurrentSize; i=child ) { /* set child to the smaller of the two children... */ child = PQ_LEFT_CHILD_INDEX(i); if( (child != pq->CurrentSize) && /*(PGetRating(pq->Elements[child + 1]) > PGetRating(pq->Elements[child])) )*/ (pq->cmp(pq->Elements[child + 1], pq->Elements[child], pq->context) > 0) ) { child ++; } if( /*PGetRating( pLastElement ) < PGetRating( pq->Elements[ child ] ) */ pq->cmp(pLastElement, pq->Elements[child], pq->context) < 0 ) { pq->Elements[ i ] = pq->Elements[ child ]; } else { break; } } } else { /* code to pop an element from a descending (top to bottom) pqueue */ for( i=PQ_FIRST_ENTRY; PQ_LEFT_CHILD_INDEX(i) <= pq->CurrentSize; i=child ) { /* set child to the larger of the two children... */ child = PQ_LEFT_CHILD_INDEX(i); if( (child != pq->CurrentSize) && /*(PGetRating(pq->Elements[child + 1]) < PGetRating(pq->Elements[child])) */ pq->cmp(pq->Elements[child + 1], pq->Elements[child], pq->context) < 0 ) { child ++; } if( /*PGetRating( pLastElement ) > PGetRating( pq->Elements[ child ] ) */ pq->cmp(pLastElement, pq->Elements[child], pq->context) > 0 ) { pq->Elements[ i ] = pq->Elements[ child ]; } else { break; } } } pq->Elements[i] = pLastElement; return pMaxElement; }