diff --git a/src/state/include/state/state.h b/src/state/include/state/state.h index 1f54fe5c..ff3e9081 100644 --- a/src/state/include/state/state.h +++ b/src/state/include/state/state.h @@ -156,6 +156,14 @@ class STATE_EXPORT State : public ICommandTaker { DoubleVec2D blast_position, size_t impact_range); + /** + * Returns the neighbouring points of a given position + * + * @param position Postion for which neighbouring points are returned + * @return std::vector Neighbouring points + */ + std::vector getNeighbouringPoints(DoubleVec2D position); + /** * Callback passed to all blasters to damage neighbouring actors given a * position diff --git a/src/state/src/state.cpp b/src/state/src/state.cpp index 791671eb..2d6fba72 100644 --- a/src/state/src/state.cpp +++ b/src/state/src/state.cpp @@ -81,14 +81,50 @@ void State::handleTransformRequests() { ++id) { for (const auto &bot : bots[id]) { DoubleVec2D bot_position = bot->getPosition(); - Vec2D offset = getOffsetFromPosition(bot_position, (PlayerId) id); - position_counts[offset.x][offset.y]++; - } - for (const auto &tower : towers[id]) { - DoubleVec2D tower_position = tower->getPosition(); - Vec2D offset = getOffsetFromPosition(tower_position, (PlayerId) id); - position_counts[offset.x][offset.y]++; + // Get neighbouring points + std::vector neighbouring_offsets = + getNeighbouringPoints(bot_position); + + // If the bot belongs strictly to only one offset + if (neighbouring_offsets.size() == 1) { + Vec2D offset = neighbouring_offsets[0]; + position_counts[offset.x][offset.y]++; + } else if (neighbouring_offsets.size() == + 2) { // If the bot is on an edge + Vec2D offset1 = neighbouring_offsets[0]; + Vec2D offset2 = neighbouring_offsets[1]; + + // If either of the offsets are blocked, then the bot is + // assigned to the other offset + if (path_planner->isOffsetBlocked(offset1) && + !path_planner->isOffsetBlocked(offset2)) { + position_counts[offset2.x][offset2.y]++; + } else if (path_planner->isOffsetBlocked(offset2) && + !path_planner->isOffsetBlocked(offset1)) { + position_counts[offset1.x][offset1.y]++; + } + } else if (neighbouring_offsets.size() == + 4) { // If the bot is on a vertex on the grid + uint64_t total_blocked_count = 0; + Vec2D unblocked_offset = Vec2D::null; + for (const auto &offset : neighbouring_offsets) { + if (path_planner->isOffsetBlocked(offset)) { + ++total_blocked_count; + } else { + unblocked_offset = offset; + } + } + + // If 3 offsets are blocked, assigning the actor to the final + // offset + if (total_blocked_count == 3) { + position_counts[unblocked_offset.x][unblocked_offset.y]++; + } + + // If less than three are blocked, then not assigning the bot to + // any offset + } } } @@ -103,7 +139,7 @@ void State::handleTransformRequests() { Vec2D offset = getOffsetFromPosition(bot_position, (PlayerId) id); // Checking if only one actor is in the offset position where // transforming is requested - if (position_counts[offset.x][offset.y] == 1) { + if (position_counts[offset.x][offset.y] <= 1) { produceTower(bot); } } diff --git a/src/state/src/state_helpers.cpp b/src/state/src/state_helpers.cpp index be75227e..e73d923d 100644 --- a/src/state/src/state_helpers.cpp +++ b/src/state/src/state_helpers.cpp @@ -60,4 +60,24 @@ Actor *State::getActorById(ActorId actor_id) { return tower; } +std::vector State::getNeighbouringPoints(DoubleVec2D position) { + uint64_t pos_x = std::floor(position.x), pos_y = std::floor(position.y); + + if (pos_x == position.x) { + pos_x = std::min(pos_x - 1, (uint64_t) 0); + } + if (pos_y == position.y) { + pos_y = std::min(pos_y - 1, (uint64_t) 0); + } + + std::vector neighbouring_points; + for (auto x = pos_x; x < std::floor(position.x); ++x) { + for (auto y = pos_y; y < std::floor(position.y); ++y) { + neighbouring_points.push_back(Vec2D(pos_x, pos_y)); + } + } + + return neighbouring_points; +} + } // namespace state diff --git a/test/state/state_test.cpp b/test/state/state_test.cpp index 0048defc..6a7d9f1f 100644 --- a/test/state/state_test.cpp +++ b/test/state/state_test.cpp @@ -405,7 +405,7 @@ TEST_F(StateTest, AcknowledgeTransformRequest) { std::bind(&State::constructTowerCallback, state.get(), _1); bot->setConstructTowerCallback(construct_tower_callback); - state->transformBot(bot->getActorId(), bot->getPosition()); + bot->setTransforming(true); bot->update(); bot->lateUpdate();