void BuildingPrefecture::deliverService() { if( getWorkers() > 0 && getWalkerList().size() == 0 ) { bool fireDetect = _fireDetect.getI() >= 0; WalkerPrefectPtr walker = WalkerPrefect::create( Scenario::instance().getCity() ); walker->setMaxDistance( 26 ); //bool patrol = true; if( fireDetect ) { PathWay pathway; TilePos startPos = _accessRoads.front()->getIJ(); bool pathFounded = Pathfinder::getInstance().getPath( startPos, _fireDetect, pathway, false, Size( 0 ) ); //patrol = !pathFounded; if( pathFounded ) { walker->setPathWay( pathway ); walker->setIJ( pathway.getOrigin().getIJ() ); } _fireDetect = TilePos( -1, -1 ); } walker->send2City( BuildingPrefecturePtr( this ), fireDetect ? 200 : 0 ); addWalker( walker.as<Walker>() ); } }
float ServiceWalker::evaluatePath(PathWay &pathWay) { // evaluate all buildings along the path std::set<Building*> doneBuildings; // list of evaluated building: don't do them again std::list<Tile*>& pathTileList = pathWay.getAllTiles(); int distance = 0; float res = 0.0; for (std::list<Tile*>::iterator itTile = pathTileList.begin(); itTile != pathTileList.end(); ++itTile) { Tile &tile = **itTile; std::set<Building*> reachedBuildings = getReachedBuildings(tile.getI(), tile.getJ()); for (std::set<Building*>::iterator itBuilding = reachedBuildings.begin(); itBuilding != reachedBuildings.end(); ++itBuilding) { Building& building = **itBuilding; std::pair<std::set<Building*>::iterator, bool> rc = doneBuildings.insert(&building); if (rc.second == true) { // the building has not been evaluated yet res = res + building.evaluateService(*this); } } distance++; } // std::cout << "evaluate path "; // pathWay.prettyPrint(); // std::cout << " = " << res << std::endl; return res; }
void WalkerPrefect::_checkPath2NearestFire( const ReachedBuildings& buildings ) { PathWay bestPath; int minLength = 9999; foreach( BuildingPtr building, buildings ) { if( building->getType() != B_BURNING_RUINS ) continue; PathWay tmp; bool foundPath = Pathfinder::getInstance().getPath( getIJ(), building->getTile().getIJ(), tmp, false, Size( 0 ) ); if( foundPath && tmp.getLength() < minLength ) { bestPath = tmp; minLength = tmp.getLength(); if( tmp.getLength() == 1 ) break; } } if( bestPath.getLength() > 0 ) { setPathWay( bestPath ); //_pathWay.begin(); } }
void WalkerPrefect::_checkPath2NearestFire( const ReachedBuildings& buildings ) { PathWay bestPath; int minLength = 9999; for( ReachedBuildings::const_iterator itBuilding = buildings.begin(); itBuilding != buildings.end(); ++itBuilding) { if( (*itBuilding)->getType() != B_BURNING_RUINS ) continue; PathWay tmp; bool foundPath = Pathfinder::getInstance().getPath( getIJ(), (*itBuilding)->getTile().getIJ(), tmp, false, Size( 0 ) ); if( foundPath && tmp.getLength() < minLength ) { bestPath = tmp; minLength = tmp.getLength(); if( tmp.getLength() == 1 ) break; } } if( bestPath.getLength() > 0 ) { _pathWay = bestPath; _pathWay.begin(); } }
void ServiceWalker::reservePath(PathWay &pathWay) { // reserve all buildings along the path std::set<Building*> doneBuildings; // list of evaluated building: don't do them again std::list<Tile*>& pathTileList = pathWay.getAllTiles(); for (std::list<Tile*>::iterator itTile = pathTileList.begin(); itTile != pathTileList.end(); ++itTile) { Tile &tile = **itTile; std::set<Building*> reachedBuildings = getReachedBuildings(tile.getI(), tile.getJ()); for (std::set<Building*>::iterator itBuilding = reachedBuildings.begin(); itBuilding != reachedBuildings.end(); ++itBuilding) { Building &building = **itBuilding; std::pair<std::set<Building*>::iterator, bool> rc = doneBuildings.insert(&building); if (rc.second == true) { // the building has not been reserved yet building.reserveService(_service); } } } }
bool Pathfinder::aStar( const TilePos& startPos, const TilePos& stopPos, const Size& arrivedArea, PathWay& oPathWay, int flags ) { oPathWay.init( *_tilemap, _tilemap->at( startPos ) ); // Define points to work with AStarPoint* start = getPoint( startPos ); AStarPoint* end = getPoint( stopPos ); AStarPoint* current; AStarPoint* child; // Define the open and the close list list<AStarPoint*> openList; list<AStarPoint*> closedList; list<AStarPoint*>::iterator i; int tSize = _tilemap->getSize(); map<AStarPoint*,AStarPoint::WalkableType> saveArrivedArea; TilePos arrivedAreaStart( math::clamp( stopPos.getI()-arrivedArea.getWidth(), 0, tSize ), math::clamp( stopPos.getJ()-arrivedArea.getHeight(), 0, tSize) ); TilePos arrivedAreaStop( math::clamp( stopPos.getI()+arrivedArea.getWidth(), 0, tSize ), math::clamp( stopPos.getJ()+arrivedArea.getHeight(), 0, tSize) ); for( int i=arrivedAreaStart.getI(); i <= arrivedAreaStop.getI(); i++ ) { for( int j=arrivedAreaStart.getJ(); j <= arrivedAreaStop.getJ(); j++ ) { AStarPoint* ap = getPoint( TilePos( i, j) ); if( ap ) { saveArrivedArea[ ap ] = ap->priorWalkable; ap->priorWalkable = AStarPoint::alwaysWalkable; } } } unsigned int n = 0; // Add the start point to the openList openList.push_back(start); start->opened = true; while (n == 0 || (current != end && n < getMaxLoopCount() )) { // Look for the smallest F value in the openList and make it the current point for (i = openList.begin(); i != openList.end(); ++ i) { if (i == openList.begin() || (*i)->getFScore() <= current->getFScore()) { current = (*i); } } // Stop if we reached the end if( current == end ) { break; } // Remove the current point from the openList openList.remove(current); current->opened = false; // Add the current point to the closedList closedList.push_back(current); current->closed = true; // Get all current's adjacent walkable points for (int x = -1; x < 2; x ++) { for (int y = -1; y < 2; y ++) { // If it's current point then pass if (x == 0 && y == 0) { continue; } // Get this point child = getPoint( current->getPos() + TilePos( x, y ) ); // If it's closed or not walkable then pass if (child->closed || !child->isWalkable() ) { continue; } // If we are at a corner if (x != 0 && y != 0) { // if the next horizontal point is not walkable or in the closed list then pass //AStarPoint* tmpPoint = getPoint( current->pos + TilePos( 0, y ) ); TilePos tmp = current->getPos() + TilePos( 0, y ); if( !pointIsWalkable( tmp ) || getPoint( tmp )->closed) { continue; } tmp = current->getPos() + TilePos( x, 0 ); // if the next vertical point is not walkable or in the closed list then pass if( !pointIsWalkable( tmp ) || getPoint( tmp )->closed) { continue; } } // If it's already in the openList if (child->opened) { // If it has a wroste g score than the one that pass through the current point // then its path is improved when it's parent is the current point if (child->getGScore() > child->getGScore(current)) { // Change its parent and g score child->setParent(current); child->computeScores(end); } } else { // Add it to the openList with current point as parent openList.push_back(child); child->opened = true; // Compute it's g, h and f score child->setParent(current); child->computeScores(end); } } } n++; } // Reset for (i = openList.begin(); i != openList.end(); ++ i) { (*i)->opened = false; } for (i = closedList.begin(); i != closedList.end(); ++ i) { (*i)->closed = false; } for( map<AStarPoint*,AStarPoint::WalkableType>::iterator it=saveArrivedArea.begin(); it != saveArrivedArea.end(); it++ ) { it->first->priorWalkable = it->second; } if( n == getMaxLoopCount() ) { return false; } // Resolve the path starting from the end point list<AStarPoint*> lPath; while( current->hasParent() && current != start ) { lPath.push_front( current ); current = current->getParent(); n++; } for( list<AStarPoint*>::iterator lpIt=lPath.begin(); lpIt != lPath.end(); lpIt++ ) { oPathWay.setNextTile( _tilemap->at( (*lpIt)->getPos() ) ); } return oPathWay.getLength() > 0; }