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(); }
TileTopBlockIterator::TileTopBlockIterator(const TilePos& tile, int block_size, int tile_width) : block_size(block_size), is_end(false) { // at first get the chunk, whose row and column is at the top right of the tile mc::ChunkPos topright_chunk = mc::ChunkPos::byRowCol(4 * tile_width * tile.getY(), 2 * tile_width * tile.getX() + 2); // now get the first visible block from this chunk in this tile top = mc::LocalBlockPos(8, 6, mc::CHUNK_HEIGHT * 16 - 1).toGlobalPos(topright_chunk); // and set this as start current = top; // calculate bounds of the tile min_row = top.getRow() + 1; max_row = top.getRow() + (64 * tile_width) + 4; max_col = top.getCol() + 2; min_col = max_col - (32 * tile_width); // calculate position of the first block, relative row/col in this tile are needed int row = current.getRow() - min_row; int col = current.getCol() - min_col; // every column is a 1/2 block and every row is a 1/4 block draw_x = col * block_size / 2; // -1/2 blocksize, because we would see the top side of the blocks in the tile if not draw_y = row * block_size / 4 - block_size / 2; // -16 }
TilePos Tilemap::fit( const TilePos& pos ) const { TilePos ret; ret.setI( math::clamp( pos.i(), 0, _d->size ) ); ret.setJ( math::clamp( pos.j(), 0, _d->size ) ); return ret; }
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 ); }
foreach( it, buildings ) { if( (*it)->type() == object::house ) { HousePtr house = it->as<House>(); TilePos pos = house->pos(); int hash = (pos.i() << 8) | pos.i(); _d->servedHouses[ hash ] = house->habitants().count(); } }
void TopdownTileRenderer::renderTile(const TilePos& tile_pos, RGBAImage& tile) { int texture_size = images->getTextureSize(); tile.setSize(getTileSize(), getTileSize()); for (int x = 0; x < tile_width; x++) { for (int z = 0; z < tile_width; z++) { mc::ChunkPos chunkpos(tile_pos.getX() * tile_width + x, tile_pos.getY() * tile_width + z); current_chunk = world->getChunk(chunkpos); if (current_chunk != nullptr) renderChunk(*current_chunk, tile, texture_size*16*x, texture_size*16*z); } } }
std::list<Tile*> Tilemap::getFilledRectangle(const TilePos& start, const TilePos& stop ) { std::list<Tile*> res; for (int i = start.getI(); i <= stop.getI(); ++i) { for (int j = start.getJ(); j <= stop.getJ(); ++j) { if( is_inside( TilePos( i, j ) )) { res.push_back(&at( TilePos( i, j ) ) ); } } } return res; }
TilesArray Layer::_getSelectedArea( TilePos startPos ) { __D_IMPL(_d,Layer) TilePos outStartPos, outStopPos; Tile* startTile = startPos.i() < 0 ? _d->camera->at( _d->startCursorPos, true ) // tile under the cursor (or NULL) : _d->camera->at( startPos ); Tile* stopTile = _d->camera->at( _d->lastCursorPos, true ); TilePos startPosTmp = startTile->epos(); TilePos stopPosTmp = stopTile->epos(); outStartPos = TilePos( std::min<int>( startPosTmp.i(), stopPosTmp.i() ), std::min<int>( startPosTmp.j(), stopPosTmp.j() ) ); outStopPos = TilePos( std::max<int>( startPosTmp.i(), stopPosTmp.i() ), std::max<int>( startPosTmp.j(), stopPosTmp.j() ) ); return _city()->tilemap().getArea( outStartPos, outStopPos ); }
WarpTile::WarpTile(TilePos pos, PlayfieldInfo *pfi) : MapTile(pos), holePixmap(this) { targetTile = 0; playfield = pfi; holeOpen = true; QTransform tf; if(pos.x() > MAPW/2) tf.scale(-1,1); holePixmap.setPixmap(Sprite::loadBitmap("wow-sprites/warphole.bmp", 2).transformed(tf)); connect(&closedTimer, SIGNAL(timeout()), this, SLOT(reopen())); }
std::list<AStarPoint*> Pathfinder::getTraversingPoints( const TilePos& start, const TilePos& stop ) { std::list<AStarPoint*> points; if( start == stop ) return points; points.push_back( getPoint( start ) ); TilePos housePos = stop; while( points.back()->getPos() != housePos ) { TilePos ij = points.back()->getPos(); TilePos move( math::clamp( housePos.getI() - ij.getI(), -1, 1 ), math::clamp( housePos.getJ() - ij.getJ(), -1, 1 ) ); points.push_back( getPoint( ij + move ) ); } return points; }
void Garden::build( CityPtr city, const TilePos& pos ) { // this is the same arrangement of garden tiles as existed in C3 int theGrid[2][2] = {{113, 110}, {112, 111}}; Construction::build( city, pos ); setPicture( ResourceGroup::entertaiment, theGrid[pos.getI() % 2][pos.getJ() % 2] ); if( getSize().getArea() == 1 ) { TilemapTiles tilesAround = city->getTilemap().getRectangle( getTilePos() - TilePos( 1, 1), getTilePos() + TilePos( 1, 1 ) ); foreach( Tile* tile, tilesAround ) { GardenPtr garden = tile->getOverlay().as<Garden>(); if( garden.isValid() ) { garden->update(); } }
int getGScore(AStarPoint* p) { int offset = p->tile->get_terrain().isRoad() ? -5 : +10; TilePos pos = tile ? tile->getIJ() : TilePos( 0, 0 ); TilePos otherPos = p->tile->getIJ(); return p->g + ((pos.getI() == otherPos.getI() || pos.getJ() == otherPos.getJ()) ? 10 : 14) + offset; }
/* INCORRECT! */ bool Wharf::canBuild(const TilePos& pos ) const { bool is_constructible = Construction::canBuild( pos ); // We can build wharf only on straight border of water and land // // ?WW? ???? ???? ???? // ?XX? WXX? ?XXW ?XX? // ?XX? WXX? ?XXW ?XX? // ???? ???? ???? ?WW? // bool bNorth = true; bool bSouth = true; bool bWest = true; bool bEast = true; Tilemap& tilemap = Scenario::instance().getCity().getTilemap(); std::list<Tile*> rect = tilemap.getRectangle( pos + TilePos( -1, -1 ), Size( _size+2 ), false); for (std::list<Tile*>::iterator itTiles = rect.begin(); itTiles != rect.end(); ++itTiles) { Tile &tile = **itTiles; std::cout << tile.getI() << " " << tile.getJ() << " " << pos.getI() << " " << pos.getJ() << std::endl; // if (tiles.get_terrain().isWater()) if (tile.getJ() > (pos.getJ() + _size -1) && !tile.get_terrain().isWater()) { bNorth = false; } if (tile.getJ() < pos.getJ() && !tile.get_terrain().isWater()) { bSouth = false; } if (tile.getI() > (pos.getI() + _size -1) && !tile.get_terrain().isWater()) { bEast = false; } if (tile.getI() < pos.getI() && !tile.get_terrain().isWater()) { bWest = false; } } return (is_constructible && (bNorth || bSouth || bEast || bWest)); }
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 ); }
Pathway FishingBoat::Impl::findFishingPlace(PlayerCityPtr city, TilePos pos ) { city::Helper helper( city ); FishPlaceList places = helper.find<FishPlace>( walker::fishPlace, city::Helper::invalidPos ); int minDistance = 999; FishPlacePtr nearest; foreach( it, places ) { FishPlacePtr place = *it; int currentDistance = pos.distanceFrom( place->pos() ); if( currentDistance < minDistance ) { minDistance = currentDistance; nearest = place; } }
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(); }
// Get tiles inside of rectangle TilesArray Tilemap::getArea(const TilePos& start, const TilePos& stop ) const { TilesArray res; int expected = math::min((abs(stop.i() - start.i()) + 1) * (abs(stop.j() - start.j()) + 1), 100); res.reserve(expected); Rect r( start.i(), start.j(), stop.i(), stop.j() ); r.repair(); for (int i = r.left(); i <= r.right(); ++i) { for (int j = r.top(); j <= r.bottom(); ++j) { if( isInside( TilePos( i, j ) )) { res.push_back( &( const_cast<Tilemap*>( this )->at( TilePos( i, j ) )) ); } } } return res; }
bool Pathfinder::aStar( const TilePos& startPos, const TilePos& stopPos, const Size& arrivedArea, PathWay& oPathWay, int flags ) { oPathWay.init( *_tilemap, _tilemap->at( startPos ) ); // Define points to work with AStarPoint* start = getPoint( startPos ); AStarPoint* end = getPoint( stopPos ); AStarPoint* current; AStarPoint* child; // Define the open and the close list list<AStarPoint*> openList; list<AStarPoint*> closedList; list<AStarPoint*>::iterator i; int tSize = _tilemap->getSize(); map<AStarPoint*,AStarPoint::WalkableType> saveArrivedArea; TilePos arrivedAreaStart( math::clamp( stopPos.getI()-arrivedArea.getWidth(), 0, tSize ), math::clamp( stopPos.getJ()-arrivedArea.getHeight(), 0, tSize) ); TilePos arrivedAreaStop( math::clamp( stopPos.getI()+arrivedArea.getWidth(), 0, tSize ), math::clamp( stopPos.getJ()+arrivedArea.getHeight(), 0, tSize) ); for( int i=arrivedAreaStart.getI(); i <= arrivedAreaStop.getI(); i++ ) { for( int j=arrivedAreaStart.getJ(); j <= arrivedAreaStop.getJ(); j++ ) { AStarPoint* ap = getPoint( TilePos( i, j) ); if( ap ) { saveArrivedArea[ ap ] = ap->priorWalkable; ap->priorWalkable = AStarPoint::alwaysWalkable; } } } unsigned int n = 0; // Add the start point to the openList openList.push_back(start); start->opened = true; while (n == 0 || (current != end && n < getMaxLoopCount() )) { // Look for the smallest F value in the openList and make it the current point for (i = openList.begin(); i != openList.end(); ++ i) { if (i == openList.begin() || (*i)->getFScore() <= current->getFScore()) { current = (*i); } } // Stop if we reached the end if( current == end ) { break; } // Remove the current point from the openList openList.remove(current); current->opened = false; // Add the current point to the closedList closedList.push_back(current); current->closed = true; // Get all current's adjacent walkable points for (int x = -1; x < 2; x ++) { for (int y = -1; y < 2; y ++) { // If it's current point then pass if (x == 0 && y == 0) { continue; } // Get this point child = getPoint( current->getPos() + TilePos( x, y ) ); // If it's closed or not walkable then pass if (child->closed || !child->isWalkable() ) { continue; } // If we are at a corner if (x != 0 && y != 0) { // if the next horizontal point is not walkable or in the closed list then pass //AStarPoint* tmpPoint = getPoint( current->pos + TilePos( 0, y ) ); TilePos tmp = current->getPos() + TilePos( 0, y ); if( !pointIsWalkable( tmp ) || getPoint( tmp )->closed) { continue; } tmp = current->getPos() + TilePos( x, 0 ); // if the next vertical point is not walkable or in the closed list then pass if( !pointIsWalkable( tmp ) || getPoint( tmp )->closed) { continue; } } // If it's already in the openList if (child->opened) { // If it has a wroste g score than the one that pass through the current point // then its path is improved when it's parent is the current point if (child->getGScore() > child->getGScore(current)) { // Change its parent and g score child->setParent(current); child->computeScores(end); } } else { // Add it to the openList with current point as parent openList.push_back(child); child->opened = true; // Compute it's g, h and f score child->setParent(current); child->computeScores(end); } } } n++; } // Reset for (i = openList.begin(); i != openList.end(); ++ i) { (*i)->opened = false; } for (i = closedList.begin(); i != closedList.end(); ++ i) { (*i)->closed = false; } for( map<AStarPoint*,AStarPoint::WalkableType>::iterator it=saveArrivedArea.begin(); it != saveArrivedArea.end(); it++ ) { it->first->priorWalkable = it->second; } if( n == getMaxLoopCount() ) { return false; } // Resolve the path starting from the end point list<AStarPoint*> lPath; while( current->hasParent() && current != start ) { lPath.push_front( current ); current = current->getParent(); n++; } for( list<AStarPoint*>::iterator lpIt=lPath.begin(); lpIt != lPath.end(); lpIt++ ) { oPathWay.setNextTile( _tilemap->at( (*lpIt)->getPos() ) ); } return oPathWay.getLength() > 0; }
int getHScore(AStarPoint* p) { TilePos pos = tile ? tile->getIJ() : TilePos( 0, 0 ); TilePos otherPos = p->tile->getIJ(); return (abs(otherPos.getI() - pos.getI()) + abs(otherPos.getJ() - pos.getJ())) * 10; }
bool Pathfinder::pointIsWalkable( const TilePos& pos ) { return (pointExists( pos ) && grid[ pos.getI() ][ pos.getJ() ]->isWalkable() ); }
bool Pathfinder::pointExists( const TilePos& pos ) { return ( pos.getI() < grid.size() && pos.getJ() < grid[pos.getI()].size() ); }
void PlayerArmy::setFortPos(const TilePos& base) { _d->fortPos = base; setName( utils::format( 0xff, "expedition_from_%dx%d", base.i(), base.j() ) ); }
bool isValidLocation(const TilePos &pos) { return pos.i() >= 0 && pos.j() >=0; }
TilesArea::TilesArea(const Tilemap &tmap, const TilePos& leftup, const TilePos& rightdown) { _size = Size( abs( rightdown.i() - leftup.i() ), abs( rightdown.j() - leftup.j() ) ); append( tmap.area( leftup, rightdown ) ); }
void GameLoader::Impl::initEntryExitTile( const TilePos& tlPos, Tilemap& tileMap, const unsigned int picIdStart, bool exit ) { unsigned int idOffset = 0; TilePos tlOffset; if( tlPos.getI() == 0 || tlPos.getI() == tileMap.getSize() - 1 ) { tlOffset = TilePos( 0, 1 ); idOffset = (tlPos.getI() == 0 ? 1 : 3 ); } else if( tlPos.getJ() == 0 || tlPos.getJ() == tileMap.getSize() - 1 ) { tlOffset = TilePos( 1, 0 ); idOffset = (tlPos.getJ() == 0 ? 2 : 0 ); } Tile& signTile = tileMap.at( tlPos + tlOffset ); StringHelper::debug( 0xff, "(%d, %d)", tlPos.getI(), tlPos.getJ() ); StringHelper::debug( 0xff, "(%d, %d)", tlOffset.getI(), tlOffset.getJ() ); signTile.setPicture( ResourceGroup::land3a, picIdStart + idOffset ); signTile.setFlag( Tile::tlRock, true ); }
void Build::_updatePreviewTiles( bool force ) { __D_REF(d,Build); Tile* curTile = _camera()->at( _lastCursorPos(), true ); if( !curTile ) return; if( !force && d.lastTilePos == curTile->epos() ) return; if( !d.multiBuilding ) { _setStartCursorPos( _lastCursorPos() ); d.startTilePos = curTile->pos(); } d.lastTilePos = curTile->epos(); _discardPreview(); d.money4Construction = 0; if( d.borderBuilding ) { Tile* startTile = _camera()->at( d.startTilePos ); // tile under the cursor (or NULL) Tile* stopTile = _camera()->at( _lastCursorPos(), true ); TilesArray pathTiles = RoadPropagator::createPath( _city()->tilemap(), startTile->epos(), stopTile->epos(), d.roadAssignment, d.kbShift ); Tilemap& tmap = _city()->tilemap(); TilePos leftUpCorner = pathTiles.leftUpCorner(); TilePos rigthDownCorner = pathTiles.rightDownCorner(); TilePos leftDownCorner( leftUpCorner.i(), rigthDownCorner.j() ); TilesArray ret; int mmapSize = std::max<int>( leftUpCorner.j() - rigthDownCorner.j() + 1, rigthDownCorner.i() - leftUpCorner.i() + 1 ); for( int y=0; y < mmapSize; y++ ) { for( int t=0; t <= y; t++ ) { TilePos tpos = leftDownCorner + TilePos( t, mmapSize - 1 - ( y - t ) ); if( pathTiles.contain( tpos ) ) ret.push_back( &tmap.at( tpos ) ); } } for( int x=1; x < mmapSize; x++ ) { for( int t=0; t < mmapSize-x; t++ ) { TilePos tpos = leftDownCorner + TilePos( x + t, t ); if( pathTiles.contain( tpos ) ) ret.push_back( &tmap.at( tpos ) ); } } pathTiles = ret; for( auto tile : pathTiles ) _checkPreviewBuild( tile->epos() ); } else { TilesArray tiles = _getSelectedArea( d.startTilePos ); for( auto tile : tiles ) _checkPreviewBuild( tile->epos() ); } d.sortBuildTiles(); d.text.image.fill( ColorList::clear, Rect() ); d.text.font.setColor( ColorList::red ); d.text.font.draw( d.text.image, fmt::format( "{} Dn", d.money4Construction ), Point() ); }
void HighBridge::_checkParams( DirectionType& direction, TilePos& start, TilePos& stop, const TilePos& curPos ) const { start = curPos; Tilemap& tilemap = Scenario::instance().getCity()->getTilemap(); Tile& tile = tilemap.at( curPos ); if( tile.getTerrain().isRoad() ) { direction = D_NONE; return; } int imdId = tile.getTerrain().getOriginalImgId(); if( imdId == 384 || imdId == 385 || imdId == 386 || imdId == 387 ) { PtrTilesArea tiles = tilemap.getFilledRectangle( curPos - TilePos( 10, 0), curPos ); for( PtrTilesArea::reverse_iterator it=tiles.rbegin(); it != tiles.rend(); it++ ) { imdId = (*it)->getTerrain().getOriginalImgId(); if( imdId == 376 || imdId == 377 || imdId == 378 || imdId == 379 ) { stop = (*it)->getIJ(); direction = abs( stop.getI() - start.getI() ) > 3 ? D_NORTH_WEST : D_NONE; break; } } } else if( imdId == 376 || imdId == 377 || imdId == 378 || imdId == 379 ) { PtrTilesArea tiles = tilemap.getFilledRectangle( curPos, curPos + TilePos( 10, 0) ); for( PtrTilesArea::reverse_iterator it=tiles.rbegin(); it != tiles.rend(); it++ ) { imdId = (*it)->getTerrain().getOriginalImgId(); if( imdId == 384 || imdId == 385 || imdId == 386 || imdId == 387 ) { stop = (*it)->getIJ(); direction = abs( stop.getI() - start.getI() ) > 3 ? D_SOUTH_EAST : D_NONE; break; } } } else if( imdId == 372 || imdId == 373 || imdId == 374 || imdId == 375 ) { PtrTilesArea tiles = tilemap.getFilledRectangle( curPos, curPos + TilePos( 0, 10) ); for( PtrTilesArea::reverse_iterator it=tiles.rbegin(); it != tiles.rend(); it++ ) { imdId = (*it)->getTerrain().getOriginalImgId(); if( imdId == 380 || imdId == 381 || imdId == 382 || imdId == 383 ) { stop = (*it)->getIJ(); direction = abs( stop.getJ() - start.getJ() ) > 3 ? D_NORTH_EAST : D_NONE; break; } } } else if( imdId == 380 || imdId == 381 || imdId == 382 || imdId == 383 ) { PtrTilesArea tiles = tilemap.getFilledRectangle( curPos - TilePos( 0, 10), curPos ); for( PtrTilesArea::reverse_iterator it=tiles.rbegin(); it != tiles.rend(); it++ ) { imdId = (*it)->getTerrain().getOriginalImgId(); if( imdId == 372 || imdId == 373 || imdId == 374 || imdId == 375 ) { stop = (*it)->getIJ(); direction = abs( stop.getJ() - start.getJ() ) > 3 ? D_SOUTH_WEST : D_NONE; break; } } } else { direction = D_NONE; } }
bool isValid( const TilePos& pos ) { return ( pos.getI() >= 0 && pos.getJ() >= 0 && pos.getI() < (int)grid.size() && pos.getJ() < (int)grid[pos.getI()].size() ); }
std::list<Tile*> Tilemap::getRectangle( const TilePos& start, const TilePos& stop, const bool corners /*= true*/ ) { std::list<Tile*> res; int delta_corners = 0; if (! corners) { delta_corners = 1; } /*Rect maxRect( 0, 0, _size, _size ); Rect rect( start.getI()+delta_corners, start.getJ()+delta_corners, stop.getI()-delta_corners, stop.getJ()-delta_corners ); rect.constrainTo( maxRect ); for( int i=rect.getLeft(); i < rect.getRight(); i++ ) for( int j=rect.getTop(); j < rect.getBottom(); j++ ) ret.push_back( &at( TilePos( i, j ) ) ); */ for(int i = start.getI()+delta_corners; i <= stop.getI()-delta_corners; ++i) { if (is_inside( TilePos( i, start.getJ() ) )) { res.push_back( &at(i, start.getJ() )); } if (is_inside( TilePos( i, stop.getJ() ) )) { res.push_back( &at( i, stop.getJ() )); } } for (int j = start.getJ()+1; j <= stop.getJ()-1; ++j) // corners have been handled already { if (is_inside( TilePos( start.getI(), j ) )) { res.push_back(&at(start.getI(), j)); } if (is_inside( TilePos( stop.getI(), j ) )) { res.push_back(&at(stop.getI(), j)); } } return res; }
bool Tilemap::is_inside(const TilePos& pos ) const { return ( pos.getI() >= 0 && pos.getJ()>=0 && pos.getI()<_size && pos.getJ()<_size); }