StreetConnections BuildOperation::calculateStreetConnections(
    const MapCoords& mapCoords, const ToDrawOrToReplaceWith& toDrawOrToReplaceWith) const {

    // Angrenzende Straßen (auf der Karte und im BuildOperationResult) checken
    const Map* map = context.game->getMap();
    auto isStreetThere = [&](const MapCoords& mapCoordsInLamdba) {
        if (map->isStreetAt(mapCoordsInLamdba)) {
            return true;
        }

        auto iter = result.find(mapCoordsInLamdba);
        if (iter != result.cend()) {
            std::shared_ptr<MapObjectFixed>& mapObjectToUse = (toDrawOrToReplaceWith == TO_DRAW) ?
                iter->second->mapObjectToDraw : iter->second->mapObjectToReplaceWith;
            return (std::dynamic_pointer_cast<Street>(mapObjectToUse) != nullptr);
        }

        return false;
    };

    bool isStreetNorth = isStreetThere(MapCoords(mapCoords.x(), mapCoords.y() - 1));
    bool isStreetEast = isStreetThere(MapCoords(mapCoords.x() + 1, mapCoords.y()));
    bool isStreetSouth = isStreetThere(MapCoords(mapCoords.x(), mapCoords.y() + 1));
    bool isStreetWest = isStreetThere(MapCoords(mapCoords.x() - 1, mapCoords.y()));

    StreetConnections streetConnections;
    streetConnections.set(StreetConnections::BIT_POS_NORTH, isStreetNorth);
    streetConnections.set(StreetConnections::BIT_POS_EAST, isStreetEast);
    streetConnections.set(StreetConnections::BIT_POS_SOUTH, isStreetSouth);
    streetConnections.set(StreetConnections::BIT_POS_WEST, isStreetWest);

    return streetConnections;
}
/**
 * @brief Testet das Ausführen einer einfachen Bauoperation.
 */
TEST_F(BuildOperationTest, regularBuild) {
    const MapObjectType* marketplace = configMgr->getMapObjectType("marketplace");

    // Testaufbau
    player->coins = 5000;
    colony->getGoods(configMgr->getGood("tools")).inventory = 20;
    colony->getGoods(configMgr->getGood("wood")).inventory = 40;
    colony->getGoods(configMgr->getGood("bricks")).inventory = 30;

    BuildOperation buildOperation(context, *player);
    buildOperation.requestBuildWhenNothingInTheWay(MapCoords(45, 33), marketplace, Direction::SOUTH);
    buildOperation.requestBuildWhenNothingInTheWay(MapCoords(37, 33), marketplace, Direction::NORTH);
    buildOperation.requestBuildWhenNothingInTheWay(MapCoords(38, 37), marketplace, Direction::WEST);
    buildOperation.doBuild();

    // Testauswertung: Resourcen korrekt abgezogen
    ASSERT_EQ(4400, player->coins);
    ASSERT_EQ(8, colony->getGoods(configMgr->getGood("tools")).inventory);
    ASSERT_EQ(10, colony->getGoods(configMgr->getGood("wood")).inventory);
    ASSERT_EQ(30, colony->getGoods(configMgr->getGood("bricks")).inventory);

    // Testauswertung: Gebäude in die Map übernommen
    assertCorrectBuild({45, 33}, marketplace, Direction::SOUTH, 4, 3);
    assertCorrectBuild({37, 33}, marketplace, Direction::NORTH, 4, 3);
    assertCorrectBuild({38, 37}, marketplace, Direction::WEST, 3, 4);
}
/**
 * @brief Fügt einen Abreißauftrag der Queue hinzu und prüft, ob alle betroffenen Kacheln als "zu entfernen"
 * markiert werden
 */
TEST_F(BuildOperationTest, demolishMapObject) {
    BuildOperation buildOperation(context, *player);
    buildOperation.requestDemolish(*context.game->getMap()->getMapObjectFixedAt({48, 40}));

    BuildOperationResult result = buildOperation.getResult();
    ASSERT_EQ(BuildOperationResult::OK, result.result);
    ASSERT_EQ(4, result.size());
    ASSERT_EQ(true, result.at(MapCoords(48, 40))->deleteMapObjectThere);
    ASSERT_EQ(true, result.at(MapCoords(49, 40))->deleteMapObjectThere);
    ASSERT_EQ(true, result.at(MapCoords(48, 41))->deleteMapObjectThere);
    ASSERT_EQ(true, result.at(MapCoords(49, 41))->deleteMapObjectThere);
}
    virtual void SetUp() {
        GameTest::SetUp();

        FourthDirection southView = Direction::SOUTH;

        northernForest1 = game->addHarvestable(
            MapCoords(30, 30), configMgr->getMapObjectType("northern-forest1"), southView);
        northernForest1->setAge(1.0);

        northernForest2 = game->addHarvestable(
            MapCoords(30, 31), configMgr->getMapObjectType("northern-forest2"), southView);
        northernForest2->setAge(1.3);
    }
    virtual void SetUp() {
        GameTest::SetUp();

        sheepFarm = dynamic_cast<Building*>(game->addStructure(
            MapCoords(28, 30), configMgr->getMapObjectType("sheep-farm"),
            Direction::SOUTH, game->getPlayer(0)));
        cattleFarm = dynamic_cast<Building*>(game->addStructure(
            MapCoords(38, 28), configMgr->getMapObjectType("cattle-farm"),
            Direction::SOUTH, game->getPlayer(0)));

        // Schafe/Rinder so einstellen, dass sie ewig zum Grasfressen brauchen.
        // Wir wollen nicht, dass während des Tests welche zurücklaufen.
        configMgr->getMapObjectType("sheep")->secondsToProduce = 9999;
    }
void WindowManager::OnMouseMotionEvent(unsigned int x, unsigned int y)
{
   MapCoords(x, y);

   // hand over to root window
   m_spRootWindow->OnMouseMotionEvent(x, y);

   // check if mouse left any rectangle
   if (!m_listAllTrackMouseLeaveEntries.empty())
   {
      std::list<T_TrackMouseLeaveEntry>::iterator iter = m_listAllTrackMouseLeaveEntries.begin(),
         stop = m_listAllTrackMouseLeaveEntries.end();

      Point p(x,y);
      while (iter != stop)
      {
         const T_TrackMouseLeaveEntry& entry = *iter;
         if (!entry.first.IsInside(p))
         {
            entry.second();

            // remove entry; returns iterator to next element
            iter = m_listAllTrackMouseLeaveEntries.erase(iter);
         }
         else
            ++iter;
      }
   }
}
Exemple #7
0
	Cube* Map::Get(size_t x, size_t y, size_t z) {		
		ItCubeInstance res = m_data.find(MapCoords(x,y,z));
		if( res == m_data.end() )
			return NULL;

		return std::get<0>(res->second);
	}
/**
 * @brief Spezialtest "halbe Kreuzung"
 *
 * Wir bauen einen Feldweg von (46, 31) nach (46, 33).
 * Allerdings reicht das Geld nur für eine Kachel.
 *
 * Wir erwarten, dass beim Bau nur ein T-Stück entsteht, obwohl eine Kreuzung gezogen wurde.
 */
TEST_F(BuildOperationTest, partialCrossroads) {
    const Map* map = game->getMap();
    const MapObjectType* farmRoad = configMgr->getMapObjectType("farm-road");

    // Testaufbau
    player->coins = 5;

    BuildOperation buildOperation(context, *player);
    for (int y = 31; y <= 33; y++) {
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(46, y), farmRoad, Direction::SOUTH);
    }
    buildOperation.doBuild();

    // Testauswertung
    ASSERT_EQ(0, player->coins);

    assertCorrectBuild({46, 31}, farmRoad, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_SOUTH,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({46, 31}))->streetConnections);

    assertCorrectBuild({46, 32}, farmRoad, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_NORTH | StreetConnections::BIT_MASK_EAST | StreetConnections::BIT_MASK_WEST,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({46, 32}))->streetConnections);

    ASSERT_TRUE(map->getMapObjectFixedAt({46, 33}) == nullptr);
}
/**
 * @brief Testet das Ausführen einer Bauoperation, die Straßen überbaut bzw. anpasst
 *
 * Ziehe Straßenzug von (46, 31) nach (46, 36).
 * 4 Kacheln kommen neu dazu, 2 werden überbaut (wovon nur eine was kostet).
 */
TEST_F(BuildOperationTest, overbuildAndAdeptStreet) {
    const Map* map = game->getMap();

    const MapObjectType* farmRoad = configMgr->getMapObjectType("farm-road");
    const MapObjectType* cobbledStreet = configMgr->getMapObjectType("cobbled-street");

    // Testaufbau
    player->coins = 1000;
    colony->getGoods(configMgr->getGood("tools")).inventory = 10;
    colony->getGoods(configMgr->getGood("wood")).inventory = 20;
    colony->getGoods(configMgr->getGood("bricks")).inventory = 25;

    BuildOperation buildOperation(context, *player);
    for (int y = 31; y <= 36; y++) {
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(46, y), cobbledStreet, Direction::SOUTH);
    }

    unsigned long mapObjectsCountBefore = game->getMap()->getMapObjects().size();
    buildOperation.doBuild();
    unsigned long mapObjectsCountAfter = game->getMap()->getMapObjects().size();

    // Testauswertung: Sicherstellen, dass die Anzahl der Map-Objekte stimmt.
    // Nicht, dass es zwei Map-Objekte auf derselben Koordinate gibt
    ASSERT_EQ(mapObjectsCountBefore + 4, mapObjectsCountAfter);

    // Testauswertung: Resourcen korrekt abgezogen (nur 5 der 6 Kacheln kosten was)
    ASSERT_EQ(975, player->coins);
    ASSERT_EQ(10, colony->getGoods(configMgr->getGood("tools")).inventory);
    ASSERT_EQ(20, colony->getGoods(configMgr->getGood("wood")).inventory);
    ASSERT_EQ(20, colony->getGoods(configMgr->getGood("bricks")).inventory);

    // Testauswertung: Straßen in die Map übernommen bzw. angepasst
    assertCorrectBuild({46, 31}, cobbledStreet, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_SOUTH,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({46, 31}))->streetConnections);

    assertCorrectBuild({46, 32}, cobbledStreet, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_NORTH | StreetConnections::BIT_MASK_EAST |
              StreetConnections::BIT_MASK_SOUTH | StreetConnections::BIT_MASK_WEST,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({46, 32}))->streetConnections);

    for (int y = 33; y <= 35; y++) {
        assertCorrectBuild({ 46, y }, cobbledStreet, Direction::SOUTH, 1, 1);
        ASSERT_EQ(StreetConnections::BIT_MASK_NORTH | StreetConnections::BIT_MASK_SOUTH,
                  dynamic_cast<const Street*>(map->getMapObjectFixedAt({ 46, y }))->streetConnections);
    }

    assertCorrectBuild({46, 36}, cobbledStreet, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_NORTH | StreetConnections::BIT_MASK_EAST | StreetConnections::BIT_MASK_WEST,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({46, 36}))->streetConnections);

    assertCorrectBuild({45, 32}, farmRoad, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_EAST | StreetConnections::BIT_MASK_WEST,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({45, 32}))->streetConnections);

    assertCorrectBuild({47, 32}, farmRoad, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_WEST,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({47, 32}))->streetConnections);
}
Exemple #10
0
    virtual void SetUp() {
        GameTest::SetUp();

        weavingMill = dynamic_cast<Building*>(game->addStructure(
            MapCoords(31, 30), configMgr->getMapObjectType("weaving-mill1"),
            Direction::SOUTH, game->getPlayer(0)));
        sheepFarm1 = dynamic_cast<Building*>(game->addStructure(
            MapCoords(35, 35), configMgr->getMapObjectType("sheep-farm"),
            Direction::SOUTH, game->getPlayer(0)));
        sheepFarm2 = dynamic_cast<Building*>(game->addStructure(
            MapCoords(30, 35), configMgr->getMapObjectType("sheep-farm"),
            Direction::SOUTH, game->getPlayer(0)));

        // keine Wartezeit am Träger einstellen
        weavingMill->nextCarrierMinTicks = 0;

        ASSERT_TRUE(weavingMill->carriers.empty());
    }
Exemple #11
0
	Cube* Map::GetByPixel(GLfloat x, GLfloat y, GLfloat z){
		GLfloat cubeSize=Cube::m_size;
		x+=cubeSize*0.5;
		y+=cubeSize*0.5;
		z+=cubeSize*0.5;
		ItCubeInstance res = m_data.find(MapCoords((size_t)(x/Cube::m_size),(size_t)(y/Cube::m_size),(size_t)(z/Cube::m_size)));
		if( res == m_data.end() )
			return NULL;
		
		return std::get<0>(res->second);
	}
Exemple #12
0
/**
 * @brief Testet, ob die Webstube einen Träger zur Schaffarm mit dem volleren Lager schickt
 */
TEST_F(CarrierTest, checkThatCarrierIsSentToFullerInventoryFirst) {
    // Testaufbau
    sheepFarm1->productionSlots.output.inventory = 2;
    sheepFarm2->productionSlots.output.inventory = 3;

    // Testdurchführung
    game->update(500);
    ASSERT_EQ(1, weavingMill->carriers.size());

    const Carrier* carrier = *weavingMill->carriers.cbegin();
    ASSERT_EQ(MapCoords(30, 35), *carrier->route.crbegin());
}
Exemple #13
0
	bool Map::Exists(size_t x, size_t y, size_t z){
		/*if( x > m_width || x < 0 ||
		y > m_height || y < 0 ||
		z > m_depth || z < 0 )
			throw std::out_of_range("Position is out of the map in Exists");*/
			
		if( m_data.find(MapCoords(x,y,z)) == m_data.end() ){
			return false;
		}else{
			return true;
		}
	}
bool WindowManager::OnMouseButtonEvent(bool bPressed, int iMouseButton, unsigned int x, unsigned int y)
{
   MapCoords(x, y);

   // hand over to root window
   bool bRet = m_spRootWindow->OnMouseButtonEvent(bPressed, iMouseButton, x, y);

   if (!bPressed)
      ClearTrackMouseUpWindows(iMouseButton);

   return bRet;
}
Exemple #15
0
void Map::moveMapObject(MapObjectMoving* mapObject, const DoubleMapCoords newMapCoords) {
    const int mapWidth = mapObject->getMapWidth();
    const int mapHeight = mapObject->getMapHeight();

    // Fläche auf den MapTiles ummarkieren.
    // Wir markieren mehrere Kacheln, wenn sich das Objekt zwischen zwei Kacheln befindet.
    const DoubleMapCoords& mapCoords = mapObject->getMapCoords();
    for (int my = int(std::floor(mapCoords.y())); my < int(std::ceil(mapCoords.y())) + mapHeight; my++) {
        for (int mx = int(std::floor(mapCoords.x())); mx < int(std::ceil(mapCoords.x())) + mapWidth; mx++) {
            getMapTileAt(MapCoords(mx, my))->mapObjectsMoving.remove(mapObject);
        }
    }

    mapObject->setMapCoords(newMapCoords);

    for (int my = int(std::floor(newMapCoords.y())); my < int(std::ceil(newMapCoords.y())) + mapHeight; my++) {
        for (int mx = int(std::floor(newMapCoords.x())); mx < int(std::ceil(newMapCoords.x())) + mapWidth; mx++) {
            getMapTileAt(MapCoords(mx, my))->mapObjectsMoving.push_back(mapObject);
        }
    }
}
/**
 * @brief Überprüft, ob man die Objekte in der richtigen Reihenfolge wieder aus der Liste kriegt
 */
TEST_F(BuildOperationTest, orderOfInsertion) {
    const MapObjectType* pioneersHouse1 = configMgr->getMapObjectType("pioneers-house1");

    BuildOperation buildOperation(context, *player);

    buildOperation.requestBuild({36, 37}, pioneersHouse1, Direction::EAST);
    buildOperation.requestBuild({39, 40}, pioneersHouse1, Direction::EAST);
    buildOperation.requestBuild({36, 39}, pioneersHouse1, Direction::EAST);
    buildOperation.requestBuild({39, 34}, pioneersHouse1, Direction::EAST);

    const std::list<MapObjectToBuild>& mapObjectsToBuild = buildOperation.getMapObjectsToBuild();
    auto iter = mapObjectsToBuild.cbegin();

    ASSERT_EQ(MapCoords(36, 37), iter->mapCoords);
    iter++;
    ASSERT_EQ(MapCoords(39, 40), iter->mapCoords);
    iter++;
    ASSERT_EQ(MapCoords(36, 39), iter->mapCoords);
    iter++;
    ASSERT_EQ(MapCoords(39, 34), iter->mapCoords);
    iter++;
    ASSERT_TRUE(iter == mapObjectsToBuild.cend());
}
Exemple #17
0
void Map::deleteMapObject(MapObject* mapObject) {
    mapObjects.remove(mapObject);

    const int mapWidth = mapObject->getMapWidth();
    const int mapHeight = mapObject->getMapHeight();

    // Unterscheidung nach fixen und beweglichen Map-Objekten
    MapObjectFixed* mapObjectFixed = dynamic_cast<MapObjectFixed*>(mapObject);
    if (mapObjectFixed != nullptr) {
        const MapCoords& mapCoords = mapObjectFixed->getMapCoords();

        // Fläche auf den MapTiles als belegt markieren
        for (int my = mapCoords.y(); my < mapCoords.y() + mapHeight; my++) {
            for (int mx = mapCoords.x(); mx < mapCoords.x() + mapWidth; mx++) {
                getMapTileAt(MapCoords(mx, my))->mapObjectFixed = nullptr;
            }
        }
    }
    else {
        MapObjectMoving* mapObjectMoving = dynamic_cast<MapObjectMoving*>(mapObject);
        if (mapObjectMoving != nullptr) {
            // Fläche auf den MapTiles ummarkieren.
            // Es sind u.U. mehrere Kacheln markiert, wenn sich das Objekt zwischen zwei Kacheln befindet.
            const DoubleMapCoords& mapCoords = mapObjectMoving->getMapCoords();
            for (int my = int(std::floor(mapCoords.y())); my < int(std::ceil(mapCoords.y())) + mapHeight; my++) {
                for (int mx = int(std::floor(mapCoords.x())); mx < int(std::ceil(mapCoords.x())) + mapWidth; mx++) {
                    getMapTileAt(MapCoords(mx, my))->mapObjectsMoving.remove(mapObjectMoving);
                }
            }
        }
        else {
            assert (false);
        }
    }

    delete mapObject;
}
Exemple #18
0
/**
 * @brief Testet, ob bei gleich vollem Lager der Träger zum Gebäude schickt,
 * was länger nicht abgeholt wurde. Webstube muss aus 2 Schaffarmen die richtige wählen.
 */
TEST_F(CarrierTest, checkThatCarrierIsSentByLastCollectionWhenSameInventory) {
    // Testaufbau
    sheepFarm1->productionSlots.output.inventory = 1;
    sheepFarm2->productionSlots.output.inventory = 1;

    sheepFarm1->lastGoodsCollections = 42;
    sheepFarm2->lastGoodsCollections = 46;

    // Testdurchführung
    game->update(500);
    ASSERT_EQ(1, weavingMill->carriers.size());

    const Carrier* carrier = *weavingMill->carriers.cbegin();
    ASSERT_EQ(MapCoords(35, 35), *carrier->route.crbegin());
}
/**
 * @brief Überprüft, ob Überlappungen beim Hinzufügen von Bauaufträgen korrekt erkannt werden.
 */
TEST_F(BuildOperationTest, overlappingRequestBuild) {
    const MapObjectType* marketplace = configMgr->getMapObjectType("marketplace");

    {
        // Ersten Marktplatz setzen
        BuildOperation buildOperation(context, *player);
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(45, 33), marketplace, Direction::SOUTH);
        ASSERT_EQ(12, buildOperation.getResult().size());

        // Weiteren Marktplatz überlappen -> es darf sich nix tun
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(48, 32), marketplace, Direction::WEST);
        ASSERT_EQ(12, buildOperation.getResult().size());

        // Weiteren Marktplatz überlappen über Bauqueue und bestehendes Objekt  -> es darf sich auch nix tun
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(43, 31), marketplace, Direction::WEST);
        ASSERT_EQ(12, buildOperation.getResult().size());

        // Weiteren Marktplatz korrekt hinzufügen
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(49, 33), marketplace, Direction::EAST);
        ASSERT_EQ(24, buildOperation.getResult().size());
    }

    {
        const MapCoords mapCoords(47, 39);

        // Mit requestBuildWhenNothingInTheWay darf ich auf der Karte nicht überlappen
        BuildOperation buildOperation(context, *player);
        buildOperation.requestBuildWhenNothingInTheWay(mapCoords, marketplace, Direction::SOUTH);
        ASSERT_EQ(0, buildOperation.getResult().size());

        // Mit requestBuild schon
        buildOperation.requestBuild(mapCoords, marketplace, Direction::SOUTH);
        ASSERT_EQ(12, buildOperation.getResult().size());
    }

}
void PFO_CubeColorBlockGL::GetCoords(int            indx,
                                 SC_CoordArray& topCoords,
                                 SC_CoordArray& bottomCoords,
                                 const double&  reduceFactor)
{

    cubeData->GetBlockCoords(indx, topCoords, bottomCoords);

    if (reduceFactor < 0.999)
    {
        Line3D pointLine;
        pointLine.stPt = cubeData->GetCoord(indx);

        for (int k = 0; k < topCoords.Size(); k++)
        {
            pointLine.endPt = topCoords[k];
            topCoords[k] = pointLine.PointOnLine(reduceFactor);
            pointLine.endPt = bottomCoords[k];
            bottomCoords[k] = pointLine.PointOnLine(reduceFactor);
        }
    }
    MapCoords(topCoords);
    MapCoords(bottomCoords);
}
Exemple #21
0
void Map::addMapObject(MapObject* mapObject) {
    // Objekt in die Liste einreihen
    mapObjects.push_front(mapObject);

    int mapWidth = mapObject->getMapWidth();
    int mapHeight = mapObject->getMapHeight();

    // Unterscheidung nach fixen und beweglichen Map-Objekten
    // Fläche auf den MapTiles als belegt markieren

    MapObjectFixed* mapObjectFixed = dynamic_cast<MapObjectFixed*>(mapObject);
    if (mapObjectFixed != nullptr) {
        const MapCoords& mapCoords = mapObjectFixed->getMapCoords();

        for (int my = mapCoords.y(); my < mapCoords.y() + mapHeight; my++) {
            for (int mx = mapCoords.x(); mx < mapCoords.x() + mapWidth; mx++) {
                getMapTileAt(MapCoords(mx, my))->mapObjectFixed = mapObjectFixed;
            }
        }
        return;
    }

    MapObjectMoving* mapObjectMoving = dynamic_cast<MapObjectMoving*>(mapObject);
    if (mapObjectMoving != nullptr) {
        const DoubleMapCoords& mapCoords = mapObjectMoving->getMapCoords();

        for (int my = int(std::floor(mapCoords.y())); my < int(std::ceil(mapCoords.y())) + mapHeight; my++) {
            for (int mx = int(std::floor(mapCoords.x())); mx < int(std::ceil(mapCoords.x())) + mapWidth; mx++) {
                getMapTileAt(MapCoords(mx, my))->mapObjectsMoving.push_back(mapObjectMoving);
            }
        }
        return;
    }

    assert(false);
}
/**
 * @brief Überprüft, ob korrekt erkannt wird, wenn was im Weg is
 */
TEST_F(BuildOperationTest, somethingInTheWay) {
    const MapObjectType* tavern = configMgr->getMapObjectType("tavern");

    {
        // Wirtshaus normal einsetzen: genug Platz
        BuildOperation buildOperation(context, *player);
        buildOperation.requestBuild(MapCoords(45, 33), tavern, Direction::SOUTH);
        const BuildOperationResult& result = buildOperation.getResult();
        ASSERT_EQ(BuildOperationResult::OK, result.result);
        ASSERT_EQ(6, result.size());
        ASSERT_EQ(true, result.at(MapCoords(46, 35))->buildAllowed);
    }

    {
        // Wirtshaus gedreht einsetzen: genug Platz
        BuildOperation buildOperation(context, *player);
        buildOperation.requestBuild(MapCoords(45, 33), tavern, Direction::WEST);
        const BuildOperationResult& result = buildOperation.getResult();
        ASSERT_EQ(BuildOperationResult::OK, result.result);
        ASSERT_EQ(6, result.size());
        ASSERT_EQ(true, result.at(MapCoords(47, 34))->buildAllowed);
    }

    {
        // Wirtshaus normal einsetzen: ein Feldweg im Weg
        BuildOperation buildOperation(context, *player);
        buildOperation.requestBuild(MapCoords(39, 34), tavern, Direction::NORTH);
        const BuildOperationResult& result = buildOperation.getResult();
        ASSERT_EQ(BuildOperationResult::NOT_OK, result.result);
        ASSERT_EQ(6, result.size());
        ASSERT_EQ(false, result.at(MapCoords(40, 35))->buildAllowed);
    }

    {
        // Wirtshaus gedreht einsetzen: ein Feldweg im Weg
        BuildOperation buildOperation(context, *player);
        buildOperation.requestBuild(MapCoords(38, 36), tavern, Direction::EAST);
        const BuildOperationResult& result = buildOperation.getResult();
        ASSERT_EQ(BuildOperationResult::NOT_OK, result.result);
        ASSERT_EQ(6, result.size());
        ASSERT_EQ(false, result.at(MapCoords(40, 37))->buildAllowed);
    }
}
/**
 * @brief Test, der Straßenanpassung testet, wenn die Resourcen nicht mehr reichen.
 * Beim Bau dürfen nur Ersetzungen vorgenommen werden, die angrenzen an Straßen, wofür die Resourcen reichen.
 *
 * Wir bauen einen Feldweg von (43, 44) nach (47, 44).
 * Allerdings reicht das Geld nur für zwei Kacheln.
 */
TEST_F(BuildOperationTest, adeptStreetsOutOfResources) {
    const Map* map = game->getMap();
    const MapObjectType* farmRoad = configMgr->getMapObjectType("farm-road");
    const MapObjectType* cobbledStreet = configMgr->getMapObjectType("cobbled-street");

    // Testaufbau
    player->coins = 10;

    BuildOperation buildOperation(context, *player);
    for (int x = 43; x <= 47; x++) {
        buildOperation.requestBuildWhenNothingInTheWay(MapCoords(x, 44), farmRoad, Direction::SOUTH);
    }
    buildOperation.doBuild();

    // Testauswertung

    // Resourcen korrekt nur für 2 Kacheln abgezogen
    ASSERT_EQ(0, player->coins);

    // Bau korrekt
    assertCorrectBuild({43, 44}, farmRoad, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_EAST | StreetConnections::BIT_MASK_SOUTH,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({43, 44}))->streetConnections);

    assertCorrectBuild({44, 44}, farmRoad, Direction::SOUTH, 1, 1);

    for (int x = 45; x <= 47; x++) {
        ASSERT_TRUE(game->getMap()->getMapObjectFixedAt({x, 44}) == nullptr);
    }

    // partielle Anpassung an (44, 44): nur West! Für die Ost-Verbindung reichen die Resourcen nicht
    ASSERT_EQ(StreetConnections::BIT_MASK_WEST,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({44, 44}))->streetConnections);

    // Anpassung an (43, 45)
    assertCorrectBuild({43, 45}, cobbledStreet, Direction::SOUTH, 1, 1);
    ASSERT_EQ(StreetConnections::BIT_MASK_NORTH,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({43, 45}))->streetConnections);

    // Keine Anpassungen an (45, 45), (47, 45), (47, 43), da die Resourcen nicht reichen
    ASSERT_EQ(0, dynamic_cast<const Street*>(map->getMapObjectFixedAt({45, 45}))->streetConnections);
    ASSERT_EQ(0, dynamic_cast<const Street*>(map->getMapObjectFixedAt({47, 45}))->streetConnections);
    ASSERT_EQ(StreetConnections::BIT_MASK_NORTH,
              dynamic_cast<const Street*>(map->getMapObjectFixedAt({47, 43}))->streetConnections);
}
void BuildOperation::rebuildResultDemolish() {
    for (const MapObjectToBuild& mapObjectToBuild : mapObjectsToBuild) {
        const MapCoords& mapCoords = mapObjectToBuild.mapCoords;
        const MapObjectFixed* mapObjectFixed = context.game->getMap()->getMapObjectFixedAt(mapCoords);
        assert(mapObjectFixed != nullptr);

        std::shared_ptr<BuildOperationResultBit> resultBit(new BuildOperationResultBit());
        resultBit->buildAllowed = true;
        resultBit->deleteMapObjectThere = true;

        // ResultBit den Koordinaten zuweisen
        for (int y = 0, my = mapObjectToBuild.mapCoords.y(); y < mapObjectFixed->getMapHeight(); y++, my++) {
            for (int x = 0, mx = mapObjectToBuild.mapCoords.x(); x < mapObjectFixed->getMapWidth(); x++, mx++) {
                result[MapCoords(mx, my)] = resultBit;
            }
        }
    }

    // TODO Straßen umbiegen, wenn wir löschen
}
Exemple #25
0
	/* Update the visibility of the cube x,y,z.
	 * add: true = adding a cube, false = removing */
	void Map::UpdateVisibility(size_t x, size_t y, size_t z) throw(std::out_of_range) {	
		ItCubeInstance cube, neighbour1, neighbour2, neighbour3, neighbour4, neighbour5, neighbour6, end;
		cube = m_data.find(MapCoords(x,y,z));
		end = m_data.end();
		if( cube == end )
			throw std::out_of_range("Cube is not in the map in UpdateVisibility");
		neighbour1 = m_data.find(MapCoords(x-1,y,z));
		neighbour2 = m_data.find(MapCoords(x+1,y,z));
		neighbour3 = m_data.find(MapCoords(x,y-1,z));
		neighbour4 = m_data.find(MapCoords(x,y+1,z));
		neighbour5 = m_data.find(MapCoords(x,y,z-1));
		neighbour6 = m_data.find(MapCoords(x,y,z+1));
		
		if( std::get<1>(cube->second) && neighbour1 != end && neighbour2 != end && neighbour3 != end
		&& neighbour4 != end && neighbour5 != end && neighbour6 != end ) {
			// It can be hidden
			Cube* pointer = std::get<0>(cube->second);
			cube->second = std::make_tuple(pointer,false);
		}
		else if( !std::get<1>(cube->second) ) {
			Cube* pointer = std::get<0>(cube->second);
			cube->second = std::make_tuple(pointer,true);
		}
	}
    virtual void SetUp() {
        GameTest::SetUp();

        FourthDirection southView = Direction::SOUTH;
        Player* player = game->getPlayer(0);
        const MapObjectType* cobbledStreet = configMgr->getMapObjectType("cobbled-street");

        office1 = dynamic_cast<Building*>(game->getMap()->getMapObjectFixedAt(MapCoords(28, 18)));

        // keine Wartezeit am Träger einstellen
        office1->nextCarrierMinTicks = 0;

        // Rinderfarm bauen und Zick-Zack-Straße zum Kontor ziehen
        game->addStreet(MapCoords(28, 20), cobbledStreet, southView, player, StreetConnections("0010"));
        game->addStreet(MapCoords(28, 21), cobbledStreet, southView, player, StreetConnections("1010"));
        game->addStreet(MapCoords(28, 22), cobbledStreet, southView, player, StreetConnections("1001"));
        game->addStreet(MapCoords(27, 22), cobbledStreet, southView, player, StreetConnections("0101"));
        game->addStreet(MapCoords(26, 22), cobbledStreet, southView, player, StreetConnections("0110"));
        game->addStreet(MapCoords(26, 23), cobbledStreet, southView, player, StreetConnections("1010"));
        game->addStreet(MapCoords(26, 24), cobbledStreet, southView, player, StreetConnections("1010"));
        game->addStreet(MapCoords(26, 25), cobbledStreet, southView, player, StreetConnections("1010"));
        game->addStreet(MapCoords(26, 26), cobbledStreet, southView, player, StreetConnections("1000"));
        cattleFarm = dynamic_cast<Building*>(game->addStructure(
            MapCoords(26, 27), configMgr->getMapObjectType("cattle-farm"), southView, player));
    }
/**
 * @brief Test, ob der Marktkarren die Route korrekt abläuft. Besonders wichtig ist der Übergang zwischen 2 Kacheln
 * Wir machen die Rinderfarm-Lager voll, damit das Kontor abholen muss und testen damit, ob der Marktkarren
 * ordnungsgemäß läuft.
 *
 * Siehe `doc/carrier-walking-test.xcf` für den Testaufbau und die einzelnen Schritte
 */
TEST_F(CarrierWalkingTest, checkThatCarrierWalksCorrectlyOnTheStreet) {
    // Da es keine halbe Ticks gibt, treten Rundungsfehler zwischen den echten Koordinaten und den theoretisch
    // errechneten Koordinaten auf. Dies ist der maximale Fehler, den die Tests erlauben.
    const double allowedCoordsError = 0.01;

    Colony* colony = office1->getColony();
    const Good* cattleGood = configMgr->getGood("cattle");

    // Lager voll machen
    cattleFarm->productionSlots.output.increaseInventory(999);

    // Anfangsbedingungen: kein Marktkarren da, Gebäudelager voll und bereit zur Abholung, 5t in der Kolonie
    ASSERT_EQ(5, colony->getGoods(cattleGood).inventory);

    ASSERT_TRUE(office1->carriers.empty());

    ASSERT_TRUE(cattleFarm->productionSlots.output.isInventoryFull());
    ASSERT_FALSE(cattleFarm->productionSlots.output.markedForPickup);

    // "Start": Erstes Update nach 1ms aufrufen. Danach sollte nun ein Marktkarren mit Abholauftrag da sein.
    office1->setLastUpdateTicks(0);
    game->update(1);

    ASSERT_EQ(1, office1->carriers.size());
    const Carrier* carrier = *office1->carriers.cbegin();

    ASSERT_EQ(1, office1->getLastUpdateTicks());
    ASSERT_EQ(1, carrier->getLastUpdateTicks());
    ASSERT_EQ(carrier->owningBuilding, office1);
    ASSERT_TRUE(carrier->route.back() == MapCoords(26, 27));
    ASSERT_TRUE(carrier->onOutboundTrip);
    ASSERT_EQ("cattle", carrier->carriedGoods.good->name);
    ASSERT_EQ(0, carrier->carriedGoods.inventory);
    ASSERT_TRUE(carrier->getMapCoords() == DoubleMapCoords(28, 19));
    ASSERT_TRUE(carrier->getCurrentMovingDirection() == Direction::SOUTH);

    ASSERT_TRUE(cattleFarm->productionSlots.output.markedForPickup);

    // "Step 1": Testet Bewegung innerhalb einer Kachel
    // Nach einer Sekunde: Der Marktkarren muss nun eine dreiviertelte Kachel (speed = 0.75, siehe EconomicsMgr) bewegt sein.
    game->update(1000); // Träger sollte sich (1000 * 0,75 =) 0,75 Kacheln fortbewegt haben

    ASSERT_EQ(1001, office1->getLastUpdateTicks());
    ASSERT_EQ(1001, carrier->getLastUpdateTicks());
    ASSERT_NEAR(28, carrier->getMapCoords().x(), allowedCoordsError);
    ASSERT_NEAR(19.75, carrier->getMapCoords().y(), allowedCoordsError);
    ASSERT_TRUE(carrier->getCurrentMovingDirection() == Direction::SOUTH);

    // "Step 2": Test, wenn eine Kachel geradlinig übersprungen wird
    game->update(2500); // Träger sollte sich (2500 * 0,75 =) 1,875 Kacheln fortbewegt haben

    ASSERT_EQ(3501, office1->getLastUpdateTicks());
    ASSERT_EQ(3501, carrier->getLastUpdateTicks());
    ASSERT_NEAR(28, carrier->getMapCoords().x(), allowedCoordsError);
    ASSERT_NEAR(21.625, carrier->getMapCoords().y(), allowedCoordsError);
    ASSERT_TRUE(carrier->getCurrentMovingDirection() == Direction::SOUTH);

    // "Step 3": Test, wenn mehrere Kacheln, auch über Ecken hinweg, übersprungen werden
    game->update(8000); // Träger sollte sich (8000 * 0,75 =) 6 Kacheln fortbewegt haben

    ASSERT_EQ(11501, office1->getLastUpdateTicks());
    ASSERT_EQ(11501, carrier->getLastUpdateTicks());
    ASSERT_NEAR(26, carrier->getMapCoords().x(), allowedCoordsError);
    ASSERT_NEAR(25.625, carrier->getMapCoords().y(), allowedCoordsError);
    ASSERT_TRUE(carrier->getCurrentMovingDirection() == Direction::SOUTH);

    // Am Gebäude ankommen, sollte den Rücktransport triggern
    game->update(2000); // Träger sollte sich (2000 * 0,75 =) 1,5 Kacheln fortbewegt haben. Ziel wurde bereits nach 1,375 Kacheln erreicht.

    ASSERT_EQ(1, office1->carriers.size());
    carrier = *office1->carriers.cbegin();

    ASSERT_EQ(13501, office1->getLastUpdateTicks());
    ASSERT_EQ(13501, carrier->getLastUpdateTicks());
    ASSERT_TRUE(carrier->route.back() == MapCoords(28, 19));
    ASSERT_FALSE(carrier->onOutboundTrip);
    ASSERT_EQ("cattle", carrier->carriedGoods.good->name);
    ASSERT_EQ(4, carrier->carriedGoods.inventory); // Rinderfarm kann nur 4 Tonnen halten
    ASSERT_TRUE(carrier->getMapCoords() == DoubleMapCoords(26, 27));
    ASSERT_TRUE(carrier->getCurrentMovingDirection() == Direction::NORTH);

    ASSERT_EQ(0, cattleFarm->productionSlots.output.inventory);
    ASSERT_FALSE(cattleFarm->productionSlots.output.markedForPickup);

    // Ein großer Zeitsprung und der Rücktransport sollte längst erledigt sein.
    game->update(20000);

    ASSERT_TRUE(office1->carriers.empty());
    ASSERT_EQ(9, colony->getGoods(cattleGood).inventory);
}
/* Fall 1: ganz normal
 *
 *   x=23
 *   |
 * □□▨□□
 * □▨▨▨□
 * ▨▨▣▨▨ — y=12
 * □▨▨▨□
 * □□▨□□
 */
TEST(CatchmentAreaTest, isInsideCatchmentArea_Normal) {
    Building building;
    building.setMapWidth(1);
    building.setMapHeight(1);
    building.setMapCoords(MapCoords(23, 12));
    building.setView(Direction::SOUTH);

    RectangleData<char>* catchmentArea = new RectangleData<char>(5, 5);
    memcpy(catchmentArea->data, "0010001110111110111000100", 25);

    MapObjectType mapObjectType;
    mapObjectType.catchmentArea.reset(catchmentArea);
    building.setMapObjectType(&mapObjectType);

    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(23, 12))); // Gebäude selber
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(22, 12))); // Punkte innerhalb Einzugsbereich
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(21, 12)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(23, 11)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(23, 10)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(24, 13)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(21, 10))); // Punkte außerhalb Einzugsbereich
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(22, 10)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(21, 11)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(23, 9))); // Außerhalb des Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(23, 15)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(20, 12)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(26, 12)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(0, 0)));
}
/* Fall 3: prüft, ob sich alles korrekt verhält, wenn das Gebäude gedreht ist.
 *
 *    Süd                  Ost                Nord                 West
 *   =====                =====              ======               ======
 *
 *    x=88                 x=88                x=88                 x=88
 *    |                    |                   |                    |
 * □□□□□□□□□              □□□□              ▨▨▨□□□□□□              □▨▨▨
 * □▨▨▣▣▣▨▨▨ — y=42       □▨▨□              ▨▨▨▣▣▣▨▨□ — y=42       □▨▨▨
 * □▨▨▣▣▣▨▨▨              □▨▨□              ▨▨▨▣▣▣▨▨□              □▨▨▨
 * □□□□□□▨▨▨              □▣▣□ — y=42       □□□□□□□□□              □▣▣□ — y=42
 *                        □▣▣□                                     □▣▣□
 *                        □▣▣□                                     □▣▣□
 *                        ▨▨▨□                                     □▨▨□
 *                        ▨▨▨□                                     □▨▨□
 *                        ▨▨▨□                                     □□□□
 *
 * Wir prüfen immer dieselben MapCoords im Test.
 * Je nach Gebäude-View sind wir dann innerhalb ..oder außerhalb des Einzugsbereichs.
 */
TEST(CatchmentAreaTest, isInsideCatchmentArea_Views) {
    Building building;
    building.setMapCoords(MapCoords(88, 42));
    building.setView(Direction::SOUTH);

    RectangleData<char>* catchmentArea = new RectangleData<char>(9, 4);
    memcpy(catchmentArea->data, "000000000011111111011111111000000111", 36);

    MapObjectType mapObjectType;
    mapObjectType.catchmentArea.reset(catchmentArea);
    building.setMapObjectType(&mapObjectType);

    building.setMapWidth(3);
    building.setMapHeight(2);
    building.setView(Direction::SOUTH);
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(88, 42))); // Mitte

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 41))); // Ecken des Quer-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 41)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 44)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 44)));

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 39)));  // Ecken des Hochkant-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 39)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 47)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 47)));

    building.setMapWidth(2);
    building.setMapHeight(3);
    building.setView(Direction::EAST);
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(88, 42))); // Mitte

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 41))); // Ecken des Quer-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 41)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 44)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 44)));

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 39)));  // Ecken des Hochkant-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 39)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 47)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 47)));

    building.setMapWidth(3);
    building.setMapHeight(2);
    building.setView(Direction::NORTH);
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(88, 42))); // Mitte

    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 41))); // Ecken des Quer-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 41)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 44)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 44)));

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 39)));  // Ecken des Hochkant-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 39)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 47)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 47)));

    building.setMapWidth(2);
    building.setMapHeight(3);
    building.setView(Direction::WEST);
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(88, 42))); // Mitte

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 41))); // Ecken des Quer-Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 41)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(85, 44)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(93, 44)));

    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 39)));  // Ecken des Hochkant-Rechtecks
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 39)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(87, 47)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(90, 47)));
}
/* Fall 2: asymmetrisch mit größerem Gebäude
 *
 *   x=11
 *   |
 * □□▨▨▨▨□□
 * □▨▨▨▨▨▨□
 * ▨▨▣▣▣▣▨▨ — y=33
 * ▨▨▣▣▣▣▨▨
 * ▨▨▣▣▣▣▨▨
 * □▨▨▨▨▨▨□
 * □□▨▨▨▨□□
 */
TEST(CatchmentAreaTest, isInsideCatchmentArea_AsymmetricLargeBuilding) {
    Building building;
    building.setMapWidth(4);
    building.setMapHeight(3);
    building.setMapCoords(MapCoords(11, 33));
    building.setView(Direction::SOUTH);

    RectangleData<char>* catchmentArea = new RectangleData<char>(8, 7);
    memcpy(catchmentArea->data, "00111100011111101111111111111111111111110111111000111100", 56);

    MapObjectType mapObjectType;
    mapObjectType.catchmentArea.reset(catchmentArea);
    building.setMapObjectType(&mapObjectType);

    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(11, 33))); // Gebäude selber
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(14, 35))); //
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(13, 34))); //
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(11, 31))); // Punkte innerhalb Einzugsbereich
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(15, 32)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(9, 33)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(16, 35)));
    ASSERT_TRUE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(12, 37)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(9, 31))); // Punkte außerhalb Einzugsbereich
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(9, 32)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(10, 31)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(16, 37)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(8, 33))); // Außerhalb des Rechtecks
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(17, 33)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(14, 30)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(14, 38)));
    ASSERT_FALSE(CatchmentArea::isInsideCatchmentArea(building, MapCoords(0, 0)));
}