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; }
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; } }