From a8217eb334f4b6e583837434ecf299c86fb3408f Mon Sep 17 00:00:00 2001 From: Alayan Date: Wed, 17 Apr 2019 17:05:34 +0200 Subject: [PATCH] Shrink some challenge management code --- src/challenges/challenge_status.cpp | 38 ++++++++-------------- src/challenges/challenge_status.hpp | 35 +++++++++++---------- src/challenges/story_mode_status.cpp | 47 ++++++++++------------------ src/race/race_manager.hpp | 3 +- 4 files changed, 50 insertions(+), 73 deletions(-) diff --git a/src/challenges/challenge_status.cpp b/src/challenges/challenge_status.cpp index d4cc05ca8..7f8bfbd68 100644 --- a/src/challenges/challenge_status.cpp +++ b/src/challenges/challenge_status.cpp @@ -44,48 +44,36 @@ void ChallengeStatus::load(const XMLNode* challenges_node) return; } - m_state[0] = CH_INACTIVE; - m_state[1] = CH_INACTIVE; - m_state[2] = CH_INACTIVE; - m_state[3] = CH_INACTIVE; + m_active = 0; + m_solved = 0; std::string solved; if (node->get("solved", &solved)) { + // Solving at a difficulty also marks lower difficulties as solved if (solved == "easy") - m_state[0] = CH_SOLVED; + m_solved = 0x01; else if (solved == "medium") - { - m_state[0] = CH_SOLVED; - m_state[1] = CH_SOLVED; - } + m_solved = 0x03; else if (solved == "hard") - { - m_state[0] = CH_SOLVED; - m_state[1] = CH_SOLVED; - m_state[2] = CH_SOLVED; - } + m_solved = 0x07; else if (solved == "best") - { - m_state[0] = CH_SOLVED; - m_state[1] = CH_SOLVED; - m_state[2] = CH_SOLVED; - m_state[3] = CH_SOLVED; - } + m_solved = 0x0F; } // if has 'solved' attribute if (!node->get("best_while_slower", &m_max_req_in_lower_diff)) m_max_req_in_lower_diff = false; } // load //----------------------------------------------------------------------------- - +// Solve not only the current difficulty but all those before +// e.g. if you solved hard then you also get easy. +// Also resets active flag. void ChallengeStatus::setSolved(RaceManager::Difficulty d) { - // solve not only the current difficulty but all those before - // e.g. if you solved hard then you also get easy - for (int curr = 0; curr <= d; curr++) + if ((int) d <= 3) { - m_state[curr] = CH_SOLVED; + m_solved |= (0x0F >> (3 - (int) d)); + m_active &= ~m_solved; // Sets to 0 all bits which are at 1 in m_solved } } // setSolved diff --git a/src/challenges/challenge_status.hpp b/src/challenges/challenge_status.hpp index 65eda0678..38c2c94e1 100644 --- a/src/challenges/challenge_status.hpp +++ b/src/challenges/challenge_status.hpp @@ -53,12 +53,9 @@ class XMLNode; class ChallengeStatus : public NoCopy { private: - /** The different states the challenge can be in. */ - enum {CH_INACTIVE, // challenge not yet possible - CH_ACTIVE, // challenge possible, but not yet solved - CH_SOLVED} // challenge was solved - - m_state[RaceManager::DIFFICULTY_COUNT]; + // Stores the active and solved status for each difficulty with a bitmask + int m_active; + int m_solved; // If the challenge's SuperTux time requirement has been beaten // in a (s)lower difficulty. @@ -71,10 +68,8 @@ public: ChallengeStatus(const ChallengeData* data) { m_data = data; - m_state[RaceManager::DIFFICULTY_EASY] = CH_INACTIVE; - m_state[RaceManager::DIFFICULTY_MEDIUM] = CH_INACTIVE; - m_state[RaceManager::DIFFICULTY_HARD] = CH_INACTIVE; - m_state[RaceManager::DIFFICULTY_BEST] = CH_INACTIVE; + m_active = 0; + m_solved = 0; m_max_req_in_lower_diff = false; } virtual ~ChallengeStatus() {}; @@ -87,29 +82,35 @@ public: */ bool isSolved(RaceManager::Difficulty d) const { - return m_state[d]==CH_SOLVED; + return ((m_solved >> (int) d)&0x01) == 1; } // isSolved // ------------------------------------------------------------------------ /** Returns true if this challenge was solved at any difficult. */ - bool isSolvedAtAnyDifficulty() const + bool isSolvedAtAnyDifficulty() const { return m_solved != 0; } + /** Returns the highest difficulty at which this challenge was solved. + */ + RaceManager::Difficulty highestSolved() const { - return m_state[0]==CH_SOLVED || m_state[1]==CH_SOLVED || - m_state[2]==CH_SOLVED || m_state[3]==CH_SOLVED; - } // isSolvedAtAnyDifficulty + return (m_solved & 0x08) ? RaceManager::DIFFICULTY_BEST : + (m_solved & 0x04) ? RaceManager::DIFFICULTY_HARD : + (m_solved & 0x02) ? RaceManager::DIFFICULTY_MEDIUM : + (m_solved & 0x01) ? RaceManager::DIFFICULTY_EASY : + RaceManager::DIFFICULTY_NONE; + } // highestSolved // ------------------------------------------------------------------------ /** True if this challenge is active at the given difficulty. */ bool isActive(RaceManager::Difficulty d) const { - return m_state[d]==CH_ACTIVE; + return ((m_active >> (int) d)&0x01) == 1; } // isActive // ------------------------------------------------------------------------ /** Sets this challenge to be active. */ void setActive(RaceManager::Difficulty d) { - m_state[d] = CH_ACTIVE; + m_active |= (0x01 << (int) d); } // setActive // ------------------------------------------------------------------------ /** Returns if this challenge is only an unlock list */ diff --git a/src/challenges/story_mode_status.cpp b/src/challenges/story_mode_status.cpp index 5425e764e..31cb458d7 100644 --- a/src/challenges/story_mode_status.cpp +++ b/src/challenges/story_mode_status.cpp @@ -95,26 +95,26 @@ void StoryModeStatus::computeActive(bool first_call) { // Changed challenge // ----------------- - if((i->second)->isSolvedAtAnyDifficulty()) + if(!i->second->isUnlockList() && (i->second)->isSolvedAtAnyDifficulty()) { int gp_factor = i->second->isGrandPrix() ? GP_FACTOR : 1; - if (i->second->isSolved(RaceManager::DIFFICULTY_BEST) && !i->second->isUnlockList()) + if (i->second->isSolved(RaceManager::DIFFICULTY_BEST)) { m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_BEST]*gp_factor; m_best_challenges++; } - else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD) && !i->second->isUnlockList()) + else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD)) { m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_HARD]*gp_factor; m_hard_challenges++; } - else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM) && !i->second->isUnlockList()) + else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM)) { m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_MEDIUM]*gp_factor; m_medium_challenges++; } - else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY) && !i->second->isUnlockList()) + else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY)) { m_points += CHALLENGE_POINTS[RaceManager::DIFFICULTY_EASY]*gp_factor; m_easy_challenges++; @@ -127,32 +127,19 @@ void StoryModeStatus::computeActive(bool first_call) lockFeature(i->second); } - if (i->second->isSolved(RaceManager::DIFFICULTY_BEST)) + switch(i->second->highestSolved()) { - // challenge beaten at hardest, nothing more to do here - continue; - } - else if (i->second->isSolved(RaceManager::DIFFICULTY_HARD)) - { - i->second->setActive(RaceManager::DIFFICULTY_BEST); - } - else if (i->second->isSolved(RaceManager::DIFFICULTY_MEDIUM)) - { - i->second->setActive(RaceManager::DIFFICULTY_BEST); - i->second->setActive(RaceManager::DIFFICULTY_HARD); - } - else if (i->second->isSolved(RaceManager::DIFFICULTY_EASY)) - { - i->second->setActive(RaceManager::DIFFICULTY_BEST); - i->second->setActive(RaceManager::DIFFICULTY_HARD); - i->second->setActive(RaceManager::DIFFICULTY_MEDIUM); - } - else - { - i->second->setActive(RaceManager::DIFFICULTY_BEST); - i->second->setActive(RaceManager::DIFFICULTY_HARD); - i->second->setActive(RaceManager::DIFFICULTY_MEDIUM); - i->second->setActive(RaceManager::DIFFICULTY_EASY); + // Uses switch fallthrough + case RaceManager::DIFFICULTY_NONE: + i->second->setActive(RaceManager::DIFFICULTY_EASY); + case RaceManager::DIFFICULTY_EASY: + i->second->setActive(RaceManager::DIFFICULTY_MEDIUM); + case RaceManager::DIFFICULTY_MEDIUM: + i->second->setActive(RaceManager::DIFFICULTY_HARD); + case RaceManager::DIFFICULTY_HARD: + i->second->setActive(RaceManager::DIFFICULTY_BEST); + default: + break; } } // for i diff --git a/src/race/race_manager.hpp b/src/race/race_manager.hpp index b038fdc33..0ead9a8cf 100644 --- a/src/race/race_manager.hpp +++ b/src/race/race_manager.hpp @@ -254,7 +254,8 @@ public: DIFFICULTY_HARD, DIFFICULTY_BEST, DIFFICULTY_LAST = DIFFICULTY_BEST, - DIFFICULTY_COUNT}; + DIFFICULTY_COUNT, + DIFFICULTY_NONE}; /** Different kart types: A local player, a player connected via network, * an AI kart, the leader kart (currently not used), a ghost kart and