From e6797fa193c63983c98dca8fcf04459cf10de25a Mon Sep 17 00:00:00 2001
From: Trianta <56975502+Trimutex@users.noreply.github.com>
Date: Fri, 13 Oct 2023 19:22:11 -0500
Subject: [PATCH] Split into BFS at first and DFS after

---
 src/botinterface.cpp | 83 +++++++++++++++++++++++++++++++++++---------
 src/botinterface.hpp |  6 +++-
 src/gamestate.cpp    |  2 +-
 3 files changed, 72 insertions(+), 19 deletions(-)

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<char> >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries)
+    void AISnake::GetNewPath(const std::vector< std::vector<char> >& 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<char> >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries) {
         std::queue<sf::Vector2f> search;
-        std::stack<sf::Vector2f> botPathUnsanitized;
         std::vector<std::vector<bool>> visited(boundaries.y, std::vector<bool> (boundaries.x, false));
-        sf::Vector2f currentLocation;
-        std::array<sf::Vector2f, 4> 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<sf::Vector2f, 4> 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<char> >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries) {
+        std::stack<sf::Vector2f> search;
+        std::vector<std::vector<bool>> visited(boundaries.y, std::vector<bool> (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<sf::Vector2f, 4> 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<sf::Vector2f> path;
         AISnake();
-        void GetNewPath(const std::vector< std::vector<char> >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries);
+        void GetNewPath(const std::vector< std::vector<char> >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries, const int snakeSize);
         PlayerDirection GetInput(const sf::Vector2f* source);
+    private:
+        std::stack<sf::Vector2f> botPathUnsanitized;
+        void BFS(const std::vector< std::vector<char> >& gameBoard, const sf::Vector2f& source, const sf::Vector2f& boundaries);
+        void DFS(const std::vector< std::vector<char> >& 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); 
         }