void Disorder::timeStep( const unsigned int time ) { if( GameDate::isYearChanged() ) { _d->rioterInLastYear = _d->rioterInThisYear; _d->rioterInThisYear = 0; } if( !GameDate::isWeekChanged() ) return; Helper helper( _city() ); HouseList houses = helper.find<House>( building::house ); WalkerList walkers = _city()->walkers( walker::protestor ); HouseList criminalizedHouse; _d->currentCrimeLevel = 0; _d->maxCrimeLevel = 0; foreach( house, houses ) { int crimeLvl = (*house)->getServiceValue( Service::crime )+1; if( crimeLvl >= _d->minCrimeLevel ) { criminalizedHouse.push_back( *house ); } _d->currentCrimeLevel += crimeLvl; _d->maxCrimeLevel = std::max<int>( _d->maxCrimeLevel, crimeLvl ); }
void HealthCare::Impl::updateReasons( PlayerCityPtr city ) { int lvl = math::clamp<int>( value / (health::maxValue/health::levelNumber), 0, health::levelNumber-1 ); std::string mainReason = healthDescription[ lvl ]; int clinics_n = city->statistic().objects.count( object::clinic ); mainReason += clinics_n > 0 ? "_clinic##" : "##"; reasons << mainReason; if( lvl > health::levelNumber / 3 ) { for( int i=0; reasonsInfo[ i ].type != object::unknown; i++ ) { object::TypeSet availableTypes; availableTypes.insert( reasonsInfo[ i ].type ); HouseList housesWantEvolve = city->statistic().houses.ready4evolve( availableTypes ); if( housesWantEvolve.size() > 0 ) { reasons << reasonsInfo[i].info; } } } }
void WorkingBuilding::timeStep( const unsigned long time ) { Building::timeStep( time ); for( WalkerList::iterator it=_d->walkerList.begin(); it != _d->walkerList.end(); ) { if( (*it)->isDeleted() ) { it = _d->walkerList.erase( it ); } else { ++it; } } if( game::Date::isMonthChanged() && numberWorkers() > 0 ) { city::Helper helper( _city() ); TilePos offset( 8, 8 ); TilePos myPos = pos(); HouseList houses = helper.find<House>( objects::house, myPos - offset, myPos + offset ); float averageDistance = 0; foreach( it, houses ) { if( (*it)->spec().level() < HouseLevel::smallVilla ) { averageDistance += myPos.distanceFrom( (*it)->pos() ); } } if( houses.size() > 0 ) averageDistance /= houses.size(); _d->laborAccessKoeff = math::clamp( math::percentage( averageDistance, 8 ) * 2, 25, 100 ); }
HouseList HouseManager::filterHouses(uint32 townId) { HouseList ret; for(const HousePtr& house : m_houses) if(house->getTownId() == townId) ret.push_back(house); return ret; }
HouseList Statistic::_Houses::habitable() const { HouseList houses = find(); for( auto it=houses.begin(); it != houses.end(); ) { if( (*it)->habitants().count() > 0 ) ++it; else it = houses.erase( it ); } return houses; }
HouseList Statistic::_Houses::ready4evolve(const object::TypeSet& checkTypes ) const { HouseList houses = find(); for( auto it=houses.begin(); it != houses.end(); ) { object::Type btype; (*it)->spec().next().checkHouse( *it, nullptr, &btype ); if( checkTypes.count( btype ) ) it = houses.erase( it ); else ++it; } return houses; }
void Migration::Impl::createMigrationFromCity( PlayerCityPtr city ) { HouseList houses = city->statistic().houses.find(); const int minWorkersNumber = 4; for( HouseList::iterator i=houses.begin(); i != houses.end(); ) { int houseWorkless = (*i)->unemployed(); if( !(*i)->enterArea().empty() && houseWorkless > minWorkersNumber ) { ++i; } else { i = houses.erase( i ); } } if( !houses.empty() ) { int number = math::random( houses.size() ); HouseList randHouses = houses.random( number ); for( auto house : randHouses ) { ImmigrantPtr emigrant = Immigrant::create( city ); if( emigrant.isValid() ) { house->removeHabitants( minWorkersNumber ); emigrant->leaveCity( *(house->enterArea().front()) ); emigrant->setThinks( "##immigrant_no_work_for_me##" ); } } } }
HousePtr Immigrant::_findBlankHouse() { CityHelper hlp( _getCity() ); HouseList houses = hlp.find< House >( building::house ); HousePtr blankHouse; _d->destination = TilePos( -1, -1 ); HouseList::iterator itHouse = houses.begin(); while( itHouse != houses.end() ) { if( (*itHouse)->getAccessRoads().size() > 0 && ( (*itHouse)->getHabitants().count() < (*itHouse)->getMaxHabitants() ) ) { itHouse++; } else { itHouse = houses.erase( itHouse ); } } if( houses.size() > 0 ) { itHouse = houses.begin(); std::advance(itHouse, rand() % houses.size() ); blankHouse = *itHouse; _d->destination = blankHouse->getTilePos(); } return blankHouse; }
void RandomPlague::_exec( Game& game, unsigned int time) { int population = game.city()->states().population; if( _d->popRange.contain( population ) ) { Logger::info( "Execute random plague event" ); _d->isDeleted = true; HouseList houses = game.city()->statistic().houses.habitable(); unsigned int number4burn = math::clamp<unsigned int>( (houses.size() * _d->strong / 100), 1u, 100u ); for( unsigned int k=0; k < number4burn; k++ ) { HousePtr house = houses.random(); house->setState( pr::health, 0.f ); } } }
void HealthCare::Impl::updateValue(PlayerCityPtr city) { HouseList habitable = city->statistic().houses.habitable(); value = 0; avgMinHealth = 100; int houseWithBadHealth = 0; for( auto house : habitable ) { unsigned int hLvl = house->state( pr::health ); value += hLvl; if( hLvl < health::bad ) { avgMinHealth += hLvl; houseWithBadHealth++; } } value /= (habitable.size()+1); avgMinHealth /= (houseWithBadHealth+1); }
void ProsperityRating::_checkStats() { HouseList habitable = _city()->statistic().houses.habitable(); int prosperityCap = 0; for( auto house : habitable) { prosperityCap += house->spec().prosperity(); if( house->spec().isPatrician() ) _d->now.patricianCount += house->habitants().count(); else _d->now.plebsCount += house->habitants().count(); } if( habitable.size() > 0 ) { prosperityCap /= habitable.size(); } _d->now.prosperity = math::clamp<int>( prosperityCap, 0, _d->now.prosperity + 2 ); _d->now.houseCapTrand = _d->now.prosperity - _d->prev.prosperity; }
int Statistic::_Objects::laborAccess(WorkingBuildingPtr wb) const { if( wb.isNull() ) return 0; TilePos offset( maxLaborDistance, maxLaborDistance ); TilePos wbpos = wb->pos(); HouseList houses = find<House>( object::house, wbpos - offset, wbpos + offset ); float averageDistance = 0; for( auto house : houses ) { if( house->level() > HouseLevel::vacantLot && house->level() < HouseLevel::smallVilla ) { averageDistance += wbpos.distanceFrom( house->pos() ); } } if( houses.size() > 0 ) averageDistance /= houses.size(); return math::clamp( math::percentage( averageDistance, maxLaborDistance ) * 2, 25, 100 ); }
HousePtr Emigrant::_findBlankHouse() { city::Helper hlp( _city() ); HousePtr blankHouse; TilePos offset( 5, 5 ); HouseList houses = hlp.find<House>( building::house, pos() - offset, pos() + offset ); _checkHouses( houses ); if( houses.empty() ) { houses = hlp.find<House>( building::house ); _checkHouses( houses ); } if( houses.size() > 0 ) { blankHouse = houses.random(); } return blankHouse; }
void Disorder::Impl::weekUpdate( unsigned int time, PlayerCityPtr rcity ) { HouseList houses = rcity->statistic().houses.find(); const WalkerList& walkers = rcity->statistic().walkers.find( walker::protestor ); HouseList criminalizedHouse; crime.level.current = 0; crime.level.maximum = 0; for( auto house : houses ) { int currentValue = house->getServiceValue( Service::crime )+1; if( currentValue >= crime.level.minimum ) { criminalizedHouse.push_back( house ); } crime.level.current += currentValue; crime.level.maximum = std::max<int>( crime.level.maximum, currentValue ); } if( houses.size() > 0 ) crime.level.current /= houses.size(); if( criminalizedHouse.size() > walkers.size() ) { HousePtr house = criminalizedHouse.random(); int hCrimeLevel = house->getServiceValue( Service::crime ); int sentiment = rcity->sentiment(); int randomValue = math::random( crime::maxValue ); if (sentiment >= minSentiment4protest ) { if ( randomValue >= sentiment + 20 ) { if ( hCrimeLevel > crime::level4protestor ) { generateProtestor( rcity, house ); } } } else if ( sentiment >= minSentiment4mugger ) { if ( randomValue >= sentiment + 40 ) { if ( hCrimeLevel >= crime::level4mugger ) { generateMugger( rcity, house ); } else if ( hCrimeLevel > crime::level4protestor ) { generateProtestor( rcity, house ); } } } else if( sentiment < minSentiment4mugger ) { if ( randomValue >= sentiment + 50 ) { if ( hCrimeLevel >= crime::level4rioter ) { generateRioter( rcity, house ); } else if ( hCrimeLevel >= crime::level4mugger ) { generateMugger( rcity, house ); } else if ( hCrimeLevel > crime::level4protestor ) { generateProtestor( rcity, house ); } } } } }