// // Created by Micha on 27/09/2021. // #include "SensoryMemory.h" #include "../GameWorld.h" //------------------------------- ctor ---------------------------------------- //----------------------------------------------------------------------------- SensoryMemory::SensoryMemory(Vehicle* owner, Uint32 MemorySpan) : m_Owner(owner), m_MemorySpan(MemorySpan) {} //--------------------- MakeNewRecordIfNotAlreadyPresent ---------------------- void SensoryMemory::makeNewRecordIfNotAlreadyPresent(Vehicle* Opponent) { // else check to see if this Opponent already exists in the memory. If it // doesn't, create a new record if (m_MemoryMap.find(Opponent) == m_MemoryMap.end()) { m_MemoryMap[Opponent] = MemoryRecord(); } } //------------------------ RemoveBotFromMemory ----------------------- --------- // // this removes a bot's record from memory //----------------------------------------------------------------------------- void SensoryMemory::removeBotFromMemory(Vehicle* Bot) { auto record = m_MemoryMap.find(Bot); if (record != m_MemoryMap.end()) { m_MemoryMap.erase(record); } } //----------------------- UpdateWithSoundSource ------------------------------- // // this updates the record for an individual opponent. Note, there is no need to // test if the opponent is within the FOV because that test will be done when // the UpdateVision method is called //----------------------------------------------------------------------------- void SensoryMemory::updateWithSoundSource(Vehicle* NoiseMaker) { // make sure the bot being examined is not this bot if (m_Owner != NoiseMaker) { // if the bot is already part of the memory then update its data, else // create a new memory record and add it to the memory makeNewRecordIfNotAlreadyPresent(NoiseMaker); MemoryRecord& info = m_MemoryMap[NoiseMaker]; // test if there is LOS between bots if (m_Owner->getGameWorld()->isLOSOkay(m_Owner->getPosition(), NoiseMaker->getPosition())) { info.shootable = true; // record the position of the bot info.lastSensedPosition = NoiseMaker->getPosition(); } else { info.shootable = false; } // record the time it was sensed info.timeLastSensed = SDL_GetTicks(); } } //----------------------------- UpdateVision ---------------------------------- // // this method iterates through all the bots in the game world to test if // they are in the field of view. Each bot's memory record is updated // accordingly //----------------------------------------------------------------------------- void SensoryMemory::updateVision() { // for each bot in the world test to see if it is visible to the owner of // this class // const std::list& bots = m_Owner->GetWorld()->GetAllBots(); // std::list::const_iterator curBot; for (auto curBot : m_Owner->getGameWorld()->getAllBots()) { // make sure the bot being examined is not this bot if (m_Owner != curBot) { // make sure it is part of the memory map makeNewRecordIfNotAlreadyPresent(curBot); // get a reference to this bot's data MemoryRecord& info = m_MemoryMap[curBot]; // test if there is LOS between bots if (m_Owner->getGameWorld()->isLOSOkay(m_Owner->getPosition(), curBot->getPosition())) { info.shootable = true; // test if the bot is within FOV if (m_Owner->getGameWorld() ->isSecondInFOVOfFirst(m_Owner->getPosition(), m_Owner->getFacingVec(), curBot->getPosition(), m_Owner->getFieldOfView(), m_Owner->getViewDistance())) { info.timeLastSensed = SDL_GetTicks(); info.lastSensedPosition = curBot->getPosition(); info.timeLastVisible = SDL_GetTicks(); if (!info.withinFOV) { info.withinFOV = true; info.timeBecameVisible = info.timeLastSensed; } } else { info.withinFOV = false; } } else { info.shootable = false; info.withinFOV = false; } } } // next bot } //------------------------ GetListOfRecentlySensedOpponents ------------------- // // returns a list of the bots that have been sensed recently //----------------------------------------------------------------------------- std::list SensoryMemory::getListOfRecentlySensedOpponents() const { // this will store all the opponents the bot can remember std::list opponents; Uint32 CurrentTime = SDL_GetTicks(); // MemoryMap::const_iterator curRecord = m_MemoryMap.begin(); // for (curRecord; curRecord != m_MemoryMap.end(); ++curRecord) { for (auto curRecord : m_MemoryMap) { // if this bot has been updated in the memory recently, add to list // Uint32 current = CurrentTime; // Uint32 lasTTimeSensed = curRecord.second.timeLastSensed; // Uint32 difference = CurrentTime - curRecord.second.timeLastSensed; // bool temp = (CurrentTime - curRecord.second.timeLastSensed) // <= m_MemorySpan; if ((CurrentTime - curRecord.second.timeLastSensed) <= m_MemorySpan) { opponents.push_back(curRecord.first); } } return opponents; } //----------------------------- isOpponentShootable //-------------------------------- // // returns true if the bot given as a parameter can be shot (ie. its not // obscured by walls) //----------------------------------------------------------------------------- bool SensoryMemory::isOpponentShootable(Vehicle* Opponent) const { MemoryMap::const_iterator it = m_MemoryMap.find(Opponent); if (it != m_MemoryMap.end()) { return it->second.shootable; } return false; } //----------------------------- isOpponentWithinFOV //-------------------------------- // // returns true if the bot given as a parameter is within FOV //----------------------------------------------------------------------------- bool SensoryMemory::isOpponentWithinFOV(Vehicle* Opponent) const { MemoryMap::const_iterator it = m_MemoryMap.find(Opponent); if (it != m_MemoryMap.end()) { return it->second.withinFOV; } return false; } //---------------------------- getLastRecordedPositionOfOpponent //------------------- // // returns the last recorded position of the bot //----------------------------------------------------------------------------- glm::vec2 SensoryMemory::getLastRecordedPositionOfOpponent( Vehicle* Opponent) const { MemoryMap::const_iterator it = m_MemoryMap.find(Opponent); if (it != m_MemoryMap.end()) { return it->second.lastSensedPosition; } throw std::runtime_error( "< SensoryMemory::getLastRecordedPositionOfOpponent>: Attempting " "to get position of unrecorded bot"); } //----------------------------- GetTimeOpponentHasBeenVisible //---------------------- // // returns the amount of time the given bot has been visible //----------------------------------------------------------------------------- Uint32 SensoryMemory::getTimeOpponentHasBeenVisible(Vehicle* Opponent) const { MemoryMap::const_iterator it = m_MemoryMap.find(Opponent); if (it != m_MemoryMap.end() && it->second.withinFOV) { return SDL_GetTicks() - it->second.timeBecameVisible; } return 0; } //-------------------- GetTimeOpponentHasBeenOutOfView ------------------------ // // returns the amount of time the given opponent has remained out of view // returns a high value if opponent has never been seen or not present //----------------------------------------------------------------------------- Uint32 SensoryMemory::getTimeOpponentHasBeenOutOfView(Vehicle* Opponent) const { MemoryMap::const_iterator it = m_MemoryMap.find(Opponent); if (it != m_MemoryMap.end()) { return SDL_GetTicks() - it->second.timeLastVisible; } return (std::numeric_limits::max)(); } //------------------------ GetTimeSinceLastSensed ---------------------- // // returns the amount of time the given bot has been visible //----------------------------------------------------------------------------- Uint32 SensoryMemory::getTimeSinceLastSensed(Vehicle* Opponent) const { MemoryMap::const_iterator it = m_MemoryMap.find(Opponent); if (it != m_MemoryMap.end() && it->second.withinFOV) { return SDL_GetTicks() - it->second.timeLastSensed; } return 0; } /* //---------------------- RenderBoxesAroundRecentlySensed ---------------------- // // renders boxes around the opponents it has sensed recently. //----------------------------------------------------------------------------- void SensoryMemory::renderBoxesAroundRecentlySensed() const { std::list opponents = getListOfRecentlySensedOpponents(); std::list::const_iterator it; for (it = opponents.begin(); it != opponents.end(); ++it) { gdi->OrangePen(); glm::vec2 p = (*it)->getPosition(); float b = (*it)->BRadius(); gdi->Line(p.x - b, p.y - b, p.x + b, p.y - b); gdi->Line(p.x + b, p.y - b, p.x + b, p.y + b); gdi->Line(p.x + b, p.y + b, p.x - b, p.y + b); gdi->Line(p.x - b, p.y + b, p.x - b, p.y - b); } } */