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 ""; }
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; }
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 ""; }
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 ) }
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(); } } }