HAAStarResult RoutePlanner::setupHierarchicalOpenList(Unit *unit, const Vec2i &target) { // get Transitions for start cluster Transitions transitions; Vec2i startCluster = ClusterMap::cellToCluster(unit->getPos()); ClusterMap *clusterMap = world->getCartographer()->getClusterMap(); clusterMap->getTransitions(startCluster, unit->getCurrField(), transitions); DiagonalDistance dd(target); nsgSearchEngine->getNeighbourFunc().setSearchCluster(startCluster); bool startTrap = true; // attempt quick path from unit->pos to each transition, // if successful add transition to open list AnnotatedMap *aMap = world->getCartographer()->getMasterMap(); aMap->annotateLocal(unit); for (Transitions::iterator it = transitions.begin(); it != transitions.end(); ++it) { float cost = quickSearch(unit->getCurrField(), unit->getSize(), unit->getPos(), (*it)->nwPos); if (cost != numeric_limits<float>::infinity()) { tSearchEngine->setOpen(*it, dd((*it)->nwPos), cost); startTrap = false; } } aMap->clearLocalAnnotations(unit); if (startTrap) { // do again, without annnotations, return TRAPPED if all else goes well bool locked = true; for (Transitions::iterator it = transitions.begin(); it != transitions.end(); ++it) { float cost = quickSearch(unit->getCurrField(), unit->getSize(), unit->getPos(), (*it)->nwPos); if (cost != numeric_limits<float>::infinity()) { tSearchEngine->setOpen(*it, dd((*it)->nwPos), cost); locked = false; } } if (locked) { return HAAStarResult::FAILURE; } } if (startTrap) { return HAAStarResult::START_TRAP; } return HAAStarResult::COMPLETE; }
/** Determine legality of a proposed move for a unit. This function is the absolute last say * in such matters. * @param unit the unit attempting to move * @param pos2 the position unit desires to move to * @return true if move may proceed, false if not legal. */ bool RoutePlanner::isLegalMove(Unit *unit, const Vec2i &pos2) const { assert(world->getMap()->isInside(pos2)); assert(unit->getPos().dist(pos2) < 1.5); if (unit->getPos().dist(pos2) > 1.5) { unit->clearPath(); return false; } const Vec2i &pos1 = unit->getPos(); const int &size = unit->getSize(); const Field &field = unit->getCurrField(); Zone zone = field == Field::AIR ? Zone::AIR : Zone::LAND; AnnotatedMap *annotatedMap = world->getCartographer()->getMasterMap(); if (!annotatedMap->canOccupy(pos2, size, field)) { return false; // obstruction in field } if ( pos1.x != pos2.x && pos1.y != pos2.y ) { // Proposed move is diagonal, check if cells either 'side' are free. // eg.. XXXX // X1FX The Cells marked 'F' must both be free // XF2X for the move 1->2 to be legit // XXXX Vec2i diag1, diag2; getDiags(pos1, pos2, size, diag1, diag2); if (!annotatedMap->canOccupy(diag1, 1, field) || !annotatedMap->canOccupy(diag2, 1, field) || !world->getMap()->getCell(diag1)->isFree(zone) || !world->getMap()->getCell(diag2)->isFree(zone)) { return false; // obstruction, can not move to pos2 } } for (int i = pos2.x; i < unit->getSize() + pos2.x; ++i) { for (int j = pos2.y; j < unit->getSize() + pos2.y; ++j) { if (world->getMap()->getCell(i,j)->getUnit(zone) != unit && !world->getMap()->isFreeCell(Vec2i(i, j), field)) { return false; // blocked by another unit } } } // pos2 is free, and nothing is in the way return true; }
bool RoutePlanner::isLegalMove(Unit *unit, const Vec2i &pos2) const { assert(world->getMap()->isInside(pos2)); assert(unit->getPos().dist(pos2) < 1.5); if (unit->getPos().dist(pos2) > 1.5) { unit->clearPath(); return false; } const Vec2i &pos1 = unit->getPos(); const int &size = unit->getSize(); const Field &field = unit->getCurrField(); Zone zone; if (field == Field::AIR) { zone = Zone::AIR; } else if (field == Field::LAND) { zone = Zone::LAND; } else if (field == Field::WALL || field == Field::STAIR) { zone = Zone::WALL; } AnnotatedMap *annotatedMap = world->getCartographer()->getMasterMap(); if (!annotatedMap->canOccupy(pos2, size, field)) { return false; } if ( pos1.x != pos2.x && pos1.y != pos2.y ) { Vec2i diag1, diag2; getDiags(pos1, pos2, size, diag1, diag2); if (!annotatedMap->canOccupy(diag1, 1, field) || !annotatedMap->canOccupy(diag2, 1, field) || !world->getMap()->getCell(diag1)->isFree(zone) || !world->getMap()->getCell(diag2)->isFree(zone)) { return false; } } for (int i = pos2.x; i < unit->getSize() + pos2.x; ++i) { for (int j = pos2.y; j < unit->getSize() + pos2.y; ++j) { if (world->getMap()->getCell(i,j)->getUnit(zone) != unit && !world->getMap()->isFreeCell(Vec2i(i, j), field)) { return false; } } } return true; }