Completely removed getRaceResultOrder functions, added debug support

for duplicated ranks to world_with_rank.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5898 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2010-09-05 14:05:59 +00:00
parent 442168e845
commit ebf6f561a9
7 changed files with 113 additions and 151 deletions

View File

@@ -55,7 +55,7 @@ void FollowTheLeaderRace::countdownReachedZero()
// kart, otherwise remove the last kart.
int position_to_remove = m_karts[0]->getPosition()==1
? getCurrentNumKarts() : 1;
const Kart *kart = getKartAtPosition(position_to_remove);
Kart *kart = getKartAtPosition(position_to_remove);
if(!kart || kart->isEliminated())
{
fprintf(stderr,"Problem with removing leader: position %d not found\n",
@@ -80,8 +80,13 @@ void FollowTheLeaderRace::countdownReachedZero()
// position, since the eliminated kart was already removed
// from the value returned by getCurrentNumKarts (and we have
// to remove the kart before we can call updateRacePosition).
setKartPosition(kart->getWorldKartId(),
getCurrentNumKarts()+1);
// Note that we can not call WorldWithRank::setKartPosition
// here, since it would not properly support debugging kart
// ranks (since this kart would get its position set again
// in updateRacePosition). We only set the rank of the eliminated
// kart, and updateRacePosition will then call setKartPosition
// for the now eliminated kart.
kart->setPosition(getCurrentNumKarts()+1);
updateRacePosition();
}
}
@@ -136,66 +141,15 @@ void FollowTheLeaderRace::restartRace()
std::string FollowTheLeaderRace::getIdent() const
{
return FTL_IDENT;
}
} // getIdent
//-----------------------------------------------------------------------------
/** Sets the title for all karts that is displayed in the icon list. In
* this mode the title for the first kart is set to 'leader'.
*/
RaceGUIBase::KartIconDisplayInfo* FollowTheLeaderRace::getKartsDisplayInfo()
{
LinearWorld::getKartsDisplayInfo();
m_kart_display_info[0].special_title = _("Leader");
return m_kart_display_info;
}
//-----------------------------------------------------------------------------
void FollowTheLeaderRace::getRaceResultOrder(std::vector<int> *order)
{
const unsigned int num_karts = getNumKarts();
order->resize(num_karts);
int *scores = new int[num_karts];
double *race_time = new double[num_karts];
// Ignore kart 0, since it was the leader
(*order)[0] = -1;
for( unsigned int kart_id = 1; kart_id < num_karts; ++kart_id )
{
(*order)[kart_id] = kart_id;
scores[kart_id] = race_manager->getKartScore(kart_id);
race_time[kart_id] = race_manager->getOverallTime(kart_id);
// check this kart is not in front of leader. If it is, give a score of 0
if( getLapForKart(kart_id) * getTrack()->getTrackLength()
+ getDistanceDownTrackForKart(kart_id)
> getLapForKart(0) * getTrack()->getTrackLength()
+ getDistanceDownTrackForKart(0))
{
scores[kart_id] = 0;
}
}
//Bubblesort
bool sorted;
do
{
sorted = true;
for( unsigned int i = 1; i < num_karts - 1; ++i )
{
if( scores[(*order)[i]] < scores[(*order)[i+1]] ||
(scores[(*order)[i]] == scores[(*order)[i+1]]
&& race_time[(*order)[i]] > race_time[(*order)[i+1]]) )
{
int tmp = (*order)[i];
(*order)[i] = (*order)[i+1];
(*order)[i+1] = tmp;
sorted = false;
}
}
} while(!sorted);
for(unsigned int i=1; i<num_karts; i++)
{
//FIXME JOERGH setKartPosition((*order)[i], i);
}
delete []scores;
delete []race_time;
}
} // getKartsDisplayInfo

View File

@@ -47,9 +47,6 @@ public:
virtual bool isRaceOver();
virtual bool raceHasLaps(){ return false; }
/** Called by the race result GUI at the end of the race to know the final order
(fill in the 'order' array) */
virtual void getRaceResultOrder(std::vector<int> *order);
};

View File

@@ -580,12 +580,11 @@ void LinearWorld::moveKartAfterRescue(Kart* kart)
*/
void LinearWorld::updateRacePosition()
{
// Mostly for debugging:
beginSetKartPositions();
const unsigned int kart_amount = m_karts.size();
#ifdef DEBUG
std::vector<bool> rank_used;
for (unsigned int n=0; n<=kart_amount; n++)
rank_used.push_back(false);
bool rank_changed = false;
#endif
@@ -602,9 +601,9 @@ void LinearWorld::updateRacePosition()
// crossing the finishing line and become second!
if(kart->isEliminated() || kart->hasFinishedRace())
{
#ifdef DEBUG
rank_used[kart->getPosition()] = true;
#endif
// This is only necessary to support debugging inconsistencies
// in kart position parameters.
setKartPosition(i, kart->getPosition());
continue;
}
KartInfo& kart_info = m_kart_info[i];
@@ -655,9 +654,11 @@ void LinearWorld::updateRacePosition()
#endif
}
} //next kart
#ifdef DEBUG
if (rank_used[p])
#ifndef DEBUG
setKartPosition(i, p);
#else
if (!setKartPosition(i,p))
{
std::cerr << "ERROR, same rank used twice!!\n";
@@ -668,13 +669,7 @@ void LinearWorld::updateRacePosition()
<< "), is at lap (" << getLapForKart(d) << "), is at distance("
<< getDistanceDownTrackForKart(d) << "), is eliminated(" << m_karts[d]->isEliminated() << ")" << std::endl;
}
std::cerr << "Used ranks:\n";
for (unsigned int d=1; d<=kart_amount; d++)
{
std::cerr << " rank " << d << " used : " << rank_used[d] << std::endl;
}
std::cerr << "Who has each ranking so far :\n";
for (unsigned int d=0; d<i; d++)
{
@@ -685,11 +680,9 @@ void LinearWorld::updateRacePosition()
history->Save();
assert(false);
}
rank_used[p] = true;
rank_changed |= kart->getPosition()!=p;
#endif
setKartPosition(i, p);
// Switch on faster music if not already done so, if the
// first kart is doing its last lap, and if the estimated
// remaining time is less than 30 seconds.
@@ -759,6 +752,7 @@ void LinearWorld::updateRacePosition()
} // if rank_changed
#endif
endSetKartPositions();
} // updateRacePosition
//-----------------------------------------------------------------------------

View File

@@ -123,6 +123,7 @@ std::string ThreeStrikesBattle::getIdent() const
//-----------------------------------------------------------------------------
void ThreeStrikesBattle::updateKartRanks()
{
beginSetKartPositions();
// sort karts by their times then give each one its position.
// in battle-mode, long time = good (meaning he survived longer)
@@ -165,6 +166,7 @@ void ThreeStrikesBattle::updateKartRanks()
setKartPosition(karts_list[n], n+1);
}
delete [] karts_list;
endSetKartPositions();
} // updateKartRank
//-----------------------------------------------------------------------------

View File

@@ -24,13 +24,15 @@ void WorldWithRank::init()
{
World::init();
m_position_index.resize(m_karts.size());
m_position_used.resize(m_karts.size());
m_position_setting_initialised = false;
} // init
//-----------------------------------------------------------------------------
/** Returns the kart with a given position.
* \param p The position of the kart, 1<=p<=num_karts).
*/
const Kart* WorldWithRank::getKartAtPosition(unsigned int p) const
Kart* WorldWithRank::getKartAtPosition(unsigned int p) const
{
if(p<1 || p>m_position_index.size())
return NULL;
@@ -39,66 +41,71 @@ const Kart* WorldWithRank::getKartAtPosition(unsigned int p) const
} // getKartAtPosition
//-----------------------------------------------------------------------------
void WorldWithRank::setKartPosition(unsigned int kart_id,
/** This function must be called before starting to set all kart positions
* again. It's mainly used to add some debug support, i.e. detect if the
* same position is set in different karts.
*/
void WorldWithRank::beginSetKartPositions()
{
#ifdef DEBUG
assert(!m_position_setting_initialised);
m_position_setting_initialised = true;
for(unsigned int i=0; i<m_position_used.size(); i++)
m_position_used[i] = false;
#endif
} // beginSetKartPositions
//-----------------------------------------------------------------------------
/** Sets the position of a kart. This will be saved in this object to allow
* quick lookup of which kart is on a given position, but also in the
* kart objects.
* \param kart_id The index of the kart to set the position for.
* \param position The position of the kart (1<=position<=num karts).
* \return false if this position was already set, i.e. an inconsistency in
* kart positions has occurred. This is used in debug mode only to
* allow the calling function to print debug information.
*/
bool WorldWithRank::setKartPosition(unsigned int kart_id,
unsigned int position)
{
m_position_index[position-1] = kart_id;
m_karts[kart_id]->setPosition(position);
#ifdef DEBUG
assert(m_position_setting_initialised);
if(m_position_used[position-1])
{
std::cerr << "== TWO KARTS ARE BEING GIVEN THE SAME POSITION!! ==\n";
for (unsigned int j=0; j < m_position_index.size(); j++)
{
if (!m_position_used[j])
{
std::cout << " No kart is yet set at position " << j << std::endl;
}
else
{
std::cout << " Kart " << m_position_index[j]
<< " is at position " << j << std::endl;
}
}
std::cout << "Kart " << kart_id << " is being given position "
<< position << ", but this position is already taken\n";
return false;
}
m_position_used[position-1] = true;
#endif
return true;
} // setKartPosition
// ----------------------------------------------------------------------------
/** Called by the race result GUI at the end of the race to know the final
* order.
* \param[out] order returns the order of karts. order[0] will contain the ID
* of the first kart, order[1] the ID of the second kart,
* etc... Array dimension will be adjusted to the number of
* karts.
//-----------------------------------------------------------------------------
/** Called once the last position was set. Note that we should not test
* if all positions were set, since e.g. for eliminated and finished karts
* the position won't be set anymore.
*/
void WorldWithRank::getRaceResultOrder(std::vector<int> *order)
void WorldWithRank::endSetKartPositions()
{
const unsigned int num_karts = getNumKarts();
order->resize(num_karts);
#ifndef NDEBUG
for (unsigned int i=0; i < num_karts; i++) (*order)[i] = -1;
bool positions_ok = true;
#endif
for (unsigned int i=0; i < num_karts; i++)
{
const int position = getKart(i)->getPosition()-1;
#ifndef NDEBUG
// sanity checks
if ((*order)[position] != -1)
{
std::cerr << "== TWO KARTS ARE BEING GIVEN THE SAME POSITION!! ==\n";
for (unsigned int j=0; j < num_karts; j++)
{
if ((*order)[j] == -1)
{
std::cout << " No kart is yet set at position " << j << std::endl;
}
else
{
std::cout << " Kart " << (*order)[j] << " is at position " << j << std::endl;
}
}
std::cout << "Kart " << i << " is being given posiiton " << (getKart(i)->getPosition()-1)
<< ", but this position is already taken\n";
positions_ok = false;
}
#endif
// actually assign the position
(*order)[position] = i; // even for eliminated karts
}
#ifndef NDEBUG
if (!positions_ok) history->Save();
assert(positions_ok);
#endif
} // getRaceResultOrder
assert(m_position_setting_initialised);
m_position_setting_initialised = false;
} // endSetKartPositions

View File

@@ -34,6 +34,18 @@ class WorldWithRank : public World
private:
/** This contains a mapping from race position to kart index. */
std::vector<int> m_position_index;
#ifdef DEBUG
/** Used for debugging to help detect if the same kart position
* is used more than once. */
std::vector<bool> m_position_used;
/** True if beginSetKartPositions was called, false after
* endSetKartPositions. Used to make sure the sequence of calls
* is correct. */
bool m_position_setting_initialised;
#endif
public:
WorldWithRank() : World() {}
/** call just after instanciating. can't be moved to the contructor as child
@@ -41,13 +53,12 @@ public:
results will be incorrect */
virtual void init();
void setKartPosition(unsigned int kart_id,
void beginSetKartPositions();
bool setKartPosition(unsigned int kart_id,
unsigned int position);
const Kart* getKartAtPosition(unsigned int p) const;
/** Called by the race result GUI at the end of the race to know the
* final order (fill in the 'order' array) */
virtual void getRaceResultOrder(std::vector<int> *order);
}; // WorldWithRank
void endSetKartPositions();
Kart* getKartAtPosition(unsigned int p) const;
}; // WorldWithRank
#endif

View File

@@ -109,8 +109,6 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
WorldWithRank *world = (WorldWithRank*)World::getWorld();
const unsigned int num_karts = world->getNumKarts();
std::vector<int> order;
world->getRaceResultOrder(&order);
const bool display_time = (world->getClockMode() == WorldStatus::CLOCK_CHRONO);
@@ -126,13 +124,11 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
m_rankings_y_bottom = -1;
int kart_id = 0; // 'i' below is not reliable because some karts (e.g. leader) will be skipped
for (unsigned int i = 0; i < num_karts; ++i)
for (unsigned int position = 1; position <= num_karts; position++)
{
if (order[i] == -1) continue;
const Kart* current_kart = world->getKartAtPosition(position);
stringw kart_results_line;
const Kart *current_kart = world->getKart(order[i]);
const stringw& kart_name = current_kart->getName();
std::string time_string;
@@ -147,8 +143,8 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
//This shows position + driver name + time + points earned + total points
if (race_manager->getMajorMode() == RaceManager::MAJOR_MODE_GRAND_PRIX)
{
const int prev_score = race_manager->getKartPrevScore(order[i]);
const int new_score = race_manager->getKartScore(order[i]);
const int prev_score = race_manager->getKartPrevScore(current_kart->getWorldKartId());
const int new_score = race_manager->getKartScore(current_kart->getWorldKartId());
if (display_time)
{
@@ -191,6 +187,7 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
const int entry_width = (show_highscores? m_area.getWidth()*2/3 : m_area.getWidth());
const int icon_size = text_height;
unsigned int i = current_kart->getWorldKartId();
core::rect< s32 > entry_area(10 + icon_size, lines_from_y + line_h*i,
entry_width , lines_from_y + line_h*(i+1));
core::rect< s32 > icon_area (5 , lines_from_y + line_h*i,