Pathway Emigrant::_findSomeWay( TilePos startPoint ) { HousePtr house = _findBlankHouse(); _d->failedWayCount++; Pathway pathway; if( house.isValid() ) { pathway = PathwayHelper::create( startPoint, house->pos(), PathwayHelper::roadFirst ); if( !pathway.isValid() ) { pathway = PathwayHelper::create( startPoint, ptr_cast<Construction>(house), PathwayHelper::roadFirst ); } if( pathway.isValid() ) { _lockHouse( house ); } } if( !pathway.isValid() || _d->failedWayCount > 10 ) { pathway = PathwayHelper::create( startPoint, _city()->borderInfo().roadExit, PathwayHelper::allTerrain ); } return pathway; }
void Wolf::_findNewWay( const TilePos& start ) { WalkerList walkers = _city()->statistic().walkers .find<Walker>( walker::any, config::distance::animalRandrom, start ) .exclude<Wolf>(); Pathway pathway; if( !walkers.empty() ) { WalkerPtr wlk = walkers.random(); pathway = PathwayHelper::create( start, wlk->pos(), PathwayHelper::allTerrain ); } if( !pathway.isValid() ) { pathway = PathwayHelper::randomWay( _city(), start, config::distance::animalRandrom ); } if( pathway.isValid() ) { setPos( start ); setPathway( pathway ); go(); } else { die(); } }
void Water::_updatePaths() { auto reservoir = _d->overlay.selected.as<Reservoir>(); if( reservoir.isValid() ) { _d->ways.clear(); PathwayCondition wayCondition; auto fountains = reservoir->aquifer().overlays<Fountain>(); for( auto fountain : fountains ) { Pathway pathway = PathwayHelper::create( reservoir->pos(), fountain->pos(), wayCondition.bySomething(), Pathway::fourDirection ); if( pathway.isValid() ) _d->ways.push_back( { pathway.allTiles(), ColorList::red } ); } } auto fountain = _d->overlay.underMouse.as<Fountain>(); if( fountain.isValid() ) { _d->ways.clear(); PathwayCondition wayCondition; auto reservoirs = _map().rect( 10, fountain->pos() ).overlays<Reservoir>(); for( auto reservoir : reservoirs ) { Pathway pathway = PathwayHelper::create( reservoir->pos(), fountain->pos(), wayCondition.bySomething() ); if( pathway.isValid() ) _d->ways.push_back( { pathway.allTiles(), ColorList::blue } ); } } }
inline Pathway Statistic::_Walkers::freeTile( TilePos target, TilePos currentPos, const int range ) const { for( int currentRange=1; currentRange <= range; currentRange++ ) { TilePos offset( currentRange, currentRange ); gfx::TilesArray tiles = _parent.map.perimetr( currentPos - offset, currentPos + offset ); tiles = tiles.walkables( true ); float crntDistance = target.distanceFrom( currentPos ); for( auto tile : tiles ) { SmartList<T> eslist = _parent.rcity.walkers( tile->pos() ).select<T>(); if( !eslist.empty() ) continue; if( target.distanceFrom( tile->pos() ) > crntDistance ) continue; Pathway pathway = PathwayHelper::create( currentPos, tile->pos(), PathwayHelper::allTerrain ); if( pathway.isValid() ) { return pathway; } } } return Pathway(); }
Pathway findWay( const TilesArray& startTiles, const TilesArray& arrivedTiles ) { if( arrivedTiles.empty() || startTiles.empty() ) return Pathway(); Pathfinder& pathfinder = Pathfinder::instance(); unsigned int mainLimiter = 10; unsigned int stTileLimiter = startTiles.size() > mainLimiter ? startTiles.size() / mainLimiter : 1; for( unsigned int tileIndex = 0; tileIndex < startTiles.size(); tileIndex += stTileLimiter ) { Tile* rtile = startTiles[ tileIndex ]; unsigned int arvTileLimiter = arrivedTiles.size() > mainLimiter ? arrivedTiles.size() / mainLimiter : 1; for( unsigned int arvTileIndex=0; arvTileIndex < arrivedTiles.size(); arvTileIndex += arvTileLimiter ) { Tile* endTile = arrivedTiles[ arvTileIndex ]; Pathway way = pathfinder.getPath( *rtile, *endTile, Pathfinder::customCondition | Pathfinder::fourDirection ); if( way.isValid() ) return way; } } return Pathway(); }
void EnemySoldier::_check4attack() { //try find any walkers in range Pathway pathway = _findPathway2NearestEnemy( 10 ); if( !pathway.isValid() ) { int size = _city()->tilemap().size(); pathway = _findPathway2NearestConstruction( size/2 ); } if( !pathway.isValid() ) { pathway = PathwayHelper::create( pos(), _city()->borderInfo().roadExit, PathwayHelper::allTerrain ); setTarget( TilePos( -1, -1) ); } if( !pathway.isValid() ) { pathway = PathwayHelper::randomWay( _city(), pos(), 10 ); setTarget( TilePos( -1, -1) ); _failedWayCounter++; } if( _failedWayCounter > 4 ) { pathway = Pathway(); } if( pathway.isValid() ) { _setSubAction( target().i() >= 0 ? go2enemy : go2position ); _updatePathway( pathway ); go(); } else { //impossible state, but... Logger::warning( "EnemySoldier: can't find any path" ); die(); } }
void RomeSoldier::_duckout() { Pathway way = PathwayHelper::way2border( _city(), pos() ); if( !way.isValid() ) { way = PathwayHelper::randomWay( _city(), pos(), maxDistanceFromBase ); } if( way.isValid() ) { _setSubAction( duckout ); setPathway( way ); go(); } else { die(); } }
void RomeSoldier::send2expedition(const std::string& name) { _d->expedition = name; TilePos cityEnter = _city()->borderInfo().roadEntry; Pathway way = PathwayHelper::create( pos(), cityEnter, PathwayHelper::allTerrain ); if( way.isValid() ) { setPathway( way ); _setSubAction( (SldrAction)expedition ); go(); } }
void Emigrant::_reachedPathway() { bool gooutCity = true; Walker::_reachedPathway(); if( pos() == _city()->borderInfo().roadExit ) { city::MigrationPtr migration; migration << _city()->findService( city::Migration::defaultName() ); if( migration.isValid() ) { migration->citizenLeaveCity( this ); } deleteLater(); return; } HousePtr house = ptr_cast<House>( _city()->getOverlay( pos() ) ); if( house.isValid() ) { _append2house( house ); gooutCity = (_d->peoples.count() > 0); } else { if( _checkNearestHouse() ) { return; } } if( gooutCity ) { Pathway way = _findSomeWay( pos() ); if( way.isValid() ) { _updatePathway( way ); go(); } else { die(); } } else { deleteLater(); } }
void Animal::_findNewWay( const TilePos& start ) { Pathway pathway = PathwayHelper::randomWay( _city(), start, config::distance::animalRandrom ); if( pathway.isValid() ) { setPos( start ); setPathway( pathway ); go(); } else { die(); } }
void Patrician::_findNewWay( const TilePos& start ) { Pathway pathway = PathwayHelper::randomWay( _getCity(), start, 10 ); if( pathway.isValid() ) { setPathway( pathway ); setIJ( start ); go(); } else { die(); } }
Pathway EnemySoldier::_findPathway2NearestEnemy( unsigned int range ) { Pathway ret; WalkerList walkers = _findEnemiesInRange( range ); for( auto wlk : walkers) { ret = PathwayHelper::create( pos(), wlk->pos(), PathwayHelper::allTerrain ); if( ret.isValid() ) { return ret; } } return Pathway(); }
void CartPusher::_brokePathway(TilePos pos) { _d->brokePathCounter++; if( _pathway().isValid() && _d->brokePathCounter < 5 ) { Pathway way = PathwayHelper::create( pos, _pathway().stopPos(), PathwayHelper::roadFirst ); if( way.isValid() ) { setPathway( way ); go(); return; } } Logger::warning( "CartPusher::_brokePathway not destination point [%d,%d]", pos.i(), pos.j() ); deleteLater(); }
Pathway ChastenerElephant::_findPathway2NearestConstruction( unsigned int range ) { Pathway ret; for( unsigned int tmpRange=1; tmpRange <= range; tmpRange++ ) { ConstructionList constructions = _findContructionsInRange( tmpRange ); foreach( it, constructions ) { ConstructionPtr c = ptr_cast<Construction>( *it ); ret = PathwayHelper::create( pos(), c->pos(), makeDelegate( _d.data(), &Impl::mayMove ) ); if( ret.isValid() ) { return ret; } } }
void Mugger::timeStep(const unsigned long time) { Walker::timeStep( time ); switch( _d->state ) { case Impl::searchHouse: { city::Helper helper( _city() ); TilePos offset(10, 10); HouseList houses = helper.find<House>( objects::house, pos() - offset, pos() + offset ); std::map< int, HouseList > houseEpxens; foreach( it, houses ) { int money = (*it)->getServiceValue( Service::forum ); houseEpxens[ money ] << *it; } for( std::map< int, HouseList >::reverse_iterator expHList = houseEpxens.rbegin(); expHList != houseEpxens.rend(); ++expHList ) { HouseList& hlist = expHList->second; foreach( hIt, hlist ) { Pathway pathway = PathwayHelper::create( pos(), ptr_cast<Construction>( *hIt ), PathwayHelper::allTerrain ); //find path to most expensive house, fire this!!! if( pathway.isValid() ) { setPos( pathway.startPos() ); setPathway( pathway ); go(); _d->state = Impl::go2destination; break; } } _d->state = Impl::go2anyplace; } }
Pathway RomeSoldier::_findPathway2NearestEnemy( unsigned int range ) { Pathway ret; for( unsigned int tmpRange=1; tmpRange <= range; tmpRange++ ) { WalkerList walkers = _findEnemiesInRange( tmpRange ); for( auto w : walkers) { ret = PathwayHelper::create( pos(), w->pos(), PathwayHelper::allTerrain ); if( ret.isValid() ) { return ret; } } } return Pathway(); }
void RomeSoldier::_back2base() { FortPtr b = base(); if( b.isValid() ) { Pathway way = PathwayHelper::create( pos(), b->freeSlot( this ), PathwayHelper::allTerrain ); if( way.isValid() ) { setPathway( way ); _setSubAction( go2position ); go(); return; } } else { die(); } }
Pathway ChastenerElephant::_findPathway2NearestConstruction( unsigned int range ) { Pathway ret; ElephantWayCondition condition; for( unsigned int tmpRange=1; tmpRange <= range; tmpRange++ ) { ConstructionList constructions = _findContructionsInRange( tmpRange ); for( auto construction : constructions ) { ret = PathwayHelper::create( pos(), construction->pos(), condition.mayMove() ); if( ret.isValid() ) { return ret; } } } return Pathway(); }
void WallGuard::_brokePathway(TilePos p) { Soldier::_brokePathway( p ); if( _d->patrolPosition.i() >= 0 ) { Pathway way = PathwayHelper::create( pos(), _d->patrolPosition, PathwayHelper::allTerrain ); if( way.isValid() ) { setPathway( way ); go(); } else { _setSubAction( patrol ); setPathway( Pathway() ); wait( game::Date::days2ticks( DateTime::daysInWeek ) ); } } }
void RomeSoldier::_brokePathway(TilePos p) { Soldier::_brokePathway( p ); if( gfx::tilemap::isValidLocation( _d->patrolPosition ) ) { Pathway way = PathwayHelper::create( pos(), _d->patrolPosition, PathwayHelper::allTerrain ); if( way.isValid() ) { setPathway( way ); go(); } else { _setSubAction( patrol ); _setAction( acNone ); setPathway( Pathway() ); } } }
Pathway PathwayHelper::randomWay(CityPtr city, TilePos startPos, int walkRadius) { int loopCounter = 0; //loop limiter do { const Tilemap& tmap = city->getTilemap(); TilePos destPos( std::rand() % walkRadius - walkRadius / 2, std::rand() % walkRadius - walkRadius / 2 ); destPos = (startPos+destPos).fit( TilePos( 0, 0 ), TilePos( tmap.getSize()-1, tmap.getSize()-1 ) ); if( tmap.at( destPos ).isWalkable( true) ) { Pathway pathway = create( city, startPos, destPos, PathwayHelper::allTerrain ); if( pathway.isValid() ) { return pathway; } } } while( ++loopCounter < 20 ); return Pathway(); }
void FishingBoat::timeStep(const unsigned long time) { Ship::timeStep( time ); if( _d->dateUpdate.daysTo( game::Date::current() ) > 0 ) { _d->dateUpdate = game::Date::current(); switch( _d->mode ) { case ready2Catch: { _animationRef().clear(); Pathway way = _d->findFishingPlace( _city(), pos() ); if( way.isValid() ) { setPathway( way ); go(); _d->mode = go2fishplace; } } break; case catchFish: { _animationRef().clear(); _setAction( acWork ); city::Helper helper( _city() ); FishPlaceList places = helper.find<FishPlace>( walker::fishPlace, pos() ); if( !places.empty() ) { FishPlacePtr fishplace = places.front(); _d->stock.setQty( math::clamp( _d->stock.qty()+10, 0, _d->stock.capacity() ) ); } else { _d->mode = ready2Catch; } if( _d->stock.qty() == _d->stock.capacity() ) { _d->mode = finishCatch; } } break; case finishCatch: { if( _d->base != 0 ) { Pathway way = PathwayHelper::create( pos(), _d->base->landingTile().pos(), PathwayHelper::deepWater ); if( way.isValid() ) { _d->mode = back2base; setPathway( way ); go(); } _setAction( acMove ); } else { Logger::warning( "Broken fishing boat" ); deleteLater(); } } break; case go2fishplace: break; case back2base: break; case wait: break; case unloadFish: if( _d->stock.qty() > 0 && _d->base != 0 ) { _d->stock.setQty( math::clamp( _d->stock.qty()-10, 0, 100 ) ); _d->base->updateProgress( 10 ); } if( _d->stock.qty() == 0 ) { _d->mode = ready2Catch; } break; } } }
void TraineeWalker::_computeWalkerPath( bool roadOnly ) { if( !gfx::tilemap::isValidLocation( _d->baseLocation ) ) { Logger::warning( "!!! WARNING: trainee walker baselocation is unaccessible at [%d,%d]", _d->baseLocation.i(), _d->baseLocation.j() ); deleteLater(); return; } BuildingPtr base = ( _city()->getOverlay( _d->baseLocation ).as<Building>()); if( !base.isValid() ) { Logger::warning( "!!! WARNING: trainee walker base is null at [%d,%d]", _d->baseLocation.i(), _d->baseLocation.j() ); deleteLater(); return; } _d->maxNeed = 0; // need of this trainee in buildings Pathway finalPath; BuildingList buildings; for( auto buildingType : _d->necBuildings ) buildings.append( _city()->statistic().objects.find<Building>( buildingType ) ); TilesArray startArea = roadOnly ? base->roadside() : base->enterArea(); DirectRoute droute; _d->maxNeed = 0; unsigned int minDistance = _d->maxDistance; bool isNeedTrainee = false; for( auto bld : buildings ) { float howMuchNeedMyService = bld->evaluateTrainee( type() ); if( howMuchNeedMyService > 0 ) { isNeedTrainee = true; break; } } if( !isNeedTrainee ) { Logger::warning( "!!! WARNING: not need trainee walker from [%d,%d]", base->pos().i(), base->pos().j() ); deleteLater(); return; } std::set<BuildingPtr> checkedBuilding; for( auto itile : startArea ) { TilePos startPos = itile->pos(); for( auto bld : buildings ) { bool buildingAlsoServicing = checkedBuilding.count( bld ) > 0; if( buildingAlsoServicing ) continue; checkedBuilding.insert( bld ); float curNeed = bld->evaluateTrainee( type() ); if( _d->maxNeed < curNeed ) { Pathway way = PathwayHelper::create( startPos, bld, roadOnly ? PathwayHelper::roadOnly : PathwayHelper::allTerrain ); if( way.isValid() && way.length() < minDistance ) { _d->maxNeed = curNeed; droute = DirectRoute( bld.object(), way ); } } } } if( droute.first.isValid() ) { finalPath = droute.second; _d->destLocation = droute.first->pos(); } if( finalPath.isValid() ) { // some building needs that trainee!!! setPos( finalPath.startPos() ); setPathway( finalPath ); } else { // nobody needs him... deleteLater(); } }
static void __createRivers(Game& game ) { PlayerCityPtr oCity = game.city(); Tilemap& oTilemap = oCity->tilemap(); TerrainGeneratorHelper tgHelper; Pathfinder& pathfinder = Pathfinder::instance(); pathfinder.setCondition( makeDelegate( &tgHelper, &TerrainGeneratorHelper::canBuildRiver ) ); TilesArray terrainTiles = oTilemap.getArea( TilePos(0,0), Size( oTilemap.size() ) ); for( TilesArray::iterator it=terrainTiles.begin(); it != terrainTiles.end(); ) { Tile* tile = *it; if( tile->isWalkable( true ) || tile->getFlag( Tile::tlTree ) ) { ++it; } else { it = terrainTiles.erase( it ); } } int riverCount = 0; for( int tryCount=0; tryCount < 20; tryCount++ ) { if( riverCount++ > oTilemap.size() / 60 ) break; Tile* centertile = terrainTiles.random(); Pathway way; for( int range=0; range < 99; range++ ) { TilesArray perimeter = oTilemap.getRectangle( range, centertile->pos() ); foreach( it, perimeter ) { Tile* currentTile = *it; if( currentTile->getFlag( Tile::tlWater ) ) { way = pathfinder.getPath( *centertile, *currentTile, Pathfinder::customCondition | Pathfinder::fourDirection ); if( way.isValid() ) { break; } } } if( way.isValid() ) break; } if( way.isValid() ) { TilesArray wayTiles = way.allTiles(); foreach( it, wayTiles ) { TileOverlayPtr overlay = TileOverlayFactory::instance().create( constants::objects::river ); //Picture pic = Picture::load( ResourceGroup::land1a, 62 + math::random( 57 ) ); (*it)->setPicture( Picture::getInvalid() ); //(*it)->setOriginalImgId( TileHelper::convPicName2Id( pic.name() ) ); (*it)->setOriginalImgId( 0 ); bool isWater = (*it)->getFlag( Tile::tlWater ); CityAreaInfo info = { oCity, (*it)->pos(), TilesArray() }; overlay->build( info ); oCity->overlays().push_back( overlay ); if( isWater ) break; }
void Rioter::timeStep(const unsigned long time) { Walker::timeStep( time ); switch( _d->state ) { case Impl::searchHouse: { city::Helper helper( _city() ); ConstructionList constructions = helper.find<Construction>( objects::house ); for( ConstructionList::iterator it=constructions.begin(); it != constructions.end(); ) { HousePtr h = ptr_cast<House>( *it ); if( h->spec().level() <= _d->houseLevel ) { it=constructions.erase( it ); } else { ++it; } } Pathway pathway = _d->findTarget( _city(), constructions, pos() ); //find more expensive house, fire this!!! if( pathway.isValid() ) { setPos( pathway.startPos() ); setPathway( pathway ); go(); _d->state = Impl::go2destination; } else //not find house, try find any, that rioter can destroy { _d->state = Impl::searchAnyBuilding; } } break; case Impl::searchAnyBuilding: { city::Helper helper( _city() ); ConstructionList constructions = helper.find<Construction>( objects::house ); for( ConstructionList::iterator it=constructions.begin(); it != constructions.end(); ) { TileOverlay::Type type = (*it)->type(); TileOverlay::Group group = (*it)->group(); if( type == objects::house || type == objects::road || _d->excludeGroups.count( group ) > 0 ) { it=constructions.erase( it ); } else { it++; } } Pathway pathway = _d->findTarget( _city(), constructions, pos() ); if( pathway.isValid() ) { setPos( pathway.startPos() ); setPathway( pathway ); go(); _d->state = Impl::go2destination; } else { _d->state = Impl::go2anyplace; } } break; case Impl::go2anyplace: { Pathway pathway = PathwayHelper::randomWay( _city(), pos(), 10 ); if( pathway.isValid() ) { setPathway( pathway ); go(); _d->state = Impl::go2destination; } else { die(); _d->state = Impl::wait; } } break; case Impl::go2destination: case Impl::wait: break; case Impl::destroyConstruction: { if( game::Date::isDayChanged() ) { city::Helper helper( _city() ); ConstructionList constructions = helper.find<Construction>( objects::any, pos() - TilePos( 1, 1), pos() + TilePos( 1, 1) ); for( ConstructionList::iterator it=constructions.begin(); it != constructions.end(); ) { if( (*it)->type() == objects::road || _d->excludeGroups.count( (*it)->group() ) > 0 ) { it=constructions.erase( it ); } else { ++it; } } if( constructions.empty() ) { _animationRef().clear(); _setAction( acMove ); _d->state = Impl::searchHouse; } else { foreach( it, constructions ) { ConstructionPtr c = *it; c->updateState( Construction::fire, 1 ); c->updateState( Construction::damage, 1 ); if( c->state( Construction::damage ) < 10 || c->state( Construction::fire ) < 10 ) { events::GameEventPtr e = events::Disaster::create( c->tile(), events::Disaster::riots ); e->dispatch(); } break; } } } } break; default: break; }