//////////////////////////////////////////////////////////////////////////////// // Match // //////////////////////////////////////////////////////////////////////////////// bool GameCore::checkMatch(const CoreCoord::Coord &coord1, const CoreCoord::Coord &coord2) { //Game is already over. if(m_status != Status::Continue) return false; //Both must be valid coords. if(!isValidCoord(coord1) || !isValidCoord(coord2)) return false; //Coords must be different. if(coord1 == coord2) return false; //Get the cards. auto &card1 = getCardAt(coord1); auto &card2 = getCardAt(coord2); //Already matched... if(card1.matched || card2.matched) return false; auto cardsAreEqual = (card1.value == card2.value); if(cardsAreEqual) { ++m_matchedPairsCount; const_cast<Card &>(card1).matched = true; const_cast<Card &>(card2).matched = true; if(m_matchCountAsTry) ++m_triesCount; } else { //Player miss the cards // TryCount is incremented ALWAYS in this situation. ++m_triesCount; } checkStatus(); return cardsAreEqual; }
bool GameCore::isValidIndex(int index) const { return isValidCoord(indexToCoord(index)); }
bool Pathfinder::getWalkable(const sf::Vector2i& coord){ if (isValidCoord(coord)){ return m_nodes[coord.x + (coord.y * m_mapWidth)]->walkable(); } return false; }
// Update the routes, this method is called each time // a new tower is built or a present tower is destroyed. // // This method uses a Greedy algorithm to calculate the routes. // // To begin with, the target node is pushed into the priority // queue with distance 0. While the priorit queue is not // empty, at each iteration, the node with minimal distance will // be popped from the queue. Then its adjacent nodes will // be inspected. For each adjacent node, if it has not been // visited before, it will be pushed into the queue with the // new distance and its direction and visited flag will be set. // // The Creeps can go horizontally, vertically or diagonally. // A diagonal direction is valid only when the the diagonal // grid can be accessed from both the two ways: // e.g. // A | B A -> D is valid only when both // --+-- A -> B -> D is valid and // C | D A -> C -> D is valid // // Creeps can can directly go from A to D if Both B and C // is not occupied by towers. // // By introducing the diagonal shortcuts, the routes will // be more natural. void GridMap::updateRoute() { // horizontal and vertical offsets static const int offset_x[] = {-1, 0, 1, 0}; static const int offset_y[] = {0, 1, 0, -1}; // diagonal offsets static const int d_offset_x[] = {-1, -1, 1, 1}; static const int d_offset_y[] = {-1, 1, 1, -1}; // Correspondencies between index and position // // offset d_offset: // +---+---+---+ +---+---+---+ // | | 3 | | | 0 | | 3 | // +---+---+---+ +---+---+---+ // | 0 | | 2 | | | | | // +---+---+---+ +---+---+---+ // | | 1 | | | 1 | | 2 | // +---+---+---+ +---+---+---+ // // if offset[i] is invalid, then // d_offset[i] and // d_offset[(i + 1) % 4] is invalid. // horizontal and vertical directions static const Grid::Direction dirs[] = { Grid::RIGHT, Grid::UP, Grid::LEFT, Grid::DOWN }; // diagonal directions static const Grid::Direction ddirs[] = { Grid::BOTTOMRIGHT, Grid::TOPRIGHT, Grid::TOPLEFT, Grid::BOTTOMLEFT }; // Step1: Clear all grids' direction to be Grid::NONE // and mark all grids as un-visited clearGridsFlags(); // Step2: Begin Greedy Search std::priority_queue<GreedyNode> pq; pq.push(GreedyNode(_target_x, _target_y, 0)); _visited[_target_y][_target_x] = true; while (not pq.empty()) { // indicate whether the diagonal direction is available bool diagonal_valid[] = {true, true, true, true}; // take one node from the queue GreedyNode node = pq.top(); pq.pop(); int x = node.x, y = node.y; int dist = node.dist; // Inspect the adjacent nodes for (size_t i = 0; i < 4; ++i) { // Next node's coordinate int next_x = x + offset_x[i]; int next_y = y + offset_y[i]; if (isValidCoord(next_x, next_y)) { if (not _visited[next_y][next_x]) { // Update the grid's direction _grids[next_y][next_x].setDirection(dirs[i]); // Push the node into the queue pq.push(GreedyNode(next_x, next_y, dist + 10)); // Mark the grid as visited _visited[next_y][next_x] = true; } } else { // The coordinate is invalid // Thus the corresponding diagonal coordinate is invalid diagonal_valid[i] = false; diagonal_valid[(i + 1) % 4] = false; } } // Further inspect the diagonally adjacent nodes for (size_t i = 0; i < 4; ++i) { if (diagonal_valid[i]) { int next_x = x + d_offset_x[i]; int next_y = y + d_offset_y[i]; if (not _visited[next_y][next_x]) { // Update the grid's direction _grids[next_y][next_x].setDirection(ddirs[i]); // Push the node into the queue pq.push(GreedyNode(next_x, next_y, dist + 14)); // Mark the grid as visited _visited[next_y][next_x] = true; } } } } }
std::string Pathfinder::getAreaName(const sf::Vector2i& coord){ if (isValidCoord(coord)){ return m_nodes[coord.x + (coord.y * m_mapWidth)]->area(); } return "noNode"; }