void Military::timeStep(const unsigned int time )
{
  if( game::Date::isMonthChanged() )
  {
    DateTime curDate = game::Date::current();
    //clear old notificationse
    for( Notifications::iterator it=_d->notifications.begin(); it != _d->notifications.end(); )
    {
      if( it->date.monthsTo( curDate ) > notificationHistoryMonths ) { it = _d->notifications.erase( it ); }
      else { ++it; }
    }
  }

  if( game::Date::isWeekChanged() )
  {
    world::EmpirePtr empire = _city()->empire();

    for( Notifications::iterator it=_d->notifications.begin(); it != _d->notifications.end(); )
    {
      world::ObjectPtr object = empire->findObject( it->objectName );

      if( object.isValid() ) { ++it; }
      else { it = _d->notifications.erase( it ); }
    }
  }

  if( _d->needUpdateMilitaryThreat || game::Date::isMonthChanged() )
  {
    _d->needUpdateMilitaryThreat = false;

    EnemySoldierList enemiesInCity = _city()->walkers().select<EnemySoldier>();

    _d->threatValue = enemiesInCity.size() * enemySoldiertThreat;
  }  
}
예제 #2
0
std::string RomeSoldier::thoughts(Thought th) const
{
  if( th == thCurrent )
  {
    TilePos offset( 10, 10 );
    EnemySoldierList enemies = _city()->statistic().walkers.find<EnemySoldier>( walker::any, pos() - offset, pos() + offset );
    if( enemies.empty() )
    {
      return Soldier::thoughts( th );
    }
    else
    {
      RomeSoldierList ourSoldiers = _city()->statistic().walkers.find<RomeSoldier>( walker::any, pos() - offset, pos() + offset );
      int enemyStrength = 0;
      int ourStrength = 0;

      for( auto enemy : enemies) { enemyStrength += enemy->strike(); }
      for( auto sldr : ourSoldiers ) { ourStrength += sldr->strike(); }

      if( ourStrength > enemyStrength )
      {
        int diff = enemyStrength > 0 ? ourStrength / enemyStrength : 99;
        switch( diff )
        {
        case 1: return "";

        case 4: return "##enemies_very_easy##";

        default: break;
        }
      }
      else
      {
        int diff = ourStrength > 0 ? enemyStrength / ourStrength : 99;
        switch( diff )
        {
        case 1:

        case 3: return "##enemies_hard_to_me##";
        case 4: return "##enemies_very_hard##";

        default: break;
        }
      }

      Logger::warning( "RomeSoldier: current thinks unknown state" );
      return "##enemies_unknown_state##";
    }
  }

  return "";
}
예제 #3
0
bool WallGuard::_tryAttack()
{
  EnemySoldierList enemies = _findEnemiesInRange( attackDistance() * 2 ).select<EnemySoldier>();

  if( !enemies.empty() )
  {
    //find nearest walkable wall
    EnemySoldierPtr soldierInAttackRange = _findNearbyEnemy( enemies );

    if( soldierInAttackRange.isValid() )
    {
      _setSubAction( fightEnemy );
      fight();
      _changeDirection();
    }
    else
    {
      PathwayPtr shortestWay;
      int minDistance = 999;
      for( auto enemy : enemies )
      {
        FortificationList nearestWall = _findNearestWalls( enemy );
        PathwayList wayList = _d->base->getWays( pos(), nearestWall );

        for( auto way : wayList )
        {
          double tmpDistance = way->stopPos().distanceFrom( enemy->pos() );
          if( tmpDistance < minDistance )
          {
            shortestWay = way;
            minDistance = tmpDistance;
          }
        }
      }

      if( shortestWay.isValid() )
      {
        _updatePathway( *shortestWay.object() );
        _setSubAction( go2position );
        go();
        return true;
      }
    }
  }

  return false;
}
예제 #4
0
void Mars::_doBlessing(PlayerCityPtr city)
{
  EnemySoldierList enemies;
  enemies << city->walkers( walker::any );

  bool blessingDone = false;
  int step = enemies.size() / 3;
  for( int k=0; k < step; k++ )
  {
    int index = math::random( enemies.size() );
    EnemySoldierList::iterator it = enemies.begin();
    std::advance( it, index );
    (*it)->die();
    blessingDone = true;
  }

  if( blessingDone )
  {
    events::GameEventPtr event = events::ShowInfobox::create( _("##spirit_of_mars_title##"),
                                                              _("##spirit_of_mars_text##"),
                                                              events::ShowInfobox::send2scribe );
    event->dispatch();
  }
}
예제 #5
0
std::string WallGuard::thoughts(Thought th) const
{
  switch( th )
  {
  case thCurrent:
  {
    TilePos offset( 10, 10 );
    EnemySoldierList enemies = _city()->statistic().walkers.find<EnemySoldier>( walker::any, pos() - offset, pos() + offset );
    if( enemies.empty() )
    {
      return Soldier::thoughts(th);
    }
    else
    {
      return "##city_have_defence##";
    }
  }
  break;

  default: break;
  }

  return "";
}
예제 #6
0
void WallGuard::timeStep(const unsigned long time)
{
  Soldier::timeStep( time );

  switch( _subAction() )
  {
  case fightEnemy:
  {
    EnemySoldierList enemies = _findEnemiesInRange( attackDistance() ).select<EnemySoldier>();

    bool haveEnemiesInRande = !enemies.empty();
    if( haveEnemiesInRande )
    {
      if( _animation().atEnd() )
      {
        EnemySoldierPtr p = _findNearbyEnemy( enemies );
        turn( p->pos() );
        _fire( p->pos() );
        _updateAnimation( time+1 );
      }
    }
    else
    {
      _back2base();
    }
  }
  break;

  case check4attack:
  {
    bool haveEnemies = _findEnemiesInRange( attackDistance() ).count<EnemySoldier>() > 0;

    if( haveEnemies )
    {
      fight();
    }
    else
    {
      bool haveEnemies = _tryAttack();
      if( !haveEnemies )
      {
        _back2base();
      }
    }
  }
  break;

  case patrol:
    if( game::Date::isDayChanged() )
    {
      bool haveEnemies = _tryAttack();
      if( !haveEnemies )
      {
        _back2base();
      }
    }
  break;

  default: break;
  } // end switch( _d->action )
}
예제 #7
0
void BuildAny::_exec( Game& game, unsigned int )
{  
  if( _overlay.isNull() )
    return;

  TileOverlayPtr ctOv = game.city()->getOverlay( _pos );

  bool mayBuild = true;
  if( ctOv.isValid() )
  {
    mayBuild = ctOv->isDestructible();
  }

  city::Helper helper( game.city() );
  TilePos offset(10, 10);
  EnemySoldierList enemies = helper.find<EnemySoldier>( walker::any, _pos - offset, _pos + offset );
  if( !enemies.empty() && _overlay->group() != objects::disasterGroup )
  {
    GameEventPtr e = WarningMessage::create( "##too_close_to_enemy_troops##" );
    e->dispatch();
    return;
  }

  if( !_overlay->isDeleted() && mayBuild )
  {
    CityAreaInfo info = { game.city(), _pos, TilesArray() };
    bool buildOk = _overlay->build( info );

    if( !buildOk )
      return;

    helper.updateDesirability( _overlay, city::Helper::onDesirability );
    game.city()->addOverlay( _overlay );

    ConstructionPtr construction = ptr_cast<Construction>( _overlay );
    if( construction.isValid() )
    {
      const MetaData& buildingData = MetaDataHolder::getData( _overlay->type() );
      game.city()->funds().resolveIssue( FundIssue( city::Funds::buildConstruction,
                                                    -(int)buildingData.getOption( MetaDataOptions::cost ) ) );

      if( construction->group() != objects::disasterGroup )
      {
        GameEventPtr e = PlaySound::create( "buildok", 1, 100 );
        e->dispatch();
      }

      if( construction->isNeedRoadAccess() && construction->getAccessRoads().empty() )
      {
        GameEventPtr e = WarningMessage::create( "##building_need_road_access##" );
        e->dispatch();
      }

      std::string error = construction->errorDesc();
      if( !error.empty() )
      {
        GameEventPtr e = WarningMessage::create( error );
        e->dispatch();
      }

      WorkingBuildingPtr wb = ptr_cast<WorkingBuilding>( construction );
      if( wb.isValid() && wb->maximumWorkers() > 0 )
      {
        unsigned int worklessCount = statistic::getWorklessNumber( game.city() );
        if( worklessCount < wb->maximumWorkers() )
        {
          GameEventPtr e = WarningMessage::create( "##city_need_more_workers##" );
          e->dispatch();
        }
      }
    }
  }
  else
  {
    ConstructionPtr construction = ptr_cast<Construction>( _overlay );
    if( construction.isValid() )
    {
      GameEventPtr e = WarningMessage::create( construction->errorDesc() );
      e->dispatch();
    }
  }
}