Shrink some challenge management code

This commit is contained in:
Alayan 2019-04-17 17:05:34 +02:00
parent 67775fc1ea
commit a8217eb334
4 changed files with 50 additions and 73 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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