diff --git a/src/botinterface.cpp b/src/botinterface.cpp index ff38e6c..6545e41 100755 --- a/src/botinterface.cpp +++ b/src/botinterface.cpp @@ -38,25 +38,42 @@ namespace snakeplusplus // Gets a new path for the bot to follow // Uses DFS algorithm - void AISnake::GetNewPath(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries) + void AISnake::GetNewPath(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries, const int snakeSize) { + // Search for food + if (snakeSize < 160) { + BFS(gameBoard, source, boundaries); + } else { + DFS(gameBoard, source, boundaries); + } + // Create path for food + path.push(botPathUnsanitized.top()); + botPathUnsanitized.pop(); + while (!botPathUnsanitized.empty()) { + sf::Vector2f deltaVector = botPathUnsanitized.top() - path.top(); + int delta = abs(deltaVector.x) + abs(deltaVector.y); + if (delta == 1) { + path.push(botPathUnsanitized.top()); + } + botPathUnsanitized.pop(); + } + } + + void AISnake::BFS(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries) { std::queue search; - std::stack botPathUnsanitized; std::vector> visited(boundaries.y, std::vector (boundaries.x, false)); - sf::Vector2f currentLocation; - std::array localLocations; bool foodFound = false; search.push(source); - // Search for food while (!search.empty()) { - currentLocation = search.front(); + sf::Vector2f currentLocation = search.front(); search.pop(); if (foodFound) { break; } if (visited.at(currentLocation.y).at(currentLocation.x)) { continue; } - botPathUnsanitized.push(currentLocation); if (gameBoard.at(currentLocation.y).at(currentLocation.x) == 'X') { foodFound = true; } + botPathUnsanitized.push(currentLocation); + std::array localLocations; localLocations.fill(currentLocation); localLocations[0].y += 1; localLocations[1].x += 1; @@ -84,17 +101,49 @@ namespace snakeplusplus } visited.at(currentLocation.y).at(currentLocation.x) = true; } - // Create path for food - path.push(botPathUnsanitized.top()); - botPathUnsanitized.pop(); - while (!botPathUnsanitized.empty()) { - currentLocation = botPathUnsanitized.top(); - sf::Vector2f deltaVector = currentLocation - path.top(); - int delta = abs(deltaVector.x) + abs(deltaVector.y); - if (delta == 1) { - path.push(botPathUnsanitized.top()); + } + + void AISnake::DFS(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries) { + std::stack search; + std::vector> visited(boundaries.y, std::vector (boundaries.x, false)); + bool foodFound = false; + search.push(source); + while (!search.empty()) { + sf::Vector2f currentLocation = search.top(); + search.pop(); + if (foodFound) { break; } + if (visited.at(currentLocation.y).at(currentLocation.x)) { continue; } + if (gameBoard.at(currentLocation.y).at(currentLocation.x) == 'X') { + foodFound = true; } - botPathUnsanitized.pop(); + botPathUnsanitized.push(currentLocation); + std::array localLocations; + localLocations.fill(currentLocation); + localLocations[0].y += 1; + localLocations[1].x += 1; + localLocations[2].y -= 1; + localLocations[3].x -= 1; + for (auto i : localLocations) { + try { + if (gameBoard.at(i.y).at(i.x) == 'X') { + botPathUnsanitized.push(i); + foodFound = true; + } + } catch (const std::out_of_range& error) { + continue; // Out of bounds + } + } + for (sf::Vector2f newLocation : localLocations) { + try { + if ((!visited.at(newLocation.y).at(newLocation.x)) + && (gameBoard.at(newLocation.y).at(newLocation.x) == ' ')) { + search.push(newLocation); + } + } catch (const std::out_of_range& error) { + continue; // Out of bounds + } + } + visited.at(currentLocation.y).at(currentLocation.x) = true; } } } diff --git a/src/botinterface.hpp b/src/botinterface.hpp index 152cbb2..5664235 100755 --- a/src/botinterface.hpp +++ b/src/botinterface.hpp @@ -12,8 +12,12 @@ namespace snakeplusplus public: std::stack path; AISnake(); - void GetNewPath(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries); + void GetNewPath(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries, const int snakeSize); PlayerDirection GetInput(const sf::Vector2f* source); + private: + std::stack botPathUnsanitized; + void BFS(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries); + void DFS(const std::vector< std::vector >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries); }; } diff --git a/src/gamestate.cpp b/src/gamestate.cpp index 95b069f..5e37107 100755 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -121,7 +121,7 @@ namespace snakeplusplus PlayerDirection controller; if (isBotControlled) { if (bot.path.empty()) { - bot.GetNewPath(gameBoard, player.headLocation, GetGameBoundaries()); + bot.GetNewPath(gameBoard, player.headLocation, GetGameBoundaries(), player.body.size()); } controller = bot.GetInput(&player.headLocation); }