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)); }
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; }
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 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 ); }
bool RoadPropagator::getPath( const Tile& destination, ConstWayOnTiles& oPathWay ) const { TilePos startPos = _d->startTile.getIJ(); TilePos stopPos = destination.getIJ(); int iStep = (startPos.getI() < stopPos.getI()) ? 1 : -1; int jStep = (startPos.getJ() < stopPos.getJ()) ? 1 : -1; std::cout << "RoadPropagator::getPath" << std::endl; StringHelper::debug( 0xff, "(%d, %d) to (%d, %d)", startPos.getI(), startPos.getJ(), stopPos.getI(), stopPos.getJ() ); if( startPos == stopPos ) { oPathWay.push_back( &_d->startTile ); return true; } std::cout << "propagate by I axis" << std::endl; // propagate on I axis for( TilePos tmp( startPos.getI(), stopPos.getJ() ); ; tmp+=TilePos( iStep, 0 ) ) { const Tile& curTile = _d->tilemap.at( tmp ); if( curTile.getTerrain().isConstructible() || curTile.getTerrain().isRoad() || curTile.getTerrain().isAqueduct() ) { StringHelper::debug( 0xff, "+ (%d, %d)", curTile.getI(), curTile.getJ() ); oPathWay.push_back( &curTile ); } else return false; if (tmp.getI() == stopPos.getI()) break; } std::cout << "propagate by J axis" << std::endl; // propagate on J axis for( int j = startPos.getJ();; j+=jStep ) { const Tile& curTile = _d->tilemap.at( startPos.getI(), j ); if( curTile.getTerrain().isConstructible() || curTile.getTerrain().isRoad() || curTile.getTerrain().isAqueduct() ) { std::cout << "+ (" << curTile.getI() << " " << curTile.getJ() << ") "; oPathWay.push_back( &curTile ); } else return false; if( j == stopPos.getJ() ) break; } return true; }
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(); } }
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 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; }
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() ); }
bool Tilemap::is_inside(const TilePos& pos ) const { return ( pos.getI() >= 0 && pos.getJ()>=0 && pos.getI()<_size && pos.getJ()<_size); }
bool isValid( const TilePos& pos ) { return ( pos.getI() >= 0 && pos.getJ() >= 0 && pos.getI() < (int)grid.size() && pos.getJ() < (int)grid[pos.getI()].size() ); }
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; } }
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; }
std::string Json::serialize(const Variant &data, bool &success, const std::string& tab) { std::string str; success = true; if( !data.isValid() ) // invalid or null? { str = "null"; } else if( (data.type() == Variant::List) || (data.type() == Variant::NStringArray) ) // variant is a list? { StringArray values; const VariantList rlist = data.toList(); for( VariantList::const_iterator it = rlist.begin(); it != rlist.end(); it++) { std::string serializedValue = serialize( *it, "" ); if( serializedValue.empty() ) { success = false; break; } values.push_back( serializedValue ); } str = "[ " + join( values, ", " ) + " ]"; } // else if(data.type() == Variant::Hash) // variant is a hash? // { // const VariantHash vhash = data.toHash(); // QHashIterator<std::string, Variant> it( vhash ); // str = "{ "; // QList<QByteArray> pairs; // // while(it.hasNext()) // { // it.next(); // QByteArray serializedValue = serialize(it.value(), ""); // // if(serializedValue.isNull()) // { // success = false; // break; // } // // pairs << tab.toAscii() + sanitizeString(it.key()).toUtf8() + " : " + serializedValue; // } // // str += join(pairs, ", "); // str += " }"; // } else if(data.type() == Variant::Map) // variant is a map? { VariantMap vmap = data.toMap(); str = "{ \n"; StringArray pairs; for( VariantMap::iterator it = vmap.begin(); it != vmap.end(); it++ ) { std::string serializedValue = serialize( it->second, tab + " "); if( serializedValue.empty()) { //success = false; pairs.push_back( tab + sanitizeString( it->first ) + std::string( " : \"nonSerializableValue\"" ) ); continue; } pairs.push_back( tab + sanitizeString( it->first ) + " : " + serializedValue ); } str += join(pairs, ",\n"); std::string rtab( tab ); rtab.resize( std::max<int>( 0, tab.size() - 2 ) ); str += std::string( "\n" ) + rtab + "}"; } else if((data.type() == Variant::String) || (data.type() == Variant::NByteArray)) // a string or a byte array? { str = sanitizeString( data.toString() ); } else if(data.type() == Variant::Double || data.type() == Variant::Float) // double? { str = StringHelper::format( 0xff, "\"%f\"", data.toDouble() ); if( str.find(".") == std::string::npos && str.find("e") == std::string::npos ) { str += ".0"; } } else if( data.type() == Variant::NTilePos) { TilePos pos = data.toTilePos(); str = StringHelper::format( 0xff, "[ %d, %d ]", pos.getI(), pos.getJ() ); } else if( data.type() == Variant::NSize) { Size size = data.toSize(); str = StringHelper::format( 0xff, "[ %d, %d ]", size.getWidth(), size.getHeight() ); } else if( data.type() == Variant::NPoint) { Point pos = data.toPoint(); str = StringHelper::format( 0xff, "[ %d, %d ]", pos.getX(), pos.getY() ); } else if( data.type() == Variant::NPointF) { PointF pos = data.toPointF(); str = StringHelper::format( 0xff, "[ \"%f\", \"%f\" ]", pos.getX(), pos.getY() ); } else if (data.type() == Variant::Bool) // boolean value? { str = data.toBool() ? "true" : "false"; } else if (data.type() == Variant::ULongLong) // large unsigned number? { str = StringHelper::format( 0xff, "%u", data.toULongLong() ); } else if ( data.canConvert( Variant::LongLong ) ) // any signed number? { str = StringHelper::format( 0xff, "%d", data.toLongLong() ); } else if (data.canConvert( Variant::Long )) { str = StringHelper::format( 0xff, "%d", data.toLongLong() ); } else if (data.canConvert( Variant::String ) ) // can value be converted to string? { // this will catch Date, DateTime, Url, ... str = sanitizeString( data.toString() ); } else { success = false; } if (success) { return str; } else { return std::string(); } }