Пример #1
0
  Game::Outcome Game::Move(int a, int b, int& pointDelta)
  {
    pointDelta = 0;

    // sort a & b so that a < b (makes stuff easier)
    if(b < a)
    {
      std::swap(a, b);
    }

    Card cardA = GetAt(a);
    Card cardB = GetAt(b);
    Point ptA = IndexToXY(a);
    Point ptB = IndexToXY(b);

    // must be similar cards
    if(cardA.m_face != cardB.m_face)
    {
      return Game::InvalidMove;
    }
    // must be valid cards
    if(cardA.m_face == Card::Blank)
    {
      return Game::InvalidMove;
    }
    // must be near eachother.
    if((abs(ptA.first - ptB.first) > 1) || (abs(ptA.second - ptB.second) > 1))
    {
      return Game::InvalidMove;
    }
    // must not be the same card.
    if(a == b)
    {
      return Game::InvalidMove;
    }

    // OK; appears to be a legal move.  Go ahead.
    m_arena.erase(m_arena.begin() + b);
    m_arena.erase(m_arena.begin() + a);

    // deal out cards.
    _DealOut();

    // Check for winnar!
    if(0 == m_arena.size())
    {
      pointDelta = 10;
      return GameWon;
    }

    // check for loser!
    int nMovesLeft = 0;
    // go through each card and see if it has a move. if so, break.
    int x, y;
    for(y = 0; y < m_arenaHeight; y ++)
    {
      for(x = 0; x < m_arenaWidth; x ++)
      {
        if(_HasMovesAvailable(x, y))
        {
          nMovesLeft = 1;
          break;
        }
      }
      if(nMovesLeft)
      {
        break;
      }
    }
    if(!nMovesLeft)
    {
      pointDelta = (int)m_arena.size();
      pointDelta = -pointDelta;
      return GameLost;
    }

    return Success;
  }
Пример #2
0
std::set<AbsTile> getVisibleTiles(AbsTile pos, unsigned range, bool viewThroughObstacles, bool includeObstacles, bool removeOccupiedTiles) // Does not include self pos
{
    if (range == 0)
        return { pos }; // but why

    MapDataRef map = getCurrentMap()->getCurrentMap();
    std::set<AbsTile> tilesInRange;

    // Detect tiles around, using range
    for (unsigned i {}; i < Def::TileArraySize; ++i)
    {
        auto xy = IndexToXY(i);
        unsigned distance = distanceBetweenTiles(pos, toVector2(xy));
        
        if (distance <= range) // jackpot
            tilesInRange.emplace(toVector2(xy));
    }

    std::set<AbsTile> viewObstacles;  // obstacles which doesn't block view
    std::set<AbsTile> blockObstacles; // obstacles which block view
    std::set<AbsTile> passableTiles;

    for (auto& xy : tilesInRange)
    {
        const TileData& tileData = map->getTile(xy.x, xy.y);

        if (!tileData.isVisible())
            continue;

        if (!tileData.isObstacle() && (!removeOccupiedTiles || !tileData.occupied))
            passableTiles.emplace(xy);

        if (tileData.isViewObstacle())
            viewObstacles.emplace(xy);

        if (tileData.isBlockObstacle())
            blockObstacles.emplace(xy);
    }

    for (auto& entity : map->getEntities())
        if (entity->HasComponent<BlockTileComponent>())
        {
            AbsTile ePos = entity->GetComponent<PositionComponent>().xy;

            if (ePos == pos)
                continue;

            viewObstacles.erase(ePos);
            passableTiles.erase(ePos);
            blockObstacles.emplace(std::move(ePos));
        }

    if (viewThroughObstacles)
    {
        if (!includeObstacles)
            return passableTiles;

        else
        {
            std::set<AbsTile> result;

            result.insert(blockObstacles.begin(), blockObstacles.end());
            result.insert(viewObstacles.begin(), viewObstacles.end());
            result.insert(passableTiles.begin(), passableTiles.end());

            return result;
        }
    }

    std::set<AbsTile> visibleTiles = passableTiles;

    for (const AbsTile& obstacle : blockObstacles) /// todo: optimize this ? Make some blocks of obstacles to compare with fewer rays ?
    {
        Vector2fTriplet rays = getTileOutterCorners(pos, obstacle);

        // Check shadowed tiles
        for (const AbsTile& xy : passableTiles)
        {
            // Is tile farther away than the obstacle ?
            if (graphicalDistanceBetweenTiles(pos, xy) < graphicalDistanceBetweenTiles(pos, obstacle))
                continue;

            // Is tile contained in obstacle shadow ?
            Nz::Vector2f tileCenter = getTileCenter(xy);

            if (isRight(rays.first, rays.second, tileCenter) && isLeft(rays.first, rays.third, tileCenter)) // Contained in the shadow
            {
                auto tileToErase = std::find(visibleTiles.begin(), visibleTiles.end(), xy);

                if (tileToErase != visibleTiles.end())
                    visibleTiles.erase(tileToErase);

                else
                    NazaraDebug(Nz::String { "getVisibleTiles: Tile [" } +Nz::String::Number(xy.x) + ";" + Nz::String::Number(xy.y) + "] not found (bug to fix)");
            }
        }
    }

    if (!includeObstacles)
        return visibleTiles;

    else
    {
        std::set<AbsTile> result;

        result.insert(blockObstacles.begin(), blockObstacles.end());
        result.insert(viewObstacles.begin(), viewObstacles.end());
        result.insert(passableTiles.begin(), passableTiles.end());

        return result;
    }
}