diff --git a/.gitignore b/.gitignore index c90802d..99352dd 100755 --- a/.gitignore +++ b/.gitignore @@ -33,7 +33,19 @@ *.json *.ps1 +# ---> CMake +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +build + # Extras .vs* -build -bin \ No newline at end of file diff --git a/src/botinterface.cpp b/src/botinterface.cpp index 4712adf..15bfbba 100755 --- a/src/botinterface.cpp +++ b/src/botinterface.cpp @@ -2,6 +2,7 @@ #include "common.hpp" #include #include +#include #include #include #include @@ -42,6 +43,15 @@ namespace snakeplusplus return; } + void AISnake::AdjustProbability(double amount) + { + probabilityBFS += amount; + if (probabilityBFS > 1.0) { probabilityBFS = 1.0; } + if (probabilityBFS < 0.0) { probabilityBFS = 0.0; } + std::cout << "[Info - AISnake] New BFS probability: " << probabilityBFS << std::endl; + return; + } + // 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, const int snakeSize) diff --git a/src/botinterface.hpp b/src/botinterface.hpp index 8bbbfb0..7bf29b7 100755 --- a/src/botinterface.hpp +++ b/src/botinterface.hpp @@ -15,8 +15,9 @@ namespace snakeplusplus 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); void UpdateProbability(int snakeSize); + void AdjustProbability(double amount); private: - double probabilityBFS = 1.000; + double probabilityBFS = 0.500; 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 d5f3ee1..98840d0 100755 --- a/src/gamestate.cpp +++ b/src/gamestate.cpp @@ -1,4 +1,5 @@ // GameState.cpp +#include #include #include #include "botinterface.hpp" @@ -24,16 +25,30 @@ namespace snakeplusplus void GameEngine::Reset() { - graphics.CheckContinue(isBotControlled); + AddIteration(); player.Reset(); - if (isBotControlled) { - while (!bot.path.empty()) { bot.path.pop(); } - } + if (isBotControlled) { while (!bot.path.empty()) { bot.path.pop(); } } PrepareGameBoard(); isGameOver = false; + graphics.SetShowGame((amountPlayed + 1) % 50 == 0); return; } + void GameEngine::AddIteration(void) + { + graphics.CheckContinue(isBotControlled); + if (player.body.size() > 40) + { + UpdateAverage(); + double adjustmentAmount = 0.002; + if (average > player.body.size()) { bot.AdjustProbability(adjustmentAmount); } + else { bot.AdjustProbability(-adjustmentAmount); } + } + std::cout << "[Info - GameEngine] Current average: " << average << std::endl; + std::cout << "[Info - GameEngine] Previous iteration size: " << player.body.size() << std::endl; + + } + void GameEngine::Loop(void) { int currentScore = 0; @@ -44,7 +59,7 @@ namespace snakeplusplus PlaceNewSnakePart(MovePlayer()); RegenerateFood(); currentScore = player.body.size() * 100; - bot.UpdateProbability(player.body.size()); + //bot.UpdateProbability(player.body.size()); graphics.DisplayGameState(gameBoard, currentScore); } return; @@ -52,26 +67,22 @@ namespace snakeplusplus sf::Vector2f GameEngine::MovePlayer(void) { - sf::Vector2f newHeadPosition; - newHeadPosition.x = player.headLocation.x + player.speed.x; - newHeadPosition.y = player.headLocation.y + player.speed.y; - return newHeadPosition; + return sf::Vector2f(player.headLocation.x + player.speed.x, player.headLocation.y + player.speed.y); } + sf::Vector2f GameEngine::GetGameBoundaries(void) { return graphics.gameBoundaries; } - void GameEngine::PlaceNewSnakePart(sf::Vector2f location) - { + void GameEngine::PlaceNewSnakePart(sf::Vector2f location) { if (!player.speed.x && !player.speed.y) { return; } - try - { - char* locationState; - locationState = &gameBoard.at(location.y).at(location.x); - if (*locationState == 'O' && (player.body.size() > 1)) + try { + char* locationState = &gameBoard.at(location.y).at(location.x); + if (*locationState == 'O' && (player.body.size() > 1)) { isGameOver = true; // Game should end (Snake touching snake) + } *locationState = 'O'; player.body.push(locationState); player.headLocation = location; @@ -83,23 +94,20 @@ namespace snakeplusplus return; } + // Generates new food until not colliding with player - void GameEngine::RegenerateFood(void) + void GameEngine::RegenerateFood() { - sf::Vector2f newLocation = playerFood.location; - bool isUpdated = false; - while (gameBoard.at(newLocation.y).at(newLocation.x) == 'O') - { - isUpdated = true; + // Generate a new food location if the current one is occupied + while (gameBoard.at(playerFood.location.y).at(playerFood.location.x) == 'O') { playerFood.GenerateNewFood(GetGameBoundaries()); - newLocation = playerFood.location; } - if (isUpdated) { - gameBoard.at(newLocation.y).at(newLocation.x) = 'X'; - } - return; + + // Update the game board with the new food location + gameBoard.at(playerFood.location.y).at(playerFood.location.x) = 'X'; } + void GameEngine::PrepareGameBoard(void) { gameBoard.clear(); @@ -155,4 +163,9 @@ namespace snakeplusplus } return; } + void GameEngine::UpdateAverage() { + totalLength += player.body.size(); + amountPlayed += 1; + average = (double)totalLength / amountPlayed; + } } diff --git a/src/gamestate.hpp b/src/gamestate.hpp index 19d8350..e71949d 100755 --- a/src/gamestate.hpp +++ b/src/gamestate.hpp @@ -17,6 +17,7 @@ namespace snakeplusplus GameEngine(); void Start(void); void Reset(void); + void AddIteration(void); sf::Vector2f GetGameBoundaries(void); private: std::vector< std::vector > gameBoard; @@ -33,6 +34,10 @@ namespace snakeplusplus void RegenerateFood(void); void PrepareGameBoard(void); void UpdatePlayerSpeed(); + void UpdateAverage(); + int totalLength = 0; + int amountPlayed = 0; + double average = 0; }; } diff --git a/src/playerinterface.cpp b/src/playerinterface.cpp index 55a7ca3..fe4a5f4 100755 --- a/src/playerinterface.cpp +++ b/src/playerinterface.cpp @@ -87,6 +87,7 @@ namespace snakeplusplus void PlayerOutput::DisplayGameState(std::vector< std::vector >& gameBoard, int score) { CheckWindowEvents(); + if (delay == sf::milliseconds(0)) { return; } char* letterOnBoard; for (float y = 0; y < gameBoundaries.y; y++) { @@ -120,6 +121,12 @@ namespace snakeplusplus return; } + void PlayerOutput::SetShowGame(bool isShowing) { + if (isShowing) { delay = sf::milliseconds(2); } + else { delay = sf::milliseconds(0); } + return; + } + void PlayerOutput::CheckWindowEvents(void) { while (gameWindow.pollEvent(event)) @@ -127,6 +134,14 @@ namespace snakeplusplus if ((event.type == sf::Event::Closed) || (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))) gameWindow.close(); + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Equal)) { + if (delay > sf::milliseconds(16)) { continue; } + delay += sf::milliseconds(1); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Hyphen)) { + if (delay == sf::milliseconds(0)) { continue; } + delay -= sf::milliseconds(1); + } } } diff --git a/src/playerinterface.hpp b/src/playerinterface.hpp index 9098822..5f5fb3a 100755 --- a/src/playerinterface.hpp +++ b/src/playerinterface.hpp @@ -20,6 +20,7 @@ namespace snakeplusplus void DisplayGameState(std::vector< std::vector >& gameBoard, int score); void DisplayScore(int score); void StartGameWindow(void); + void SetShowGame(bool isShowing); private: void CheckWindowEvents(void); void DisplayEndScreen(void); @@ -31,7 +32,7 @@ namespace snakeplusplus sf::RectangleShape drawObject; sf::Event event; bool isWindowAlive; - sf::Time delay = sf::milliseconds(10); + sf::Time delay = sf::milliseconds(1); }; }