// Run only from path thread PATHRESULT fpathExecute(PATHJOB job) { PATHRESULT result; result.droidID = job.droidID; memset(&result.sMove, 0, sizeof(result.sMove)); result.retval = FPR_FAILED; result.originalDest = Vector2i(job.destX, job.destY); ASR_RETVAL retval = fpathAStarRoute(&result.sMove, &job); ASSERT(retval != ASR_OK || result.sMove.asPath, "Ok result but no path in result"); ASSERT(retval == ASR_FAILED || result.sMove.numPoints > 0, "Ok result but no length of path in result"); switch (retval) { case ASR_NEAREST: if (job.acceptNearest) { objTrace(job.droidID, "** Nearest route -- accepted **"); result.retval = FPR_OK; } else { objTrace(job.droidID, "** Nearest route -- rejected **"); result.retval = FPR_FAILED; } break; case ASR_FAILED: objTrace(job.droidID, "** Failed route **"); // Is this really a good idea? Was in original code. if (job.propulsion == PROPULSION_TYPE_LIFT && (job.droidType != DROID_TRANSPORTER && job.droidType != DROID_SUPERTRANSPORTER)) { objTrace(job.droidID, "Doing fallback for non-transport VTOL"); fpathSetMove(&result.sMove, job.destX, job.destY); result.retval = FPR_OK; } else { result.retval = FPR_FAILED; } break; case ASR_OK: objTrace(job.droidID, "Got route of length %d", result.sMove.numPoints); result.retval = FPR_OK; break; } return result; }
// Run only from path thread static void fpathExecute(PATHJOB *psJob, PATHRESULT *psResult) { ASR_RETVAL retval = fpathAStarRoute(&psResult->sMove, psJob); ASSERT(retval != ASR_OK || psResult->sMove.asPath, "Ok result but no path in result"); ASSERT(retval == ASR_FAILED || psResult->sMove.numPoints > 0, "Ok result but no length of path in result"); switch (retval) { case ASR_NEAREST: if (psJob->acceptNearest) { objTrace(psJob->droidID, "** Nearest route -- accepted **"); psResult->retval = FPR_OK; } else { objTrace(psJob->droidID, "** Nearest route -- rejected **"); psResult->retval = FPR_FAILED; } break; case ASR_FAILED: objTrace(psJob->droidID, "** Failed route **"); // Is this really a good idea? Was in original code. if (psJob->propulsion == PROPULSION_TYPE_LIFT && (psJob->droidType != DROID_TRANSPORTER && psJob->droidType != DROID_SUPERTRANSPORTER)) { objTrace(psJob->droidID, "Doing fallback for non-transport VTOL"); fpathSetMove(&psResult->sMove, psJob->destX, psJob->destY); psResult->retval = FPR_OK; } else { psResult->retval = FPR_FAILED; } break; case ASR_OK: objTrace(psJob->droidID, "Got route of length %d", psResult->sMove.numPoints); psResult->retval = FPR_OK; break; } }
void fpathTest(int x, int y, int x2, int y2) { MOVE_CONTROL sMove; FPATH_RETVAL r; int i; // On non-debug builds prevent warnings about defining but not using fpathJobQueueLength (void)fpathJobQueueLength; /* Check initial state */ assert(fpathThread != NULL); assert(fpathMutex != NULL); assert(fpathSemaphore != NULL); assert(pathJobs.empty()); assert(pathResults.empty()); fpathRemoveDroidData(0); // should not crash /* This should not leak memory */ sMove.asPath = NULL; for (i = 0; i < 100; i++) { fpathSetMove(&sMove, 1, 1); } free(sMove.asPath); sMove.asPath = NULL; /* Test one path */ sMove.Status = MOVEINACTIVE; r = fpathSimpleRoute(&sMove, 1, x, y, x2, y2); assert(r == FPR_WAIT); sMove.Status = MOVEWAITROUTE; assert(fpathJobQueueLength() == 1 || fpathResultQueueLength() == 1); fpathRemoveDroidData(2); // should not crash, nor remove our path assert(fpathJobQueueLength() == 1 || fpathResultQueueLength() == 1); while (fpathResultQueueLength() == 0) { wzYieldCurrentThread(); } assert(fpathJobQueueLength() == 0); assert(fpathResultQueueLength() == 1); r = fpathSimpleRoute(&sMove, 1, x, y, x2, y2); assert(r == FPR_OK); assert(sMove.numPoints > 0 && sMove.asPath); assert(sMove.asPath[sMove.numPoints - 1].x == x2); assert(sMove.asPath[sMove.numPoints - 1].y == y2); assert(fpathResultQueueLength() == 0); /* Let one hundred paths flower! */ sMove.Status = MOVEINACTIVE; for (i = 1; i <= 100; i++) { r = fpathSimpleRoute(&sMove, i, x, y, x2, y2); assert(r == FPR_WAIT); } while (fpathResultQueueLength() != 100) { wzYieldCurrentThread(); } assert(fpathJobQueueLength() == 0); for (i = 1; i <= 100; i++) { sMove.Status = MOVEWAITROUTE; r = fpathSimpleRoute(&sMove, i, x, y, x2, y2); assert(r == FPR_OK); assert(sMove.numPoints > 0 && sMove.asPath); assert(sMove.asPath[sMove.numPoints - 1].x == x2); assert(sMove.asPath[sMove.numPoints - 1].y == y2); } assert(fpathResultQueueLength() == 0); /* Kill a hundred flowers */ sMove.Status = MOVEINACTIVE; for (i = 1; i <= 100; i++) { r = fpathSimpleRoute(&sMove, i, x, y, x2, y2); assert(r == FPR_WAIT); } for (i = 1; i <= 100; i++) { fpathRemoveDroidData(i); } //assert(pathJobs.empty()); // can now be marked .deleted as well assert(pathResults.empty()); (void)r; // Squelch unused-but-set warning. }
void fpathSetDirectRoute(DROID *psDroid, SDWORD targetX, SDWORD targetY) { fpathSetMove(&psDroid->sMove, targetX, targetY); }