bool EnemySoldier::_tryAttack()
{
  WalkerList enemies = _findEnemiesInRange( attackDistance() );

  if( !enemies.empty() )
  {
    _setSubAction( Soldier::fightEnemy );
    setTarget( enemies.front()->pos() );
    fight();
  }
  else
  {
    ConstructionList constructions = _findContructionsInRange( attackDistance() );
    if( !constructions.empty() )
    {
      _setSubAction( Soldier::destroyBuilding );
      setTarget( constructions.front()->pos() );
      fight();
    }
  }

  if( action() == acFight )
  {
    bool needMeMove = false;
    _city()->statistic().map.isTileBusy<EnemySoldier>( pos(), this, needMeMove );

    if( needMeMove )
    {
      _move2freePos( target() );
    }
  }

  return action() == acFight;
}
Exemple #2
0
void RandomFire::_exec( Game& game, unsigned int time)
{
  int population = game.city()->population();
  if( population > _d->minPopulation && population < _d->maxPopulation )
  {
    Logger::warning( "Execute random fire event" );
    _d->isDeleted = true;

    Priorities<int> exclude;
    exclude << objects::waterGroup
            << objects::roadGroup
            << objects::disasterGroup;

    ConstructionList ctrs;
    ctrs << game.city()->overlays();

    for( ConstructionList::iterator it=ctrs.begin(); it != ctrs.end(); )
    {
      if( exclude.count( (*it)->group() ) ) { it = ctrs.erase( it ); }
      else { ++it; }
    }

    unsigned int number4burn = math::clamp<unsigned int>( (ctrs.size() * _d->strong / 100), 1u, 100u );

    for( unsigned int k=0; k < number4burn; k++ )
    {
      ConstructionPtr building = ctrs.random();
      building->burn();
    }
  }
}
void RandomFire::_exec( Game& game, unsigned int time)
{
    int population = game.city()->states().population;
    if( _d->popRange.contain( population ) )
    {
        Logger::warning( "Execute random fire event" );
        _d->isDeleted = true;

        std::set<object::Group> exclude;
        exclude << object::group::water
                << object::group::road
                << object::group::disaster;

        ConstructionList ctrs = statistic::getObjectsNotIs<Construction>( game.city(), exclude );

        unsigned int number4burn = math::clamp<unsigned int>( (ctrs.size() * _d->strong / 100), 1u, 100u );

        for( unsigned int k=0; k < number4burn; k++ )
        {
            ConstructionPtr building = ctrs.random();
            building->burn();
        }
    }
}
Exemple #4
0
void RomeArcher::timeStep(const unsigned long time)
{
  Soldier::timeStep( time );

  switch( _subAction() )
  {
  case Soldier::fightEnemy:
  {
    WalkerList enemies = _findEnemiesInRange( attackDistance() );

    if( !enemies.empty() )
    {
      WalkerPtr p = enemies.front();
      turn( p->pos() );

      if( _animationRef().index() == (int)(_animationRef().frameCount()-1) )
      {
        _fire( p->pos() );
        _updateAnimation( time+1 );
      }
    }
    else
    {
      //_check4attack();
      send2patrol();
    }
  }
  break;

  case Soldier::destroyBuilding:
  {
    ConstructionList constructions = _findContructionsInRange( attackDistance() );

    if( !constructions.empty() )
    {
      ConstructionPtr b = constructions.front();
      turn( b->pos() );

      if( _animationRef().index() == (int)(_animationRef().frameCount()-1) )
      {
        _fire( b->pos() );
        _updateAnimation( time+1 );
      }
    }
    else
    {
      //_check4attack();
      send2patrol();
    }
  }

  case Soldier::patrol:
    if( game::Date::current().day() % 2 == 0 )
    {
      _tryAttack();
    }
  break;

  default: break;
  } // end switch( _d->action )
}
ConstructionList EnemySoldier::_findContructionsInRange( unsigned int range )
{
  ConstructionList ret;
  Tilemap& tmap = _map();

  for( unsigned int k=0; k <= range; k++ )
  {
    ConstructionList blds = tmap.rect( k, pos() )
                                .overlays()
                                .select<Construction>();

    for( auto b : blds )
    {
      if( !_atExclude.count( b->group() ) )
      {
        ret.push_back( b );
      }
    }
  }

  if( ret.empty() )
    return ret;

  switch( _atPriority )
  {
  case attackFood:
  case attackCitizen:
  case attackIndustry:
  {
    ConstructionList tmpRet;
    object::Group needGroup;
    switch( _atPriority )
    {
    case attackIndustry: needGroup = object::group::industry; break;
    case attackFood: needGroup = object::group::food; break;
    case attackCitizen:  needGroup = object::group::house; break;
    case attackSenate: needGroup = object::group::administration; break;
    default: needGroup = object::group::unknown; break;
    }

    for( auto bld : ret )
    {
      if( bld->group() == needGroup )
      {
        tmpRet << bld;
      }
    }

    if( !tmpRet.empty() )
      return tmpRet;
  }
  break;

  case attackBestBuilding:
  {
    ConstructionPtr maxBuilding = ret.front();
    unsigned int maxCost = __getCost( maxBuilding );

    foreach( it, ret )
    {
      unsigned int cost = __getCost( *it );
      if( cost > maxCost )
      {
        maxCost = cost;
        maxBuilding = *it;
      }
    }

    if( maxBuilding.isValid() )
    {
      ret.clear();
      ret << maxBuilding;
      return ret;
    }
  }
  break;

  default:
  break;
  }
Exemple #6
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;
  }