Пример #1
0
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;
}
Пример #2
0
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();
  }
}
Пример #3
0
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 } );
    }
  }
}
Пример #4
0
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();
}
Пример #5
0
  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();
  }
Пример #6
0
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();
  }
}
Пример #7
0
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();
  }
}
Пример #8
0
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();
  }
}
Пример #9
0
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();
  }
}
Пример #10
0
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();
  }
}
Пример #11
0
void Patrician::_findNewWay( const TilePos& start )
{
  Pathway pathway = PathwayHelper::randomWay( _getCity(), start, 10 );

  if( pathway.isValid() )
  {
    setPathway( pathway );
    setIJ( start );
    go();
  }
  else
  {
    die();
  }
}
Пример #12
0
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();
}
Пример #13
0
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;
      }
    }
  }
Пример #15
0
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;
    }
  }
Пример #16
0
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();
}
Пример #17
0
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();
  }
}
Пример #18
0
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();
}
Пример #19
0
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 ) );
    }
  }
}
Пример #20
0
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() );
    }
  }
}
Пример #21
0
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();
}
Пример #22
0
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;
    }
  }
}
Пример #23
0
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();
  }
}
Пример #24
0
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;
      }
Пример #25
0
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;
  }